X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=ff47fecfcd01d4abe4f8d59a71f2003c4f284ec0;hb=f6bbe22d9906cde52f86658daa9ee444f2ec3a6e;hp=b1c86f9c1981485badb18cbd6aa16a0959ff0264;hpb=e2c09f3117bc608a26f2172a0f07a0df41922730;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index b1c86f9c..ff47fecf 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -151,14 +151,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 @@ -344,7 +342,7 @@ def get_imagelist(mydb, vnf_id, nfvo_tenant=None): image_list = [] vms = mydb.get_rows(SELECT=('image_id','image_list'), FROM='vms', WHERE={'vnf_id': vnf_id}) for vm in vms: - if vm["image_id"] not in image_list: + if vm["image_id"] and vm["image_id"] not in image_list: image_list.append(vm["image_id"]) if vm["image_list"]: vm_image_list = yaml.load(vm["image_list"]) @@ -890,7 +888,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 = [] @@ -1070,6 +1069,11 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): devices.append(device) + if not db_vm.get("image_id"): + if not db_vm["pdu_type"]: + raise NfvoException("Not defined image for VDU") + # create a fake image + # cloud-init boot_data = {} if vdu.get("cloud-init"): @@ -1288,8 +1292,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": @@ -2262,7 +2265,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 = [] @@ -2405,7 +2408,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) @@ -2437,7 +2440,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) @@ -2448,7 +2450,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']) @@ -2460,32 +2461,47 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): str(nsd["id"]), str(rsp["id"]), str(iface["member-vnf-index-ref"])), httperrors.Bad_Request) - existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',), - 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", - 255)}) - if not existing_ifaces: + ingress_existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',), + 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-ingress-connection-point-ref", + 255)}) + if not ingress_existing_ifaces: raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point" - "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing " + "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing " "connection-point name at VNFD '{}'".format( - str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-connection-point-ref"]), - str(iface.get("vnfd-id-ref"))[:255]), - httperrors.Bad_Request) - interface_uuid = existing_ifaces[0]["uuid"] + str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-ingress-connection-point-ref"]), + str(iface.get("vnfd-id-ref"))[:255]), httperrors.Bad_Request) + + egress_existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',), + 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-egress-connection-point-ref", + 255)}) + if not egress_existing_ifaces: + raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point" + "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing " + "connection-point name at VNFD '{}'".format( + str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-egress-connection-point-ref"]), + str(iface.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request) + + ingress_interface_uuid = ingress_existing_ifaces[0]["uuid"] + egress_interface_uuid = egress_existing_ifaces[0]["uuid"] sce_rsp_hop_uuid = str(uuid4()) uuid_list.append(sce_rsp_hop_uuid) db_sce_rsp_hop = { "uuid": sce_rsp_hop_uuid, "if_order": if_order, - "interface_id": interface_uuid, + "ingress_interface_id": ingress_interface_uuid, + "egress_interface_id": egress_interface_uuid, "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index], "sce_rsp_id": sce_rsp_uuid, } 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) @@ -2524,7 +2540,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) @@ -2615,7 +2630,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 @@ -2648,7 +2663,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: @@ -2959,8 +2974,8 @@ def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extr def update(d, u): - '''Takes dict d and updates it with the values in dict u.''' - '''It merges all depth levels''' + """Takes dict d and updates it with the values in dict u. + It merges all depth levels""" for k, v in u.iteritems(): if isinstance(v, collections.Mapping): r = update(d.get(k, {}), v) @@ -2979,6 +2994,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) @@ -3110,6 +3126,8 @@ def create_instance(mydb, tenant_id, instance_dict): raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id), httperrors.Bad_Request) if net_instance_desc.get("vim-network-name"): scenario_net["vim-network-name"] = net_instance_desc["vim-network-name"] + if net_instance_desc.get("vim-network-id"): + scenario_net["vim-network-id"] = net_instance_desc["vim-network-id"] if net_instance_desc.get("name"): scenario_net["name"] = net_instance_desc["name"] if 'ip-profile' in net_instance_desc: @@ -3142,7 +3160,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: @@ -3179,17 +3199,28 @@ 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 = {} @@ -3250,7 +3281,7 @@ def create_instance(mydb, tenant_id, instance_dict): lookfor_network = True lookfor_filter["name"] = sce_net.get("vim_network_name") elif sce_net["external"]: - if sce_net['vim_id'] is not None: + if sce_net.get('vim_id'): # there is a netmap at datacenter_nets database # TODO REVISE!!!! create_network = False lookfor_network = True @@ -3280,7 +3311,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: @@ -3367,8 +3398,9 @@ def create_instance(mydb, tenant_id, instance_dict): sfs_created = [] for cp in rsp['connection_points']: count = mydb.get_rows( - SELECT=('vms.count'), - FROM="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h on interfaces.uuid=h.interface_id", + SELECT='vms.count', + FROM="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h " + "on interfaces.uuid=h.ingress_interface_id", WHERE={'h.uuid': cp['uuid']})[0]['count'] instance_vnf = next((item for item in db_instance_vnfs if item['sce_vnf_id'] == cp['sce_vnf_id']), None) instance_vms = [item for item in db_instance_vms if item['instance_vnf_id'] == instance_vnf['uuid']] @@ -3383,6 +3415,10 @@ def create_instance(mydb, tenant_id, instance_dict): for i in range(count): # create sfis sfi_uuid = str(uuid4()) + extra_params = { + "ingress_interface_id": cp["ingress_interface_id"], + "egress_interface_id": cp["egress_interface_id"] + } uuid_list.append(sfi_uuid) db_sfi = { "uuid": sfi_uuid, @@ -3401,7 +3437,7 @@ def create_instance(mydb, tenant_id, instance_dict): "status": "SCHEDULED", "item": "instance_sfis", "item_id": sfi_uuid, - "extra": yaml.safe_dump({"params": "", "depends_on": [dependencies[i]]}, + "extra": yaml.safe_dump({"params": extra_params, "depends_on": [dependencies[i]]}, default_flow_style=True, width=256) } sfis_created.append(task_index) @@ -3552,12 +3588,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) @@ -3629,8 +3667,12 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): } db_instance_nets.append(db_net) + lookfor_filter = {} if net.get("vim-network-name"): - lookfor_filter = {"name": net["vim-network-name"]} + lookfor_filter["name"] = net["vim-network-name"] + if net.get("vim-network-id"): + lookfor_filter["id"] = net["vim-network-id"] + if lookfor_filter: task_action = "FIND" task_extra = {"params": (lookfor_filter,)} else: @@ -4523,7 +4565,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): iface2iface = {} where = {"item": "instance_vms", "item_id": target_vm["uuid"], "action": "CREATE"} - vim_action_to_clone = mydb.get_rows(FROM="vim_actions", WHERE=where) + vim_action_to_clone = mydb.get_rows(FROM="vim_wim_actions", WHERE=where) if not vim_action_to_clone: raise NfvoException("Cannot find the vim_action at database with {}".format(where), httperrors.Internal_Server_Error) vim_action_to_clone = vim_action_to_clone[0] @@ -4621,7 +4663,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): # {"instance_sfs": db_instance_sfs}, # {"instance_classifications": db_instance_classifications}, # {"instance_sfps": db_instance_sfps}, - {"vim_actions": db_vim_actions} + {"vim_wim_actions": db_vim_actions} ] logger.debug("create_vdu done DB tables: %s", yaml.safe_dump(db_tables, indent=4, default_flow_style=False)) @@ -5418,7 +5460,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'): @@ -5432,7 +5474,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) @@ -5518,9 +5560,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))