bug 668. Fix existing flavor as not created
[osm/RO.git] / osm_ro / nfvo.py
index 4341422..15f04d6 100644 (file)
@@ -126,11 +126,12 @@ def get_non_used_vim_name(datacenter_name, datacenter_id, tenant_name, tenant_id
     if name not in vim_threads["names"]:
         vim_threads["names"].append(name)
         return name
-    name = datacenter_name[:16] + "." + tenant_name[:16]
-    if name not in vim_threads["names"]:
-        vim_threads["names"].append(name)
-        return name
-    name = datacenter_id + "-" + tenant_id
+    if tenant_name:
+        name = datacenter_name[:16] + "." + tenant_name[:16]
+        if name not in vim_threads["names"]:
+            vim_threads["names"].append(name)
+            return name
+    name = datacenter_id
     vim_threads["names"].append(name)
     return name
 
@@ -151,14 +152,12 @@ def get_non_used_wim_name(wim_name, wim_id, tenant_name, tenant_id):
 
 def start_service(mydb, persistence=None, wim=None):
     global db, global_config
-    db = nfvo_db.nfvo_db()
+    db = nfvo_db.nfvo_db(lock=db_lock)
+    mydb.lock = db_lock
     db.connect(global_config['db_host'], global_config['db_user'], global_config['db_passwd'], global_config['db_name'])
     global ovim
 
-    if persistence:
-        persistence.lock = db_lock
-    else:
-        persistence = WimPersistence(db, lock=db_lock)
+    persistence = persistence or  WimPersistence(db)
 
     # Initialize openvim for SDN control
     # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
@@ -239,7 +238,7 @@ def start_service(mydb, persistence=None, wim=None):
             except Exception as e:
                 raise NfvoException("Error at VIM  {}; {}: {}".format(vim["type"], type(e).__name__, e),
                                     httperrors.Internal_Server_Error)
-            thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['vim_tenant_id'], vim['vim_tenant_name'],
+            thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['datacenter_id'], vim['vim_tenant_name'],
                                                 vim['vim_tenant_id'])
             new_thread = vim_thread.vim_thread(task_lock, thread_name, vim['datacenter_name'],
                                                vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim)
@@ -307,6 +306,9 @@ def clean_db(mydb):
         nb_deleted += len(actions_to_delete)
         if len(actions_to_delete) < 100:
             break
+    # clean locks
+    mydb.update_rows("vim_wim_actions", UPDATE={"worker": None}, WHERE={"worker<>": None})
+
     if nb_deleted:
         logger.debug("Removed {} unused vim_wim_actions".format(nb_deleted))
 
@@ -806,7 +808,7 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
         try:
             flavor_vim_id = None
             flavor_vim_id=vim.get_flavor_id_from_data(flavor_dict)
-            flavor_create="false"
+            flavor_created="false"
         except vimconn.vimconnException as e:
             pass
         try:
@@ -879,6 +881,21 @@ def _lookfor_or_create_image(db_image, mydb, descriptor):
         db_image["uuid"] = image_uuid
         return None
 
