Fixing SFC 14/6714/8
authorEduardo Sousa <esousa@whitestack.com>
Wed, 17 Oct 2018 16:10:04 +0000 (17:10 +0100)
committerEduardo Sousa <esousa@whitestack.com>
Mon, 22 Oct 2018 15:34:59 +0000 (16:34 +0100)
Fixes the changes made in RO to allow SFC to be working again.
Takes care of the dependencies when deleting the different parts,
such as SFIs, SFs, Classifications and SFPs.

Change-Id: Ifc408fae6ea33b6e1c7c0096106150069b62cc91
Signed-off-by: Eduardo Sousa <esousa@whitestack.com>
docker/Dockerfile-local
osm_ro/nfvo.py
osm_ro/vim_thread.py

index 881e103..7fc62e3 100644 (file)
@@ -2,8 +2,6 @@ from ubuntu:xenial
 
 LABEL authors="Gennadiy Dubina, Alfonso Tierno, Gerardo Garcia"
 
-COPY . /root/RO
-
 RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive apt-get -y install software-properties-common && \
     DEBIAN_FRONTEND=noninteractive add-apt-repository -y cloud-archive:queens && \
@@ -17,8 +15,11 @@ RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive apt-get -y install python-openstacksdk python-openstackclient && \
     DEBIAN_FRONTEND=noninteractive pip2 install untangle && \
     DEBIAN_FRONTEND=noninteractive pip2 install -e git+https://github.com/python-oca/python-oca#egg=oca && \
-    DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-client && \
-    /root/RO/scripts/install-osm-im.sh --develop && \
+    DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-client
+
+COPY . /root/RO
+
+RUN /root/RO/scripts/install-osm-im.sh --develop && \
     /root/RO/scripts/install-lib-osm-openvim.sh --develop && \
     make -C /root/RO prepare && \
     mkdir -p /var/log/osm && \
@@ -61,4 +62,3 @@ ENV RO_DB_HOST="" \
     OPENMANO_TENANT=osm
 
 CMD RO-start.sh
-
index dd3b6aa..e16c38f 100644 (file)
@@ -3851,68 +3851,21 @@ def delete_instance(mydb, tenant_id, instance_id):
         # "number_tasks": 0 # filled bellow
     }
 
-    # 2.1 deleting VMs
-    # vm_fail_list=[]
-    for sce_vnf in instanceDict['vnfs']:
-        datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
-        vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None
-        if datacenter_key not in myvims:
-            try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
-            except NfvoException as e:
-                logger.error(str(e))
-                myvim_thread = None
-            myvim_threads[datacenter_key] = myvim_thread
-            vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"],
-                       datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
-            if len(vims) == 0:
-                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"],
-                                                                                        sce_vnf["datacenter_tenant_id"]))
-                myvims[datacenter_key] = None
-            else:
-                myvims[datacenter_key] = vims.values()[0]
-        myvim = myvims[datacenter_key]
-        myvim_thread = myvim_threads[datacenter_key]
-        for vm in sce_vnf['vms']:
-            if not myvim:
-                error_msg += "\n    VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"])
-                continue
-            db_vim_action = {
-                "instance_action_id": instance_action_id,
-                "task_index": task_index,
-                "datacenter_vim_id": sce_vnf["datacenter_tenant_id"],
-                "action": "DELETE",
-                "status": "SCHEDULED",
-                "item": "instance_vms",
-                "item_id": vm["uuid"],
-                "extra": yaml.safe_dump({"params": vm["interfaces"]},
-                                        default_flow_style=True, width=256)
-            }
-            db_vim_actions.append(db_vim_action)
-            for interface in vm["interfaces"]:
-                if not interface.get("instance_net_id"):
-                    continue
-                if interface["instance_net_id"] not in net2vm_dependencies:
-                    net2vm_dependencies[interface["instance_net_id"]] = []
-                net2vm_dependencies[interface["instance_net_id"]].append(task_index)
-            task_index += 1
-
-    # 2.2 deleting NETS
-    # net_fail_list=[]
-    for net in instanceDict['nets']:
-        vimthread_affected[net["datacenter_tenant_id"]] = None
-        datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
+    # 2.1 deleting VNFFGs
+    for sfp in instanceDict.get('sfps', ()):
+        vimthread_affected[sfp["datacenter_tenant_id"]] = None
+        datacenter_key = (sfp["datacenter_id"], sfp["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sfp["datacenter_id"], sfp["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             myvim_threads[datacenter_key] = myvim_thread
-            vims = get_vim(mydb, tenant_id, datacenter_id=net["datacenter_id"],
-                           datacenter_tenant_id=net["datacenter_tenant_id"])
+            vims = get_vim(mydb, tenant_id, datacenter_id=sfp["datacenter_id"],
+                           datacenter_tenant_id=sfp["datacenter_tenant_id"])
             if len(vims) == 0:
-                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp["datacenter_id"], sfp["datacenter_tenant_id"]))
                 myvims[datacenter_key] = None
             else:
                 myvims[datacenter_key] = vims.values()[0]
