From: David Garcia Date: Thu, 28 Oct 2021 00:00:43 +0000 (+0200) Subject: Feature 10887: Add cross-model relations support X-Git-Tag: release-v11.0-start^0 X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FLCM.git;a=commitdiff_plain;h=b4ebcd0dd81e08d7294156c2aca10d84ca9bb824 Feature 10887: Add cross-model relations support Changes: - Update the `osm_lcm.ns.NsLcm._add_vca_relations` function, and decouple it into simpler and smaller functions. - Get relation data for the descriptor taking into account the changes introduced here: https://osm.etsi.org/gerrit/11212/ - Add `osm_lcm.data_utils.vca` module to take care of VCA related parts in the IM - Add a couple of functions into the `osm_lcm.data_utils` package: - nsd: get_vnf_profile(), get_ns_configuration(), get_ns_configuration_relation_list() - nsr: get_nsd(), get_deployed_vca_list(), get_deployed_vca() - vnfd: get_relation_list() - Rename `osm_lcm.data_utils.vnfd.get_kdu_profile` to `osm_lcm.data_utils.vnfd.get_kdu_resource_profile` Change-Id: I6da29e656d092e17c85b44f5b3960a6ca3aa3ad8 Signed-off-by: David Garcia --- diff --git a/osm_lcm/data_utils/nsd.py b/osm_lcm/data_utils/nsd.py index 2917c04..9b6fb81 100644 --- a/osm_lcm/data_utils/nsd.py +++ b/osm_lcm/data_utils/nsd.py @@ -23,11 +23,20 @@ ## import ast +from osm_lcm.data_utils.list_utils import find_in_list + def get_vnf_profiles(nsd): return nsd.get("df")[0].get("vnf-profile", ()) +def get_vnf_profile(nsd, vnf_profile_id): + return find_in_list( + get_vnf_profiles(nsd), + lambda vnf_profile: vnf_profile["id"] == vnf_profile_id, + ) + + def get_virtual_link_profiles(nsd): return nsd.get("df")[0].get("virtual-link-profile", ()) @@ -36,3 +45,11 @@ def replace_vnf_id(nsd, old_vnf_id, new_vnf_id): dict_str = str(nsd) dict_str.replace(old_vnf_id, new_vnf_id) return ast.literal_eval(dict_str) + + +def get_ns_configuration(nsd): + return nsd.get("ns-configuration", {}) + + +def get_ns_configuration_relation_list(nsd): + return get_ns_configuration(nsd).get("relation", []) diff --git a/osm_lcm/data_utils/nsr.py b/osm_lcm/data_utils/nsr.py index 006713c..f2fccb6 100644 --- a/osm_lcm/data_utils/nsr.py +++ b/osm_lcm/data_utils/nsr.py @@ -22,6 +22,7 @@ # contact: fbravo@whitestack.com ## +from osm_lcm.data_utils import list_utils from osm_lcm.lcm_utils import get_iterable @@ -39,3 +40,18 @@ def get_deployed_kdu(nsr_deployed, kdu_name, member_vnf_index): ): break return deployed_kdu, index + + +def get_nsd(nsr): + return nsr.get("nsd", {}) + + +def get_deployed_vca_list(nsr): + return nsr.get("_admin", ()).get("deployed", ()).get("VCA", []) + + +def get_deployed_vca(nsr, filter): + return list_utils.find_in_list( + get_deployed_vca_list(nsr), + lambda vca: all(vca[key] == value for key, value in filter.items()), + ) diff --git a/osm_lcm/data_utils/vca.py b/osm_lcm/data_utils/vca.py new file mode 100644 index 0000000..2116549 --- /dev/null +++ b/osm_lcm/data_utils/vca.py @@ -0,0 +1,222 @@ +# Copyright 2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any, Dict, NoReturn + + +def safe_get_ee_relation( + nsr_id: str, ee_relation: Dict[str, Any], vnf_profile_id: str = None +) -> Dict[str, Any]: + return { + "nsr-id": nsr_id, + "vnf-profile-id": ee_relation.get("vnf-profile-id") or vnf_profile_id, + "vdu-profile-id": ee_relation.get("vdu-profile-id"), + "kdu-resource-profile-id": ee_relation.get("kdu-resource-profile-id"), + "execution-environment-ref": ee_relation.get("execution-environment-ref"), + "endpoint": ee_relation["endpoint"], + } + + +class EELevel: + VDU = "vdu" + VNF = "vnf" + KDU = "kdu" + NS = "ns" + + @staticmethod + def get_level(ee_relation: dict): + """Get the execution environment level""" + level = None + if ( + not ee_relation["vnf-profile-id"] + and not ee_relation["vdu-profile-id"] + and not ee_relation["kdu-resource-profile-id"] + ): + level = EELevel.NS + elif ( + ee_relation["vnf-profile-id"] + and not ee_relation["vdu-profile-id"] + and not ee_relation["kdu-resource-profile-id"] + ): + level = EELevel.VNF + elif ( + ee_relation["vnf-profile-id"] + and ee_relation["vdu-profile-id"] + and not ee_relation["kdu-resource-profile-id"] + ): + level = EELevel.VDU + elif ( + ee_relation["vnf-profile-id"] + and not ee_relation["vdu-profile-id"] + and ee_relation["kdu-resource-profile-id"] + ): + level = EELevel.KDU + else: + raise Exception("invalid relation endpoint") + return level + + +class EERelation(dict): + """Represents the execution environment of a relation""" + + def __init__( + self, + relation_ee: Dict[str, Any], + ) -> NoReturn: + """ + Args: + relation_ee: Relation Endpoint object in the VNFd or NSd. + Example: + { + "nsr-id": <>, + "vdu-profile-id": <>, + "kdu-resource-profile-id": <>, + "vnf-profile-id": <>, + "execution-environment-ref": <>, + "endpoint": <>, + } + """ + for key, value in relation_ee.items(): + self.__setitem__(key, value) + + @property + def vdu_profile_id(self): + """Returns the vdu-profile id""" + return self["vdu-profile-id"] + + @property + def kdu_resource_profile_id(self): + """Returns the kdu-resource-profile id""" + return self["kdu-resource-profile-id"] + + @property + def vnf_profile_id(self): + """Returns the vnf-profile id""" + return self["vnf-profile-id"] + + @property + def execution_environment_ref(self): + """Returns the reference to the execution environment (id)""" + return self["execution-environment-ref"] + + @property + def endpoint(self): + """Returns the endpoint of the execution environment""" + return self["endpoint"] + + @property + def nsr_id(self) -> str: + """Returns the nsr id""" + return self["nsr-id"] + + +class Relation(dict): + """Represents a relation""" + def __init__(self, name, provider: EERelation, requirer: EERelation) -> NoReturn: + """ + Args: + name: Name of the relation. + provider: Execution environment that provides the service for the relation. + requirer: Execution environment that requires the service from the provider. + """ + self.__setitem__("name", name) + self.__setitem__("provider", provider) + self.__setitem__("requirer", requirer) + + @property + def name(self) -> str: + """Returns the name of the relation""" + return self["name"] + + @property + def provider(self) -> EERelation: + """Returns the provider endpoint""" + return self["provider"] + + @property + def requirer(self) -> EERelation: + """Returns the requirer endpoint""" + return self["requirer"] + + +class DeployedComponent(dict): + """Represents a deployed component (nsr["_admin"]["deployed"])""" + def __init__(self, data: Dict[str, Any]): + """ + Args: + data: dictionary with the data of the deployed component + """ + for key, value in data.items(): + self.__setitem__(key, value) + + @property + def vnf_profile_id(self): + """Returns the vnf-profile id""" + return self["member-vnf-index"] + + @property + def ee_id(self): + raise NotImplementedError() + + @property + def config_sw_installed(self) -> bool: + raise NotImplementedError() + + +class DeployedK8sResource(DeployedComponent): + """Represents a deployed component for a kdu resource""" + def __init__(self, data: Dict[str, Any]): + super().__init__(data) + + @property + def ee_id(self): + """Returns the execution environment id""" + model = self["kdu-instance"] + application_name = self["resource-name"] + return f"{model}.{application_name}.k8s" + + @property + def config_sw_installed(self) -> bool: + return True + + +class DeployedVCA(DeployedComponent): + """Represents a VCA deployed component""" + def __init__(self, nsr_id: str, deployed_vca: Dict[str, Any]) -> NoReturn: + """ + Args: + db_nsr: NS record + vca_index: Vca index for the deployed VCA + """ + super().__init__(deployed_vca) + self.nsr_id = nsr_id + + @property + def ee_id(self) -> str: + """Returns the execution environment id""" + return self["ee_id"] + + @property + def vdu_profile_id(self) -> str: + """Returns the vdu-profile id""" + return self["vdu_id"] + + @property + def execution_environment_ref(self) -> str: + """Returns the execution environment id""" + return self["ee_descriptor_id"] + + @property + def config_sw_installed(self) -> bool: + return self.get("config_sw_installed", False) diff --git a/osm_lcm/data_utils/vnfd.py b/osm_lcm/data_utils/vnfd.py index 17a98a9..714487c 100644 --- a/osm_lcm/data_utils/vnfd.py +++ b/osm_lcm/data_utils/vnfd.py @@ -101,7 +101,7 @@ def get_vdu_profile(vnfd, vdu_profile_id): ) -def get_kdu_profile(vnfd, kdu_profile_id): +def get_kdu_resource_profile(vnfd, kdu_profile_id): return list_utils.find_in_list( vnfd.get("df", ())[0]["kdu-resource-profile"], lambda kdu_profile: kdu_profile["id"] == kdu_profile_id, @@ -121,6 +121,10 @@ def get_configuration(vnfd, entity_id): ) +def get_relation_list(vnfd, entity_id): + return (get_configuration(vnfd, entity_id) or {}).get("relation", []) + + def get_virtual_link_profiles(vnfd): return vnfd.get("df")[0].get("virtual-link-profile", ()) diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index fc2c9f6..ab25be3 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -17,6 +17,7 @@ ## import asyncio +from typing import Any, Dict import yaml import logging import logging.handlers @@ -31,7 +32,21 @@ from jinja2 import ( ) from osm_lcm import ROclient -from osm_lcm.data_utils.nsr import get_deployed_kdu +from osm_lcm.data_utils.nsr import ( + get_deployed_kdu, + get_deployed_vca, + get_deployed_vca_list, + get_nsd, +) +from osm_lcm.data_utils.vca import ( + DeployedComponent, + DeployedK8sResource, + DeployedVCA, + EELevel, + Relation, + EERelation, + safe_get_ee_relation, +) from osm_lcm.ng_ro import NgRoClient, NgRoException from osm_lcm.lcm_utils import ( LcmException, @@ -41,8 +56,13 @@ from osm_lcm.lcm_utils import ( get_iterable, populate_dict, ) -from osm_lcm.data_utils.nsd import get_vnf_profiles +from osm_lcm.data_utils.nsd import ( + get_ns_configuration_relation_list, + get_vnf_profile, + get_vnf_profiles, +) from osm_lcm.data_utils.vnfd import ( + get_relation_list, get_vdu_list, get_vdu_profile, get_ee_sorted_initial_config_primitive_list, @@ -55,12 +75,13 @@ from osm_lcm.data_utils.vnfd import ( get_scaling_aspect, get_number_of_instances, get_juju_ee_ref, - get_kdu_profile, + get_kdu_resource_profile, ) from osm_lcm.data_utils.list_utils import find_in_list from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur from osm_lcm.data_utils.dict_utils import parse_yaml_strings from osm_lcm.data_utils.database.vim_account import VimAccountDB +from n2vc.definitions import RelationEndpoint from n2vc.k8s_helm_conn import K8sHelmConnector from n2vc.k8s_helm3_conn import K8sHelm3Connector from n2vc.k8s_juju_conn import K8sJujuConnector @@ -1827,9 +1848,8 @@ class NsLcm(LcmBase): await self._add_vca_relations( logging_text=logging_text, nsr_id=nsr_id, - vca_index=vca_index, - vca_id=vca_id, vca_type=vca_type, + vca_index=vca_index, ) # if SSH access is required, then get execution environment SSH public @@ -2630,14 +2650,249 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "Exit") self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate") + def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]): + if vnfd_id not in cached_vnfds: + cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id}) + return cached_vnfds[vnfd_id] + + def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]): + if vnf_profile_id not in cached_vnfrs: + cached_vnfrs[vnf_profile_id] = self.db.get_one( + "vnfrs", + { + "member-vnf-index-ref": vnf_profile_id, + "nsr-id-ref": nsr_id, + }, + ) + return cached_vnfrs[vnf_profile_id] + + def _is_deployed_vca_in_relation( + self, vca: DeployedVCA, relation: Relation + ) -> bool: + found = False + for endpoint in (relation.provider, relation.requirer): + if endpoint["kdu-resource-profile-id"]: + continue + found = ( + vca.vnf_profile_id == endpoint.vnf_profile_id + and vca.vdu_profile_id == endpoint.vdu_profile_id + and vca.execution_environment_ref == endpoint.execution_environment_ref + ) + if found: + break + return found + + def _update_ee_relation_data_with_implicit_data( + self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None + ): + ee_relation_data = safe_get_ee_relation( + nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id + ) + ee_relation_level = EELevel.get_level(ee_relation_data) + if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[ + "execution-environment-ref" + ]: + vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"]) + vnfd_id = vnf_profile["vnfd-id"] + db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds) + entity_id = ( + vnfd_id + if ee_relation_level == EELevel.VNF + else ee_relation_data["vdu-profile-id"] + ) + ee = get_juju_ee_ref(db_vnfd, entity_id) + if not ee: + raise Exception( + f"not execution environments found for ee_relation {ee_relation_data}" + ) + ee_relation_data["execution-environment-ref"] = ee["id"] + return ee_relation_data + + def _get_ns_relations( + self, + nsr_id: str, + nsd: Dict[str, Any], + vca: DeployedVCA, + cached_vnfds: Dict[str, Any], + ): + relations = [] + db_ns_relations = get_ns_configuration_relation_list(nsd) + for r in db_ns_relations: + relation_provider = self._update_ee_relation_data_with_implicit_data( + nsr_id, nsd, r["provider"], cached_vnfds + ) + relation_requirer = self._update_ee_relation_data_with_implicit_data( + nsr_id, nsd, r["requirer"], cached_vnfds + ) + provider = EERelation(relation_provider) + requirer = EERelation(relation_requirer) + relation = Relation(r["name"], provider, requirer) + vca_in_relation = self._is_deployed_vca_in_relation(vca, relation) + if vca_in_relation: + relations.append(relation) + return relations + + def _get_vnf_relations( + self, + nsr_id: str, + nsd: Dict[str, Any], + vca: DeployedVCA, + cached_vnfds: Dict[str, Any], + ): + relations = [] + vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id) + vnf_profile_id = vnf_profile["id"] + vnfd_id = vnf_profile["vnfd-id"] + db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds) + db_vnf_relations = get_relation_list(db_vnfd, vnfd_id) + for r in db_vnf_relations: + relation_provider = self._update_ee_relation_data_with_implicit_data( + nsr_id, nsd, r["provider"], cached_vnfds, vnf_profile_id=vnf_profile_id + ) + relation_requirer = self._update_ee_relation_data_with_implicit_data( + nsr_id, nsd, r["requirer"], cached_vnfds, vnf_profile_id=vnf_profile_id + ) + provider = EERelation(relation_provider) + requirer = EERelation(relation_requirer) + relation = Relation(r["name"], provider, requirer) + vca_in_relation = self._is_deployed_vca_in_relation(vca, relation) + if vca_in_relation: + relations.append(relation) + return relations + + def _get_kdu_resource_data( + self, + ee_relation: EERelation, + db_nsr: Dict[str, Any], + cached_vnfds: Dict[str, Any], + ) -> DeployedK8sResource: + nsd = get_nsd(db_nsr) + vnf_profiles = get_vnf_profiles(nsd) + vnfd_id = find_in_list( + vnf_profiles, + lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id, + )["vnfd-id"] + db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds) + kdu_resource_profile = get_kdu_resource_profile( + db_vnfd, ee_relation.kdu_resource_profile_id + ) + kdu_name = kdu_resource_profile["kdu-name"] + deployed_kdu, _ = get_deployed_kdu( + db_nsr.get("_admin", ()).get("deployed", ()), + kdu_name, + ee_relation.vnf_profile_id, + ) + deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]}) + return deployed_kdu + + def _get_deployed_component( + self, + ee_relation: EERelation, + db_nsr: Dict[str, Any], + cached_vnfds: Dict[str, Any], + ) -> DeployedComponent: + nsr_id = db_nsr["_id"] + deployed_component = None + ee_level = EELevel.get_level(ee_relation) + if ee_level == EELevel.NS: + vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None}) + if vca: + deployed_component = DeployedVCA(nsr_id, vca) + elif ee_level == EELevel.VNF: + vca = get_deployed_vca( + db_nsr, + { + "vdu_id": None, + "member-vnf-index": ee_relation.vnf_profile_id, + "ee_descriptor_id": ee_relation.execution_environment_ref, + }, + ) + if vca: + deployed_component = DeployedVCA(nsr_id, vca) + elif ee_level == EELevel.VDU: + vca = get_deployed_vca( + db_nsr, + { + "vdu_id": ee_relation.vdu_profile_id, + "member-vnf-index": ee_relation.vnf_profile_id, + "ee_descriptor_id": ee_relation.execution_environment_ref, + }, + ) + if vca: + deployed_component = DeployedVCA(nsr_id, vca) + elif ee_level == EELevel.KDU: + kdu_resource_data = self._get_kdu_resource_data( + ee_relation, db_nsr, cached_vnfds + ) + if kdu_resource_data: + deployed_component = DeployedK8sResource(kdu_resource_data) + return deployed_component + + async def _add_relation( + self, + relation: Relation, + vca_type: str, + db_nsr: Dict[str, Any], + cached_vnfds: Dict[str, Any], + cached_vnfrs: Dict[str, Any], + ) -> bool: + deployed_provider = self._get_deployed_component( + relation.provider, db_nsr, cached_vnfds + ) + deployed_requirer = self._get_deployed_component( + relation.requirer, db_nsr, cached_vnfds + ) + if ( + deployed_provider + and deployed_requirer + and deployed_provider.config_sw_installed + and deployed_requirer.config_sw_installed + ): + provider_db_vnfr = ( + self._get_vnfr( + relation.provider.nsr_id, + relation.provider.vnf_profile_id, + cached_vnfrs, + ) + if relation.provider.vnf_profile_id + else None + ) + requirer_db_vnfr = ( + self._get_vnfr( + relation.requirer.nsr_id, + relation.requirer.vnf_profile_id, + cached_vnfrs, + ) + if relation.requirer.vnf_profile_id + else None + ) + provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr) + requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr) + provider_relation_endpoint = RelationEndpoint( + deployed_provider.ee_id, + provider_vca_id, + relation.provider.endpoint, + ) + requirer_relation_endpoint = RelationEndpoint( + deployed_requirer.ee_id, + requirer_vca_id, + relation.requirer.endpoint, + ) + await self.vca_map[vca_type].add_relation( + provider=provider_relation_endpoint, + requirer=requirer_relation_endpoint, + ) + # remove entry from relations list + return True + return False + async def _add_vca_relations( self, logging_text, nsr_id, + vca_type: str, vca_index: int, timeout: int = 3600, - vca_type: str = None, - vca_id: str = None, ) -> bool: # steps: @@ -2646,59 +2901,28 @@ class NsLcm(LcmBase): # 3. add relations try: - vca_type = vca_type or "lxc_proxy_charm" - # STEP 1: find all relations for this VCA # read nsr record db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) - nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]}) + nsd = get_nsd(db_nsr) # this VCA data - my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index] - - # read all ns-configuration relations - ns_relations = list() - db_ns_relations = deep_get(nsd, ("ns-configuration", "relation")) - if db_ns_relations: - for r in db_ns_relations: - # check if this VCA is in the relation - if my_vca.get("member-vnf-index") in ( - r.get("entities")[0].get("id"), - r.get("entities")[1].get("id"), - ): - ns_relations.append(r) - - # read all vnf-configuration relations - vnf_relations = list() - db_vnfd_list = db_nsr.get("vnfd-id") - if db_vnfd_list: - for vnfd in db_vnfd_list: - db_vnf_relations = None - db_vnfd = self.db.get_one("vnfds", {"_id": vnfd}) - db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"]) - if db_vnf_configuration: - db_vnf_relations = db_vnf_configuration.get("relation", []) - if db_vnf_relations: - for r in db_vnf_relations: - # check if this VCA is in the relation - if my_vca.get("vdu_id") in ( - r.get("entities")[0].get("id"), - r.get("entities")[1].get("id"), - ): - vnf_relations.append(r) + deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index] + my_vca = DeployedVCA(nsr_id, deployed_vca_dict) + + cached_vnfds = {} + cached_vnfrs = {} + relations = [] + relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds)) + relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds)) # if no relations, terminate - if not ns_relations and not vnf_relations: + if not relations: self.logger.debug(logging_text + " No relations") return True - self.logger.debug( - logging_text - + " adding relations\n {}\n {}".format( - ns_relations, vnf_relations - ) - ) + self.logger.debug(logging_text + " adding relations {}".format(relations)) # add all relations start = time() @@ -2709,124 +2933,25 @@ class NsLcm(LcmBase): self.logger.error(logging_text + " : timeout adding relations") return False - # reload nsr from database (we need to update record: _admin.deloyed.VCA) + # reload nsr from database (we need to update record: _admin.deployed.VCA) db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) - # for each defined NS relation, find the VCA's related - for r in ns_relations.copy(): - from_vca_ee_id = None - to_vca_ee_id = None - from_vca_endpoint = None - to_vca_endpoint = None - vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA")) - for vca in vca_list: - if vca.get("member-vnf-index") == r.get("entities")[0].get( - "id" - ) and vca.get("config_sw_installed"): - from_vca_ee_id = vca.get("ee_id") - from_vca_endpoint = r.get("entities")[0].get("endpoint") - if vca.get("member-vnf-index") == r.get("entities")[1].get( - "id" - ) and vca.get("config_sw_installed"): - to_vca_ee_id = vca.get("ee_id") - to_vca_endpoint = r.get("entities")[1].get("endpoint") - if from_vca_ee_id and to_vca_ee_id: - # add relation - await self.vca_map[vca_type].add_relation( - ee_id_1=from_vca_ee_id, - ee_id_2=to_vca_ee_id, - endpoint_1=from_vca_endpoint, - endpoint_2=to_vca_endpoint, - vca_id=vca_id, - ) - # remove entry from relations list - ns_relations.remove(r) - else: - # check failed peers - try: - vca_status_list = db_nsr.get("configurationStatus") - if vca_status_list: - for i in range(len(vca_list)): - vca = vca_list[i] - vca_status = vca_status_list[i] - if vca.get("member-vnf-index") == r.get("entities")[ - 0 - ].get("id"): - if vca_status.get("status") == "BROKEN": - # peer broken: remove relation from list - ns_relations.remove(r) - if vca.get("member-vnf-index") == r.get("entities")[ - 1 - ].get("id"): - if vca_status.get("status") == "BROKEN": - # peer broken: remove relation from list - ns_relations.remove(r) - except Exception: - # ignore - pass - - # for each defined VNF relation, find the VCA's related - for r in vnf_relations.copy(): - from_vca_ee_id = None - to_vca_ee_id = None - from_vca_endpoint = None - to_vca_endpoint = None - vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA")) - for vca in vca_list: - key_to_check = "vdu_id" - if vca.get("vdu_id") is None: - key_to_check = "vnfd_id" - if vca.get(key_to_check) == r.get("entities")[0].get( - "id" - ) and vca.get("config_sw_installed"): - from_vca_ee_id = vca.get("ee_id") - from_vca_endpoint = r.get("entities")[0].get("endpoint") - if vca.get(key_to_check) == r.get("entities")[1].get( - "id" - ) and vca.get("config_sw_installed"): - to_vca_ee_id = vca.get("ee_id") - to_vca_endpoint = r.get("entities")[1].get("endpoint") - if from_vca_ee_id and to_vca_ee_id: - # add relation - await self.vca_map[vca_type].add_relation( - ee_id_1=from_vca_ee_id, - ee_id_2=to_vca_ee_id, - endpoint_1=from_vca_endpoint, - endpoint_2=to_vca_endpoint, - vca_id=vca_id, - ) - # remove entry from relations list - vnf_relations.remove(r) - else: - # check failed peers - try: - vca_status_list = db_nsr.get("configurationStatus") - if vca_status_list: - for i in range(len(vca_list)): - vca = vca_list[i] - vca_status = vca_status_list[i] - if vca.get("vdu_id") == r.get("entities")[0].get( - "id" - ): - if vca_status.get("status") == "BROKEN": - # peer broken: remove relation from list - vnf_relations.remove(r) - if vca.get("vdu_id") == r.get("entities")[1].get( - "id" - ): - if vca_status.get("status") == "BROKEN": - # peer broken: remove relation from list - vnf_relations.remove(r) - except Exception: - # ignore - pass - - # wait for next try - await asyncio.sleep(5.0) + # for each relation, find the VCA's related + for relation in relations.copy(): + added = await self._add_relation( + relation, + vca_type, + db_nsr, + cached_vnfds, + cached_vnfrs, + ) + if added: + relations.remove(relation) - if not ns_relations and not vnf_relations: + if not relations: self.logger.debug("Relations added") break + await asyncio.sleep(5.0) return True @@ -5118,7 +5243,7 @@ class NsLcm(LcmBase): ) scaling_info["vdu-create"][vdu_delta["id"]] = instances_number for kdu_delta in delta.get("kdu-resource-delta", {}): - kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"]) + kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"]) kdu_name = kdu_profile["kdu-name"] resource_name = kdu_profile["resource-name"] @@ -5248,7 +5373,7 @@ class NsLcm(LcmBase): ) scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number for kdu_delta in delta.get("kdu-resource-delta", {}): - kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"]) + kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"]) kdu_name = kdu_profile["kdu-name"] resource_name = kdu_profile["resource-name"]