X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=49705004e0e1b545e615408b73d1fedfc7c1d1ba;hb=refs%2Fheads%2Ffeature7928;hp=f65f08f9f5ffe5f77e5513199c40bf3c56d36ae0;hpb=55fe3970aa7fb2dad4d5d13409fdd3efcd65bec2;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index f65f08f9..49705004 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 = [] @@ -986,6 +1006,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # connection points vaiable declaration cp_name2iface_uuid = {} + cp_name2vdu_id = {} cp_name2vm_uuid = {} cp_name2db_interface = {} vdu_id2cp_name = {} # stored only when one external connection point is presented at this VDU @@ -993,6 +1014,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # table vms (vdus) vdu_id2uuid = {} vdu_id2db_table_index = {} + mgmt_access = {} for vdu in vnfd.get("vdu").itervalues(): for vdu_descriptor in vnfd_descriptor["vdu"]: @@ -1146,6 +1168,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): cp = vnfd.get("connection-point")[iface.get("external-connection-point-ref")] db_interface["external_name"] = get_str(cp, "name", 255) cp_name2iface_uuid[db_interface["external_name"]] = iface_uuid + cp_name2vdu_id[db_interface["external_name"]] = vdu_id cp_name2vm_uuid[db_interface["external_name"]] = vm_uuid cp_name2db_interface[db_interface["external_name"]] = db_interface for cp_descriptor in vnfd_descriptor["connection-point"]: @@ -1260,6 +1283,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: @@ -1296,7 +1336,6 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # if pg.get("strategy") == "ISOLATION": # VNF mgmt configuration - mgmt_access = {} if vnfd["mgmt-interface"].get("vdu-id"): mgmt_vdu_id = get_str(vnfd["mgmt-interface"], "vdu-id", 255) if mgmt_vdu_id not in vdu_id2uuid: @@ -1305,6 +1344,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vnf=vnfd_id, vdu=mgmt_vdu_id), httperrors.Bad_Request) mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]] + mgmt_access["vdu-id"] = 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): if cp_name2db_interface[vdu_id2cp_name[mgmt_vdu_id]]: @@ -1320,20 +1360,26 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): httperrors.Bad_Request) mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]] mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]] + mgmt_access["vdu-id"] = cp_name2vdu_id[vnfd["mgmt-interface"]["cp"]] # mark this interface as of type mgmt if cp_name2db_interface[vnfd["mgmt-interface"]["cp"]]: cp_name2db_interface[vnfd["mgmt-interface"]["cp"]]["type"] = "mgmt" default_user = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}), "default-user", 64) - if default_user: mgmt_access["default_user"] = default_user + required = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}), "required", 6) if required: mgmt_access["required"] = required + password_ = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}), + "password", 64) + if password_: + mgmt_access["password"] = password_ + if mgmt_access: db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256) @@ -2264,7 +2310,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 = [] @@ -3223,8 +3269,16 @@ def create_instance(mydb, tenant_id, instance_dict): # <-- 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"): @@ -3234,6 +3288,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 @@ -3321,8 +3391,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, @@ -3341,6 +3415,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 @@ -3421,6 +3496,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, @@ -3436,6 +3512,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) } @@ -3447,6 +3524,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, @@ -3462,6 +3540,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) } @@ -3492,6 +3571,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, @@ -3514,6 +3594,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) } @@ -3526,6 +3607,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, @@ -3541,6 +3623,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) } @@ -3656,6 +3739,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, @@ -3686,6 +3770,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 @@ -3896,12 +3981,12 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): cloud_config_vm = unify_cloud_config({"key-pairs": params["instance_parameters"]["mgmt_keys"]}, cloud_config_vm) - if vm.get("instance_parameters") and vm["instance_parameters"].get("mgmt_keys"): - cloud_config_vm = unify_cloud_config({"key-pairs": vm["instance_parameters"]["mgmt_keys"]}, - cloud_config_vm) - # if ssh_access and ssh_access['required'] and ssh_access['default-user'] and tenant[0].get('RO_pub_key'): - # RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]} - # cloud_config_vm = unify_cloud_config(cloud_config_vm, RO_key) + if vm.get("instance_parameters") and "mgmt_keys" in vm["instance_parameters"]: + if vm["instance_parameters"]["mgmt_keys"]: + cloud_config_vm = unify_cloud_config({"key-pairs": vm["instance_parameters"]["mgmt_keys"]}, + cloud_config_vm) + if RO_pub_key: + cloud_config_vm = unify_cloud_config(cloud_config_vm, {"key-pairs": [RO_pub_key]}) if vm.get("boot_data"): cloud_config_vm = unify_cloud_config(vm["boot_data"], cloud_config_vm) @@ -3925,6 +4010,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"], @@ -3964,6 +4050,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) } @@ -4041,6 +4128,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 @@ -4081,6 +4169,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 @@ -4119,6 +4208,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 @@ -4157,6 +4247,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 @@ -4198,6 +4289,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) } @@ -4252,6 +4344,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 @@ -4540,6 +4633,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 @@ -4551,6 +4645,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) } @@ -4598,9 +4693,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) @@ -4641,6 +4737,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. @@ -4679,27 +4776,34 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): for vm in sce_vnf['vms']: if not action_over_all and sce_vnf['uuid'] not in input_vnfs and sce_vnf['vnf_name'] not in input_vnfs and \ sce_vnf['member_vnf_index'] not in input_vnfs and \ - vm['uuid'] not in input_vms and vm['name'] not in input_vms: + vm['uuid'] not in input_vms and vm['name'] not in input_vms and \ + sce_vnf['member_vnf_index'] + "-" + vm['vdu_osm_id'] not in input_vms: # TODO conside vm_count_index continue try: if "add_public_key" in action_dict: - mgmt_access = {} if sce_vnf.get('mgmt_access'): mgmt_access = yaml.load(sce_vnf['mgmt_access']) - ssh_access = mgmt_access['config-access']['ssh-access'] + if not input_vms and mgmt_access.get("vdu-id") != vm['vdu_osm_id']: + continue + default_user = mgmt_access.get("default-user") + password = mgmt_access.get("password") + if mgmt_access.get(vm['vdu_osm_id']): + default_user = mgmt_access[vm['vdu_osm_id']].get("default-user", default_user) + password = mgmt_access[vm['vdu_osm_id']].get("password", password) + tenant = mydb.get_rows_by_id('nfvo_tenants', nfvo_tenant) try: - if ssh_access['required'] and ssh_access['default-user']: - if 'ip_address' in vm: + if 'ip_address' in vm: mgmt_ip = vm['ip_address'].split(';') - password = mgmt_access['config-access'].get('password') priv_RO_key = decrypt_key(tenant[0]['encrypted_RO_priv_key'], tenant[0]['uuid']) - myvim.inject_user_key(mgmt_ip[0], ssh_access['default-user'], + data = myvim.inject_user_key(mgmt_ip[0], action_dict.get('user', default_user), action_dict['add_public_key'], password=password, ro_key=priv_RO_key) - else: - raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']), - httperrors.Internal_Server_Error) + vm_result[ vm['uuid'] ] = {"vim_result": 200, + "description": "Public key injected", + "name":vm['name'] + } + except KeyError: raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']), httperrors.Internal_Server_Error) @@ -5101,7 +5205,13 @@ def datacenter_action(mydb, tenant_id, datacenter, action_dict): #get datacenter info datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter) - if 'net-update' in action_dict: + if 'check-connectivity' in action_dict: + try: + myvim.check_vim_connectivity() + except vimconn.vimconnException as e: + #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e)) + raise NfvoException(str(e), e.http_code) + elif 'net-update' in action_dict: try: nets = myvim.get_network_list(filter_dict={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'}) #print content