@@ -3920,40 +3873,37 @@ def delete_instance(mydb, tenant_id, instance_id):
         myvim_thread = myvim_threads[datacenter_key]
 
         if not myvim:
-            error_msg += "\n    Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"])
+            error_msg += "\n    vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp['vim_sfp_id'], sfp["datacenter_id"])
             continue
-        extra = {"params": (net['vim_net_id'], net['sdn_net_id'])}
-        if net2vm_dependencies.get(net["uuid"]):
-            extra["depends_on"] = net2vm_dependencies[net["uuid"]]
+        extra = {"params": (sfp['vim_sfp_id'])}
         db_vim_action = {
             "instance_action_id": instance_action_id,
             "task_index": task_index,
-            "datacenter_vim_id": net["datacenter_tenant_id"],
+            "datacenter_vim_id": sfp["datacenter_tenant_id"],
             "action": "DELETE",
             "status": "SCHEDULED",
-            "item": "instance_nets",
-            "item_id": net["uuid"],
+            "item": "instance_sfps",
+            "item_id": sfp["uuid"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
         db_vim_actions.append(db_vim_action)
 
-    # 2.3 deleting VNFFGs
-
-    for sfp in instanceDict.get('sfps', ()):
-        vimthread_affected[sfp["datacenter_tenant_id"]] = None
-        datacenter_key = (sfp["datacenter_id"], sfp["datacenter_tenant_id"])
+    for classification in instanceDict['classifications']:
+        vimthread_affected[classification["datacenter_tenant_id"]] = None
+        datacenter_key = (classification["datacenter_id"], classification["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sfp["datacenter_id"], sfp["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, classification["datacenter_id"], classification["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             myvim_threads[datacenter_key] = myvim_thread
-            vims = get_vim(mydb, tenant_id, datacenter_id=sfp["datacenter_id"],
-                           datacenter_tenant_id=sfp["datacenter_tenant_id"])
+            vims = get_vim(mydb, tenant_id, datacenter_id=classification["datacenter_id"],
+                           datacenter_tenant_id=classification["datacenter_tenant_id"])
             if len(vims) == 0:
-                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp["datacenter_id"], sfp["datacenter_tenant_id"]))
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification["datacenter_id"],
+                                                                                               classification["datacenter_tenant_id"]))
                 myvims[datacenter_key] = None
             else:
                 myvims[datacenter_key] = vims.values()[0]
@@ -3961,17 +3911,19 @@ def delete_instance(mydb, tenant_id, instance_id):
         myvim_thread = myvim_threads[datacenter_key]
 
         if not myvim:
-            error_msg += "\n    vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp['vim_sfp_id'], sfp["datacenter_id"])
+            error_msg += "\n    vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification['vim_classification_id'],
+                                                                                                                   classification["datacenter_id"])
             continue
