+ 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
+ :param vnfd: vnfd descriptor dict
+ :return:
+ """
+ # iterate over all deployment units within each VNFDs
+ for u in vnfd.get("virtual_deployment_units"):
+ # 1. get the name of the docker image to start and the assigned DC
+ vnf_name = vnfd.get("name")
+ if vnf_name not in self.remote_docker_image_urls:
+ raise Exception("No image name for %r found. Abort." % vnf_name)
+ docker_name = self.remote_docker_image_urls.get(vnf_name)
+ target_dc = vnfd.get("dc")
+ # 2. perform some checks to ensure we can start the container
+ assert(docker_name is not None)
+ assert(target_dc is not None)
+ if not self._check_docker_image_exists(docker_name):
+ raise Exception("Docker image %r not found. Abort." % docker_name)
+
+ # 3. get the resource limits
+ res_req = u.get("resource_requirements")
+ cpu_list = res_req.get("cpu").get("cores")
+ if not cpu_list or len(cpu_list)==0:
+ cpu_list="1"
+ cpu_bw = res_req.get("cpu").get("cpu_bw")
+ if not cpu_bw:
+ cpu_bw=1
+ mem_num = str(res_req.get("memory").get("size"))
+ if len(mem_num)==0:
+ mem_num="2"
+ mem_unit = str(res_req.get("memory").get("size_unit"))
+ if str(mem_unit)==0:
+ mem_unit="GB"
+ mem_limit = float(mem_num)
+ if mem_unit=="GB":
+ mem_limit=mem_limit*1024*1024*1024
+ elif mem_unit=="MB":
+ mem_limit=mem_limit*1024*1024
+ elif mem_unit=="KB":
+ mem_limit=mem_limit*1024
+ mem_lim = int(mem_limit)
+ cpu_period, cpu_quota = self._calculate_cpu_cfs_values(float(cpu_bw))
+
+ # 4. generate the volume paths for the docker container
+ volumes=list()
+ # a volume to extract log files
+ #tempfile.mkdtemp(dir="/tmp/results/%s/%s"%(self.uuid,vnf_name))
+ docker_log_path = "/tmp/results/%s/%s"%(self.uuid,vnf_name)
+ LOG.debug("LOG path for vnf %s is %s."%(vnf_name,docker_log_path))
+ #docker_log_path = tempfile.mkdtemp(dir=docker_log_path)
+ if not os.path.exists(docker_log_path):
+ os.makedirs(docker_log_path)
+ with open(docker_log_path+"/testfile", "w") as tf:
+ tf.write("placeholder")
+ tf.close()
+
+ volumes.append(docker_log_path+":/mnt/share/")
+
+
+ # 5. do the dc.startCompute(name="foobar") call to run the container
+ # TODO consider flavors, and other annotations
+ intfs = vnfd.get("connection_points")
+
+ # TODO: get all vnf id's from the nsd for this vnfd and use those as dockername
+ # use the vnf_id in the nsd as docker name
+ # so deployed containers can be easily mapped back to the nsd
+ vnf_name2id = defaultdict(lambda: "NotExistingNode",
+ reduce(lambda x, y: dict(x, **y),
+ map(lambda d: {d["vnf_name"]: d["vnf_id"]},
+ self.nsd["network_functions"])))
+ self.vnf_name2docker_name[vnf_name] = vnf_name2id[vnf_name]
+ # self.vnf_name2docker_name[vnf_name] = GK.get_next_vnf_name()
+
+ LOG.info("Starting %r as %r in DC %r" % (vnf_name, self.vnf_name2docker_name[vnf_name], vnfd.get("dc")))
+ LOG.debug("Interfaces for %r: %r" % (vnf_name, intfs))
+ vnfi = target_dc.startCompute(
+ self.vnf_name2docker_name[vnf_name],
+ network=intfs,
+ image=docker_name,
+ flavor_name="small",
+ cpu_quota=cpu_quota,
+ cpu_period=cpu_period,
+ cpuset=cpu_list,
+ mem_limit=mem_lim,
+ volumes=volumes)
+ 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).
+ :param instance_uuid: UUID of the service instance to search in.
+ :param name: VNF name or Docker name. We are fuzzy here.
+ :return:
+ """
+ dn = name
+ if name in self.vnf_name2docker_name:
+ dn = self.vnf_name2docker_name[name]
+ for vnfi in self.instances[instance_uuid]["vnf_instances"]:
+ if vnfi.name == dn:
+ return vnfi
+ LOG.warning("No container with name: %r found.")
+ return None
+
+ @staticmethod
+ def _vnf_reconfigure_network(vnfi, if_name, net_str):
+ """
+ Reconfigure the network configuration of a specific interface
+ of a running container.
+ :param vnfi: container instacne
+ :param if_name: interface name
+ :param net_str: network configuration string, e.g., 1.2.3.4/24
+ :return:
+ """
+ intf = vnfi.intf(intf=if_name)
+ if intf is not None:
+ intf.setIP(net_str)
+ LOG.debug("Reconfigured network of %s:%s to %r" % (vnfi.name, if_name, net_str))
+ else:
+ LOG.warning("Interface not found: %s:%s. Network reconfiguration skipped." % (vnfi.name, if_name))
+
+
+ def _trigger_emulator_start_scripts_in_vnfis(self, vnfi_list):
+ for vnfi in vnfi_list:
+ config = vnfi.dcinfo.get("Config", dict())
+ env = config.get("Env", list())
+ for env_var in env:
+ var, cmd = map(str.strip, map(str, env_var.split('=', 1)))
+ LOG.debug("%r = %r" % (var , cmd))
+ if var=="SON_EMU_CMD":
+ LOG.info("Executing entry point script in %r: %r" % (vnfi.name, cmd))
+ # execute command in new thread to ensure that GK is not blocked by VNF
+ t = threading.Thread(target=vnfi.cmdPrint, args=(cmd,))
+ t.daemon = True
+ t.start()
+