+ 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. do the dc.startCompute(name="foobar") call to run the container
+ # TODO consider flavors, and other annotations
+ intfs = vnfd.get("connection_points")
+ # mgmt connection points can be skipped, this is considered to be the connection the default docker0 bridge
+ intfs = [intf for intf in intfs if 'mgmt' not in intf['id']]
+
+ # 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")
+ return vnfi
+
+ 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:
+ if "SON_EMU_CMD=" in env_var:
+ cmd = str(env_var.split("=")[1])
+ LOG.info("Executing entrypoint script in %r: %r" % (vnfi.name, cmd))
+ vnfi.cmdPrint(cmd)
+