X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=bd9d3689f173df9330822865e4fc88cc6e14bb31;hb=66eba6ece53cd85d0efbe8b4ff4f414c812b347b;hp=c864be3bffcc2d2b10fe4a3192f85d53c36aec11;hpb=e2ff1ce8a93112562bf604aadd4c6a0f59e6869e;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index c864be3b..bd9d3689 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -38,6 +38,7 @@ import console_proxy_thread as cli import vimconn import logging import collections +import math from uuid import uuid4 from db_base import db_base_Exception @@ -138,9 +139,14 @@ def start_service(mydb): 'log_level_of': 'DEBUG' } try: + # starts ovim library ovim = ovim_module.ovim(ovim_configuration) ovim.start_service() + #delete old unneeded vim_actions + clean_db(mydb) + + # starts vim_threads from_= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\ 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid' select_ = ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin', @@ -224,6 +230,37 @@ def get_version(): return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config["version"], global_config["version_date"] )) +def clean_db(mydb): + """ + Clean unused or old entries at database to avoid unlimited growing + :param mydb: database connector + :return: None + """ + # get and delete unused vim_actions: all elements deleted, one week before, instance not present + now = t.time()-3600*24*7 + instance_action_id = None + nb_deleted = 0 + while True: + actions_to_delete = mydb.get_rows( + SELECT=("item", "item_id", "instance_action_id"), + FROM="vim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid " + "left join instance_scenarios as i on ia.instance_id=i.uuid", + WHERE={"va.action": "DELETE", "va.modified_at<": now, "i.uuid": None, + "va.status": ("DONE", "SUPERSEDED")}, + LIMIT=100 + ) + for to_delete in actions_to_delete: + mydb.delete_row(FROM="vim_actions", WHERE=to_delete) + if instance_action_id != to_delete["instance_action_id"]: + instance_action_id = to_delete["instance_action_id"] + mydb.delete_row(FROM="instance_actions", WHERE={"uuid": instance_action_id}) + nb_deleted += len(actions_to_delete) + if len(actions_to_delete) < 100: + break + if nb_deleted: + logger.debug("Removed {} unused vim_actions".format(nb_deleted)) + + def get_flavorlist(mydb, vnf_id, nfvo_tenant=None): '''Obtain flavorList @@ -816,9 +853,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vnf_uuid = str(uuid4()) uuid_list.append(vnf_uuid) vnfd_uuid_list.append(vnf_uuid) + vnfd_id = get_str(vnfd, "id", 255) db_vnf = { "uuid": vnf_uuid, - "osm_id": get_str(vnfd, "id", 255), + "osm_id": vnfd_id, "name": get_str(vnfd, "name", 255), "description": get_str(vnfd, "description", 255), "tenant_id": tenant_id, @@ -852,9 +890,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): for vdu in vnfd.get("vdu").itervalues(): vm_uuid = str(uuid4()) uuid_list.append(vm_uuid) + vdu_id = get_str(vdu, "id", 255) db_vm = { "uuid": vm_uuid, - "osm_id": get_str(vdu, "id", 255), + "osm_id": vdu_id, "name": get_str(vdu, "name", 255), "description": get_str(vdu, "description", 255), "vnf_id": vnf_uuid, @@ -901,74 +940,6 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): device["image checksum"] = str(volume["image-checksum"]) devices.append(device) - # table flavors - db_flavor = { - "name": get_str(vdu, "name", 250) + "-flv", - "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)), - "ram": int(vdu["vm-flavor"].get("memory-mb", 1)), - "disk": int(vdu["vm-flavor"].get("storage-gb", 1)), - } - # EPA TODO revise - extended = {} - numa = {} - if devices: - extended["devices"] = devices - if vdu.get("guest-epa"): # TODO or dedicated_int: - epa_vcpu_set = False - if vdu["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int: - numa_node_policy = vdu["guest-epa"].get("numa-node-policy") - if numa_node_policy.get("node"): - numa_node = numa_node_policy["node"]['0'] - if numa_node.get("num-cores"): - numa["cores"] = numa_node["num-cores"] - epa_vcpu_set = True - if numa_node.get("paired-threads"): - if numa_node["paired-threads"].get("num-paired-threads"): - numa["paired-threads"] = int(numa_node["paired-threads"]["num-paired-threads"]) - epa_vcpu_set = True - if len(numa_node["paired-threads"].get("paired-thread-ids")): - numa["paired-threads-id"] = [] - for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues(): - numa["paired-threads-id"].append( - (str(pair["thread-a"]), str(pair["thread-b"])) - ) - if numa_node.get("num-threads"): - numa["threads"] = int(numa_node["num-threads"]) - epa_vcpu_set = True - if numa_node.get("memory-mb"): - numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1) - if vdu["guest-epa"].get("mempage-size"): - if vdu["guest-epa"]["mempage-size"] != "SMALL": - numa["memory"] = max(int(db_flavor["ram"] / 1024), 1) - if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set: - if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED": - if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \ - vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER": - numa["cores"] = max(db_flavor["vcpus"], 1) - else: - numa["threads"] = max(db_flavor["vcpus"], 1) - if numa: - extended["numas"] = [numa] - if extended: - extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256) - db_flavor["extended"] = extended_text - # look if flavor exist - - temp_flavor_dict = {'disk': db_flavor.get('disk', 1), - 'ram': db_flavor.get('ram'), - 'vcpus': db_flavor.get('vcpus'), - 'extended': db_flavor.get('extended') - } - existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict) - if existing_flavors: - flavor_uuid = existing_flavors[0]["uuid"] - else: - flavor_uuid = str(uuid4()) - uuid_list.append(flavor_uuid) - db_flavor["uuid"] = flavor_uuid - db_flavors.append(db_flavor) - db_vm["flavor_id"] = flavor_uuid - # cloud-init boot_data = {} if vdu.get("cloud-init"): @@ -996,11 +967,14 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): db_vms_index += 1 # table interfaces (internal/external interfaces) + flavor_epa_interfaces = [] cp_name2iface_uuid = {} cp_name2vm_uuid = {} cp_name2db_interface = {} + vdu_id2cp_name = {} # stored only when one external connection point is presented at this VDU # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()): for iface in vdu.get("interface").itervalues(): + flavor_epa_interface = {} iface_uuid = str(uuid4()) uuid_list.append(iface_uuid) db_interface = { @@ -1008,12 +982,15 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): "internal_name": get_str(iface, "name", 255), "vm_id": vm_uuid, } + flavor_epa_interface["name"] = db_interface["internal_name"] if iface.get("virtual-interface").get("vpci"): db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12) + flavor_epa_interface["vpci"] = db_interface["vpci"] if iface.get("virtual-interface").get("bandwidth"): bps = int(iface.get("virtual-interface").get("bandwidth")) - db_interface["bw"] = bps/1000 + db_interface["bw"] = int(math.ceil(bps/1000000.0)) + flavor_epa_interface["bandwidth"] = "{} Mbps".format(db_interface["bw"]) if iface.get("virtual-interface").get("type") == "OM-MGMT": db_interface["type"] = "mgmt" @@ -1023,11 +1000,13 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"): db_interface["type"] = "data" db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12) + flavor_epa_interface["dedicated"] = "no" if iface["virtual-interface"]["type"] == "SR-IOV" \ + else "yes" + flavor_epa_interfaces.append(flavor_epa_interface) else: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual" "-interface':'type':'{}'. Interface type is not supported".format( - str(vnfd["id"])[:255], str(vdu["id"])[:255], - iface.get("virtual-interface").get("type")), + vnfd_id, vdu_id, iface.get("virtual-interface").get("type")), HTTP_Bad_Request) if iface.get("external-connection-point-ref"): @@ -1040,6 +1019,15 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): for cp_descriptor in vnfd_descriptor["connection-point"]: if cp_descriptor["name"] == db_interface["external_name"]: break + else: + raise KeyError() + + if vdu_id in vdu_id2cp_name: + vdu_id2cp_name[vdu_id] = None # more than two connecdtion point for this VDU + else: + vdu_id2cp_name[vdu_id] = db_interface["external_name"] + + # port security if str(cp_descriptor.get("port-security-enabled")).lower() == "false": db_interface["port_security"] = 0 elif str(cp_descriptor.get("port-security-enabled")).lower() == "true": @@ -1048,7 +1036,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':" "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present" " at connection-point".format( - vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"], + vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], cp=iface.get("vnfd-connection-point-ref")), HTTP_Bad_Request) elif iface.get("internal-connection-point-ref"): @@ -1069,13 +1057,82 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':" "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not" " referenced by any internal-vld".format( - vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"], + vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], cp=iface.get("vdu-internal-connection-point-ref")), HTTP_Bad_Request) if iface.get("position") is not None: db_interface["created_at"] = int(iface.get("position")) - 1000 db_interfaces.append(db_interface) + # table flavors + db_flavor = { + "name": get_str(vdu, "name", 250) + "-flv", + "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)), + "ram": int(vdu["vm-flavor"].get("memory-mb", 1)), + "disk": int(vdu["vm-flavor"].get("storage-gb", 1)), + } + # EPA TODO revise + extended = {} + numa = {} + if devices: + extended["devices"] = devices + if flavor_epa_interfaces: + numa["interfaces"] = flavor_epa_interfaces + if vdu.get("guest-epa"): # TODO or dedicated_int: + epa_vcpu_set = False + if vdu["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int: + numa_node_policy = vdu["guest-epa"].get("numa-node-policy") + if numa_node_policy.get("node"): + numa_node = numa_node_policy["node"]['0'] + if numa_node.get("num-cores"): + numa["cores"] = numa_node["num-cores"] + epa_vcpu_set = True + if numa_node.get("paired-threads"): + if numa_node["paired-threads"].get("num-paired-threads"): + numa["paired-threads"] = int(numa_node["paired-threads"]["num-paired-threads"]) + epa_vcpu_set = True + if len(numa_node["paired-threads"].get("paired-thread-ids")): + numa["paired-threads-id"] = [] + for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues(): + numa["paired-threads-id"].append( + (str(pair["thread-a"]), str(pair["thread-b"])) + ) + if numa_node.get("num-threads"): + numa["threads"] = int(numa_node["num-threads"]) + epa_vcpu_set = True + if numa_node.get("memory-mb"): + numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1) + if vdu["guest-epa"].get("mempage-size"): + if vdu["guest-epa"]["mempage-size"] != "SMALL": + numa["memory"] = max(int(db_flavor["ram"] / 1024), 1) + if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set: + if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED": + if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \ + vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER": + numa["cores"] = max(db_flavor["vcpus"], 1) + else: + numa["threads"] = max(db_flavor["vcpus"], 1) + if numa: + extended["numas"] = [numa] + if extended: + extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256) + db_flavor["extended"] = extended_text + # look if flavor exist + temp_flavor_dict = {'disk': db_flavor.get('disk', 1), + 'ram': db_flavor.get('ram'), + 'vcpus': db_flavor.get('vcpus'), + 'extended': db_flavor.get('extended') + } + existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict) + if existing_flavors: + flavor_uuid = existing_flavors[0]["uuid"] + else: + flavor_uuid = str(uuid4()) + uuid_list.append(flavor_uuid) + db_flavor["uuid"] = flavor_uuid + db_flavors.append(db_flavor) + db_vm["flavor_id"] = flavor_uuid + # VNF affinity and antiaffinity for pg in vnfd.get("placement-groups").itervalues(): pg_name = get_str(pg, "name", 255) @@ -1084,7 +1141,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if vdu_id not in vdu_id2db_table_index: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':" "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format( - vnf=vnfd["id"], pg=pg_name, vdu=vdu_id), + vnf=vnfd_id, pg=pg_name, vdu=vdu_id), HTTP_Bad_Request) db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name # TODO consider the case of isolation and not colocation @@ -1093,19 +1150,24 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # VNF mgmt configuration mgmt_access = {} if vnfd["mgmt-interface"].get("vdu-id"): - if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid: + mgmt_vdu_id = get_str(vnfd["mgmt-interface"], "vdu-id", 255) + if mgmt_vdu_id not in vdu_id2uuid: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':" "'{vdu}'. Reference to a non-existing vdu".format( - vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]), + vnf=vnfd_id, vdu=mgmt_vdu_id), HTTP_Bad_Request) mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]] + # if only one cp is defined by this VDU, mark this interface as of type "mgmt" + if vdu_id2cp_name.get(mgmt_vdu_id): + cp_name2db_interface[vdu_id2cp_name[mgmt_vdu_id]]["type"] = "mgmt" + if vnfd["mgmt-interface"].get("ip-address"): mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].get("ip-address")) if vnfd["mgmt-interface"].get("cp"): if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. " "Reference to a non-existing connection-point".format( - vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]), + vnf=vnfd_id, cp=vnfd["mgmt-interface"]["cp"]), HTTP_Bad_Request) mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]] mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]] @@ -1474,8 +1536,7 @@ def get_vnf_id(mydb, tenant_id, vnf_id): content = mydb.get_rows(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\ SELECT=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \ 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\ - WHERE={'vnfs.uuid': vnf_id}, - WHERE_NOT={'interfaces.external_name': None} ) + WHERE={'vnfs.uuid': vnf_id, 'interfaces.external_name<>': None} ) #print content data['vnf']['external-connections'] = content @@ -1662,8 +1723,7 @@ def new_scenario(mydb, tenant_id, topo): #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces for name,vnf in vnfs.items(): - where={} - where_or={"tenant_id": tenant_id, 'public': "true"} + where = {"OR": {"tenant_id": tenant_id, 'public': "true"}} error_text = "" error_pos = "'topology':'nodes':'" + name + "'" if 'vnf_id' in vnf: @@ -1672,14 +1732,12 @@ def new_scenario(mydb, tenant_id, topo): if 'VNF model' in vnf: error_text += " 'VNF model' " + vnf['VNF model'] where['name'] = vnf['VNF model'] - if len(where) == 0: + if len(where) == 1: raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos, HTTP_Bad_Request) vnf_db = mydb.get_rows(SELECT=('uuid','name','description'), FROM='vnfs', - WHERE=where, - WHERE_OR=where_or, - WHERE_AND_OR="AND") + WHERE=where) if len(vnf_db)==0: raise NfvoException("unknown" + error_text + " at " + error_pos, HTTP_Not_Found) elif len(vnf_db)>1: @@ -1689,7 +1747,7 @@ def new_scenario(mydb, tenant_id, topo): #get external interfaces ext_ifaces = mydb.get_rows(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'), FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id', - WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name':None} ) + WHERE={'vnfs.uuid':vnf['uuid'], 'external_name<>': None} ) for ext_iface in ext_ifaces: vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']} @@ -1928,8 +1986,7 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version): # 1: Check that VNF are present at database table vnfs and update content into scenario dict for name,vnf in scenario["vnfs"].iteritems(): - where={} - where_or={"tenant_id": tenant_id, 'public': "true"} + where = {"OR": {"tenant_id": tenant_id, 'public': "true"}} error_text = "" error_pos = "'scenario':'vnfs':'" + name + "'" if 'vnf_id' in vnf: @@ -1938,13 +1995,11 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version): if 'vnf_name' in vnf: error_text += " 'vnf_name' " + vnf['vnf_name'] where['name'] = vnf['vnf_name'] - if len(where) == 0: + if len(where) == 1: raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos, HTTP_Bad_Request) vnf_db = mydb.get_rows(SELECT=('uuid', 'name', 'description'), FROM='vnfs', - WHERE=where, - WHERE_OR=where_or, - WHERE_AND_OR="AND") + WHERE=where) if len(vnf_db) == 0: raise NfvoException("Unknown" + error_text + " at " + error_pos, HTTP_Not_Found) elif len(vnf_db) > 1: @@ -1955,7 +2010,7 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version): # get external interfaces ext_ifaces = mydb.get_rows(SELECT=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'), FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id', - WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name': None} ) + WHERE={'vnfs.uuid':vnf['uuid'], 'external_name<>': None} ) for ext_iface in ext_ifaces: vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type': ext_iface['type']} # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly @@ -2144,7 +2199,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): elif vld.get("provider-network").get("overlay-type") == "VLAN": db_sce_net["type"] = "data" else: - db_sce_net["type"] = "bridge" + # later on it will be fixed to bridge or data depending on the type of interfaces attached to it + db_sce_net["type"] = None db_sce_nets.append(db_sce_net) # ip-profile, link db_ip_profile with db_sce_net @@ -2168,7 +2224,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])), HTTP_Bad_Request) - existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',), + existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid', 'i.type as iface_type'), FROM="interfaces as i join vms on i.vm_id=vms.uuid", WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index], 'external_name': get_str(iface, "vnfd-connection-point-ref", @@ -2181,6 +2237,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): str(iface.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request) interface_uuid = existing_ifaces[0]["uuid"] + if existing_ifaces[0]["iface_type"] == "data" and not db_sce_net["type"]: + db_sce_net["type"] = "data" sce_interface_uuid = str(uuid4()) uuid_list.append(sce_net_uuid) db_sce_interface = { @@ -2191,6 +2249,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): # "ip_address": #TODO } db_sce_interfaces.append(db_sce_interface) + if not db_sce_net["type"]: + db_sce_net["type"] = "bridge" db_tables = [ {"scenarios": db_scenarios}, @@ -2409,7 +2469,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc else: av_index = None - vm_id = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None), + vm_id, _ = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None), myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'], availability_zone_index=av_index, availability_zone_list=vnf_availability_zones) @@ -3224,6 +3284,7 @@ def delete_instance(mydb, tenant_id, instance_id): myvims = {} myvim_threads = {} vimthread_affected = {} + net2vm_dependencies = {} task_index = 0 instance_action_id = get_task_id() @@ -3262,36 +3323,29 @@ def delete_instance(mydb, tenant_id, instance_id): 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 - try: - 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) - } - task_index += 1 - db_vim_actions.append(db_vim_action) - - except vimconn.vimconnNotFoundException as e: - error_msg+="\n VM VIM_id={} not found at datacenter={}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"]) - logger.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found", - vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id']) - except vimconn.vimconnException as e: - error_msg+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"], e.http_code, str(e)) - logger.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s", - e.http_code, vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'], str(e)) + 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']: - # TODO if not net['created']: - # TODO continue #skip not created nets - vimthread_affected[net["datacenter_tenant_id"]] = None datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"]) if datacenter_key not in myvims: @@ -3314,31 +3368,21 @@ def delete_instance(mydb, tenant_id, instance_id): if not myvim: error_msg += "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"]) continue - try: - db_vim_action = { - "instance_action_id": instance_action_id, - "task_index": task_index, - "datacenter_vim_id": net["datacenter_tenant_id"], - "action": "DELETE", - "status": "SCHEDULED", - "item": "instance_nets", - "item_id": net["uuid"], - "extra": yaml.safe_dump({"params": (net['vim_net_id'], net['sdn_net_id'])}, - default_flow_style=True, width=256) - } - task_index += 1 - db_vim_actions.append(db_vim_action) - - except vimconn.vimconnNotFoundException as e: - error_msg += "\n NET VIM_id={} not found at datacenter={}".format(net['vim_net_id'], net["datacenter_id"]) - logger.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found", - net['uuid'], net['vim_net_id'], str(net['vnf_net_id'])) - except vimconn.vimconnException as e: - error_msg += "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net['vim_net_id'], - net["datacenter_id"], - e.http_code, str(e)) - logger.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s", - e.http_code, net['uuid'], net['vim_net_id'], str(net['vnf_net_id']), str(e)) + extra = {"params": (net['vim_net_id'], net['sdn_net_id'])} + if net2vm_dependencies.get(net["uuid"]): + extra["depends_on"] = net2vm_dependencies[net["uuid"]] + db_vim_action = { + "instance_action_id": instance_action_id, + "task_index": task_index, + "datacenter_vim_id": net["datacenter_tenant_id"], + "action": "DELETE", + "status": "SCHEDULED", + "item": "instance_nets", + "item_id": net["uuid"], + "extra": yaml.safe_dump(extra, default_flow_style=True, width=256) + } + task_index += 1 + db_vim_actions.append(db_vim_action) db_instance_action["number_tasks"] = task_index db_tables = [