Merge remote-tracking branch 'upstream/master'
authorstevenvanrossem <steven.vanrossem@intec.ugent.be>
Tue, 15 Nov 2016 19:35:43 +0000 (20:35 +0100)
committerstevenvanrossem <steven.vanrossem@intec.ugent.be>
Tue, 15 Nov 2016 19:35:43 +0000 (20:35 +0100)
1  2 
src/emuvim/api/sonata/dummygatekeeper.py

@@@ -75,7 -75,6 +75,7 @@@ class Gatekeeper(object)
      def __init__(self):
          self.services = dict()
          self.dcs = dict()
 +        self.net = None
          self.vnf_counter = 0  # used to generate short names for VNFs (Mininet limitation)
          LOG.info("Create SONATA dummy gatekeeper.")
  
@@@ -181,9 -180,6 +181,9 @@@ class Service(object)
          eline_fwd_links = [l for l in vlinks if (l["id"] in fwd_links) and (l["connectivity_type"] == "E-Line")]
          elan_fwd_links = [l for l in vlinks if (l["id"] in fwd_links) and (l["connectivity_type"] == "E-LAN")]
  
 +        GK.net.deployed_elines.extend(eline_fwd_links)
 +        GK.net.deployed_elans.extend(elan_fwd_links)
 +
          # 4a. deploy E-Line links
          # cookie is used as identifier for the flowrules installed by the dummygatekeeper
          # eg. different services get a unique cookie for their flowrules
          # 4b. deploy E-LAN links
          base = 10
          for link in elan_fwd_links:
 +
 +            elan_vnf_list=[]
 +
              # generate lan ip address
              ip = 1
              for intf in link["connection_points_reference"]:
                  if vnf_id in self.sap_identifiers:
                      src_docker_name = "{0}_{1}".format(vnf_id, intf_name)
                      vnf_id = src_docker_name
 +                else:
 +                    src_docker_name = vnf_id
                  vnf_name = vnf_id2vnf_name[vnf_id]
                  LOG.debug(
                      "Setting up E-LAN link. %s(%s:%s) -> %s" % (
                          self._vnf_reconfigure_network(vnfi, intf_name, ip_address)
                          # increase for the next ip address on this E-LAN
                          ip += 1
 +
 +                        # add this vnf and interface to the E-LAN for tagging
 +                        network = self.vnfds[vnf_name].get("dc").net  # there should be a cleaner way to find the DCNetwork
 +                        elan_vnf_list.append({'name':src_docker_name,'interface':intf_name})
 +
 +
 +            # install the VLAN tags for this E-LAN
 +            network.setLAN(elan_vnf_list)
              # increase the base ip address for the next E-LAN
              base += 1
  
          LOG.info("Service started. Instance id: %r" % instance_uuid)
          return instance_uuid
  
+     def stop_service(self, instance_uuid):
+         """
+         This method stops a running service instance.
+         It iterates over all VNF instances, stopping them each
+         and removing them from their data center.
+         :param instance_uuid: the uuid of the service instance to be stopped
+         """
+         LOG.info("Stopping service %r" % self.uuid)
+         # get relevant information
+         # instance_uuid = str(self.uuid.uuid4())
+         vnf_instances = self.instances[instance_uuid]["vnf_instances"]
+         for v in vnf_instances:
+             self._stop_vnfi(v)
+         if not GK_STANDALONE_MODE:
+             # remove placement?
+             # self._remove_placement(RoundRobinPlacement)
+             None
+         # last step: remove the instance from the list of all instances
+         del self.instances[instance_uuid]
      def _start_vnfd(self, vnfd):
          """
          Start a single VNFD of this service
              vnfi = target_dc.startCompute(self.vnf_name2docker_name[vnf_name], network=intfs, image=docker_name, flavor_name="small")
              return vnfi
  
+     def _stop_vnfi(self, vnfi):
+         """
+         Stop a VNF instance.
+         :param vnfi: vnf instance to be stopped
+         """
+         # Find the correct datacenter
+         status = vnfi.getStatus()
+         dc = vnfi.datacenter
+         # stop the vnfi
+         LOG.info("Stopping the vnf instance contained in %r in DC %r" % (status["name"], dc))
+         dc.stopCompute(status["name"])
      def _get_vnf_instance(self, instance_uuid, name):
          """
          Returns the Docker object for the given VNF name (or Docker name).
                  self.package_content_path,
                  make_relative_path(self.manifest.get("entry_service_template")))
              self.nsd = load_yaml(nsd_path)
 +            GK.net.deployed_nsds.append(self.nsd)
              LOG.debug("Loaded NSD: %r" % self.nsd.get("name"))
  
      def _load_vnfd(self):
@@@ -529,7 -548,7 +566,7 @@@ class RoundRobinDcPlacement(object)
      """
      def place(self, nsd, vnfds, dcs):
          c = 0
-         dcs_list = list(dcs.itervalues()) 
+         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
@@@ -608,7 -627,7 +645,7 @@@ class Instantiations(fr.Resource)
          if service_uuid in GK.services:
              # ok, we have a service uuid, lets start the service
              service_instance_uuid = GK.services.get(service_uuid).start_service()
-             return {"service_instance_uuid": service_instance_uuid}
+             return {"service_instance_uuid": service_instance_uuid}, 201
          return "Service not found", 404
  
      def get(self):
          return {"service_instantiations_list": [
              list(s.instances.iterkeys()) for s in GK.services.itervalues()]}
  
+     def delete(self):
+         """
+         Stops a running service specified by its service and instance UUID.
+         """
+         # try to extract the service  and instance UUID from the request
+         json_data = request.get_json(force=True)
+         service_uuid = json_data.get("service_uuid")
+         instance_uuid = json_data.get("service_instance_uuid")
+         # try to be fuzzy
+         if service_uuid is None and len(GK.services) > 0:
+             #if we don't get a service uuid, we simply stop the last service in the list
+             service_uuid = list(GK.services.iterkeys())[0]
+         if instance_uuid is None and len(GK.services[service_uuid].instances) > 0:
+             instance_uuid = list(GK.services[service_uuid].instances.iterkeys())[0]
+         if service_uuid in GK.services and instance_uuid in GK.services[service_uuid].instances:
+             # valid service and instance UUID, stop service
+             GK.services.get(service_uuid).stop_service(instance_uuid)
+             del GK.services.get(service_uuid).instances[instance_uuid]
+             return
+         return "Service not found", 404
+ class Exit(fr.Resource):
+     def put(self):
+         """
+         Stop the running Containernet instance regardless of data transmitted
+         """
+         GK.net.stop()
+ def initialize_GK():
+     global GK
+     GK = Gatekeeper()
  
  # create a single, global GK object
- GK = Gatekeeper()
+ GK = None
+ initialize_GK()
  # setup Flask
  app = Flask(__name__)
  app.config['MAX_CONTENT_LENGTH'] = 512 * 1024 * 1024  # 512 MB max upload
@@@ -630,11 -687,16 +705,17 @@@ api = fr.Api(app
  # define endpoints
  api.add_resource(Packages, '/packages')
  api.add_resource(Instantiations, '/instantiations')
+ api.add_resource(Exit, '/emulator/exit')
+ #def initialize_GK():
+ #    global GK
+ #    GK = Gatekeeper()
  
  
  def start_rest_api(host, port, datacenters=dict()):
      GK.dcs = datacenters
 +    GK.net = get_dc_network()
      # start the Flask server (not the best performance but ok for our use case)
      app.run(host=host,
              port=port,
@@@ -683,14 -745,6 +764,14 @@@ def generate_subnet_strings(n, start=1
          r.append("%d.0.0.%d/%d" % (i, ip, subnet_size))
      return r
  
 +def get_dc_network():
 +    """
 +    retrieve the DCnetwork where this dummygatekeeper (GK) connects to.
 +    Assume at least 1 datacenter is connected to this GK, and that all datacenters belong to the same DCNetwork
 +    :return:
 +    """
 +    assert (len(GK.dcs) > 0)
 +    return GK.dcs.values()[0].net
  
  if __name__ == '__main__':
      """