From 1b5c45f21800455901c1f7d973a2b89700f1ba0d Mon Sep 17 00:00:00 2001 From: XuHugo Date: Wed, 9 Jun 2021 12:44:52 +0800 Subject: [PATCH] create network and start create netowork and start at the same time *create network and then start all node by turn; Signed-off-by: XuHugo --- .../api/lib/configtxgen/configtx.py | 4 +- src/api-engine/api/models.py | 14 +++- .../api/routes/network/serializers.py | 4 +- src/api-engine/api/routes/network/views.py | 77 ++++++++++++++++++- src/api-engine/api/utils/port_picker.py | 26 ++++++- 5 files changed, 113 insertions(+), 12 deletions(-) diff --git a/src/api-engine/api/lib/configtxgen/configtx.py b/src/api-engine/api/lib/configtxgen/configtx.py index 35e3e2cc9..f3b5c1c5e 100644 --- a/src/api-engine/api/lib/configtxgen/configtx.py +++ b/src/api-engine/api/lib/configtxgen/configtx.py @@ -53,7 +53,7 @@ def create(self, consensus, orderers, peers, orderer_cfg=None, application=None, Admins=dict(Type="Signature",Rule="OR('{}MSP.admin')".format(orderer["name"].split(".")[0].capitalize()+"Orderer"))) )) for host in orderer['hosts']: - OrdererAddress.append('{}.{}:{}'.format(host['name'], orderer['name'].split(".", 1)[1], host["port"])) + OrdererAddress.append('{}.{}:{}'.format(host['name'], orderer['name'].split(".", 1)[1], 7050)) PeerOrganizations = [] @@ -86,7 +86,7 @@ def create(self, consensus, orderers, peers, orderer_cfg=None, application=None, for orderer in orderers: for host in orderer['hosts']: Consenters.append(dict(Host='{}.{}'.format(host['name'], orderer['name'].split(".", 1)[1]), - Port=host['port'], + Port=7050, ClientTLSCert='{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt' .format(self.filepath, orderer['name'], orderer['name'].split(".", 1)[1],host['name'], orderer['name'].split(".", 1)[1]), ServerTLSCert='{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt' diff --git a/src/api-engine/api/models.py b/src/api-engine/api/models.py index 75e8f1c4d..475a6f358 100644 --- a/src/api-engine/api/models.py +++ b/src/api-engine/api/models.py @@ -196,9 +196,14 @@ class Agent(models.Model): help_text="Create time of agent", auto_now_add=True ) - free_port = models.IntegerField( - help_text="Agent free port.", - default=30000, + # free_port = models.IntegerField( + # help_text="Agent free port.", + # default=30000, + # ) + free_ports = ArrayField( + models.IntegerField(blank=True), + help_text="Agent free ports.", + null=True ) def delete(self, using=None, keep_parents=False): @@ -320,6 +325,9 @@ class Network(models.Model): help_text="genesis block", null=True, ) + database = models.CharField( + help_text="database of network", max_length=128, default="leveldb", + ) class Meta: ordering = ("-created_at",) diff --git a/src/api-engine/api/routes/network/serializers.py b/src/api-engine/api/routes/network/serializers.py index 5738535dc..b355dd04a 100644 --- a/src/api-engine/api/routes/network/serializers.py +++ b/src/api-engine/api/routes/network/serializers.py @@ -69,11 +69,11 @@ class NetworkCreateBody(serializers.ModelSerializer): class Meta: model = Network - fields = ("name", "consensus", "organizations", "db") + fields = ("name", "consensus", "organizations", "database") extra_kwargs = {"name": {"required": True}, "consensus": {"required": True}, "organizations": {"required": True}, - "db": {"required": True}} + "database": {"required": True}} class NetworkMemberResponse(serializers.Serializer): diff --git a/src/api-engine/api/routes/network/views.py b/src/api-engine/api/routes/network/views.py index fc7d70757..cef9cda48 100644 --- a/src/api-engine/api/routes/network/views.py +++ b/src/api-engine/api/routes/network/views.py @@ -3,6 +3,8 @@ # import logging import base64 +import shutil +import os from rest_framework import viewsets, status from rest_framework.decorators import action @@ -10,6 +12,7 @@ from drf_yasg.utils import swagger_auto_schema from django.core.paginator import Paginator from django.core.exceptions import ObjectDoesNotExist +from api.exceptions import ResourceNotFound from rest_framework_jwt.authentication import JSONWebTokenAuthentication from api.routes.network.serializers import ( NetworkQuery, @@ -28,13 +31,14 @@ from api.config import CELLO_HOME from api.utils import zip_dir, zip_file from api.auth import TokenAuth +from api.lib.agent import AgentHandler LOG = logging.getLogger(__name__) class NetworkViewSet(viewsets.ViewSet): - authentication_classes = (JSONWebTokenAuthentication, TokenAuth) + #authentication_classes = (JSONWebTokenAuthentication, TokenAuth) def _genesis2base64(self, network): """ @@ -97,6 +101,60 @@ def list(self, request): ) return Response(data=[], status=status.HTTP_200_OK) + def _agent_params(self, pk): + """ + get node's params from db + :param node: node id + :return: info + """ + try: + node = Node.objects.get(id=pk) + org = node.org + if org is None: + raise ResourceNotFound + network = org.network + if network is None: + raise ResourceNotFound + agent = org.agent.get() + if agent is None: + raise ResourceNotFound + + info = {} + + # get info of node, e.g, tls, msp, config. + info["status"] = node.status + info["msp"] = node.msp + info["tls"] = node.tls + info["config_file"] = node.config_file + info["type"] = node.type + info["name"] = node.name + info["bootstrap_block"] = network.genesisblock + info["urls"] = agent.urls + info["network_type"] = network.type + info["agent_type"] = agent.type + return info + except Exception as e: + raise e + + def _start_node(self, pk): + """ + start node from agent + :param node: node id + :return: null + """ + try: + infos = self._agent_params(pk) + + agent = AgentHandler(infos) + cid = agent.create(infos) + if cid: + Node.objects.filter(id=pk).update(cid=cid) + + else: + raise ResourceNotFound + except Exception as e: + raise e + @swagger_auto_schema( request_body=NetworkCreateBody, responses=with_common_response( @@ -116,7 +174,7 @@ def create(self, request): name = serializer.validated_data.get("name") consensus = serializer.validated_data.get("consensus") organizations = serializer.validated_data.get("organizations") - db = serializer.validated_data.get("db") + database = serializer.validated_data.get("database") try: Network.objects.get(name=name) @@ -132,9 +190,9 @@ def create(self, request): nodes = Node.objects.filter(org=org) for node in nodes: if node.type == "peer": - peers[i]["hosts"].append({"name": node.name, "port": node.urls.split(":")[2]}) + peers[i]["hosts"].append({"name": node.name}) elif node.type == "orderer": - orderers[i]["hosts"].append({"name": node.name, "port": node.urls.split(":")[2]}) + orderers[i]["hosts"].append({"name": node.name}) i = i + 1 ConfigTX(name).create(consensus=consensus, orderers=orderers, peers=peers) @@ -146,6 +204,14 @@ def create(self, request): for organization in organizations: Organization.objects.filter(pk=organization).update(network=network) + org = Organization.objects.get(pk=organization) + nodes = Node.objects.filter(org=org) + for node in nodes: + try: + self._start_node(node.id) + except Exception as e: + print("err:", e) + pass response = NetworkIDSerializer(data=network.__dict__) if response.is_valid(raise_exception=True): @@ -170,6 +236,9 @@ def retrieve(self, request, pk=None): def destroy(self, request, pk=None): try: network = Network.objects.get(pk=pk) + path = "{}/{}".format(CELLO_HOME, network.name) + if os.path.exists(path): + shutil.rmtree(path, True) network.delete() except ObjectDoesNotExist: raise BaseException diff --git a/src/api-engine/api/utils/port_picker.py b/src/api-engine/api/utils/port_picker.py index 51152008a..d0db13b8d 100644 --- a/src/api-engine/api/utils/port_picker.py +++ b/src/api-engine/api/utils/port_picker.py @@ -6,7 +6,7 @@ import os from random import sample from django.core.exceptions import ObjectDoesNotExist -from api.models import Port, Node +from api.models import Port, Node, Agent CLUSTER_PORT_START = int(os.getenv("CLUSTER_PORT_START", 7050)) MAX_RETRY = 100 @@ -108,3 +108,27 @@ def set_ports_mapping(node_id=None, mapping=None, new=False): Port.objects.filter( node__id=node_id, external=port.get("external") ).update(internal=port.get("internal")) + + +def get_available_ports( + agent_id=None, + request_count=1, +): + + agent = Agent.objects.get(id=agent_id).free_ports + + used_ports = agent.free_ports + + ports = sample( + [ + i + for i in range(CLUSTER_PORT_START, 65535) + if i not in used_ports + ], + request_count, + ) + + agent.free_ports = used_ports.append(ports) + agent.save() + + return ports