-        extra = {"params": (sfp['vim_sfp_id'])}
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"]
+        extra = {"params": (classification['vim_classification_id']), "depends_on": depends_on}
         db_vim_action = {
             "instance_action_id": instance_action_id,
             "task_index": task_index,
-            "datacenter_vim_id": sfp["datacenter_tenant_id"],
+            "datacenter_vim_id": classification["datacenter_tenant_id"],
             "action": "DELETE",
             "status": "SCHEDULED",
-            "item": "instance_sfps",
-            "item_id": sfp["uuid"],
+            "item": "instance_classifications",
+            "item_id": classification["uuid"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -3982,7 +3934,7 @@ def delete_instance(mydb, tenant_id, instance_id):
         datacenter_key = (sf["datacenter_id"], sf["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sf["datacenter_id"], sf["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sf["datacenter_id"], sf["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
@@ -4000,7 +3952,8 @@ def delete_instance(mydb, tenant_id, instance_id):
         if not myvim:
             error_msg += "\n    vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf['vim_sf_id'], sf["datacenter_id"])
             continue
-        extra = {"params": (sf['vim_sf_id'])}
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"]
+        extra = {"params": (sf['vim_sf_id']), "depends_on": depends_on}
         db_vim_action = {
             "instance_action_id": instance_action_id,
             "task_index": task_index,
@@ -4019,7 +3972,7 @@ def delete_instance(mydb, tenant_id, instance_id):
         datacenter_key = (sfi["datacenter_id"], sfi["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sfi["datacenter_id"], sfi["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sfi["datacenter_id"], sfi["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
@@ -4037,7 +3990,8 @@ def delete_instance(mydb, tenant_id, instance_id):
         if not myvim:
             error_msg += "\n    vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi['vim_sfi_id'], sfi["datacenter_id"])
             continue
-        extra = {"params": (sfi['vim_sfi_id'])}
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfs"]
+        extra = {"params": (sfi['vim_sfi_id']), "depends_on": depends_on}
         db_vim_action = {
             "instance_action_id": instance_action_id,
             "task_index": task_index,
@@ -4051,20 +4005,70 @@ def delete_instance(mydb, tenant_id, instance_id):
         task_index += 1
         db_vim_actions.append(db_vim_action)
 
-    for classification in instanceDict['classifications']:
-        vimthread_affected[classification["datacenter_tenant_id"]] = None
-        datacenter_key = (classification["datacenter_id"], classification["datacenter_tenant_id"])
+    # 2.2 deleting VMs
+    # vm_fail_list=[]
+    for sce_vnf in instanceDict['vnfs']:
+        datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
+        vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, classification["datacenter_id"], classification["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             myvim_threads[datacenter_key] = myvim_thread
-            vims = get_vim(mydb, tenant_id, datacenter_id=classification["datacenter_id"],
-                           datacenter_tenant_id=classification["datacenter_tenant_id"])
+            vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"],
+                           datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
             if len(vims) == 0:
-                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification["datacenter_id"], classification["datacenter_tenant_id"]))
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"],
+                                                                                               sce_vnf["datacenter_tenant_id"]))
+                myvims[datacenter_key] = None
+            else:
+                myvims[datacenter_key] = vims.values()[0]
+        myvim = myvims[datacenter_key]
+        myvim_thread = myvim_threads[datacenter_key]
+
+        for vm in sce_vnf['vms']:
+            if not myvim:
+                error_msg += "\n    VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"])
+                continue
+            sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"]
+            db_vim_action = {
+                "instance_action_id": instance_action_id,
+                "task_index": task_index,
+                "datacenter_vim_id": sce_vnf["datacenter_tenant_id"],
+                "action": "DELETE",
+                "status": "SCHEDULED",
+                "item": "instance_vms",
+                "item_id": vm["uuid"],
+                "extra": yaml.safe_dump({"params": vm["interfaces"], "depends_on": sfi_dependencies},
+                                        default_flow_style=True, width=256)
+            }
+            db_vim_actions.append(db_vim_action)
+            for interface in vm["interfaces"]:
+                if not interface.get("instance_net_id"):
+                    continue
+                if interface["instance_net_id"] not in net2vm_dependencies:
+                    net2vm_dependencies[interface["instance_net_id"]] = []
+                net2vm_dependencies[interface["instance_net_id"]].append(task_index)
+            task_index += 1
+
+    # 2.3 deleting NETS
+    # net_fail_list=[]
+    for net in instanceDict['nets']:
+        vimthread_affected[net["datacenter_tenant_id"]] = None
+        datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
+        if datacenter_key not in myvims:
+            try:
+                _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
+            except NfvoException as e:
+                logger.error(str(e))
+                myvim_thread = None
+            myvim_threads[datacenter_key] = myvim_thread
+            vims = get_vim(mydb, tenant_id, datacenter_id=net["datacenter_id"],
+                           datacenter_tenant_id=net["datacenter_tenant_id"])
+            if len(vims) == 0:
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
                 myvims[datacenter_key] = None
             else:
                 myvims[datacenter_key] = vims.values()[0]
@@ -4072,17 +4076,25 @@ def delete_instance(mydb, tenant_id, instance_id):
         myvim_thread = myvim_threads[datacenter_key]
 
         if not myvim:
-            error_msg += "\n    vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification['vim_classification_id'], classification["datacenter_id"])
+            error_msg += "\n    Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"])
             continue
-        extra = {"params": (classification['vim_classification_id'])}
+        extra = {"params": (net['vim_net_id'], net['sdn_net_id'])}
+        if net2vm_dependencies.get(net["uuid"]):
+            extra["depends_on"] = net2vm_dependencies[net["uuid"]]
+        sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"]
+        if len(sfi_dependencies) > 0:
+            if "depends_on" in extra:
+                extra["depends_on"] += sfi_dependencies
+            else:
+                extra["depends_on"] = sfi_dependencies
         db_vim_action = {
             "instance_action_id": instance_action_id,
             "task_index": task_index,
-            "datacenter_vim_id": classification["datacenter_tenant_id"],
+            "datacenter_vim_id": net["datacenter_tenant_id"],
             "action": "DELETE",
             "status": "SCHEDULED",
-            "item": "instance_classifications",
-            "item_id": classification["uuid"],
+            "item": "instance_nets",
+            "item_id": net["uuid"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
index 7e31f09..b70d94a 100644 (file)
@@ -1064,15 +1064,14 @@ class vim_thread(threading.Thread):
     def new_sfi(self, task):
         vim_sfi_id = None
         try:
-            params = task["params"]
+            dep_id = "TASK-" + str(task["extra"]["depends_on"][0])
             task_id = task["instance_action_id"] + "." + str(task["task_index"])
-            depends = task.get("depends")
             error_text = ""
-            interfaces = task.get("depends").values()[0].get("extra").get("params")[5]
+            interfaces = task.get("depends").get(dep_id).get("extra").get("interfaces").keys()
             # At the moment, every port associated with the VM will be used both as ingress and egress ports.
             # Bear in mind that different VIM connectors might support SFI differently. In the case of OpenStack, only the
             # first ingress and first egress ports will be used to create the SFI (Port Pair).
-            port_id_list = [interfaces[0].get("vim_id")]
+            port_id_list = [interfaces[0]]
             name = "sfi-%s" % task["item_id"][:8]
             # By default no form of IETF SFC Encapsulation will be used
             vim_sfi_id = self.vim.new_sfi(name, port_id_list, port_id_list, sfc_encap=False)
@@ -1113,12 +1112,11 @@ class vim_thread(threading.Thread):
     def new_sf(self, task):
         vim_sf_id = None
         try:
-            params = task["params"]
             task_id = task["instance_action_id"] + "." + str(task["task_index"])
-            depends = task.get("depends")
             error_text = ""
+            depending_tasks = [ "TASK-" + str(dep_id) for dep_id in task["extra"]["depends_on"]]
             #sfis = task.get("depends").values()[0].get("extra").get("params")[5]
-            sfis = task.get("depends").values()
+            sfis = [task.get("depends").get(dep_task) for dep_task in depending_tasks]
             sfi_id_list = []
             for sfi in sfis:
                 sfi_id_list.append(sfi.get("vim_id"))
@@ -1164,9 +1162,9 @@ class vim_thread(threading.Thread):
         try:
             params = task["params"]
             task_id = task["instance_action_id"] + "." + str(task["task_index"])
-            depends = task.get("depends")
+            depending_task = "TASK-" + str(task.get("extra").get("depends_on")[0])
             error_text = ""
-            interfaces = task.get("depends").values()[0].get("extra").get("params")[5]
+            interfaces = task.get("depends").get(depending_task).get("vim_interfaces").keys()
             # Bear in mind that different VIM connectors might support Classifications differently.
             # In the case of OpenStack, only the first VNF attached to the classifier will be used
             # to create the Classification(s) (the "logical source port" of the "Flow Classifier").
@@ -1188,7 +1186,7 @@ class vim_thread(threading.Thread):
             if '/' not in destination_ip:
                 destination_ip += '/32'
             definition = {
-                    "logical_source_port": interfaces[0].get("vim_id"),
+                    "logical_source_port": interfaces[0],
                     "protocol": ip_proto,
                     "source_ip_prefix": source_ip,
                     "destination_ip_prefix": destination_ip,
@@ -1239,12 +1237,11 @@ class vim_thread(threading.Thread):
         try:
             params = task["params"]
             task_id = task["instance_action_id"] + "." + str(task["task_index"])
-            depends = task.get("depends")
+            depending_tasks = [task.get("depends").get("TASK-" + str(tsk_id)) for tsk_id in task.get("extra").get("depends_on")]
             error_text = ""
-            deps = task.get("depends").values()
             sf_id_list = []
             classification_id_list = []
-            for dep in deps:
+            for dep in depending_tasks:
                 vim_id = dep.get("vim_id")
                 resource = dep.get("item")
                 if resource == "instance_sfs":