X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FRO.git;a=blobdiff_plain;f=RO%2Fosm_ro%2Fnfvo.py;h=2efd61043ca2839417f6cbdc6f708617ac4769fd;hp=a28f57f617ab4fe071ee6bf4ae4ef360d5ec8b4c;hb=0fd60da673bd914ed150c83f8673569307dcc28f;hpb=7d782eff123e5b44d41437377ccca66ad1e8b21b diff --git a/RO/osm_ro/nfvo.py b/RO/osm_ro/nfvo.py index a28f57f6..2efd6104 100644 --- a/RO/osm_ro/nfvo.py +++ b/RO/osm_ro/nfvo.py @@ -20,7 +20,7 @@ # For those usages not covered by the Apache License, Version 2.0 please # contact with: nfvlabs@tid.es ## - + ''' NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances ''' @@ -29,7 +29,9 @@ __date__ ="$16-sep-2014 22:05:01$" # import imp import json +import string import yaml +from random import choice as random_choice from osm_ro import utils from osm_ro.utils import deprecated from osm_ro.vim_thread import vim_thread @@ -45,13 +47,11 @@ from osm_ro import nfvo_db from threading import Lock import time as t # TODO py3 BEGIN -# from lib_osm_openvim import ovim as ovim_module +from osm_ro.sdn import Sdn, SdnException as ovimException # from lib_osm_openvim.ovim import ovimException -from unittest.mock import MagicMock -ovim_module = MagicMock() -class ovimException(Exception): - pass -ovim_module.ovimException = ovimException +# from unittest.mock import MagicMock +# class ovimException(Exception): +# pass # TODO py3 END from Crypto.PublicKey import RSA @@ -64,11 +64,12 @@ from pkg_resources import iter_entry_points # WIM -import osm_ro.wim.wimconn as wimconn -import osm_ro.wim.wim_thread as wim_thread -from osm_ro.http_tools import errors as httperrors -from osm_ro.wim.engine import WimEngine -from osm_ro.wim.persistence import WimPersistence +from .wim import sdnconn +from .wim.wimconn_dummy import DummyConnector +from .wim.failing_connector import FailingConnector +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 # @@ -77,7 +78,7 @@ global global_config # WIM global wim_engine wim_engine = None -global wimconn_imported +global sdnconn_imported # global logger global default_volume_size @@ -90,7 +91,7 @@ plugins = {} # dictionary with VIM type as key, loaded module as value vim_threads = {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs vim_persistent_info = {} # WIM -wimconn_imported = {} # dictionary with WIM type as key, loaded module as value +sdnconn_imported = {} # dictionary with WIM type as key, loaded module as value wim_threads = {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs wim_persistent_info = {} # @@ -101,17 +102,28 @@ last_task_id = 0.0 db = None db_lock = Lock() +worker_id = None class NfvoException(httperrors.HttpMappedError): """Common Class for NFVO errors""" -def _load_vim_plugin(name): +def _load_plugin(name, type="vim"): + # type can be vim or sdn global plugins - for v in iter_entry_points('osm_rovim.plugins', name): - plugins[name] = v.load() + try: + for v in iter_entry_points('osm_ro{}.plugins'.format(type), name): + plugins[name] = v.load() + except Exception as e: + logger.critical("Cannot load osm_{}: {}".format(name, e)) + if name: + plugins[name] = FailingConnector("Cannot load osm_{}: {}".format(name, e)) if name and name not in plugins: - raise NfvoException("Unknown vim type '{}'. This plugin has not been registered".format(name), - httperrors.Bad_Request) + error_text = "Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been" \ + " registered".format(t=type, n=name) + logger.critical(error_text) + plugins[name] = FailingConnector(error_text) + # raise NfvoException("Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been registered". + # format(t=type, n=name), httperrors.Bad_Request) def get_task_id(): global last_task_id @@ -135,20 +147,29 @@ def new_task(name, params, depends=None): def is_task_id(id): return True if id[:5] == "TASK-" else False - -def get_non_used_vim_name(datacenter_name, datacenter_id, tenant_name, tenant_id): - name = datacenter_name[:16] - if name not in vim_threads["names"]: - vim_threads["names"].append(name) - return name - 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 +def get_process_id(): + """ + Obtain a unique ID for this process. If running from inside docker, it will get docker ID. If not it + will provide a random one + :return: Obtained ID + """ + # Try getting docker id. If fails, get pid + try: + with open("/proc/self/cgroup", "r") as f: + text_id_ = f.readline() + _, _, text_id = text_id_.rpartition("/") + text_id = text_id.replace("\n", "")[:12] + if text_id: + return text_id + except Exception: + pass + # Return a random id + return "".join(random_choice("0123456789abcdef") for _ in range(12)) + +def get_non_used_vim_name(datacenter_name, datacenter_id): + return "{}:{}:{}".format( + worker_id[:12], datacenter_id.replace("-", "")[:32], datacenter_name[:16] + ) # -- Move def get_non_used_wim_name(wim_name, wim_id, tenant_name, tenant_id): @@ -166,37 +187,22 @@ 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, plugins + global db, global_config, plugins, ovim, worker_id 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 persistence = persistence or WimPersistence(db) - # Initialize openvim for SDN control - # TODO: Avoid static configuration by adding new parameters to openmanod.cfg - # TODO: review ovim.py to delete not needed configuration - ovim_configuration = { - 'logger_name': 'openmano.ovim', - 'network_vlan_range_start': 1000, - 'network_vlan_range_end': 4096, - 'db_name': global_config["db_ovim_name"], - 'db_host': global_config["db_ovim_host"], - 'db_user': global_config["db_ovim_user"], - 'db_passwd': global_config["db_ovim_passwd"], - 'bridge_ifaces': {}, - 'mode': 'normal', - 'network_type': 'bridge', - #TODO: log_level_of should not be needed. To be modified in ovim - 'log_level_of': 'DEBUG' - } try: + worker_id = get_process_id() + if "rosdn_dummy" not in plugins: + plugins["rosdn_dummy"] = DummyConnector # starts ovim library - ovim = ovim_module.ovim(ovim_configuration) + ovim = Sdn(db, plugins) global wim_engine - wim_engine = wim or WimEngine(persistence) + wim_engine = wim or WimEngine(persistence, plugins) wim_engine.ovim = ovim ovim.start_service() @@ -221,7 +227,7 @@ def start_service(mydb, persistence=None, wim=None): extra.update(yaml.load(vim["dt_config"], Loader=yaml.Loader)) plugin_name = "rovim_" + vim["type"] if plugin_name not in plugins: - _load_vim_plugin(plugin_name) + _load_plugin(plugin_name, type="vim") thread_id = vim['datacenter_tenant_id'] vim_persistent_info[thread_id] = {} @@ -240,19 +246,32 @@ def start_service(mydb, persistence=None, wim=None): logger.error("Cannot launch thread for VIM {} '{}': {}".format(vim['datacenter_name'], vim['datacenter_id'], e)) 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['datacenter_id'], vim['vim_tenant_name'], - vim['vim_tenant_id']) - new_thread = vim_thread(task_lock, plugins, thread_name, vim['datacenter_name'], - vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim) + logger.critical("Cannot launch thread for VIM {} '{}': {}".format(vim['datacenter_name'], + vim['datacenter_id'], 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['datacenter_id']) + new_thread = vim_thread(task_lock, plugins, thread_name, None, + vim['datacenter_tenant_id'], db=db) new_thread.start() vim_threads["running"][thread_id] = new_thread + wims = mydb.get_rows(FROM="wim_accounts join wims on wim_accounts.wim_id=wims.uuid", + WHERE={"sdn": "true"}, + SELECT=("wim_accounts.uuid as uuid", "type", "wim_accounts.name as name")) + for wim in wims: + plugin_name = "rosdn_" + wim["type"] + if plugin_name not in plugins: + _load_plugin(plugin_name, type="sdn") + thread_id = wim['uuid'] + thread_name = get_non_used_vim_name(wim['name'], wim['uuid']) + new_thread = vim_thread(task_lock, plugins, thread_name, wim['uuid'], None, db=db) + new_thread.start() + vim_threads["running"][thread_id] = new_thread wim_engine.start_threads() except db_base_Exception as e: raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code) - except ovim_module.ovimException as e: + except ovimException as e: message = str(e) if message[:22] == "DATABASE wrong version": message = "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\ @@ -397,7 +416,7 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, da plugin_name = "rovim_" + vim["type"] if plugin_name not in plugins: try: - _load_vim_plugin(plugin_name) + _load_plugin(plugin_name, type="vim") except NfvoException as e: if ignore_errors: logger.error("{}".format(e)) @@ -970,6 +989,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # table nets (internal-vld) net_id2uuid = {} # for mapping interface with network + net_id2index = {} # for mapping interface with network for vld in vnfd.get("internal-vld").values(): net_uuid = str(uuid4()) uuid_list.append(net_uuid) @@ -982,6 +1002,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): "type": "bridge", # TODO adjust depending on connection point type } net_id2uuid[vld.get("id")] = net_uuid + net_id2index[vld.get("id")] = len(db_nets) db_nets.append(db_net) # ip-profile, link db_ip_profile with db_sce_net if vld.get("ip-profile-ref"): @@ -1174,7 +1195,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise KeyError() if vdu_id in vdu_id2cp_name: - vdu_id2cp_name[vdu_id] = None # more than two connecdtion point for this VDU + vdu_id2cp_name[vdu_id] = None # more than two connection point for this VDU else: vdu_id2cp_name[vdu_id] = db_interface["external_name"] @@ -1209,6 +1230,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if not icp: raise KeyError("is not referenced by any 'internal-vld'") + # set network type as data + if iface.get("virtual-interface") and iface["virtual-interface"].get("type") in \ + ("SR-IOV", "PCI-PASSTHROUGH"): + db_nets[net_id2index[icp_vld.get("id")]]["type"] = "data" db_interface["net_id"] = net_id2uuid[icp_vld.get("id")] if str(icp_descriptor.get("port-security-enabled")).lower() == "false": db_interface["port_security"] = 0 @@ -1348,7 +1373,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): 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"].get("cp") and vnfd.get("vdu"): 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( @@ -2428,45 +2453,48 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): # table sce_interfaces (vld:vnfd-connection-point-ref) for iface in vld.get("vnfd-connection-point-ref").values(): + # Check if there are VDUs in the descriptor vnf_index = str(iface['member-vnf-index-ref']) - # check correct parameters - if vnf_index not in vnf_index2vnf_uuid: - raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point" - "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at " - "'nsd':'constituent-vnfd'".format( - str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])), - httperrors.Bad_Request) - - 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", - 255)}) - if not existing_ifaces: - raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point" - "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing " - "connection-point name at VNFD '{}'".format( - str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]), - str(iface.get("vnfd-id-ref"))[:255]), - httperrors.Bad_Request) - interface_uuid = existing_ifaces[0]["uuid"] - if existing_ifaces[0]["iface_type"] == "data": - db_sce_net["type"] = "data" - sce_interface_uuid = str(uuid4()) - uuid_list.append(sce_net_uuid) - iface_ip_address = None - if iface.get("ip-address"): - iface_ip_address = str(iface.get("ip-address")) - db_sce_interface = { - "uuid": sce_interface_uuid, - "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index], - "sce_net_id": sce_net_uuid, - "interface_id": interface_uuid, - "ip_address": iface_ip_address, - } - db_sce_interfaces.append(db_sce_interface) - if not db_sce_net["type"]: - db_sce_net["type"] = "bridge" + existing_vdus = mydb.get_rows(SELECT=('vms.uuid'), FROM="vms", WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index]}) + if existing_vdus: + # check correct parameters + if vnf_index not in vnf_index2vnf_uuid: + raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point" + "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at " + "'nsd':'constituent-vnfd'".format( + str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])), + httperrors.Bad_Request) + + 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", + 255)}) + if not existing_ifaces: + raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point" + "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing " + "connection-point name at VNFD '{}'".format( + str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]), + str(iface.get("vnfd-id-ref"))[:255]), + httperrors.Bad_Request) + interface_uuid = existing_ifaces[0]["uuid"] + if existing_ifaces[0]["iface_type"] == "data": + db_sce_net["type"] = "data" + sce_interface_uuid = str(uuid4()) + uuid_list.append(sce_net_uuid) + iface_ip_address = None + if iface.get("ip-address"): + iface_ip_address = str(iface.get("ip-address")) + db_sce_interface = { + "uuid": sce_interface_uuid, + "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index], + "sce_net_id": sce_net_uuid, + "interface_id": interface_uuid, + "ip_address": iface_ip_address, + } + db_sce_interfaces.append(db_sce_interface) + if not db_sce_net["type"]: + db_sce_net["type"] = "bridge" # table sce_vnffgs (vnffgd) for vnffg in nsd.get("vnffgd").values(): @@ -2668,11 +2696,12 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc myNetDict["type"] = myNetType myNetDict["tenant_id"] = myvim_tenant myNetIPProfile = sce_net.get('ip_profile', None) + myProviderNetwork = sce_net.get('provider_network', None) #TODO: #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, provider_network_profile=myProviderNetwork) #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 @@ -2703,10 +2732,11 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc myNetDict["type"] = myNetType myNetDict["tenant_id"] = myvim_tenant myNetIPProfile = net.get('ip_profile', None) + myProviderNetwork = sce_net.get('provider_network', None) #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, provider_network_profile=myProviderNetwork) #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id) net['vim_id'] = network_id if sce_vnf['uuid'] not in auxNetDict: @@ -2950,7 +2980,7 @@ def get_vim_thread(mydb, tenant_id, datacenter_id_name=None, datacenter_tenant_i if datacenter_tenant_id: thread_id = datacenter_tenant_id thread = vim_threads["running"].get(datacenter_tenant_id) - else: + if not thread: where_={"td.nfvo_tenant_id": tenant_id} if datacenter_id_name: if utils.check_valid_uuid(datacenter_id_name): @@ -2962,7 +2992,7 @@ def get_vim_thread(mydb, tenant_id, datacenter_id_name=None, datacenter_tenant_i if datacenter_tenant_id: where_["dt.uuid"] = datacenter_tenant_id datacenters = mydb.get_rows( - SELECT=("dt.uuid as datacenter_tenant_id",), + SELECT=("dt.uuid as datacenter_tenant_id, d.name as datacenter_name",), FROM="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id " "join datacenters as d on d.uuid=dt.datacenter_id", WHERE=where_) @@ -2970,7 +3000,14 @@ def get_vim_thread(mydb, tenant_id, datacenter_id_name=None, datacenter_tenant_i raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict) elif datacenters: thread_id = datacenters[0]["datacenter_tenant_id"] + datacenter_name = datacenters[0]["datacenter_name"] thread = vim_threads["running"].get(thread_id) + if not thread: + thread_name = get_non_used_vim_name(datacenter_name, datacenter_id) + thread = vim_thread(task_lock, plugins, thread_name, None, + thread_id, db=mydb) + thread.start() + vim_threads["running"][thread_id] = thread if not thread: raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), httperrors.Not_Found) return thread_id, thread @@ -3030,9 +3067,18 @@ def update(d, u): return d +def _get_wim(db, wim_account_id): + # get wim from wim_account + wim_accounts = db.get_rows(FROM='wim_accounts', WHERE={"uuid": wim_account_id}) + if not wim_accounts: + raise NfvoException("Not found sdn id={}".format(wim_account_id), http_code=httperrors.Not_Found) + return wim_accounts[0]["wim_id"] + + def create_instance(mydb, tenant_id, instance_dict): # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id" # logger.debug("Creating instance...") + scenario = instance_dict["scenario"] # find main datacenter @@ -3094,6 +3140,7 @@ def create_instance(mydb, tenant_id, instance_dict): } # Auxiliary dictionaries from x to y + sce_net2wim_instance = {} sce_net2instance = {} net2task_id = {'scenario': {}} # Mapping between local networks and WIMs @@ -3182,6 +3229,13 @@ def create_instance(mydb, tenant_id, instance_dict): else: update(scenario_net['ip_profile'], ipprofile_db) + if net_instance_desc.get('provider-network'): + provider_network_db = net_instance_desc['provider-network'] + if 'provider_network' not in scenario_net: + scenario_net['provider_network'] = provider_network_db + else: + update(scenario_net['provider_network'], provider_network_db) + for vdu_id, vdu_instance_desc in vnf_instance_desc.get("vdus", {}).items(): for scenario_vm in scenario_vnf['vms']: if vdu_id == scenario_vm['osm_id'] or vdu_id == scenario_vm["name"]: @@ -3214,6 +3268,14 @@ def create_instance(mydb, tenant_id, instance_dict): scenario_net['ip_profile'] = ipprofile_db else: update(scenario_net['ip_profile'], ipprofile_db) + if 'provider-network' in net_instance_desc: + provider_network_db = net_instance_desc['provider-network'] + + if 'provider-network' not in scenario_net: + scenario_net['provider_network'] = provider_network_db + else: + update(scenario_net['provider-network'], provider_network_db) + for interface in net_instance_desc.get('interfaces', ()): if 'ip_address' in interface: for vnf in scenarioDict['vnfs']: @@ -3226,10 +3288,13 @@ def create_instance(mydb, tenant_id, instance_dict): # logger.debug("Creating instance scenario-dict MERGED:\n%s", # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)) + # 1. Creating new nets (sce_nets) in the VIM" number_mgmt_networks = 0 db_instance_nets = [] + db_instance_wim_nets = [] for sce_net in scenarioDict['nets']: + sce_net_uuid = sce_net.get('uuid', sce_net["name"]) # get involved datacenters where this network need to be created involved_datacenters = [] @@ -3246,28 +3311,6 @@ def create_instance(mydb, tenant_id, instance_dict): 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: - 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"): if sce_net.get("uuid") in instance_dict["networks"]: @@ -3286,6 +3329,7 @@ def create_instance(mydb, tenant_id, instance_dict): if site.get("datacenter") and site["datacenter"] not in involved_datacenters: involved_datacenters.append(site["datacenter"]) sce_net2instance[sce_net_uuid] = {} + sce_net2wim_instance[sce_net_uuid] = {} net2task_id['scenario'][sce_net_uuid] = {} use_network = None @@ -3299,14 +3343,39 @@ def create_instance(mydb, tenant_id, instance_dict): ) if not target_instance_nets: raise NfvoException( - "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name), - httperrors.Bad_Request) + "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 + # --> 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: + urls = [myvims[v].url for v in involved_datacenters] + if len(set(urls)) < 2: + wim_usage[sce_net['uuid']] = False + elif 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 + for datacenter_id in involved_datacenters: netmap_use = None netmap_create = None @@ -3380,7 +3449,9 @@ 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), wim_account_name) + task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None), False, + sce_net.get('provider_network', None), wim_account_name) + if lookfor_network: task_extra["find"] = (lookfor_filter,) elif lookfor_network: @@ -3393,6 +3464,45 @@ def create_instance(mydb, tenant_id, instance_dict): 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 + sdn_net_id = None + sdn_controller = vim.config.get('sdn-controller') + sce_net2wim_instance[sce_net_uuid][datacenter_id] = None + if sdn_controller and net_type in ("data", "ptp"): + wim_id = _get_wim(mydb, sdn_controller) + sdn_net_id = str(uuid4()) + sce_net2wim_instance[sce_net_uuid][datacenter_id] = sdn_net_id + task_extra["sdn_net_id"] = sdn_net_id + db_instance_wim_nets.append({ + "uuid": sdn_net_id, + "instance_scenario_id": instance_uuid, + "sce_net_id": sce_net.get("uuid"), + "wim_id": wim_id, + "wim_account_id": sdn_controller, + 'status': 'BUILD', # if create_network else "ACTIVE" + "related": related_network, + 'multipoint': True if net_type=="data" else False, + "created": create_network, # TODO py3 + "sdn": True, + }) + + task_wim_extra = {"params": [net_type, wim_account_name]} + # add sdn interfaces + if sce_net.get('provider_network') and sce_net['provider_network'].get("sdn-ports"): + task_wim_extra["sdn-ports"] = sce_net['provider_network'].get("sdn-ports") + db_vim_action = { + "instance_action_id": instance_action_id, + "status": "SCHEDULED", + "task_index": task_index, + # "datacenter_vim_id": myvim_thread_id, + "wim_account_id": sdn_controller, + "action": task_action, + "item": "instance_wim_nets", + "item_id": sdn_net_id, + "related": related_network, + "extra": yaml.safe_dump(task_wim_extra, default_flow_style=True, width=256) + } + task_index += 1 + db_vim_actions.append(db_vim_action) db_net = { "uuid": net_uuid, "osm_id": sce_net.get("osm_id") or sce_net["name"], @@ -3404,7 +3514,8 @@ def create_instance(mydb, tenant_id, instance_dict): "created": create_network, 'datacenter_id': datacenter_id, 'datacenter_tenant_id': myvim_thread_id, - 'status': 'BUILD' # if create_network else "ACTIVE" + 'status': 'BUILD', # if create_network else "ACTIVE" + 'sdn_net_id': sdn_net_id, } db_instance_nets.append(db_net) db_vim_action = { @@ -3451,6 +3562,7 @@ def create_instance(mydb, tenant_id, instance_dict): "task_index": task_index, "uuid_list": uuid_list, "db_instance_nets": db_instance_nets, + "db_instance_wim_nets": db_instance_wim_nets, "db_vim_actions": db_vim_actions, "db_ip_profiles": db_ip_profiles, "db_instance_vnfs": db_instance_vnfs, @@ -3458,6 +3570,7 @@ def create_instance(mydb, tenant_id, instance_dict): "db_instance_interfaces": db_instance_interfaces, "net2task_id": net2task_id, "sce_net2instance": sce_net2instance, + "sce_net2wim_instance": sce_net2wim_instance, } # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name']) for sce_vnf in scenarioDict.get('vnfs', ()): # sce_vnf_list: @@ -3584,7 +3697,8 @@ def create_instance(mydb, tenant_id, instance_dict): "source_ip": match["source_ip"], "destination_ip": match["destination_ip"], "source_port": match["source_port"], - "destination_port": match["destination_port"] + "destination_port": match["destination_port"], + "logical_source_port": classifier["interface_id"] } db_vim_action = { "instance_action_id": instance_action_id, @@ -3655,7 +3769,7 @@ def create_instance(mydb, tenant_id, instance_dict): {"instance_sfs": db_instance_sfs}, {"instance_classifications": db_instance_classifications}, {"instance_sfps": db_instance_sfps}, - {"instance_wim_nets": wan_links}, + {"instance_wim_nets": db_instance_wim_nets + wan_links}, {"vim_wim_actions": db_vim_actions + wim_actions} ] @@ -3670,13 +3784,13 @@ 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, wimconn.WimConnectorError, db_base_Exception) as e: + except (NfvoException, vimconn.vimconnException, sdnconn.SdnConnectorError, 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): + elif isinstance(e, sdnconn.SdnConnectorError): error_text = "WIM Exception" else: error_text = "Exception" @@ -3699,6 +3813,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): task_index = params_out["task_index"] uuid_list = params_out["uuid_list"] db_instance_nets = params_out["db_instance_nets"] + db_instance_wim_nets = params_out["db_instance_wim_nets"] db_vim_actions = params_out["db_vim_actions"] db_ip_profiles = params_out["db_ip_profiles"] db_instance_vnfs = params_out["db_instance_vnfs"] @@ -3706,15 +3821,19 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): db_instance_interfaces = params_out["db_instance_interfaces"] net2task_id = params_out["net2task_id"] sce_net2instance = params_out["sce_net2instance"] + sce_net2wim_instance = params_out["sce_net2wim_instance"] vnf_net2instance = {} + vnf_net2wim_instance = {} # 2. Creating new nets (vnf internal nets) in the VIM" # For each vnf net, we create it and we add it to instanceNetlist. if sce_vnf.get("datacenter"): + vim = myvims[sce_vnf["datacenter"]] datacenter_id = sce_vnf["datacenter"] myvim_thread_id = myvim_threads_id[sce_vnf["datacenter"]] else: + vim = myvims[default_datacenter_id] datacenter_id = default_datacenter_id myvim_thread_id = myvim_threads_id[default_datacenter_id] for net in sce_vnf['nets']: @@ -3731,12 +3850,30 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): vnf_net2instance[sce_vnf['uuid']] = {} if sce_vnf['uuid'] not in net2task_id: net2task_id[sce_vnf['uuid']] = {} - net2task_id[sce_vnf['uuid']][net['uuid']] = task_index # fill database content net_uuid = str(uuid4()) uuid_list.append(net_uuid) vnf_net2instance[sce_vnf['uuid']][net['uuid']] = net_uuid + + sdn_controller = vim.config.get('sdn-controller') + sdn_net_id = None + if sdn_controller and net_type in ("data", "ptp"): + wim_id = _get_wim(mydb, sdn_controller) + sdn_net_id = str(uuid4()) + db_instance_wim_nets.append({ + "uuid": sdn_net_id, + "instance_scenario_id": instance_uuid, + "wim_id": wim_id, + "wim_account_id": sdn_controller, + 'status': 'BUILD', # if create_network else "ACTIVE" + "related": net_uuid, + 'multipoint': True if net_type == "data" else False, + "created": True, # TODO py3 + "sdn": True, + }) + vnf_net2wim_instance[net_uuid] = sdn_net_id + db_net = { "uuid": net_uuid, "related": net_uuid, @@ -3747,6 +3884,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): "created": True, 'datacenter_id': datacenter_id, 'datacenter_tenant_id': myvim_thread_id, + 'sdn_net_id': sdn_net_id, } db_instance_nets.append(db_net) @@ -3761,7 +3899,25 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): else: task_action = "CREATE" task_extra = {"params": (net_name, net_type, net.get('ip_profile', None))} + if sdn_net_id: + task_extra["sdn_net_id"] = sdn_net_id + if sdn_net_id: + task_wim_extra = {"params": [net_type, None]} + db_vim_action = { + "instance_action_id": instance_action_id, + "status": "SCHEDULED", + "task_index": task_index, + # "datacenter_vim_id": myvim_thread_id, + "wim_account_id": sdn_controller, + "action": task_action, + "item": "instance_wim_nets", + "item_id": sdn_net_id, + "related": net_uuid, + "extra": yaml.safe_dump(task_wim_extra, default_flow_style=True, width=256) + } + task_index += 1 + db_vim_actions.append(db_vim_action) db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, @@ -3773,6 +3929,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): "related": net_uuid, "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256) } + net2task_id[sce_vnf['uuid']][net['uuid']] = task_index task_index += 1 db_vim_actions.append(db_vim_action) @@ -3946,11 +4103,13 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): netDict['net_id'] = "TASK-{}".format( net2task_id['scenario'][vnf_iface['sce_net_id']][datacenter_id]) instance_net_id = sce_net2instance[vnf_iface['sce_net_id']][datacenter_id] + instance_wim_net_id = sce_net2wim_instance[vnf_iface['sce_net_id']][datacenter_id] task_depends_on.append(net2task_id['scenario'][vnf_iface['sce_net_id']][datacenter_id]) break else: netDict['net_id'] = "TASK-{}".format(net2task_id[sce_vnf['uuid']][iface['net_id']]) instance_net_id = vnf_net2instance[sce_vnf['uuid']][iface['net_id']] + instance_wim_net_id = vnf_net2wim_instance.get(instance_net_id) task_depends_on.append(net2task_id[sce_vnf['uuid']][iface['net_id']]) # skip bridge ifaces not connected to any net if 'net_id' not in netDict or netDict['net_id'] == None: @@ -3960,9 +4119,11 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): # "uuid" # 'instance_vm_id': instance_vm_uuid, "instance_net_id": instance_net_id, + "instance_wim_net_id": instance_wim_net_id, 'interface_id': iface['uuid'], # 'vim_interface_id': , 'type': 'external' if iface['external_name'] is not None else 'internal', + 'model': iface['model'], 'ip_address': iface.get('ip_address'), 'mac_address': iface.get('mac'), 'floating_ip': int(iface.get('floating-ip', False)), @@ -4030,14 +4191,14 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): db_vm_iface_instance.update(db_vm_iface) if db_vm_iface_instance.get("ip_address"): # increment ip_address ip = db_vm_iface_instance.get("ip_address") - i = ip.rfind(".") - if i > 0: - try: + try: + i = ip.rfind(".") + if i > 0: i += 1 ip = ip[i:] + str(int(ip[:i]) + 1) db_vm_iface_instance["ip_address"] = ip - except: - db_vm_iface_instance["ip_address"] = None + except: + db_vm_iface_instance["ip_address"] = None db_instance_interfaces.append(db_vm_iface_instance) myVMDict['networks'][iface_index]["uuid"] = iface_uuid iface_index += 1 @@ -4349,6 +4510,23 @@ def delete_instance(mydb, tenant_id, instance_id): } task_index += 1 db_vim_actions.append(db_vim_action) + for sdn_net in instanceDict['sdn_nets']: + if not sdn_net["sdn"]: + continue + extra = {} + db_vim_action = { + "instance_action_id": instance_action_id, + "task_index": task_index, + "wim_account_id": sdn_net["wim_account_id"], + "action": "DELETE", + "status": "SCHEDULED", + "item": "instance_wim_nets", + "item_id": sdn_net["uuid"], + "related": sdn_net["related"], + "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 @@ -4383,18 +4561,19 @@ def get_instance_id(mydb, tenant_id, instance_id): #obtain data instance_dict = mydb.get_instance_scenario(instance_id, tenant_id, verbose=True) - for net in instance_dict["nets"]: - if net.get("sdn_net_id"): - net_sdn = ovim.show_network(net["sdn_net_id"]) - net["sdn_info"] = { - "admin_state_up": net_sdn.get("admin_state_up"), - "flows": net_sdn.get("flows"), - "last_error": net_sdn.get("last_error"), - "ports": net_sdn.get("ports"), - "type": net_sdn.get("type"), - "status": net_sdn.get("status"), - "vlan": net_sdn.get("vlan"), - } + # TODO py3 + # for net in instance_dict["nets"]: + # if net.get("sdn_net_id"): + # net_sdn = ovim.show_network(net["sdn_net_id"]) + # net["sdn_info"] = { + # "admin_state_up": net_sdn.get("admin_state_up"), + # "flows": net_sdn.get("flows"), + # "last_error": net_sdn.get("last_error"), + # "ports": net_sdn.get("ports"), + # "type": net_sdn.get("type"), + # "status": net_sdn.get("status"), + # "vlan": net_sdn.get("vlan"), + # } return instance_dict @deprecated("Instance is automatically refreshed by vim_threads") @@ -4649,6 +4828,16 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): "extra": yaml.safe_dump({"params": vm_interfaces}, default_flow_style=True, width=256) } + # get affected instance_interfaces (deleted on cascade) to check if a wim_network must be updated + deleted_interfaces = mydb.get_rows( + SELECT=("instance_wim_net_id", ), + FROM="instance_interfaces", + WHERE={"instance_vm_id": vdu_id, "instance_wim_net_id<>": None}, + ) + for deleted_interface in deleted_interfaces: + db_vim_actions.append({"TO-UPDATE": {}, "WHERE": { + "item": "instance_wim_nets", "item_id": deleted_interface["instance_wim_net_id"]}}) + task_index += 1 db_vim_actions.append(db_vim_action) vm_result["deleted"].append(vdu_id) @@ -4707,26 +4896,31 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): "uuid": iface_uuid, 'instance_vm_id': vm_uuid, "instance_net_id": vm_iface["instance_net_id"], + "instance_wim_net_id": vm_iface["instance_wim_net_id"], 'interface_id': vm_iface['interface_id'], 'type': vm_iface['type'], + 'model': vm_iface['model'], 'floating_ip': vm_iface['floating_ip'], 'port_security': vm_iface['port_security'] } db_instance_interfaces.append(db_vm_iface) + if db_vm_iface["instance_wim_net_id"]: + db_vim_actions.append({"TO-UPDATE": {}, "WHERE": { + "item": "instance_wim_nets", "item_id": db_vm_iface["instance_wim_net_id"]}}) task_params_copy = deepcopy(task_params) for iface in task_params_copy[5]: iface["uuid"] = iface2iface[iface["uuid"]] # increment ip_address - if "ip_address" in iface: - ip = iface.get("ip_address") - i = ip.rfind(".") - if i > 0: - try: + if iface.get("ip_address"): + try: + ip = iface["ip_address"] + i = ip.rfind(".") + if i > 0: i += 1 ip = ip[i:] + str(int(ip[:i]) + 1) iface["ip_address"] = ip - except: - iface["ip_address"] = None + except: + iface["ip_address"] = None if vm_name: task_params_copy[0] = vm_name db_vim_action = { @@ -4800,10 +4994,9 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): action_dict['add_public_key'], password=password, ro_key=priv_RO_key) vm_result[ vm['uuid'] ] = {"vim_result": 200, - "description": "Public key injected", - "name":vm['name'] + "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) @@ -4940,10 +5133,19 @@ def new_datacenter(mydb, datacenter_descriptor): datacenter_type = datacenter_descriptor.get("type", "openvim"); # module_info = None + for url_field in ('vim_url', 'vim_url_admin'): + # It is common that users copy and paste the URL from the VIM website + # (example OpenStack), therefore a common mistake is to include blank + # characters at the end of the URL. Let's remove it and just in case, + # lets remove trailing slash as well. + url = datacenter_descriptor.get(url_field) + if url: + datacenter_descriptor[url_field] = url.strip(string.whitespace + '/') + # load plugin plugin_name = "rovim_" + datacenter_type if plugin_name not in plugins: - _load_vim_plugin(plugin_name) + _load_plugin(plugin_name, type="vim") datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True, confidential_data=True) if sdn_port_mapping: @@ -5063,12 +5265,13 @@ def create_vim_account(mydb, nfvo_tenant, datacenter_id, name=None, vim_id=None, else: #if vim_tenant==None: #create tenant at VIM if not provided try: - _, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter, vim_user=vim_username, - vim_passwd=vim_password) + _, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter_id, vim_user=vim_username, + vim_passwd=vim_password) datacenter_name = myvim["name"] vim_tenant = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name) except vimconn.vimconnException as e: - raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id, str(e)), httperrors.Internal_Server_Error) + raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_name, e), + httperrors.Internal_Server_Error) datacenter_tenants_dict = {} datacenter_tenants_dict["created"]="true" @@ -5094,9 +5297,8 @@ def create_vim_account(mydb, nfvo_tenant, datacenter_id, name=None, vim_id=None, mydb.new_row('tenants_datacenters', tenants_datacenter_dict) # create thread - thread_name = get_non_used_vim_name(datacenter_name, datacenter_id, tenant_dict['name'], tenant_dict['uuid']) - new_thread = vim_thread(task_lock, plugins, thread_name, datacenter_name, datacenter_tenant_id, - db=db, db_lock=db_lock, ovim=ovim) + thread_name = get_non_used_vim_name(datacenter_name, datacenter_id) + new_thread = vim_thread(task_lock, plugins, thread_name, None, datacenter_tenant_id, db=db) new_thread.start() thread_id = datacenter_tenants_dict["uuid"] vim_threads["running"][thread_id] = new_thread @@ -5127,7 +5329,7 @@ def edit_vim_account(mydb, nfvo_tenant, datacenter_tenant_id, datacenter_id=None if config: original_config_dict = yaml.load(original_config, Loader=yaml.Loader) original_config_dict.update(config) - update["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256) + update_["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256) if name: update_['name'] = name if vim_tenant: @@ -5565,7 +5767,10 @@ 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) + net_provider_network_profile = None + if net_vlan: + net_provider_network_profile = {"segmentation-id": net_vlan} + content, _ = myvim.new_network(net_name, net_type, net_ipprofile, shared=net_public, provider_network_profile=net_provider_network_profile) #, **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'): @@ -5609,13 +5814,29 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor): return vim_action_get(mydb, tenant_id, datacenter, item, content) def sdn_controller_create(mydb, tenant_id, sdn_controller): - data = ovim.new_of_controller(sdn_controller) - logger.debug('New SDN controller created with uuid {}'.format(data)) - return data + try: + wim_id = ovim.new_of_controller(sdn_controller) + + # Load plugin if not previously loaded + controller_type = sdn_controller.get("type") + plugin_name = "rosdn_" + controller_type + if plugin_name not in plugins: + _load_plugin(plugin_name, type="sdn") + + thread_name = get_non_used_vim_name(sdn_controller['name'], wim_id) + new_thread = vim_thread(task_lock, plugins, thread_name, wim_id, None, db=db) + new_thread.start() + thread_id = wim_id + vim_threads["running"][thread_id] = new_thread + logger.debug('New SDN controller created with uuid {}'.format(wim_id)) + return wim_id + except ovimException as e: + raise NfvoException(e) from e def sdn_controller_update(mydb, tenant_id, controller_id, sdn_controller): data = ovim.edit_of_controller(controller_id, sdn_controller) msg = 'SDN controller {} updated'.format(data) + vim_threads["running"][controller_id].insert_task("reload") logger.debug(msg) return msg @@ -5661,20 +5882,25 @@ def datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, sdn_port_map #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid} element = dict() element["compute_node"] = compute_node["compute_node"] - for port in compute_node["ports"]: - pci = port.get("pci") - element["switch_port"] = port.get("switch_port") - element["switch_mac"] = port.get("switch_mac") - 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)) - - return ovim.set_of_port_mapping(maps, ofc_id=sdn_controller_id, switch_dpid=switch_dpid, region=datacenter_id) + if compute_node["ports"]: + for port in compute_node["ports"]: + pci = port.get("pci") + element["switch_port"] = port.get("switch_port") + element["switch_mac"] = port.get("switch_mac") + element["switch_dpid"] = port.get("switch_dpid") + element["switch_id"] = port.get("switch_id") + 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)) + + out = ovim.set_of_port_mapping(maps, sdn_id=sdn_controller_id, switch_dpid=switch_dpid, vim_id=datacenter_id) + vim_threads["running"][sdn_controller_id].insert_task("reload") + return out def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id): - maps = ovim.get_of_port_mappings(db_filter={"region": datacenter_id}) + maps = ovim.get_of_port_mappings(db_filter={"datacenter_id": datacenter_id}) result = { "sdn-controller": None, @@ -5703,24 +5929,25 @@ def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id): ports_correspondence_dict = dict() for link in maps: - if result["sdn-controller"] != link["ofc_id"]: + if result["sdn-controller"] != link["wim_id"]: raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors.Internal_Server_Error) if result["dpid"] != link["switch_dpid"]: raise NfvoException("The dpid specified for different port mappings differ", httperrors.Internal_Server_Error) + link_config = link["service_mapping_info"] element = dict() - element["pci"] = link["pci"] + element["pci"] = link.get("device_interface_id") if link["switch_port"]: element["switch_port"] = link["switch_port"] - if link["switch_mac"]: - element["switch_mac"] = link["switch_mac"] + if link_config["switch_mac"]: + element["switch_mac"] = link_config.get("switch_mac") - if not link["compute_node"] in ports_correspondence_dict: + if not link.get("interface_id") in ports_correspondence_dict: content = dict() - content["compute_node"] = link["compute_node"] + content["compute_node"] = link.get("interface_id") content["ports"] = list() - ports_correspondence_dict[link["compute_node"]] = content + ports_correspondence_dict[link.get("interface_id")] = content - ports_correspondence_dict[link["compute_node"]]["ports"].append(element) + ports_correspondence_dict[link["interface_id"]]["ports"].append(element) for key in sorted(ports_correspondence_dict): result["ports_mapping"].append(ports_correspondence_dict[key]) @@ -5728,7 +5955,7 @@ def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id): return result def datacenter_sdn_port_mapping_delete(mydb, tenant_id, datacenter_id): - return ovim.clear_of_port_mapping(db_filter={"region":datacenter_id}) + return ovim.clear_of_port_mapping(db_filter={"datacenter_id":datacenter_id}) def create_RO_keypair(tenant_id): """ @@ -5749,6 +5976,10 @@ def create_RO_keypair(tenant_id): private_key = key.exportKey(passphrase=tenant_id, pkcs=8) except (ValueError, NameError) as e: raise NfvoException("Unable to create private key: {}".format(e), httperrors.Internal_Server_Error) + if isinstance(public_key, bytes): + public_key = public_key.decode(encoding='UTF-8') + if isinstance(private_key, bytes): + private_key = private_key.decode(encoding='UTF-8') return public_key, private_key def decrypt_key (key, tenant_id): @@ -5765,6 +5996,8 @@ def decrypt_key (key, tenant_id): unencrypted_key = key.exportKey('PEM') if isinstance(unencrypted_key, ValueError): raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key), httperrors.Internal_Server_Error) + if isinstance(unencrypted_key, bytes): + unencrypted_key = unencrypted_key.decode(encoding='UTF-8') except ValueError as e: raise NfvoException("Unable to decrypt the private key: {}".format(e), httperrors.Internal_Server_Error) return unencrypted_key