def add_slice(nest_req): """ Creates the network slice """ # Recreate the NEST with None options where missiong nest = { "_id": nest_req["_id"], "status": "Init", "created_at": time.time(), # unix epoch "deployment_time": { "Placement_Time": None, "Provisioning_Time": None, "WAN_Deployment_Time": None, "NS_Deployment_Time": None, "Radio_Configuration_Time": None, "Slice_Deployment_Time": None, }, } mongoUtils.add("slice", nest) for nest_key in NEST_KEYS_OBJ: nest[nest_key] = nest_req.get(nest_key, None) for nest_key in NEST_KEYS_LIST: nest[nest_key] = nest_req.get(nest_key, []) # Check if slice monitoring has been enabled monitoring = os.getenv("KATANA_MONITORING", None) wim_monitoring = {} mon_producer = None if monitoring: # Create the Kafka producer mon_producer = create_producer() nest["slice_monitoring"] = {} # **** STEP-1: Placement **** nest["status"] = "Placement" if monitoring: mon_producer.send( "nfv_mon", value={ "action": "katana_mon", "slice_info": { "slice_id": nest["_id"], "status": "placement" }, }, ) nest["conf_comp"] = {"nf": [], "ems": []} mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Placement") placement_start_time = time.time() # Initiate the lists vim_dict = {} total_ns_list = [] ems_messages = {} # Get Details for the Network Services # i) The NS part of the core slice inst_functions = {} for connection in nest["connections"]: for key in connection: # Check if the function has been instantiated from another connection if connection[key]["_id"] in inst_functions: connection[key] = inst_functions[connection[key]["_id"]] continue # Check if the function is shared with another slice # shared_check values: 0: No shared, 1: First shared, 2: Shared shared_check = 0 shared_slice_list_key = None try: shared_slice_list_key = nest["shared"][key][connection[key] ["_id"]] shared_slice_list = connection[key]["shared"]["sharing_list"][ shared_slice_list_key] if len(shared_slice_list) > 1: shared_check = 2 else: shared_check = 1 except KeyError: pass try: err, pop_list = ns_details( connection[key]["ns_list"], connection[key]["location"], vim_dict, total_ns_list, shared_check, shared_slice_list_key, ) if pop_list: connection[key]["ns_list"] = [ x for x in connection[key]["ns_list"] if x not in pop_list ] if err: nest["status"] = f"Failed - {err}" nest["ns_inst_info"] = {} nest["total_ns_list"] = [] mongoUtils.update("slice", nest["_id"], nest) return inst_functions[connection[key]["_id"]] = connection[key] except KeyError: continue # ii) The extra NS of the slice for location in nest["coverage"]: err, _ = ns_details(nest["ns_list"], location, vim_dict, total_ns_list) if err: nest["status"] = f"Failed - {err}" nest["ns_inst_info"] = {} nest["total_ns_list"] = [] mongoUtils.update("slice", nest["_id"], nest) return nest["vim_list"] = vim_dict nest["total_ns_list"] = total_ns_list nest["deployment_time"]["Placement_Time"] = format( time.time() - placement_start_time, ".4f") # **** STEP-2: Resource Provisioning **** nest["status"] = "Provisioning" if monitoring: mon_producer.send( "nfv_mon", value={ "action": "katana_mon", "slice_info": { "slice_id": nest["_id"], "status": "provisioning" }, }, ) mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Provisioning") prov_start_time = time.time() # *** STEP-2a: Cloud *** # *** STEP-2a-i: Create the new tenant/project on the VIM *** for num, (vim, vim_info) in enumerate(vim_dict.items()): if vim_info["shared"]: vim_id = vim[:-2] else: vim_id = vim target_vim = mongoUtils.find("vim", {"id": vim_id}) target_vim_obj = pickle.loads( mongoUtils.find("vim_obj", {"id": vim_id})["obj"]) # Define project parameters if vim_info["shared"] == 1: name = "vim_{0}_katana_{1}_shared".format( num, vim_info["shared_slice_list_key"]) tenant_name = vim_info["shared_slice_list_key"] elif vim_info["shared"] == 0: name = "vim_{0}_katana_{1}".format(num, nest["_id"]) tenant_name = nest["_id"] else: # Find the shared list sharing_lists = mongoUtils.get("sharing_lists", vim_info["shared_slice_list_key"]) vim_dict[vim] = sharing_lists["vims"][target_vim["id"]] mongoUtils.update("slice", nest["_id"], nest) continue tenant_project_name = name tenant_project_description = name tenant_project_user = name tenant_project_password = "******" # If the vim is Openstack type, set quotas quotas = (vim_info["resources"] if target_vim["type"] == "openstack" or target_vim["type"] == "Openstack" else None) ids = target_vim_obj.create_slice_prerequisites( tenant_project_name, tenant_project_description, tenant_project_user, tenant_project_password, nest["_id"], quotas=quotas, ) # Register the tenant to the mongo db target_vim["tenants"][tenant_name] = name mongoUtils.update("vim", target_vim["_id"], target_vim) # STEP-2a-ii: Αdd the new VIM tenant to NFVO if target_vim["type"] == "openstack": # Update the config parameter for the tenant config_param = dict(security_groups=ids["secGroupName"]) elif target_vim["type"] == "opennebula": config_param = target_vim["config"] else: config_param = {} for nfvo_id in vim_info["nfvo_list"]: target_nfvo = mongoUtils.find("nfvo", {"id": nfvo_id}) target_nfvo_obj = pickle.loads( mongoUtils.find("nfvo_obj", {"id": nfvo_id})["obj"]) vim_id = target_nfvo_obj.addVim( tenant_project_name, target_vim["password"], target_vim["type"], target_vim["auth_url"], target_vim["username"], config_param, ) vim_info["nfvo_vim_account"] = vim_info.get("nfvo_vim_account", {}) vim_info["nfvo_vim_account"][nfvo_id] = vim_id # Register the tenant to the mongo db target_nfvo["tenants"][tenant_name] = target_nfvo["tenants"].get( nest["_id"], []) target_nfvo["tenants"][tenant_name].append(vim_id) mongoUtils.update("nfvo", target_nfvo["_id"], target_nfvo) if vim_info["shared"] == 1: sharing_lists = mongoUtils.get("sharing_lists", vim_info["shared_slice_list_key"]) sharing_lists["vims"] = sharing_lists.get("vims", {}) sharing_lists["vims"][target_vim["id"]] = vim_info mongoUtils.update("sharing_lists", vim_info["shared_slice_list_key"], sharing_lists) mongoUtils.update("slice", nest["_id"], nest) # *** STEP-2b: WAN *** if mongoUtils.count("wim") <= 0: logger.warning("There is no registered WIM") else: wan_start_time = time.time() # Crate the data for the WIM wim_data = { "_id": nest["_id"], "core_connections": [], "extra_ns": [], "slice_sla": {} } # i) Create the slice_sla data for the WIM wim_data["slice_sla"] = { "network_DL_throughput": nest["network_DL_throughput"], "network_UL_throughput": nest["network_UL_throughput"], "mtu": nest["mtu"], } # ii) Add the connections for connection in nest["connections"]: data = {} for key in connection: key_data = {} try: ns_l = connection[key]["ns_list"] except KeyError: pass else: key_data["ns"] = [] for ns in ns_l: if ns["placement_loc"] not in key_data["ns"]: key_data["ns"].append(ns["placement_loc"]) try: pnf_l = connection[key]["pnf_list"] except KeyError: pass else: key_data["pnf"] = pnf_l if key_data: data[key] = key_data if data: wim_data["core_connections"].append(data) # iii) Add the extra Network Services for ns in nest["ns_list"]: if ns["placement_loc"] not in wim_data["extra_ns"]: wim_data["extra_ns"].append(ns["placement_loc"]) # iV) Add the probes wim_data["probes"] = nest["probe_list"] # Select WIM - Assume that there is only one registered wim_list = list(mongoUtils.index("wim")) target_wim = wim_list[0] target_wim_id = target_wim["id"] target_wim_obj = pickle.loads( mongoUtils.find("wim_obj", {"id": target_wim_id})["obj"]) target_wim_obj.create_slice(wim_data) nest["wim_data"] = wim_data target_wim["slices"][nest["_id"]] = nest["_id"] mongoUtils.update("slice", nest["_id"], nest) mongoUtils.update("wim", target_wim["_id"], target_wim) # Add monitoring from WIM in nest try: wim_monitoring = target_wim["monitoring-url"] nest["slice_monitoring"]["WIM"] = wim_monitoring except KeyError: pass nest["deployment_time"]["WAN_Deployment_Time"] = format( time.time() - wan_start_time, ".4f") nest["deployment_time"]["Provisioning_Time"] = format( time.time() - prov_start_time, ".4f") # **** STEP-3: Slice Activation Phase**** nest["status"] = "Activation" if monitoring: mon_producer.send( "nfv_mon", value={ "action": "katana_mon", "slice_info": { "slice_id": nest["_id"], "status": "activation" }, }, ) mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Activation") # *** STEP-3a: Cloud *** # Instantiate NS # Store info about instantiated NSs ns_inst_info = {} nest["deployment_time"]["NS_Deployment_Time"] = {} for ns in total_ns_list: ns["start_time"] = time.time() if ns["shared_function"] == 2: # The ns is already instantiated and there is no need to instantiate again # Find the sharing list shared_list = mongoUtils.get("sharing_lists", ns["shared_slice_key"]) ns_inst_info[ns["ns-id"]] = shared_list["ns_list"][ns["nsd-id"]] nest["conf_comp"]["nf"].append(ns["nsd-id"]) continue ns_inst_info[ns["ns-id"]] = {} target_nfvo = mongoUtils.find("nfvo", {"id": ns["nfvo-id"]}) target_nfvo_obj = pickle.loads( mongoUtils.find("nfvo_obj", {"id": ns["nfvo-id"]})["obj"]) selected_vim = ns["placement_loc"]["vim"] nfvo_vim_account = vim_dict[selected_vim]["nfvo_vim_account"][ ns["nfvo-id"]] nfvo_inst_ns = target_nfvo_obj.instantiateNs(ns["ns-name"], ns["nsd-id"], nfvo_vim_account) ns_inst_info[ns["ns-id"]][ns["placement_loc"]["location"]] = { "nfvo_inst_ns": nfvo_inst_ns, "nfvo-id": ns["nfvo-id"], "ns-name": ns["ns-name"], "slice_id": nest["_id"], "vim": selected_vim, } # Check if this the first slice of a sharing list if ns["shared_function"] == 1: shared_list = mongoUtils.get("sharing_lists", ns["shared_slice_key"]) ns_inst_info[ns["ns-id"]][ns["placement_loc"] ["location"]]["shared"] = True ns_inst_info[ns["ns-id"]][ns["placement_loc"]["location"]][ "sharing_list"] = ns["shared_slice_key"] shared_list["ns_list"][ns["nsd-id"]] = ns_inst_info[ns["ns-id"]] mongoUtils.update("sharing_lists", ns["shared_slice_key"], shared_list) nest["conf_comp"]["nf"].append(ns["nsd-id"]) time.sleep(4) time.sleep(2) # Get the nsr for each service and wait for the activation for ns in total_ns_list: target_nfvo = mongoUtils.find("nfvo", {"id": ns["nfvo-id"]}) target_nfvo_obj = pickle.loads( mongoUtils.find("nfvo_obj", {"id": ns["nfvo-id"]})["obj"]) site = ns["placement_loc"] nfvo_inst_ns_id = ns_inst_info[ns["ns-id"]][ site["location"]]["nfvo_inst_ns"] insr = target_nfvo_obj.getNsr(nfvo_inst_ns_id) while insr["operational-status"] != "running" or insr[ "config-status"] != "configured": if insr["operational-status"] == "failed": error_message = ( f"Network Service {ns['nsd-id']} failed to start on NFVO {ns['nfvo-id']}." ) logger.error(error_message) nest["ns_inst_info"] = ns_inst_info nest["status"] = f"Failed - {error_message}" mongoUtils.update("slice", nest["_id"], nest) return time.sleep(10) insr = target_nfvo_obj.getNsr(nfvo_inst_ns_id) nest["deployment_time"]["NS_Deployment_Time"][ns["ns-name"]] = format( time.time() - ns["start_time"], ".4f") # Get the IPs of the instantiated NS vnf_list = [] vnfr_id_list = target_nfvo_obj.getVnfrId(insr) for ivnfr_id in vnfr_id_list: vnfr = target_nfvo_obj.getVnfr(ivnfr_id) vnf_list.append(target_nfvo_obj.getIPs(vnfr)) ns_inst_info[ns["ns-id"]][site["location"]]["vnfr"] = vnf_list nest["ns_inst_info"] = ns_inst_info mongoUtils.update("slice", nest["_id"], nest) # If monitoring parameter is set, send the ns_list to nfv_mon module if monitoring and mon_producer: mon_producer.send(topic="nfv_mon", value={ "action": "create", "ns_list": ns_inst_info }) nest["slice_monitoring"]["nfv_ns_status_monitoring"] = True # *** STEP-3b: Radio Slice Configuration *** if mongoUtils.count("ems") <= 0: logger.warning("There is no registered EMS") else: # Add the management IPs for the NS sent ems in ems_messages: ems_radio_data = { "ue_DL_throughput": nest["ue_DL_throughput"], "ue_UL_throughput": nest["ue_UL_throughput"], "group_communication_support": nest["group_communication_support"], "number_of_terminals": nest["number_of_terminals"], "positional_support": nest["positional_support"], "radio_spectrum": nest["radio_spectrum"], "device_velocity": nest["device_velocity"], "terminal_density": nest["terminal_density"], } radio_start_time = time.time() iii = 0 for connection in nest["connections"]: iii += 1 data = {} ems_id_list = [] for key in connection: # Check if the connection is shared try: shared_slice_list_key = nest["shared"][key][connection[key] ["_id"]] shared_slice_list = connection[key]["shared"][ "sharing_list"][shared_slice_list_key] shared = True if len(shared_slice_list) > 1: shared_check = 2 else: shared_check = 1 except KeyError: shared_slice_list_key = None shared = False key_data = {} try: ems_id = connection[key]["ems-id"] except KeyError: continue else: if ems_id not in ems_id_list: ems_id_list.append(ems_id) try: ns_l = connection[key]["ns_list"] except KeyError: pass else: key_data["ns"] = [] for ns in ns_l: try: ns_info = ns_inst_info[ns["ns-id"]][ connection[key]["location"]] except KeyError: ns_info = ns_inst_info[ns["ns-id"]]["Core"] ns_data = { "name": ns["ns-name"], "location": ns["placement_loc"]["location"], "vnf_list": ns_info["vnfr"], } # Add the shared information for the ns, if any if shared: ns_data["shared"] = ns_inst_info[ns["ns-id"]][ connection[key]["location"]]["shared"] ns_data["sharing_list"] = ns_inst_info[ ns["ns-id"]][connection[key] ["location"]]["sharing_list"] else: ns_data["shared"] = False key_data["ns"].append(ns_data) try: key_data["pnf"] = connection[key]["pnf_list"] except KeyError: pass else: if shared: for ipnf in connection[key]["pnf_list"]: ipnf["shared"] = True ipnf["sharing_list"] = shared_slice_list_key if key_data: data[key] = key_data if data: data["slice_sla"] = ems_radio_data data["slice_id"] = nest["_id"] for ems_id in ems_id_list: messages = ems_messages.get(ems_id, []) messages.append(data) ems_messages[ems_id] = messages for ems_id, ems_message in ems_messages.items(): # Find the EMS target_ems = mongoUtils.find("ems", {"id": ems_id}) if not target_ems: # Error handling: There is no such EMS logger.error( "EMS {} not found - No configuration".format(ems_id)) continue target_ems_obj = pickle.loads( mongoUtils.find("ems_obj", {"id": ems_id})["obj"]) # Send the message for imessage in ems_message: target_ems_obj.conf_radio(imessage) nest["conf_comp"]["ems"].append(ems_id) nest["ems_data"] = ems_messages nest["deployment_time"]["Radio_Configuration_Time"] = format( time.time() - radio_start_time, ".4f") # *** STEP-4: Finalize *** # Create Grafana Dashboard for monitoring # Create the NS status panel if monitoring: # Open the Grafana Dashboard template monitoring_slice_id = "slice_" + nest["_id"].replace("-", "_") with open("/katana-grafana/templates/new_dashboard.json", mode="r") as dashboard_file: new_dashboard = json.load(dashboard_file) new_dashboard["dashboard"]["title"] = monitoring_slice_id new_dashboard["dashboard"]["uid"] = nest["_id"] # Add the dashboard panels # Add the NS Status panels expr = "ns_status" + '{slice_id="' + nest["_id"] + '"}' targets = [{ "expr": expr, "legendFormat": "", "interval": "", "format": "table", "instant": True }] infra_targets = {} for ns in ns_inst_info.values(): for key, value in ns.items(): # Check if the VIM supports infrastructure monitoring search_vim_id = value["vim"] if value.get("shared", False): search_vim_id = search_vim_id[:-2] selected_vim = mongoUtils.find("vim", {"id": search_vim_id}) try: vim_monitoring = selected_vim["type"] vim_monitoring_list = infra_targets.get(vim_monitoring, []) for ivnf in value["vnfr"]: vim_monitoring_list += ivnf["vm_list"] infra_targets[vim_monitoring] = vim_monitoring_list except KeyError: pass # Create the VM Monitoring panels PANELS = [ "vm_state", "vm_cpu_cpu_time", "vm_cpu_overall_cpu_usage", "vm_memory_actual", "vm_memory_available", "vm_memory_usage", "vm_disk_read_bytes", "vm_disk_write_bytes", "vm_disk_errors", ] with open("/katana-grafana/templates/new_vm_monitoring_panel.json", mode="r") as panel_file: vm_panel_template = json.load(panel_file) for i, panel in enumerate(PANELS): vm_panel = copy.deepcopy(vm_panel_template) vm_panel["title"] = panel vm_panel["gridPos"] = {"h": 8, "w": 12, "x": 13, "y": i * 9} vm_panel["id"] = 10 + i vm_targets = [] for vim_type, vm_list in infra_targets.items(): for vm in vm_list: expr = (vim_type + "_" + panel + '{project=~".*' + nest["_id"] + '",vm_name="' + vm + '"}') vm_targets.append({ "expr": expr, "interval": "", "legendFormat": "" }) vm_panel["targets"] = vm_targets new_dashboard["dashboard"]["panels"].append(vm_panel) # Read and fill the NS Status panel template with open("/katana-grafana/templates/new_ns_status_panel.json", mode="r") as panel_file: ns_panel = json.load(panel_file) ns_panel["targets"] = targets new_dashboard["dashboard"]["panels"].append(ns_panel) # Add the WIM Monitoring panel if wim_monitoring: # Read and fill the panel template with open("/katana-grafana/templates/new_wim_panel.json", mode="r") as panel_file: wim_panel = json.load(panel_file) wim_panel["targets"].append({ "expr": f"rate({monitoring_slice_id}_flows[1m])", "interval": "", "legendFormat": "", "refId": "A", }) new_dashboard["dashboard"]["panels"].append(wim_panel) mon_producer.send( "nfv_mon", value={ "action": "katana_mon", "slice_info": { "slice_id": nest["_id"], "status": "running" }, }, ) # Use the Grafana API in order to create the new dashboard for the new slice grafana_url = "http://katana-grafana:3000/api/dashboards/db" headers = { "accept": "application/json", "content-type": "application/json" } grafana_user = os.getenv("GF_SECURITY_ADMIN_USER", "admin") grafana_passwd = os.getenv("GF_SECURITY_ADMIN_PASSWORD", "admin") r = requests.post( url=grafana_url, headers=headers, auth=(grafana_user, grafana_passwd), data=json.dumps(new_dashboard), ) logger.info(f"Created new Grafana dashboard for slice {nest['_id']}") logger.info(f"{nest['_id']} Status: Running") nest["status"] = "Running" nest["deployment_time"]["Slice_Deployment_Time"] = format( time.time() - nest["created_at"], ".4f") mongoUtils.update("slice", nest["_id"], nest)
def add_slice(nest_req): """ Creates the network slice """ # Recreate the NEST with None options where missiong nest = { "_id": nest_req["_id"], "status": "Init", "created_at": time.time(), # unix epoch "deployment_time": { "Placement_Time": None, "Provisioning_Time": None, "WAN_Deployment_Time": None, "NS_Deployment_Time": None, "Radio_Configuration_Time": None, "Slice_Deployment_Time": None, }, } mongoUtils.add("slice", nest) for nest_key in NEST_KEYS_OBJ: nest[nest_key] = nest_req.get(nest_key, None) for nest_key in NEST_KEYS_LIST: nest[nest_key] = nest_req.get(nest_key, []) # **** STEP-1: Placement **** nest["status"] = "Placement" nest["conf_comp"] = {"nf": [], "ems": []} mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Placement") placement_start_time = time.time() # Initiate the lists vim_dict = {} total_ns_list = [] ems_messages = {} # Get Details for the Network Services # i) The extra NS of the slice for location in nest["coverage"]: err, _ = ns_details(nest["ns_list"], location, vim_dict, total_ns_list) if err: delete_slice(nest) return del nest["ns_list"] nest["ns_list"] = copy.deepcopy(total_ns_list) # ii) The NS part of the core slice inst_functions = {} for connection in nest["connections"]: for key in connection: if connection[key]["_id"] in inst_functions: connection[key] = inst_functions[connection[key]["_id"]] continue try: err, pop_list = ns_details( connection[key]["ns_list"], connection[key]["location"], vim_dict, total_ns_list ) if pop_list: connection[key]["ns_list"] = [ x for x in connection[key]["ns_list"] if x not in pop_list ] if err: delete_slice(nest) return inst_functions[connection[key]["_id"]] = connection[key] except KeyError: continue nest["vim_list"] = vim_dict nest["total_ns_list"] = total_ns_list nest["deployment_time"]["Placement_Time"] = format(time.time() - placement_start_time, ".4f") # **** STEP-2: Resource Provisioning **** nest["status"] = "Provisioning" mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Provisioning") prov_start_time = time.time() # *** STEP-2a: Cloud *** # *** STEP-2a-i: Create the new tenant/project on the VIM *** for num, (vim, vim_info) in enumerate(vim_dict.items()): target_vim = mongoUtils.find("vim", {"id": vim}) target_vim_obj = pickle.loads(mongoUtils.find("vim_obj", {"id": vim})["obj"]) # Define project parameters tenant_project_name = "vim_{0}_katana_{1}".format(num, nest["_id"]) tenant_project_description = "vim_{0}_katana_{1}".format(num, nest["_id"]) tenant_project_user = "******".format(num, nest["_id"]) tenant_project_password = "******" # If the vim is Openstack type, set quotas quotas = ( vim_info["resources"] if target_vim["type"] == "openstack" or target_vim["type"] == "Openstack" else None ) ids = target_vim_obj.create_slice_prerequisites( tenant_project_name, tenant_project_description, tenant_project_user, tenant_project_password, nest["_id"], quotas=quotas, ) # Register the tenant to the mongo db target_vim["tenants"][nest["_id"]] = tenant_project_name mongoUtils.update("vim", target_vim["_id"], target_vim) # STEP-2a-ii: Αdd the new VIM tenant to NFVO if target_vim["type"] == "openstack": # Update the config parameter for the tenant config_param = dict(security_groups=ids["secGroupName"]) elif target_vim["type"] == "opennebula": config_param = target_vim["config"] else: config_param = {} for nfvo_id in vim_info["nfvo_list"]: target_nfvo = mongoUtils.find("nfvo", {"id": nfvo_id}) target_nfvo_obj = pickle.loads(mongoUtils.find("nfvo_obj", {"id": nfvo_id})["obj"]) vim_id = target_nfvo_obj.addVim( tenant_project_name, target_vim["password"], target_vim["type"], target_vim["auth_url"], target_vim["username"], config_param, ) vim_info["nfvo_vim_account"] = vim_info.get("nfvo_vim_account", {}) vim_info["nfvo_vim_account"][nfvo_id] = vim_id # Register the tenant to the mongo db target_nfvo["tenants"][nest["_id"]] = target_nfvo["tenants"].get(nest["_id"], []) target_nfvo["tenants"][nest["_id"]].append(vim_id) mongoUtils.update("nfvo", target_nfvo["_id"], target_nfvo) mongoUtils.update("slice", nest["_id"], nest) # *** STEP-2b: WAN *** if mongoUtils.count("wim") <= 0: logger.warning("There is no registered WIM") else: wan_start_time = time.time() # Crate the data for the WIM wim_data = {"_id": nest["_id"], "core_connections": [], "extra_ns": [], "slice_sla": {}} # i) Create the slice_sla data for the WIM wim_data["slice_sla"] = { "network_DL_throughput": nest["network_DL_throughput"], "network_UL_throughput": nest["network_UL_throughput"], "mtu": nest["mtu"], } # ii) Add the connections for connection in nest["connections"]: data = {} for key in connection: key_data = {} try: ns_l = connection[key]["ns_list"] except KeyError: pass else: key_data["ns"] = [] for ns in ns_l: if ns["placement_loc"] not in key_data["ns"]: key_data["ns"].append(ns["placement_loc"]) try: pnf_l = connection[key]["pnf_list"] except KeyError: pass else: key_data["pnf"] = pnf_l if key_data: data[key] = key_data if data: wim_data["core_connections"].append(data) # iii) Add the extra Network Services for ns in nest["ns_list"]: if ns["placement_loc"] not in wim_data["extra_ns"]: wim_data["extra_ns"].append(ns["placement_loc"]) # iV) Add the probes wim_data["probes"] = nest["probe_list"] # Select WIM - Assume that there is only one registered wim_list = list(mongoUtils.index("wim")) target_wim = wim_list[0] target_wim_id = target_wim["id"] target_wim_obj = pickle.loads(mongoUtils.find("wim_obj", {"id": target_wim_id})["obj"]) target_wim_obj.create_slice(wim_data) nest["wim_data"] = wim_data target_wim["slices"][nest["_id"]] = nest["_id"] mongoUtils.update("wim", target_wim["_id"], target_wim) nest["deployment_time"]["WAN_Deployment_Time"] = format(time.time() - wan_start_time, ".4f") nest["deployment_time"]["Provisioning_Time"] = format(time.time() - prov_start_time, ".4f") # **** STEP-3: Slice Activation Phase**** nest["status"] = "Activation" mongoUtils.update("slice", nest["_id"], nest) logger.info(f"{nest['_id']} Status: Activation") # *** STEP-3a: Cloud *** # Instantiate NS # Store info about instantiated NSs ns_inst_info = {} nest["deployment_time"]["NS_Deployment_Time"] = {} for ns in total_ns_list: ns["start_time"] = time.time() ns_inst_info[ns["ns-id"]] = {} target_nfvo = mongoUtils.find("nfvo", {"id": ns["nfvo-id"]}) target_nfvo_obj = pickle.loads(mongoUtils.find("nfvo_obj", {"id": ns["nfvo-id"]})["obj"]) selected_vim = ns["placement_loc"]["vim"] nfvo_vim_account = vim_dict[selected_vim]["nfvo_vim_account"][ns["nfvo-id"]] nfvo_inst_ns = target_nfvo_obj.instantiateNs(ns["ns-name"], ns["nsd-id"], nfvo_vim_account) ns_inst_info[ns["ns-id"]][ns["placement_loc"]["location"]] = {"nfvo_inst_ns": nfvo_inst_ns} nest["conf_comp"]["nf"].append(ns["nsd-id"]) time.sleep(4) time.sleep(2) # Get the nsr for each service and wait for the activation for ns in total_ns_list: target_nfvo = mongoUtils.find("nfvo", {"id": ns["nfvo-id"]}) target_nfvo_obj = pickle.loads(mongoUtils.find("nfvo_obj", {"id": ns["nfvo-id"]})["obj"]) site = ns["placement_loc"] nfvo_inst_ns_id = ns_inst_info[ns["ns-id"]][site["location"]]["nfvo_inst_ns"] insr = target_nfvo_obj.getNsr(nfvo_inst_ns_id) while insr["operational-status"] != "running" or insr["config-status"] != "configured": time.sleep(10) insr = target_nfvo_obj.getNsr(nfvo_inst_ns_id) nest["deployment_time"]["NS_Deployment_Time"][ns["ns-name"]] = format( time.time() - ns["start_time"], ".4f" ) # Get the IPs of the instantiated NS vnf_list = [] vnfr_id_list = target_nfvo_obj.getVnfrId(insr) for ivnfr_id in vnfr_id_list: vnfr = target_nfvo_obj.getVnfr(ivnfr_id) vnf_list.append(target_nfvo_obj.getIPs(vnfr)) ns_inst_info[ns["ns-id"]][site["location"]]["vnfr"] = vnf_list nest["ns_inst_info"] = ns_inst_info mongoUtils.update("slice", nest["_id"], nest) # *** STEP-3b: Radio Slice Configuration *** if mongoUtils.count("ems") <= 0: logger.warning("There is no registered EMS") else: # Add the management IPs for the NS sent ems in ems_messages: ems_radio_data = { "ue_DL_throughput": nest["ue_DL_throughput"], "ue_UL_throughput": nest["ue_UL_throughput"], "group_communication_support": nest["group_communication_support"], "number_of_terminals": nest["number_of_terminals"], "positional_support": nest["positional_support"], "radio_spectrum": nest["radio_spectrum"], "device_velocity": nest["device_velocity"], "terminal_density": nest["terminal_density"], } radio_start_time = time.time() for connection in nest["connections"]: data = {} ems_id_list = [] for key in connection: key_data = {} try: ems_id = connection[key]["ems-id"] except KeyError: continue else: if ems_id not in ems_id_list: ems_id_list.append(ems_id) try: ns_l = connection[key]["ns_list"] except KeyError: pass else: key_data["ns"] = [] for ns in ns_l: try: ns_info = ns_inst_info[ns["ns-id"]][connection[key]["location"]] except KeyError: ns_info = ns_inst_info[ns["ns-id"]]["Core"] ns_data = { "name": ns["ns-name"], "location": ns["placement_loc"]["location"], "vnf_list": ns_info["vnfr"], } key_data["ns"].append(ns_data) try: key_data["pnf"] = connection[key]["pnf_list"] except KeyError: pass if key_data: data[key] = key_data if data: data["slice_sla"] = ems_radio_data data["slice_id"] = nest["_id"] for ems_id in ems_id_list: messages = ems_messages.get(ems_id, []) messages.append(data) ems_messages[ems_id] = messages for ems_id, ems_message in ems_messages.items(): # Find the EMS target_ems = mongoUtils.find("ems", {"id": ems_id}) if not target_ems: # Error handling: There is no such EMS logger.error("EMS {} not found - No configuration".format(ems_id)) continue target_ems_obj = pickle.loads(mongoUtils.find("ems_obj", {"id": ems_id})["obj"]) # Send the message for imessage in ems_message: target_ems_obj.conf_radio(imessage) nest["conf_comp"]["ems"].append(ems_id) nest["ems_data"] = ems_messages nest["deployment_time"]["Radio_Configuration_Time"] = format( time.time() - radio_start_time, ".4f" ) # *** STEP-4: Finalize *** logger.info(f"{nest['_id']} Status: Running") nest["status"] = "Running" nest["deployment_time"]["Slice_Deployment_Time"] = format( time.time() - nest["created_at"], ".4f" ) mongoUtils.update("slice", nest["_id"], nest)