X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=5a972e262ed05e69b67883c615ca2adae06123c1;hb=fc7cfbf916777271ba2cf1c8edfa5d62ab9c8ce3;hp=7b8a820b46b8fb781522515db31db9eee755321c;hpb=f2813e8e41b842c0f7ad2a2fc95a1195e18cded8;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index 7b8a820b..5a972e26 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -61,6 +61,7 @@ from .http_tools import errors as httperrors from .wim.engine import WimEngine from .wim.persistence import WimPersistence from copy import deepcopy +from pprint import pformat # global global_config @@ -150,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 @@ -343,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"]) @@ -1069,6 +1068,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"): @@ -2404,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) @@ -2459,25 +2463,41 @@ 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, } @@ -2614,7 +2634,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 @@ -2647,7 +2667,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: @@ -2958,8 +2978,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) @@ -2978,6 +2998,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) @@ -3034,6 +3055,8 @@ def create_instance(mydb, tenant_id, instance_dict): # Auxiliary dictionaries from x to y sce_net2instance = {} net2task_id = {'scenario': {}} + # Mapping between local networks and WIMs + wim_usage = {} def ip_profile_IM2RO(ip_profile_im): # translate from input format to database format @@ -3107,6 +3130,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: @@ -3139,7 +3164,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: @@ -3176,6 +3203,29 @@ def create_instance(mydb, tenant_id, instance_dict): break if not involved_datacenters: involved_datacenters.append(default_datacenter_id) + target_wim_account = scenario_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: + 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"]): @@ -3235,7 +3285,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 @@ -3265,7 +3315,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: @@ -3352,8 +3402,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']] @@ -3368,6 +3419,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, @@ -3386,7 +3441,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) @@ -3499,7 +3554,8 @@ def create_instance(mydb, tenant_id, instance_dict): db_instance_action["number_tasks"] = task_index # --> WIM - wan_links = wim_engine.derive_wan_links(db_instance_nets, tenant_id) + logger.debug('wim_usage:\n%s\n\n', pformat(wim_usage)) + wan_links = wim_engine.derive_wan_links(wim_usage, db_instance_nets, tenant_id) wim_actions = wim_engine.create_actions(wan_links) wim_actions, db_instance_action = ( wim_engine.incorporate_actions(wim_actions, db_instance_action)) @@ -3613,8 +3669,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: @@ -4507,7 +4567,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] @@ -4605,7 +4665,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)) @@ -5402,7 +5462,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'): @@ -5416,7 +5476,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) @@ -5502,9 +5562,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))