X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Femuvim%2Fapi%2Fsonata%2Fdummygatekeeper.py;h=2a994bddc63a94d6f5910aecf20922ffd6970b9f;hb=d454d54713526a24da1ffbc513f1e00a1ff44f66;hp=7ae3522d6a5ea8e71ad5107a7fa06c3f3116f830;hpb=f90c1f70bbb59ab940dd7698f784594b0927baaf;p=osm%2Fvim-emu.git diff --git a/src/emuvim/api/sonata/dummygatekeeper.py b/src/emuvim/api/sonata/dummygatekeeper.py index 7ae3522..2a994bd 100755 --- a/src/emuvim/api/sonata/dummygatekeeper.py +++ b/src/emuvim/api/sonata/dummygatekeeper.py @@ -64,8 +64,12 @@ GK_STANDALONE_MODE = False FORCE_PULL = False # Automatically deploy SAPs (endpoints) of the service as new containers +# Attention: This is not a configuration switch but a global variable! Don't change its default value. DEPLOY_SAP = False +# flag to indicate if we use bidirectional forwarding rules in the automatic chaining process +BIDIRECTIONAL_CHAIN = False + class Gatekeeper(object): def __init__(self): @@ -116,7 +120,6 @@ class Service(object): self.eline_subnets_src = generate_subnet_strings(50, start=200, subnet_size=24, ip=1) self.eline_subnets_dst = generate_subnet_strings(50, start=200, subnet_size=24, ip=2) - def onboard(self): """ Do all steps to prepare this service to be instantiated @@ -163,7 +166,8 @@ class Service(object): # 3. compute placement of this service instance (adds DC names to VNFDs) if not GK_STANDALONE_MODE: - self._calculate_placement(FirstDcPlacement) + #self._calculate_placement(FirstDcPlacement) + self._calculate_placement(RoundRobinDcPlacement) # iterate over all vnfds that we have to start for vnfd in self.vnfds.itervalues(): vnfi = None @@ -210,7 +214,7 @@ class Service(object): ret = network.setChain( src_docker_name, dst_docker_name, vnf_src_interface=src_if_name, vnf_dst_interface=dst_if_name, - bidirectional=True, cmd="add-flow", cookie=cookie, priority=10) + bidirectional=BIDIRECTIONAL_CHAIN, cmd="add-flow", cookie=cookie, priority=10) # re-configure the VNFs IP assignment and ensure that a new subnet is used for each E-Link src_vnfi = self._get_vnf_instance(instance_uuid, src_name) @@ -238,8 +242,8 @@ class Service(object): if vnf_name in self.vnfds: # re-configure the VNFs IP assignment and ensure that a new subnet is used for each E-LAN - # E-LAN relies on the learning switch capability of the infrastructure switch in dockernet, - # so no explicit chaining is necessary + # E-LAN relies on the learning switch capability of Ryu which has to be turned on in the topology + # (DCNetwork(controller=RemoteController, enable_learning=True)), so no explicit chaining is necessary. vnfi = self._get_vnf_instance(instance_uuid, vnf_name) if vnfi is not None: self._vnf_reconfigure_network(vnfi, intf_name, ip_address) @@ -254,6 +258,18 @@ class Service(object): LOG.info("Service started. Instance id: %r" % instance_uuid) return instance_uuid + def stop_service(self): + """ + This method stops a running service instance. + It iterates over all VNFDs, stopping them each + and removing them from their data center. + + :return: + """ + + + + def _start_vnfd(self, vnfd): """ Start a single VNFD of this service @@ -292,6 +308,20 @@ class Service(object): vnfi = target_dc.startCompute(self.vnf_name2docker_name[vnf_name], network=intfs, image=docker_name, flavor_name="small") return vnfi + def _stop_vnfd(self, vnf_name): + """ + Stop a VNFD specified by its name. + + :param vnf_name: Name of the vnf to be stopped + :return: + """ + if vnf_name not in self.vnfds: + raise Exception("VNFD with name %s not found." % vnf_name) + vnfd = self.vnfds[vnf_name] + dc = vnfd.get("dc") + LOG.info("Stopping %r contained in %r in DC %r" % (vnf_name, self.vnf_name2docker_name[vnf_name], dc) + dc.stopCompute(self.vnf_name2docker_name[vnf_name]) + def _get_vnf_instance(self, instance_uuid, name): """ Returns the Docker object for the given VNF name (or Docker name). @@ -393,7 +423,7 @@ class Service(object): # set of the connection_point ids found in the nsd (in the examples this is 'ns') self.sap_identifiers.add(sap_vnf_id) - sap_docker_name = sap.replace(':', '_') + sap_docker_name = "%s_%s" % (sap_vnf_id, sap_vnf_interface) # add SAP to self.vnfds sapfile = pkg_resources.resource_filename(__name__, "sap_vnfd.yml") @@ -501,6 +531,20 @@ class FirstDcPlacement(object): vnfd["dc"] = list(dcs.itervalues())[0] +class RoundRobinDcPlacement(object): + """ + Placement: Distribute VNFs across all available DCs in a round robin fashion. + """ + def place(self, nsd, vnfds, dcs): + c = 0 + dcs_list = list(dcs.itervalues()) + for name, vnfd in vnfds.iteritems(): + vnfd["dc"] = dcs_list[c % len(dcs_list)] + c += 1 # inc. c to use next DC + + + + """ Resource definitions and API endpoints """ @@ -538,7 +582,7 @@ class Packages(fr.Resource): s = Service(service_uuid, file_hash, upload_path) GK.register_service_package(service_uuid, s) # generate the JSON result - return {"service_uuid": service_uuid, "size": size, "sha1": file_hash, "error": None} + return {"service_uuid": service_uuid, "size": size, "sha1": file_hash, "error": None}, 201 except Exception as ex: LOG.exception("Service package upload failed:") return {"service_uuid": None, "size": 0, "sha1": None, "error": "upload failed"}, 500 @@ -584,6 +628,22 @@ class Instantiations(fr.Resource): return {"service_instantiations_list": [ list(s.instances.iterkeys()) for s in GK.services.itervalues()]} + def delete(self): + """ + Stops a running service specified by its UUID. + + :return: + """ + # try to extract the service UUID from the request + json_data = request.get_json(force=True) + service_uuid = json_data.get("service_uuid") + + if service_uuid in GK.services: + # valid service UUID, stop service + GK.services.get(service_uuid).stop_service() + return "", 0 + return "Service not found", 404 + # create a single, global GK object GK = Gatekeeper()