X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=9a2e5e1cf20e5ba951c2d6a923d38e44a7926b34;hb=refs%2Fchanges%2F34%2F7834%2F2;hp=677c7c6dc2b9bd32575ef45cee6c2332573bf504;hpb=ebd66721b39fda2bf315102db63ea7e0dcf7becc;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index 677c7c6d..9a2e5e1c 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -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 @@ -237,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) @@ -305,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)) @@ -804,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: @@ -877,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 @@ -888,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 = [] @@ -1260,6 +1280,23 @@ 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: + cpuquota = get_resource_allocation_params(vdu["guest-epa"].get("cpu-quota")) + if cpuquota: + extended["cpu-quota"] = cpuquota + if vdu["guest-epa"].get("mem-quota"): + vduquota = get_resource_allocation_params(vdu["guest-epa"].get("mem-quota")) + if vduquota: + extended["mem-quota"] = vduquota + if vdu["guest-epa"].get("disk-io-quota"): + diskioquota = get_resource_allocation_params(vdu["guest-epa"].get("disk-io-quota")) + if diskioquota: + extended["disk-io-quota"] = diskioquota + if vdu["guest-epa"].get("vif-quota"): + vifquota = get_resource_allocation_params(vdu["guest-epa"].get("vif-quota")) + if vifquota: + extended["vif-quota"] = vifquota if numa: extended["numas"] = [numa] if extended: @@ -1291,8 +1328,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": @@ -2265,7 +2301,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 = [] @@ -2440,7 +2476,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) @@ -2451,7 +2486,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']) @@ -2504,7 +2538,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) @@ -2543,7 +2576,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) @@ -2998,6 +3030,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) @@ -3163,7 +3196,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: @@ -3200,24 +3235,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 = 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 = 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 + 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 +3279,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 @@ -3314,8 +3382,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 +3406,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 +3487,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 +3503,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 +3515,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 +3531,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 +3562,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 +3585,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 +3598,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 +3614,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 +3661,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 +3730,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 +3761,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 +4001,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 +4041,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 +4119,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 +4160,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 +4199,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 +4238,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 +4280,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 +4335,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 +4624,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 +4636,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 +4684,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 +4728,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.