+def get_resource_allocation_params(quota_descriptor):
+    """
+    read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
+    :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
+    :return: quota params for limit, reserve, shares from the descriptor object
+    """
+    quota = {}
+    if quota_descriptor.get("limit"):
+        quota["limit"] = int(quota_descriptor["limit"])
+    if quota_descriptor.get("reserve"):
+        quota["reserve"] = int(quota_descriptor["reserve"])
+    if quota_descriptor.get("shares"):
+        quota["shares"] = int(quota_descriptor["shares"])
+    return quota
+
 def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
     """
     Parses an OSM IM vnfd_catalog and insert at DB
@@ -890,7 +907,8 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
     try:
         myvnfd = vnfd_catalog.vnfd()
         try:
-            pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd, path_helper=True)
+            pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd, path_helper=True,
+                                             skip_unknown=True)
         except Exception as e:
             raise NfvoException("Error. Invalid VNF descriptor format " + str(e), httperrors.Bad_Request)
         db_vnfs = []
@@ -1262,6 +1280,15 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                                 numa["cores"] = max(db_flavor["vcpus"], 1)
                             else:
                                 numa["threads"] = max(db_flavor["vcpus"], 1)
+                            epa_vcpu_set = True
+                    if vdu["guest-epa"].get("cpu-quota") and not epa_vcpu_set:
+                        extended["cpu-quota"] = get_resource_allocation_params(vdu["guest-epa"].get("cpu-quota"))
+                    if vdu["guest-epa"].get("mem-quota"):
+                        extended["mem-quota"] = get_resource_allocation_params(vdu["guest-epa"].get("mem-quota"))
+                    if vdu["guest-epa"].get("disk-io-quota"):
+                        extended["disk-io-quota"] = get_resource_allocation_params(vdu["guest-epa"].get("disk-io-quota"))
+                    if vdu["guest-epa"].get("vif-quota"):
+                        extended["vif-quota"] = get_resource_allocation_params(vdu["guest-epa"].get("vif-quota"))
                 if numa:
                     extended["numas"] = [numa]
                 if extended:
@@ -1293,8 +1320,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                                             "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
                                                 vnf=vnfd_id, pg=pg_name, vdu=vdu_id),
                                             httperrors.Bad_Request)
-                    if vdu_id2db_table_index[vdu_id]:
-                        db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
+                    db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
                     # TODO consider the case of isolation and not colocation
                     # if pg.get("strategy") == "ISOLATION":
 
@@ -2267,7 +2293,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
     try:
         mynsd = nsd_catalog.nsd()
         try:
-            pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd)
+            pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd, skip_unknown=True)
         except Exception as e:
             raise NfvoException("Error. Invalid NS descriptor format: " + str(e), httperrors.Bad_Request)
         db_scenarios = []
@@ -2410,7 +2436,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                                                 str(iface.get("vnfd-id-ref"))[:255]),
                                             httperrors.Bad_Request)
                     interface_uuid = existing_ifaces[0]["uuid"]
-                    if existing_ifaces[0]["iface_type"] == "data" and not db_sce_net["type"]:
+                    if existing_ifaces[0]["iface_type"] == "data":
                         db_sce_net["type"] = "data"
                     sce_interface_uuid = str(uuid4())
                     uuid_list.append(sce_net_uuid)
@@ -2442,7 +2468,6 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                 db_sce_vnffgs.append(db_sce_vnffg)
 
                 # deal with rsps
-                db_sce_rsps = []
                 for rsp in vnffg.get("rsp").itervalues():
                     sce_rsp_uuid = str(uuid4())
                     uuid_list.append(sce_rsp_uuid)
@@ -2453,7 +2478,6 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                         "id": get_str(rsp, "id", 255), # only useful to link with classifiers; will be removed later in the code
                     }
                     db_sce_rsps.append(db_sce_rsp)
-                    db_sce_rsp_hops = []
                     for iface in rsp.get("vnfd-connection-point-ref").itervalues():
                         vnf_index = str(iface['member-vnf-index-ref'])
                         if_order = int(iface['order'])
@@ -2506,7 +2530,6 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                         db_sce_rsp_hops.append(db_sce_rsp_hop)
 
                 # deal with classifiers
-                db_sce_classifiers = []
                 for classifier in vnffg.get("classifier").itervalues():
                     sce_classifier_uuid = str(uuid4())
                     uuid_list.append(sce_classifier_uuid)
@@ -2545,7 +2568,6 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                     db_sce_classifier["sce_rsp_id"] = rsp["uuid"]
                     db_sce_classifiers.append(db_sce_classifier)
 
-                    db_sce_classifier_matches = []
                     for match in classifier.get("match-attributes").itervalues():
                         sce_classifier_match_uuid = str(uuid4())
                         uuid_list.append(sce_classifier_match_uuid)
@@ -2636,7 +2658,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
             #We should use the dictionary as input parameter for new_network
             #print myNetDict
             if not sce_net["external"]:
-                network_id = myvim.new_network(myNetName, myNetType, myNetIPProfile)
+                network_id, _ = myvim.new_network(myNetName, myNetType, myNetIPProfile)
                 #print "New VIM network created for scenario %s. Network id:  %s" % (scenarioDict['name'],network_id)
                 sce_net['vim_id'] = network_id
                 auxNetDict['scenario'][sce_net['uuid']] = network_id
@@ -2669,7 +2691,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 #print myNetDict
                 #TODO:
                 #We should use the dictionary as input parameter for new_network
-                network_id = myvim.new_network(myNetName, myNetType, myNetIPProfile)
+                network_id, _  = myvim.new_network(myNetName, myNetType, myNetIPProfile)
                 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
                 net['vim_id'] = network_id
                 if sce_vnf['uuid'] not in auxNetDict:
@@ -3000,6 +3022,7 @@ def create_instance(mydb, tenant_id, instance_dict):
     myvims = {}
     myvim_threads_id = {}
     datacenter = instance_dict.get("datacenter")
+    default_wim_account = instance_dict.get("wim_account")
     default_datacenter_id, vim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
     myvims[default_datacenter_id] = vim
     myvim_threads_id[default_datacenter_id], _ = get_vim_thread(mydb, tenant_id, default_datacenter_id)
@@ -3165,7 +3188,9 @@ def create_instance(mydb, tenant_id, instance_dict):
         # However, this is not possible yet.
         for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems():
             for scenario_net in scenarioDict['nets']:
-                if net_name == scenario_net["name"]:
+                if net_name == scenario_net.get("name") or net_name == scenario_net.get("osm_id") or net_name == scenario_net.get("uuid"):
+                    if "wim_account" in net_instance_desc and net_instance_desc["wim_account"] is not None:
+                        scenario_net["wim_account"] = net_instance_desc["wim_account"]
                     if 'ip-profile' in net_instance_desc:
                         ipprofile_db = ip_profile_IM2RO(net_instance_desc['ip-profile'])
                         if 'ip_profile' not in scenario_net:
@@ -3202,22 +3227,41 @@ def create_instance(mydb, tenant_id, instance_dict):
                             break
             if not involved_datacenters:
                 involved_datacenters.append(default_datacenter_id)
+            target_wim_account = sce_net.get("wim_account", default_wim_account)
 
             # --> WIM
             # TODO: use this information during network creation
-            wim_account_id = None
+            wim_account_id = wim_account_name = None
             if len(involved_datacenters) > 1 and 'uuid' in sce_net:
-                # OBS: sce_net without uuid are used internally to VNFs
-                # and the assumption is that VNFs will not be split among
-                # different datacenters
-                wim_account_id = wim_engine.find_suitable_wim_account(
-                    involved_datacenters, tenant_id)
-                wim_usage[sce_net['uuid']] = wim_account_id
+                if target_wim_account is None or target_wim_account is True:  # automatic selection of WIM
+                    # OBS: sce_net without uuid are used internally to VNFs
+                    # and the assumption is that VNFs will not be split among
+                    # different datacenters
+                    wim_account = wim_engine.find_suitable_wim_account(
+                        involved_datacenters, tenant_id)
+                    wim_account_id = wim_account['uuid']
+                    wim_account_name = wim_account['name']
+                    wim_usage[sce_net['uuid']] = wim_account_id
+                elif isinstance(target_wim_account, str):     # manual selection of WIM
+                    wim_account.persist.get_wim_account_by(target_wim_account, tenant_id)
+                    wim_account_id = wim_account['uuid']
+                    wim_account_name = wim_account['name']
+                    wim_usage[sce_net['uuid']] = wim_account_id
+                else:  # not WIM usage
+                    wim_usage[sce_net['uuid']] = False
             # <-- WIM
 
             descriptor_net = {}
-            if instance_dict.get("networks") and instance_dict["networks"].get(sce_net["name"]):
-                descriptor_net = instance_dict["networks"][sce_net["name"]]
+            if instance_dict.get("networks"):
+                if sce_net.get("uuid") in instance_dict["networks"]:
+                    descriptor_net = instance_dict["networks"][sce_net["uuid"]]
+                    descriptor_net_name = sce_net["uuid"]
+                elif sce_net.get("osm_id") in instance_dict["networks"]:
+                    descriptor_net = instance_dict["networks"][sce_net["osm_id"]]
+                    descriptor_net_name = sce_net["osm_id"]
+                elif sce_net["name"] in instance_dict["networks"]:
+                    descriptor_net = instance_dict["networks"][sce_net["name"]]
+                    descriptor_net_name = sce_net["name"]
             net_name = descriptor_net.get("vim-network-name")
             # add datacenters from instantiation parameters
             if descriptor_net.get("sites"):
@@ -3227,6 +3271,22 @@ def create_instance(mydb, tenant_id, instance_dict):
             sce_net2instance[sce_net_uuid] = {}
             net2task_id['scenario'][sce_net_uuid] = {}
 
+            use_network = None
+            related_network = None
+            if descriptor_net.get("use-network"):
+                target_instance_nets = mydb.get_rows(
+                    SELECT="related",
+                    FROM="instance_nets",
+                    WHERE={"instance_scenario_id": descriptor_net["use-network"]["instance_scenario_id"],
+                           "osm_id":  descriptor_net["use-network"]["osm_id"]},
+                )
+                if not target_instance_nets:
+                    raise NfvoException(
+                        "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name),
+                        httperrors.Bad_Request)
+                else:
+                    use_network = target_instance_nets[0]["related"]
+
             if sce_net["external"]:
                 number_mgmt_networks += 1
 
@@ -3303,7 +3363,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                 task_extra = {}
                 if create_network:
                     task_action = "CREATE"
-                    task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None))
+                    task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None), wim_account_name)
                     if lookfor_network:
                         task_extra["find"] = (lookfor_filter,)
                 elif lookfor_network:
@@ -3314,8 +3374,12 @@ def create_instance(mydb, tenant_id, instance_dict):
                 net_uuid = str(uuid4())
                 uuid_list.append(net_uuid)
                 sce_net2instance[sce_net_uuid][datacenter_id] = net_uuid
+                if not related_network:   # all db_instance_nets will have same related
+                    related_network = use_network or net_uuid
                 db_net = {
                     "uuid": net_uuid,
+                    "osm_id": sce_net.get("osm_id") or sce_net["name"],
+                    "related": related_network,
                     'vim_net_id': None,
                     "vim_name": net_vim_name,
                     "instance_scenario_id": instance_uuid,
@@ -3334,6 +3398,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                     "action": task_action,
                     "item": "instance_nets",
                     "item_id": net_uuid,
+                    "related": related_network,
                     "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256)
                 }
                 net2task_id['scenario'][sce_net_uuid][datacenter_id] = task_index
@@ -3414,6 +3479,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                         uuid_list.append(sfi_uuid)
                         db_sfi = {
                             "uuid": sfi_uuid,
+                            "related": sfi_uuid,
                             "instance_scenario_id": instance_uuid,
                             'sce_rsp_hop_id': cp['uuid'],
                             'datacenter_id': datacenter_id,
@@ -3429,6 +3495,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                             "status": "SCHEDULED",
                             "item": "instance_sfis",
                             "item_id": sfi_uuid,
+                            "related": sfi_uuid,
                             "extra": yaml.safe_dump({"params": extra_params, "depends_on": [dependencies[i]]},
                                                     default_flow_style=True, width=256)
                         }
@@ -3440,6 +3507,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                     uuid_list.append(sf_uuid)
                     db_sf = {
                         "uuid": sf_uuid,
+                        "related": sf_uuid,
                         "instance_scenario_id": instance_uuid,
                         'sce_rsp_hop_id': cp['uuid'],
                         'datacenter_id': datacenter_id,
@@ -3455,6 +3523,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                         "status": "SCHEDULED",
                         "item": "instance_sfs",
                         "item_id": sf_uuid,
+                        "related": sf_uuid,
                         "extra": yaml.safe_dump({"params": "", "depends_on": sfis_created},
                                                 default_flow_style=True, width=256)
                     }
@@ -3485,6 +3554,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                         uuid_list.append(classification_uuid)
                         db_classification = {
                             "uuid": classification_uuid,
+                            "related": classification_uuid,
                             "instance_scenario_id": instance_uuid,
                             'sce_classifier_match_id': match['uuid'],
                             'datacenter_id': datacenter_id,
@@ -3507,6 +3577,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                             "status": "SCHEDULED",
                             "item": "instance_classifications",
                             "item_id": classification_uuid,
+                            "related": classification_uuid,
                             "extra": yaml.safe_dump({"params": classification_params, "depends_on": [dependencies[i]]},
                                                     default_flow_style=True, width=256)
                         }
@@ -3519,6 +3590,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                 uuid_list.append(sfp_uuid)
                 db_sfp = {
                     "uuid": sfp_uuid,
+                    "related": sfp_uuid,
                     "instance_scenario_id": instance_uuid,
                     'sce_rsp_id': rsp['uuid'],
                     'datacenter_id': datacenter_id,
@@ -3534,6 +3606,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                     "status": "SCHEDULED",
                     "item": "instance_sfps",
                     "item_id": sfp_uuid,
+                    "related": sfp_uuid,
                     "extra": yaml.safe_dump({"params": "", "depends_on": sfs_created + classifications_created},
                                             default_flow_style=True, width=256)
                 }
@@ -3580,12 +3653,14 @@ def create_instance(mydb, tenant_id, instance_dict):
         returned_instance = mydb.get_instance_scenario(instance_uuid)
         returned_instance["action_id"] = instance_action_id
         return returned_instance
-    except (NfvoException, vimconn.vimconnException, db_base_Exception) as e:
+    except (NfvoException, vimconn.vimconnException, wimconn.WimConnectorError, db_base_Exception) as e:
         message = rollback(mydb, myvims, rollbackList)
         if isinstance(e, db_base_Exception):
             error_text = "database Exception"
         elif isinstance(e, vimconn.vimconnException):
             error_text = "VIM Exception"
+        elif isinstance(e, wimconn.WimConnectorError):
+            error_text = "WIM Exception"
         else:
             error_text = "Exception"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
@@ -3647,6 +3722,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
         vnf_net2instance[sce_vnf['uuid']][net['uuid']] = net_uuid
         db_net = {
             "uuid": net_uuid,
+            "related": net_uuid,
             'vim_net_id': None,
             "vim_name": net_name,
             "instance_scenario_id": instance_uuid,
@@ -3677,6 +3753,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
             "action": task_action,
             "item": "instance_nets",
             "item_id": net_uuid,
+            "related": net_uuid,
             "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -3916,6 +3993,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
             uuid_list.append(vm_uuid)
             db_vm = {
                 "uuid": vm_uuid,
+                "related": vm_uuid,
                 'instance_vnf_id': vnf_uuid,
                 # TODO delete "vim_vm_id": vm_id,
                 "vm_id": vm["uuid"],
@@ -3955,6 +4033,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
                 "status": "SCHEDULED",
                 "item": "instance_vms",
                 "item_id": vm_uuid,
+                "related": vm_uuid,
                 "extra": yaml.safe_dump({"params": task_params, "depends_on": task_depends_on},
                                         default_flow_style=True, width=256)
             }
@@ -4032,6 +4111,7 @@ def delete_instance(mydb, tenant_id, instance_id):
             "status": "SCHEDULED",
             "item": "instance_sfps",
             "item_id": sfp["uuid"],
+            "related": sfp["related"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -4072,6 +4152,7 @@ def delete_instance(mydb, tenant_id, instance_id):
             "status": "SCHEDULED",
             "item": "instance_classifications",
             "item_id": classification["uuid"],
+            "related": classification["related"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -4110,6 +4191,7 @@ def delete_instance(mydb, tenant_id, instance_id):
             "status": "SCHEDULED",
             "item": "instance_sfs",
             "item_id": sf["uuid"],
+            "related": sf["related"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -4148,6 +4230,7 @@ def delete_instance(mydb, tenant_id, instance_id):
             "status": "SCHEDULED",
             "item": "instance_sfis",
             "item_id": sfi["uuid"],
+            "related": sfi["related"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -4189,6 +4272,7 @@ def delete_instance(mydb, tenant_id, instance_id):
                 "status": "SCHEDULED",
                 "item": "instance_vms",
                 "item_id": vm["uuid"],
+                "related": vm["related"],
                 "extra": yaml.safe_dump({"params": vm["interfaces"], "depends_on": sfi_dependencies},
                                         default_flow_style=True, width=256)
             }
@@ -4243,6 +4327,7 @@ def delete_instance(mydb, tenant_id, instance_id):
             "status": "SCHEDULED",
             "item": "instance_nets",
             "item_id": net["uuid"],
+            "related": net["related"],
             "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
         }
         task_index += 1
@@ -4531,6 +4616,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                     for sce_vnf in instanceDict['vnfs']:
                         for vm in sce_vnf['vms']:
                             if vm["uuid"] == vdu_id:
+                                # TODO revise this should not be vm["uuid"]   instance_vms["vm_id"]
                                 vm_interfaces = vm["interfaces"]
                                 break
 
@@ -4542,6 +4628,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                         "status": "SCHEDULED",
                         "item": "instance_vms",
                         "item_id": vdu_id,
+                        "related": target_vm["related"],
                         "extra": yaml.safe_dump({"params": vm_interfaces},
                                                 default_flow_style=True, width=256)
                     }
@@ -4589,9 +4676,10 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                         pass
                     db_instance_vm = {
                         "uuid": vm_uuid,
+                        'related': vm_uuid,
                         'instance_vnf_id': target_vm['instance_vnf_id'],
                         'vm_id': target_vm['vm_id'],
-                        'vim_name': vm_name
+                        'vim_name': vm_name,
                     }
                     db_instance_vms.append(db_instance_vm)
 
@@ -4632,6 +4720,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                         "status": "SCHEDULED",
                         "item": "instance_vms",
                         "item_id": vm_uuid,
+                        "related": vm_uuid,
                         # ALF
                         # ALF
                         # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
@@ -5450,7 +5539,7 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
             net_public = net.pop("shared", False)
             net_ipprofile = net.pop("ip_profile", None)
             net_vlan = net.pop("vlan", None)
-            content = myvim.new_network(net_name, net_type, net_ipprofile, shared=net_public, vlan=net_vlan) #, **net)
+            content, _ = myvim.new_network(net_name, net_type, net_ipprofile, shared=net_public, vlan=net_vlan) #, **net)
 
             #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
             if get_sdn_controller_id(mydb, datacenter) != None and (net_type == 'data' or net_type == 'ptp'):
@@ -5464,7 +5553,7 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
                     sdn_network['type'] = net_type
                     sdn_network['name'] = net_name
                     sdn_network['region'] = datacenter_tenant_id
-                    ovim_content = ovim.new_network(sdn_network)
+                    ovim_content  = ovim.new_network(sdn_network)
                 except ovimException as e:
                     logger.error("ovimException creating SDN network={} ".format(
                         sdn_network) + str(e), exc_info=True)
@@ -5550,9 +5639,8 @@ def datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, sdn_port_map
             pci = port.get("pci")
             element["switch_port"] = port.get("switch_port")
             element["switch_mac"] = port.get("switch_mac")
-            if not pci or not (element["switch_port"] or element["switch_mac"]):
-                raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
-                                     " or 'switch_mac'", httperrors.Bad_Request)
+            if not element["switch_port"] and not element["switch_mac"]:
+                raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors.Bad_Request)
             for pci_expanded in utils.expand_brackets(pci):
                 element["pci"] = pci_expanded
                 maps.append(dict(element))