X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=NG-RO%2Fosm_ng_ro%2Fns.py;h=19ff791a6d161e2305d1204be0af8461c35ced47;hb=ae04e5e8139ac83d30ff04942c37386d92440be9;hp=096d4dfd16acc06a7508b49dc0cf8cebba7d2a83;hpb=cf14bb1f6b681cc5a5d1771e2034c306ea8b60f5;p=osm%2FRO.git diff --git a/NG-RO/osm_ng_ro/ns.py b/NG-RO/osm_ng_ro/ns.py index 096d4dfd..19ff791a 100644 --- a/NG-RO/osm_ng_ro/ns.py +++ b/NG-RO/osm_ng_ro/ns.py @@ -23,7 +23,7 @@ from random import choice as random_choice from threading import Lock from time import time from traceback import format_exc as traceback_format_exc -from typing import Any, Dict, Tuple, Type +from typing import Any, Dict, List, Optional, Tuple, Type from uuid import uuid4 from cryptography.hazmat.backends import default_backend as crypto_default_backend @@ -31,6 +31,7 @@ from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa from jinja2 import ( Environment, + select_autoescape, StrictUndefined, TemplateError, TemplateNotFound, @@ -77,8 +78,8 @@ def get_process_id(): if text_id: return text_id - except Exception: - pass + except Exception as error: + logging.exception(f"{error} occured while getting process id") # Return a random id return "".join(random_choice("0123456789abcdef") for _ in range(12)) @@ -380,7 +381,10 @@ class Ns(object): str: [description] """ try: - env = Environment(undefined=StrictUndefined) + env = Environment( + undefined=StrictUndefined, + autoescape=select_autoescape(default_for_string=True, default=True), + ) template = env.from_string(cloud_init_content) return template.render(params or {}) @@ -643,44 +647,57 @@ class Ns(object): Tuple[Dict[str, Any], bool]: [description] """ numa = {} + numa_list = [] epa_vcpu_set = False if guest_epa_quota.get("numa-node-policy"): numa_node_policy = guest_epa_quota.get("numa-node-policy") if numa_node_policy.get("node"): - numa_node = numa_node_policy["node"][0] - - if numa_node.get("num-cores"): - numa["cores"] = numa_node["num-cores"] - epa_vcpu_set = True - - paired_threads = numa_node.get("paired-threads", {}) - if paired_threads.get("num-paired-threads"): - numa["paired-threads"] = int( - numa_node["paired-threads"]["num-paired-threads"] - ) - epa_vcpu_set = True + for numa_node in numa_node_policy["node"]: + vcpu_list = [] + if numa_node.get("id"): + numa["id"] = int(numa_node["id"]) + + if numa_node.get("vcpu"): + for vcpu in numa_node.get("vcpu"): + vcpu_id = int(vcpu.get("id")) + vcpu_list.append(vcpu_id) + numa["vcpu"] = vcpu_list + + if numa_node.get("num-cores"): + numa["cores"] = numa_node["num-cores"] + epa_vcpu_set = True + + paired_threads = numa_node.get("paired-threads", {}) + if paired_threads.get("num-paired-threads"): + numa["paired_threads"] = int( + numa_node["paired-threads"]["num-paired-threads"] + ) + epa_vcpu_set = True - if paired_threads.get("paired-thread-ids"): - numa["paired-threads-id"] = [] + if paired_threads.get("paired-thread-ids"): + numa["paired-threads-id"] = [] - for pair in paired_threads["paired-thread-ids"]: - numa["paired-threads-id"].append( - ( - str(pair["thread-a"]), - str(pair["thread-b"]), + for pair in paired_threads["paired-thread-ids"]: + numa["paired-threads-id"].append( + ( + str(pair["thread-a"]), + str(pair["thread-b"]), + ) ) - ) - if numa_node.get("num-threads"): - numa["threads"] = int(numa_node["num-threads"]) - epa_vcpu_set = True + if numa_node.get("num-threads"): + numa["threads"] = int(numa_node["num-threads"]) + epa_vcpu_set = True - if numa_node.get("memory-mb"): - numa["memory"] = max(int(int(numa_node["memory-mb"]) / 1024), 1) + if numa_node.get("memory-mb"): + numa["memory"] = max(int(int(numa_node["memory-mb"]) / 1024), 1) - return numa, epa_vcpu_set + numa_list.append(numa) + numa = {} + + return numa_list, epa_vcpu_set @staticmethod def _process_guest_epa_cpu_pinning_params( @@ -728,23 +745,39 @@ class Ns(object): """ extended = {} numa = {} + numa_list = [] if target_flavor.get("guest-epa"): guest_epa = target_flavor["guest-epa"] - numa, epa_vcpu_set = Ns._process_guest_epa_numa_params( + numa_list, epa_vcpu_set = Ns._process_guest_epa_numa_params( guest_epa_quota=guest_epa ) if guest_epa.get("mempage-size"): extended["mempage-size"] = guest_epa.get("mempage-size") + if guest_epa.get("cpu-pinning-policy"): + extended["cpu-pinning-policy"] = guest_epa.get("cpu-pinning-policy") + + if guest_epa.get("cpu-thread-pinning-policy"): + extended["cpu-thread-pinning-policy"] = guest_epa.get( + "cpu-thread-pinning-policy" + ) + + if guest_epa.get("numa-node-policy"): + if guest_epa.get("numa-node-policy").get("mem-policy"): + extended["mem-policy"] = guest_epa.get("numa-node-policy").get( + "mem-policy" + ) + tmp_numa, epa_vcpu_set = Ns._process_guest_epa_cpu_pinning_params( guest_epa_quota=guest_epa, vcpu_count=int(target_flavor.get("vcpu-count", 1)), epa_vcpu_set=epa_vcpu_set, ) - numa.update(tmp_numa) + for numa in numa_list: + numa.update(tmp_numa) extended.update( Ns._process_guest_epa_quota_params( @@ -754,7 +787,7 @@ class Ns(object): ) if numa: - extended["numas"] = [numa] + extended["numas"] = numa_list return extended @@ -916,7 +949,7 @@ class Ns(object): "id": vim_info.get("vim_network_id"), }, } - elif target_vld.get("mgmt-network"): + elif target_vld.get("mgmt-network") and not vim_info.get("provider_network"): extra_dict["find_params"] = { "mgmt": True, "name": target_vld["id"], @@ -943,24 +976,25 @@ class Ns(object): @staticmethod def find_persistent_root_volumes( vnfd: dict, - target_vdu: str, + target_vdu: dict, vdu_instantiation_volumes_list: list, disk_list: list, - ) -> (list, dict): + ) -> Dict[str, any]: """Find the persistent root volumes and add them to the disk_list - by parsing the instantiation parameters + by parsing the instantiation parameters. Args: - vnfd: VNFD - target_vdu: processed VDU - vdu_instantiation_volumes_list: instantiation parameters for the each VDU as a list - disk_list: to be filled up + vnfd (dict): VNF descriptor + target_vdu (dict): processed VDU + vdu_instantiation_volumes_list (list): instantiation parameters for the each VDU as a list + disk_list (list): to be filled up Returns: - disk_list: filled VDU list which is used for VDU creation + persistent_root_disk (dict): Details of persistent root disk """ persistent_root_disk = {} + # There can be only one root disk, when we find it, it will return the result for vdu, vsd in product( vnfd.get("vdu", ()), vnfd.get("virtual-storage-desc", ()) @@ -988,8 +1022,7 @@ class Ns(object): disk_list.append(persistent_root_disk[vsd["id"]]) - # There can be only one root disk, when we find it, it will return the result - return disk_list, persistent_root_disk + return persistent_root_disk else: @@ -997,22 +1030,22 @@ class Ns(object): persistent_root_disk[vsd["id"]] = { "image_id": vdu.get("sw-image-desc"), "size": root_disk.get("size-of-storage"), + "keep": Ns.is_volume_keeping_required(root_disk), } disk_list.append(persistent_root_disk[vsd["id"]]) - return disk_list, persistent_root_disk - return disk_list, persistent_root_disk + return persistent_root_disk @staticmethod def find_persistent_volumes( persistent_root_disk: dict, - target_vdu: str, + target_vdu: dict, vdu_instantiation_volumes_list: list, disk_list: list, - ) -> list: + ) -> None: """Find the ordinary persistent volumes and add them to the disk_list - by parsing the instantiation parameters + by parsing the instantiation parameters. Args: persistent_root_disk: persistent root disk dictionary @@ -1020,9 +1053,6 @@ class Ns(object): vdu_instantiation_volumes_list: instantiation parameters for the each VDU as a list disk_list: to be filled up - Returns: - disk_list: filled VDU list which is used for VDU creation - """ # Find the ordinary volumes which are not added to the persistent_root_disk persistent_disk = {} @@ -1044,145 +1074,277 @@ class Ns(object): if disk["id"] not in persistent_disk.keys(): persistent_disk[disk["id"]] = { "size": disk.get("size-of-storage"), + "keep": Ns.is_volume_keeping_required(disk), } disk_list.append(persistent_disk[disk["id"]]) - return disk_list - @staticmethod - def _process_vdu_params( - target_vdu: Dict[str, Any], - indata: Dict[str, Any], - vim_info: Dict[str, Any], - target_record_id: str, - **kwargs: Dict[str, Any], - ) -> Dict[str, Any]: - """Function to process VDU parameters. + def is_volume_keeping_required(virtual_storage_desc: Dict[str, Any]) -> bool: + """Function to decide keeping persistent volume + upon VDU deletion. Args: - target_vdu (Dict[str, Any]): [description] - indata (Dict[str, Any]): [description] - vim_info (Dict[str, Any]): [description] - target_record_id (str): [description] + virtual_storage_desc (Dict[str, Any]): virtual storage description dictionary Returns: - Dict[str, Any]: [description] + bool (True/False) """ - vnfr_id = kwargs.get("vnfr_id") - nsr_id = kwargs.get("nsr_id") - vnfr = kwargs.get("vnfr") - vdu2cloud_init = kwargs.get("vdu2cloud_init") - tasks_by_target_record_id = kwargs.get("tasks_by_target_record_id") - logger = kwargs.get("logger") - db = kwargs.get("db") - fs = kwargs.get("fs") - ro_nsr_public_key = kwargs.get("ro_nsr_public_key") - vnf_preffix = "vnfrs:{}".format(vnfr_id) - ns_preffix = "nsrs:{}".format(nsr_id) - image_text = ns_preffix + ":image." + target_vdu["ns-image-id"] - flavor_text = ns_preffix + ":flavor." + target_vdu["ns-flavor-id"] - extra_dict = {"depends_on": [image_text, flavor_text]} - net_list = [] + if not virtual_storage_desc.get("vdu-storage-requirements"): + return False + for item in virtual_storage_desc.get("vdu-storage-requirements", {}): + if item.get("key") == "keep-volume" and item.get("value") == "true": + return True + return False + + @staticmethod + def _sort_vdu_interfaces(target_vdu: dict) -> None: + """Sort the interfaces according to position number. + + Args: + target_vdu (dict): Details of VDU to be created + """ # If the position info is provided for all the interfaces, it will be sorted # according to position number ascendingly. - if all(i.get("position") for i in target_vdu["interfaces"]): - sorted_interfaces = sorted( - target_vdu["interfaces"], - key=lambda x: (x.get("position") is None, x.get("position")), - ) - target_vdu["interfaces"] = sorted_interfaces + sorted_interfaces = sorted( + target_vdu["interfaces"], + key=lambda x: (x.get("position") is None, x.get("position")), + ) + target_vdu["interfaces"] = sorted_interfaces + + @staticmethod + def _partially_locate_vdu_interfaces(target_vdu: dict) -> None: + """Only place the interfaces which has specific position. + + Args: + target_vdu (dict): Details of VDU to be created + """ # If the position info is provided for some interfaces but not all of them, the interfaces # which has specific position numbers will be placed and others' positions will not be taken care. - else: - if any(i.get("position") for i in target_vdu["interfaces"]): - n = len(target_vdu["interfaces"]) - sorted_interfaces = [-1] * n - k, m = 0, 0 - while k < n: - if target_vdu["interfaces"][k].get("position"): + if any( + i.get("position") + 1 + for i in target_vdu["interfaces"] + if i.get("position") is not None + ): + n = len(target_vdu["interfaces"]) + sorted_interfaces = [-1] * n + k, m = 0, 0 + + while k < n: + if target_vdu["interfaces"][k].get("position") is not None: + if any(i.get("position") == 0 for i in target_vdu["interfaces"]): + idx = target_vdu["interfaces"][k]["position"] + 1 + else: idx = target_vdu["interfaces"][k]["position"] - sorted_interfaces[idx - 1] = target_vdu["interfaces"][k] - k += 1 - while m < n: - if not target_vdu["interfaces"][m].get("position"): - idy = sorted_interfaces.index(-1) - sorted_interfaces[idy] = target_vdu["interfaces"][m] - m += 1 + sorted_interfaces[idx - 1] = target_vdu["interfaces"][k] + k += 1 - target_vdu["interfaces"] = sorted_interfaces + while m < n: + if target_vdu["interfaces"][m].get("position") is None: + idy = sorted_interfaces.index(-1) + sorted_interfaces[idy] = target_vdu["interfaces"][m] + m += 1 - # If the position info is not provided for the interfaces, interfaces will be attached - # according to the order in the VNFD. + target_vdu["interfaces"] = sorted_interfaces + + @staticmethod + def _prepare_vdu_cloud_init( + target_vdu: dict, vdu2cloud_init: dict, db: object, fs: object + ) -> Dict: + """Fill cloud_config dict with cloud init details. + + Args: + target_vdu (dict): Details of VDU to be created + vdu2cloud_init (dict): Cloud init dict + db (object): DB object + fs (object): FS object + + Returns: + cloud_config (dict): Cloud config details of VDU + + """ + # cloud config + cloud_config = {} + + if target_vdu.get("cloud-init"): + if target_vdu["cloud-init"] not in vdu2cloud_init: + vdu2cloud_init[target_vdu["cloud-init"]] = Ns._get_cloud_init( + db=db, + fs=fs, + location=target_vdu["cloud-init"], + ) + + cloud_content_ = vdu2cloud_init[target_vdu["cloud-init"]] + cloud_config["user-data"] = Ns._parse_jinja2( + cloud_init_content=cloud_content_, + params=target_vdu.get("additionalParams"), + context=target_vdu["cloud-init"], + ) + + if target_vdu.get("boot-data-drive"): + cloud_config["boot-data-drive"] = target_vdu.get("boot-data-drive") + + return cloud_config + + @staticmethod + def _check_vld_information_of_interfaces( + interface: dict, ns_preffix: str, vnf_preffix: str + ) -> Optional[str]: + """Prepare the net_text by the virtual link information for vnf and ns level. + Args: + interface (dict): Interface details + ns_preffix (str): Prefix of NS + vnf_preffix (str): Prefix of VNF + + Returns: + net_text (str): information of net + + """ + net_text = "" + if interface.get("ns-vld-id"): + net_text = ns_preffix + ":vld." + interface["ns-vld-id"] + elif interface.get("vnf-vld-id"): + net_text = vnf_preffix + ":vld." + interface["vnf-vld-id"] + + return net_text + + @staticmethod + def _prepare_interface_port_security(interface: dict) -> None: + """ + + Args: + interface (dict): Interface details + + """ + if "port-security-enabled" in interface: + interface["port_security"] = interface.pop("port-security-enabled") + + if "port-security-disable-strategy" in interface: + interface["port_security_disable_strategy"] = interface.pop( + "port-security-disable-strategy" + ) + + @staticmethod + def _create_net_item_of_interface(interface: dict, net_text: str) -> dict: + """Prepare net item including name, port security, floating ip etc. + + Args: + interface (dict): Interface details + net_text (str): information of net + + Returns: + net_item (dict): Dict including net details + + """ + + net_item = { + x: v + for x, v in interface.items() + if x + in ( + "name", + "vpci", + "port_security", + "port_security_disable_strategy", + "floating_ip", + ) + } + net_item["net_id"] = "TASK-" + net_text + net_item["type"] = "virtual" + + return net_item + + @staticmethod + def _prepare_type_of_interface( + interface: dict, tasks_by_target_record_id: dict, net_text: str, net_item: dict + ) -> None: + """Fill the net item type by interface type such as SR-IOV, OM-MGMT, bridge etc. + + Args: + interface (dict): Interface details + tasks_by_target_record_id (dict): Task details + net_text (str): information of net + net_item (dict): Dict including net details + + """ + # TODO mac_address: used for SR-IOV ifaces #TODO for other types + # TODO floating_ip: True/False (or it can be None) + + if interface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH"): + # Mark the net create task as type data + if deep_get( + tasks_by_target_record_id, + net_text, + "extra_dict", + "params", + "net_type", + ): + tasks_by_target_record_id[net_text]["extra_dict"]["params"][ + "net_type" + ] = "data" + + net_item["use"] = "data" + net_item["model"] = interface["type"] + net_item["type"] = interface["type"] + + elif ( + interface.get("type") == "OM-MGMT" + or interface.get("mgmt-interface") + or interface.get("mgmt-vnf") + ): + net_item["use"] = "mgmt" + + else: + # If interface.get("type") in ("VIRTIO", "E1000", "PARAVIRT"): + net_item["use"] = "bridge" + net_item["model"] = interface.get("type") + + @staticmethod + def _prepare_vdu_interfaces( + target_vdu: dict, + extra_dict: dict, + ns_preffix: str, + vnf_preffix: str, + logger: object, + tasks_by_target_record_id: dict, + net_list: list, + ) -> None: + """Prepare the net_item and add net_list, add mgmt interface to extra_dict. + + Args: + target_vdu (dict): VDU to be created + extra_dict (dict): Dictionary to be filled + ns_preffix (str): NS prefix as string + vnf_preffix (str): VNF prefix as string + logger (object): Logger Object + tasks_by_target_record_id (dict): Task details + net_list (list): Net list of VDU + """ for iface_index, interface in enumerate(target_vdu["interfaces"]): - if interface.get("ns-vld-id"): - net_text = ns_preffix + ":vld." + interface["ns-vld-id"] - elif interface.get("vnf-vld-id"): - net_text = vnf_preffix + ":vld." + interface["vnf-vld-id"] - else: + + net_text = Ns._check_vld_information_of_interfaces( + interface, ns_preffix, vnf_preffix + ) + if not net_text: + # Interface not connected to any vld logger.error( "Interface {} from vdu {} not connected to any vld".format( iface_index, target_vdu["vdu-name"] ) ) - - continue # interface not connected to any vld + continue extra_dict["depends_on"].append(net_text) - if "port-security-enabled" in interface: - interface["port_security"] = interface.pop("port-security-enabled") + Ns._prepare_interface_port_security(interface) - if "port-security-disable-strategy" in interface: - interface["port_security_disable_strategy"] = interface.pop( - "port-security-disable-strategy" - ) - - net_item = { - x: v - for x, v in interface.items() - if x - in ( - "name", - "vpci", - "port_security", - "port_security_disable_strategy", - "floating_ip", - ) - } - net_item["net_id"] = "TASK-" + net_text - net_item["type"] = "virtual" - - # TODO mac_address: used for SR-IOV ifaces #TODO for other types - # TODO floating_ip: True/False (or it can be None) - if interface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH"): - # mark the net create task as type data - if deep_get( - tasks_by_target_record_id, - net_text, - "extra_dict", - "params", - "net_type", - ): - tasks_by_target_record_id[net_text]["extra_dict"]["params"][ - "net_type" - ] = "data" + net_item = Ns._create_net_item_of_interface(interface, net_text) - net_item["use"] = "data" - net_item["model"] = interface["type"] - net_item["type"] = interface["type"] - elif ( - interface.get("type") == "OM-MGMT" - or interface.get("mgmt-interface") - or interface.get("mgmt-vnf") - ): - net_item["use"] = "mgmt" - else: - # if interface.get("type") in ("VIRTIO", "E1000", "PARAVIRT"): - net_item["use"] = "bridge" - net_item["model"] = interface.get("type") + Ns._prepare_type_of_interface( + interface, tasks_by_target_record_id, net_text, net_item + ) if interface.get("ip-address"): net_item["ip_address"] = interface["ip-address"] @@ -1197,27 +1359,18 @@ class Ns(object): elif interface.get("mgmt-interface"): extra_dict["mgmt_vdu_interface"] = iface_index - # cloud config - cloud_config = {} - - if target_vdu.get("cloud-init"): - if target_vdu["cloud-init"] not in vdu2cloud_init: - vdu2cloud_init[target_vdu["cloud-init"]] = Ns._get_cloud_init( - db=db, - fs=fs, - location=target_vdu["cloud-init"], - ) - - cloud_content_ = vdu2cloud_init[target_vdu["cloud-init"]] - cloud_config["user-data"] = Ns._parse_jinja2( - cloud_init_content=cloud_content_, - params=target_vdu.get("additionalParams"), - context=target_vdu["cloud-init"], - ) + @staticmethod + def _prepare_vdu_ssh_keys( + target_vdu: dict, ro_nsr_public_key: dict, cloud_config: dict + ) -> None: + """Add ssh keys to cloud config. - if target_vdu.get("boot-data-drive"): - cloud_config["boot-data-drive"] = target_vdu.get("boot-data-drive") + Args: + target_vdu (dict): Details of VDU to be created + ro_nsr_public_key (dict): RO NSR public Key + cloud_config (dict): Cloud config details + """ ssh_keys = [] if target_vdu.get("ssh-keys"): @@ -1229,12 +1382,193 @@ class Ns(object): if ssh_keys: cloud_config["key-pairs"] = ssh_keys + @staticmethod + def _select_persistent_root_disk(vsd: dict, vdu: dict) -> dict: + """Selects the persistent root disk if exists. + Args: + vsd (dict): Virtual storage descriptors in VNFD + vdu (dict): VNF descriptor + + Returns: + root_disk (dict): Selected persistent root disk + """ + if vsd.get("id") == vdu.get("virtual-storage-desc", [[]])[0]: + root_disk = vsd + if root_disk.get( + "type-of-storage" + ) == "persistent-storage:persistent-storage" and root_disk.get( + "size-of-storage" + ): + return root_disk + + @staticmethod + def _add_persistent_root_disk_to_disk_list( + vnfd: dict, target_vdu: dict, persistent_root_disk: dict, disk_list: list + ) -> None: + """Find the persistent root disk and add to disk list. + + Args: + vnfd (dict): VNF descriptor + target_vdu (dict): Details of VDU to be created + persistent_root_disk (dict): Details of persistent root disk + disk_list (list): Disks of VDU + + """ + for vdu in vnfd.get("vdu", ()): + if vdu["name"] == target_vdu["vdu-name"]: + for vsd in vnfd.get("virtual-storage-desc", ()): + root_disk = Ns._select_persistent_root_disk(vsd, vdu) + if not root_disk: + continue + + persistent_root_disk[vsd["id"]] = { + "image_id": vdu.get("sw-image-desc"), + "size": root_disk["size-of-storage"], + "keep": Ns.is_volume_keeping_required(root_disk), + } + + disk_list.append(persistent_root_disk[vsd["id"]]) + break + + @staticmethod + def _add_persistent_ordinary_disks_to_disk_list( + target_vdu: dict, + persistent_root_disk: dict, + persistent_ordinary_disk: dict, + disk_list: list, + ) -> None: + """Fill the disk list by adding persistent ordinary disks. + + Args: + target_vdu (dict): Details of VDU to be created + persistent_root_disk (dict): Details of persistent root disk + persistent_ordinary_disk (dict): Details of persistent ordinary disk + disk_list (list): Disks of VDU + + """ + if target_vdu.get("virtual-storages"): + for disk in target_vdu["virtual-storages"]: + if ( + disk.get("type-of-storage") + == "persistent-storage:persistent-storage" + and disk["id"] not in persistent_root_disk.keys() + ): + persistent_ordinary_disk[disk["id"]] = { + "size": disk["size-of-storage"], + "keep": Ns.is_volume_keeping_required(disk), + } + disk_list.append(persistent_ordinary_disk[disk["id"]]) + + @staticmethod + def _prepare_vdu_affinity_group_list( + target_vdu: dict, extra_dict: dict, ns_preffix: str + ) -> List[Dict[str, any]]: + """Process affinity group details to prepare affinity group list. + + Args: + target_vdu (dict): Details of VDU to be created + extra_dict (dict): Dictionary to be filled + ns_preffix (str): Prefix as string + + Returns: + + affinity_group_list (list): Affinity group details + + """ + affinity_group_list = [] + + if target_vdu.get("affinity-or-anti-affinity-group-id"): + for affinity_group_id in target_vdu["affinity-or-anti-affinity-group-id"]: + affinity_group = {} + affinity_group_text = ( + ns_preffix + ":affinity-or-anti-affinity-group." + affinity_group_id + ) + + if not isinstance(extra_dict.get("depends_on"), list): + raise NsException("Invalid extra_dict format.") + + extra_dict["depends_on"].append(affinity_group_text) + affinity_group["affinity_group_id"] = "TASK-" + affinity_group_text + affinity_group_list.append(affinity_group) + + return affinity_group_list + + @staticmethod + def _process_vdu_params( + target_vdu: Dict[str, Any], + indata: Dict[str, Any], + vim_info: Dict[str, Any], + target_record_id: str, + **kwargs: Dict[str, Any], + ) -> Dict[str, Any]: + """Function to process VDU parameters. + + Args: + target_vdu (Dict[str, Any]): [description] + indata (Dict[str, Any]): [description] + vim_info (Dict[str, Any]): [description] + target_record_id (str): [description] + + Returns: + Dict[str, Any]: [description] + """ + vnfr_id = kwargs.get("vnfr_id") + nsr_id = kwargs.get("nsr_id") + vnfr = kwargs.get("vnfr") + vdu2cloud_init = kwargs.get("vdu2cloud_init") + tasks_by_target_record_id = kwargs.get("tasks_by_target_record_id") + logger = kwargs.get("logger") + db = kwargs.get("db") + fs = kwargs.get("fs") + ro_nsr_public_key = kwargs.get("ro_nsr_public_key") + + vnf_preffix = "vnfrs:{}".format(vnfr_id) + ns_preffix = "nsrs:{}".format(nsr_id) + image_text = ns_preffix + ":image." + target_vdu["ns-image-id"] + flavor_text = ns_preffix + ":flavor." + target_vdu["ns-flavor-id"] + extra_dict = {"depends_on": [image_text, flavor_text]} + net_list = [] + persistent_root_disk = {} + persistent_ordinary_disk = {} vdu_instantiation_volumes_list = [] disk_list = [] vnfd_id = vnfr["vnfd-id"] vnfd = db.get_one("vnfds", {"_id": vnfd_id}) + # If the position info is provided for all the interfaces, it will be sorted + # according to position number ascendingly. + if all( + True if i.get("position") is not None else False + for i in target_vdu["interfaces"] + ): + + Ns._sort_vdu_interfaces(target_vdu) + + # If the position info is provided for some interfaces but not all of them, the interfaces + # which has specific position numbers will be placed and others' positions will not be taken care. + else: + + Ns._partially_locate_vdu_interfaces(target_vdu) + + # If the position info is not provided for the interfaces, interfaces will be attached + # according to the order in the VNFD. + Ns._prepare_vdu_interfaces( + target_vdu, + extra_dict, + ns_preffix, + vnf_preffix, + logger, + tasks_by_target_record_id, + net_list, + ) + + # cloud config + cloud_config = Ns._prepare_vdu_cloud_init(target_vdu, vdu2cloud_init, db, fs) + + # Prepare VDU ssh keys + Ns._prepare_vdu_ssh_keys(target_vdu, ro_nsr_public_key, cloud_config) + if target_vdu.get("additionalParams"): vdu_instantiation_volumes_list = ( target_vdu.get("additionalParams").get("OSM").get("vdu_volumes") @@ -1243,13 +1577,13 @@ class Ns(object): if vdu_instantiation_volumes_list: # Find the root volumes and add to the disk_list - (disk_list, persistent_root_disk,) = Ns.find_persistent_root_volumes( + persistent_root_disk = Ns.find_persistent_root_volumes( vnfd, target_vdu, vdu_instantiation_volumes_list, disk_list ) # Find the ordinary volumes which are not added to the persistent_root_disk # and put them to the disk list - disk_list = Ns.find_persistent_volumes( + Ns.find_persistent_volumes( persistent_root_disk, target_vdu, vdu_instantiation_volumes_list, @@ -1257,45 +1591,19 @@ class Ns(object): ) else: + # Vdu_instantiation_volumes_list is empty + # First get add the persistent root disks to disk_list + Ns._add_persistent_root_disk_to_disk_list( + vnfd, target_vdu, persistent_root_disk, disk_list + ) + # Add the persistent non-root disks to disk_list + Ns._add_persistent_ordinary_disks_to_disk_list( + target_vdu, persistent_root_disk, persistent_ordinary_disk, disk_list + ) - # vdu_instantiation_volumes_list is empty - for vdu in vnfd.get("vdu", ()): - if vdu["name"] == target_vdu["vdu-name"]: - for vsd in vnfd.get("virtual-storage-desc", ()): - if vsd.get("id") == vdu.get("virtual-storage-desc", [[]])[0]: - root_disk = vsd - if root_disk.get( - "type-of-storage" - ) == "persistent-storage:persistent-storage" and root_disk.get( - "size-of-storage" - ): - persistent_root_disk[vsd["id"]] = { - "image_id": vdu.get("sw-image-desc"), - "size": root_disk["size-of-storage"], - } - disk_list.append(persistent_root_disk[vsd["id"]]) - - if target_vdu.get("virtual-storages"): - for disk in target_vdu["virtual-storages"]: - if ( - disk.get("type-of-storage") - == "persistent-storage:persistent-storage" - and disk["id"] not in persistent_root_disk.keys() - ): - disk_list.append({"size": disk["size-of-storage"]}) - - affinity_group_list = [] - - if target_vdu.get("affinity-or-anti-affinity-group-id"): - affinity_group = {} - for affinity_group_id in target_vdu["affinity-or-anti-affinity-group-id"]: - affinity_group_text = ( - ns_preffix + ":affinity-or-anti-affinity-group." + affinity_group_id - ) - - extra_dict["depends_on"].append(affinity_group_text) - affinity_group["affinity_group_id"] = "TASK-" + affinity_group_text - affinity_group_list.append(affinity_group) + affinity_group_list = Ns._prepare_vdu_affinity_group_list( + target_vdu, extra_dict, ns_preffix + ) extra_dict["params"] = { "name": "{}-{}-{}-{}".format( @@ -1641,7 +1949,7 @@ class Ns(object): target_record_id = "{}.{}".format(db_record, existing_item["id"]) item_ = item - if target_vim.startswith("sdn"): + if target_vim.startswith("sdn") or target_vim.startswith("wim"): # item must be sdn-net instead of net if target_vim is a sdn item_ = "sdn_net" target_record_id += ".sdn" @@ -1689,13 +1997,13 @@ class Ns(object): target_record_id = "{}.{}".format(db_record, target_item["id"]) item_ = item - if target_vim.startswith("sdn"): + if target_vim.startswith("sdn") or target_vim.startswith("wim"): # item must be sdn-net instead of net if target_vim is a sdn item_ = "sdn_net" target_record_id += ".sdn" kwargs = {} - self.logger.warning( + self.logger.debug( "ns.calculate_diff_items target_item={}".format(target_item) ) if process_params == Ns._process_flavor_params: @@ -1704,14 +2012,12 @@ class Ns(object): "db": self.db, } ) - self.logger.warning( + self.logger.debug( "calculate_diff_items for flavor kwargs={}".format(kwargs) ) if process_params == Ns._process_vdu_params: - self.logger.warning( - "calculate_diff_items self.fs={}".format(self.fs) - ) + self.logger.debug("calculate_diff_items self.fs={}".format(self.fs)) kwargs.update( { "vnfr_id": vnfr_id, @@ -1725,7 +2031,7 @@ class Ns(object): "ro_nsr_public_key": ro_nsr_public_key, } ) - self.logger.warning("calculate_diff_items kwargs={}".format(kwargs)) + self.logger.debug("calculate_diff_items kwargs={}".format(kwargs)) extra_dict = process_params( target_item, @@ -1863,7 +2169,7 @@ class Ns(object): extra_dict=change.get("extra_dict", None), ) - self.logger.warning("ns.define_all_tasks task={}".format(task)) + self.logger.debug("ns.define_all_tasks task={}".format(task)) tasks_by_target_record_id[change["target_record_id"]] = task db_new_tasks.append(task) @@ -1947,7 +2253,7 @@ class Ns(object): for db_task in db_new_tasks: target_id = db_task.pop("target_id") - self.logger.warning("target_id={} db_task={}".format(target_id, db_task)) + self.logger.debug("target_id={} db_task={}".format(target_id, db_task)) action = db_task.get("action", None) @@ -1968,7 +2274,7 @@ class Ns(object): db_ro_task["vim_info"]["vim_id"] = db_task.get("vim_id", None) nb_ro_tasks += 1 - self.logger.warning("upload_all_tasks db_ro_task={}".format(db_ro_task)) + self.logger.debug("upload_all_tasks db_ro_task={}".format(db_ro_task)) self.db.create("ro_tasks", db_ro_task) self.logger.debug(