Fix: Fixed version of tinyrpc to not break the Ryu installation.
[osm/vim-emu.git] / src / emuvim / api / tango / llcm.py
index 1d55d11..9ddc772 100755 (executable)
@@ -52,6 +52,10 @@ LOG = logging.getLogger("5gtango.llcm")
 LOG.setLevel(logging.INFO)
 
 
+CORS_HEADER = {'Access-Control-Allow-Origin': '*',
+               'Access-Control-Allow-Methods': 'GET,OPTIONS'}
+
+
 GK_STORAGE = "/tmp/vim-emu-tango-llcm/"
 UPLOAD_FOLDER = os.path.join(GK_STORAGE, "uploads/")
 CATALOG_FOLDER = os.path.join(GK_STORAGE, "catalog/")
@@ -93,11 +97,15 @@ VNF_STOP_WAIT_TIME = 5
 # offset for this: NEW_PORT (SSIID * OFFSET) + ORIGINAL_PORT
 MULTI_INSTANCE_PORT_OFFSET = 1000
 
-
 # Selected Placement Algorithm: Points to the class of the selected
 # placement algorithm.
 PLACEMENT_ALGORITHM_OBJ = None
 
+# Path to folder with <container_name>.env.yml files that contain
+# environment variables injected into the specific container
+# when it is started.
+PER_INSTANCE_ENV_CONFIGURATION_FOLDER = None
+
 
 class OnBoardingException(BaseException):
     pass
@@ -356,11 +364,30 @@ class Service(object):
             ports = list()  # Containernet naming
             port_bindings = dict()
             for i in intfs:
-                if i.get("port"):
+                if i.get("port"):  # field with a single port
                     if not isinstance(i.get("port"), int):
                         LOG.info("Field 'port' is no int CP: {}".format(i))
                     else:
-                        ports.append(i.get("port"))
+                        ports.append(i.get("port"))  # collect all ports
+                if i.get("ports"):  # list with multiple ports
+                    if not isinstance(i.get("ports"), list):
+                        LOG.info("Field 'port' is no list CP: {}".format(i))
+                    else:
+                        for p in i.get("ports"):
+                            if not isinstance(p, int):
+                                # do some parsing
+                                try:
+                                    if "/udp" in p:
+                                        p = tuple(p.split("/"))
+                                    else:
+                                        p = int(p)
+                                    ports.append(p)  # collect all ports
+                                except BaseException as ex:
+                                    LOG.error(
+                                        "Could not parse ports list: {}".format(p))
+                                    LOG.error(ex)
+                            else:
+                                ports.append(p)  # collect all ports
                 if i.get("publish"):
                     if not isinstance(i.get("publish"), dict):
                         LOG.info("Field 'publish' is no dict CP: {}".format(i))
@@ -388,6 +415,10 @@ class Service(object):
                          " Overwriting SON_EMU_CMD_STOP.")
                 cenv["SON_EMU_CMD_STOP"] = VNFD_CMD_STOP
 
+            # 5.2 inject per instance configurations based on envs
+            conf_envs = self._load_instance_conf_envs(vnf_container_instance_name)
+            cenv.update(conf_envs)
+
             # 6. Start the container
             LOG.info("Starting %r as %r in DC %r" %
                      (vnf_name, vnf_container_instance_name, target_dc))
@@ -521,6 +552,26 @@ class Service(object):
                     t.start()
                     break  # only execute one command
 
+    def _load_instance_conf_envs(self, cname):
+        """
+        Try to load an instance-specific env file. If not found,
+        just return an empty dict.
+        """
+        if PER_INSTANCE_ENV_CONFIGURATION_FOLDER is None:
+            return dict()
+        try:
+            path = os.path.expanduser(PER_INSTANCE_ENV_CONFIGURATION_FOLDER)
+            path = os.path.join(path, "{}.env.yml".format(cname))
+            res = load_yaml(path)
+            LOG.info("Loaded instance-specific env file for '{}': {}"
+                     .format(cname, res))
+            return res
+        except BaseException as ex:
+            LOG.info("No instance-specific env file found for: {}"
+                     .format(cname))
+            del ex
+        return dict()
+
     def _unpack_service_package(self):
         """
         unzip *.son file and store contents in CATALOG_FOLDER/services/<service_uuid>/
@@ -1010,7 +1061,7 @@ class Packages(fr.Resource):
             pkg["pd"]["version"] = sobj.manifest.get("version")
             pkg["created_at"] = sobj.created_at
             result.append(pkg)
-        return result, 200
+        return result, 200, CORS_HEADER
 
 
 class Services(fr.Resource):
@@ -1032,7 +1083,7 @@ class Services(fr.Resource):
             service["nsd"]["version"] = sobj.nsd.get("version")
             service["created_at"] = sobj.created_at
             result.append(service)
-        return result, 200
+        return result, 200, CORS_HEADER
 
 
 class Instantiations(fr.Resource):
@@ -1079,7 +1130,7 @@ class Instantiations(fr.Resource):
         Returns a list of UUIDs containing all running services.
         :return: dict / list
         """
-        LOG.info("GET /instantiations or /api/v3/records/services")
+        LOG.debug("GET /instantiations or /api/v3/records/services")
         # return {"service_instantiations_list": [
         #    list(s.instances.iterkeys()) for s in GK.services.itervalues()]}
         result = list()
@@ -1092,7 +1143,7 @@ class Instantiations(fr.Resource):
                 inst["status"] = "running"
                 inst["created_at"] = iobj.get("created_at")
                 result.append(inst)
-        return result, 200
+        return result, 200, CORS_HEADER
 
     def delete(self):
         """