From 01244641fdac89ce2afd5490e5c6d2bcf7ad05ae Mon Sep 17 00:00:00 2001 From: aticig Date: Thu, 28 Jul 2022 01:12:03 +0300 Subject: [PATCH] Feature 10944 Change naming of charms Modifying n2vc_conn.py/N2VCConnector _get_application_name method to generate new application naming for charms Change-Id: I1908bdbe4ce1a959a8a407f77913a414ec23fbb4 Signed-off-by: aticig --- n2vc/n2vc_juju_conn.py | 225 ++++- n2vc/tests/unit/test_n2vc_juju_conn.py | 928 +++++++++++++++++- .../unit/testdata/test_db_descriptors.py | 414 ++++++++ tox.ini | 3 +- 4 files changed, 1521 insertions(+), 49 deletions(-) create mode 100644 n2vc/tests/unit/testdata/test_db_descriptors.py diff --git a/n2vc/n2vc_juju_conn.py b/n2vc/n2vc_juju_conn.py index b2ffa0a..5dc394c 100644 --- a/n2vc/n2vc_juju_conn.py +++ b/n2vc/n2vc_juju_conn.py @@ -42,6 +42,7 @@ from n2vc.store import MotorStore from n2vc.utils import get_ee_id_components, generate_random_alfanum_string from n2vc.vca.connection import get_connection from retrying_async import retry +from typing import Tuple class N2VCJujuConnector(N2VCConnector): @@ -1225,20 +1226,41 @@ class N2VCJujuConnector(N2VCConnector): return get_ee_id_components(ee_id) - def _get_application_name(self, namespace: str) -> str: - """ - Build application name from namespace - :param namespace: - :return: app-vnf--vdu--cnt-- + @staticmethod + def _find_charm_level(vnf_id: str, vdu_id: str) -> str: + """Decides the charm level. + Args: + vnf_id (str): VNF id + vdu_id (str): VDU id + + Returns: + charm_level (str): ns-level or vnf-level or vdu-level """ + if vdu_id and not vnf_id: + raise N2VCException(message="If vdu-id exists, vnf-id should be provided.") + if vnf_id and vdu_id: + return "vdu-level" + if vnf_id and not vdu_id: + return "vnf-level" + if not vnf_id and not vdu_id: + return "ns-level" + + @staticmethod + def _generate_backward_compatible_application_name( + vnf_id: str, vdu_id: str, vdu_count: str + ) -> str: + """Generate backward compatible application name + by limiting the app name to 50 characters. - # TODO: Enforce the Juju 50-character application limit + Args: + vnf_id (str): VNF ID + vdu_id (str): VDU ID + vdu_count (str): vdu-count-index - # split namespace components - _, _, vnf_id, vdu_id, vdu_count = self._get_namespace_components( - namespace=namespace - ) + Returns: + application_name (str): generated application name + """ if vnf_id is None or len(vnf_id) == 0: vnf_id = "" else: @@ -1262,6 +1284,189 @@ class N2VCJujuConnector(N2VCConnector): application_name = "app-{}{}{}-{}".format( vnf_id, vdu_id, vdu_count, random_suffix ) + return application_name + + @staticmethod + def _generate_application_name( + charm_level: str, + vnfrs: dict, + vca_records: list, + vnf_count: str = None, + vdu_count: str = None, + ) -> str: + """Generate application name to make the relevant charm of VDU/KDU + in the VNFD descriptor become clearly visible. + Limiting the app name to 50 characters. + + Args: + charm_level (str): VNF ID + vnfrs (dict): VDU ID + vca_records (list): db_nsr["_admin"]["deployed"]["VCA"] as list + vnf_count (str): vnf count index + vdu_count (str): vdu count index + + Returns: + application_name (str): generated application name + + """ + application_name = "" + if charm_level == "ns-level": + if len(vca_records) != 1: + raise N2VCException(message="One VCA record is expected.") + # Only one VCA record is expected if it's ns-level charm. + # Shorten the charm name to its first 40 characters. + charm_name = vca_records[0]["charm_name"][:40] + if not charm_name: + raise N2VCException(message="Charm name should be provided.") + application_name = charm_name + "-ns" + + elif charm_level == "vnf-level": + if len(vca_records) < 1: + raise N2VCException(message="One or more VCA record is expected.") + # If VNF is scaled, more than one VCA record may be included in vca_records + # but ee_descriptor_id is same. + # Shorten the ee_descriptor_id and member-vnf-index-ref + # to first 12 characters. + application_name = ( + vca_records[0]["ee_descriptor_id"][:12] + + "-" + + vnf_count + + "-" + + vnfrs["member-vnf-index-ref"][:12] + + "-vnf" + ) + elif charm_level == "vdu-level": + if len(vca_records) < 1: + raise N2VCException(message="One or more VCA record is expected.") + vdu_profile_id = vnfrs["vdur"][int(vdu_count)]["vdu-id-ref"] + # If vnf/vdu is scaled, more than one VCA record may be included in vca_records + # but ee_descriptor_id is same. + # Shorten the ee_descriptor_id, member-vnf-index-ref and vdu_profile_id + # to first 12 characters. + application_name = ( + vca_records[0]["ee_descriptor_id"][:12] + + "-" + + vnf_count + + "-" + + vnfrs["member-vnf-index-ref"][:12] + + "-" + + vdu_profile_id[:12] + + "-" + + vdu_count + + "-vdu" + ) + + return application_name + + def _get_vnf_count_and_record( + self, charm_level: str, vnf_id_and_count: str + ) -> Tuple[str, dict]: + """Get the vnf count and VNF record depend on charm level + + Args: + charm_level (str) + vnf_id_and_count (str) + + Returns: + (vnf_count (str), db_vnfr(dict)) as Tuple + + """ + vnf_count = "" + db_vnfr = {} + + if charm_level in ("vnf-level", "vdu-level"): + vnf_id = "-".join(vnf_id_and_count.split("-")[:-1]) + vnf_count = vnf_id_and_count.split("-")[-1] + db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id}) + + # If the charm is ns level, it returns empty vnf_count and db_vnfr + return vnf_count, db_vnfr + + @staticmethod + def _get_vca_records(charm_level: str, db_nsr: dict, db_vnfr: dict) -> list: + """Get the VCA records from db_nsr dict + + Args: + charm_level (str): level of charm + db_nsr (dict): NS record from database + db_vnfr (dict): VNF record from database + + Returns: + vca_records (list): List of VCA record dictionaries + + """ + vca_records = {} + if charm_level == "ns-level": + vca_records = list( + filter( + lambda vca_record: vca_record["target_element"] == "ns", + db_nsr["_admin"]["deployed"]["VCA"], + ) + ) + elif charm_level in ["vnf-level", "vdu-level"]: + vca_records = list( + filter( + lambda vca_record: vca_record["member-vnf-index"] + == db_vnfr["member-vnf-index-ref"], + db_nsr["_admin"]["deployed"]["VCA"], + ) + ) + + return vca_records + + def _get_application_name(self, namespace: str) -> str: + """Build application name from namespace + + Application name structure: + NS level: -ns + VNF level: -z--vnf + VDU level: -z-- + -z-vdu + + Application naming for backward compatibility (old structure): + NS level: app- + VNF level: app-vnf--z- + VDU level: app-vnf--z-vdu- + -cnt--z- + + Args: + namespace (str) + + Returns: + application_name (str) + + """ + # split namespace components + ( + nsi_id, + ns_id, + vnf_id_and_count, + vdu_id, + vdu_count, + ) = self._get_namespace_components(namespace=namespace) + + if not ns_id: + raise N2VCException(message="ns-id should be provided.") + + charm_level = self._find_charm_level(vnf_id_and_count, vdu_id) + db_nsr = self.db.get_one("nsrs", {"_id": ns_id}) + vnf_count, db_vnfr = self._get_vnf_count_and_record( + charm_level, vnf_id_and_count + ) + vca_records = self._get_vca_records(charm_level, db_nsr, db_vnfr) + + if all("charm_name" in vca_record.keys() for vca_record in vca_records): + application_name = self._generate_application_name( + charm_level, + db_vnfr, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + else: + application_name = self._generate_backward_compatible_application_name( + vnf_id_and_count, vdu_id, vdu_count + ) return N2VCJujuConnector._format_app_name(application_name) diff --git a/n2vc/tests/unit/test_n2vc_juju_conn.py b/n2vc/tests/unit/test_n2vc_juju_conn.py index 4fef1f2..ebf36d5 100644 --- a/n2vc/tests/unit/test_n2vc_juju_conn.py +++ b/n2vc/tests/unit/test_n2vc_juju_conn.py @@ -15,7 +15,7 @@ import asyncio import logging -from unittest.mock import Mock +from unittest.mock import Mock, MagicMock from unittest.mock import patch @@ -23,6 +23,7 @@ import asynctest from n2vc.definitions import Offer, RelationEndpoint from n2vc.n2vc_juju_conn import N2VCJujuConnector from osm_common import fslocal +from osm_common.dbmemory import DbMemory from n2vc.exceptions import ( N2VCBadArgumentsException, N2VCException, @@ -30,6 +31,8 @@ from n2vc.exceptions import ( ) from n2vc.tests.unit.utils import AsyncMock from n2vc.vca.connection_data import ConnectionData +from n2vc.tests.unit.testdata import test_db_descriptors as descriptors +import yaml class N2VCJujuConnTestCase(asynctest.TestCase): @@ -134,10 +137,6 @@ class UpdateVcaStatusTest(N2VCJujuConnTestCase): self.n2vc.libjuju.get_application_configs.assert_not_called_once() -@asynctest.mock.patch("osm_common.fslocal.FsLocal.file_exists") -@asynctest.mock.patch( - "osm_common.fslocal.FsLocal.path", new_callable=asynctest.PropertyMock, create=True -) class K8sProxyCharmsTest(N2VCJujuConnTestCase): def setUp(self): super(K8sProxyCharmsTest, self).setUp() @@ -145,6 +144,13 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase): self.n2vc.libjuju.add_model = AsyncMock() self.n2vc.libjuju.deploy_charm = AsyncMock() self.n2vc.libjuju.model_exists.return_value = False + self.db = DbMemory() + self.fs = fslocal.FsLocal() + self.fs.path = "/" + self.n2vc.fs = self.fs + self.n2vc.db = self.db + self.db.create_list("nsrs", yaml.safe_load(descriptors.db_nsrs_text)) + self.db.create_list("vnfrs", yaml.safe_load(descriptors.db_vnfrs_text)) @patch( "n2vc.n2vc_juju_conn.generate_random_alfanum_string", @@ -153,43 +159,41 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase): def test_success( self, mock_generate_random_alfanum_string, - mock_path, - mock_file_exists, ): - mock_file_exists.return_value = True - mock_path.return_value = "/path" + self.n2vc.fs.file_exists = MagicMock(create_autospec=True) + self.n2vc.fs.file_exists.return_value = True ee_id = self.loop.run_until_complete( self.n2vc.install_k8s_proxy_charm( - "charm", - "nsi-id.ns-id.vnf-id.vdu", - "////path/", + "simple", + ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0", + "path", {}, ) ) self.n2vc.libjuju.add_model.assert_called_once() self.n2vc.libjuju.deploy_charm.assert_called_once_with( - model_name="ns-id-k8s", - application_name="app-vnf-vnf-id-vdu-vdu-random", - path="/path/path/", + model_name="dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s", + application_name="simple-ee-z0-vnf1-vnf", + path="//path", machine_id=None, db_dict={}, progress_timeout=None, total_timeout=None, config=None, ) - self.assertEqual(ee_id, "ns-id-k8s.app-vnf-vnf-id-vdu-vdu-random.k8s") + self.assertEqual( + ee_id, "dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s.simple-ee-z0-vnf1-vnf.k8s" + ) def test_no_artifact_path( self, - mock_path, - mock_file_exists, ): with self.assertRaises(N2VCBadArgumentsException): ee_id = self.loop.run_until_complete( self.n2vc.install_k8s_proxy_charm( - "charm", - "nsi-id.ns-id.vnf-id.vdu", + "simple", + ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0", "", {}, ) @@ -198,15 +202,13 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase): def test_no_db( self, - mock_path, - mock_file_exists, ): with self.assertRaises(N2VCBadArgumentsException): ee_id = self.loop.run_until_complete( self.n2vc.install_k8s_proxy_charm( - "charm", - "nsi-id.ns-id.vnf-id.vdu", - "/path/", + "simple", + ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0", + "path", None, ) ) @@ -214,16 +216,15 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase): def test_file_not_exists( self, - mock_path, - mock_file_exists, ): - mock_file_exists.return_value = False + self.n2vc.fs.file_exists = MagicMock(create_autospec=True) + self.n2vc.fs.file_exists.return_value = False with self.assertRaises(N2VCBadArgumentsException): ee_id = self.loop.run_until_complete( self.n2vc.install_k8s_proxy_charm( - "charm", - "nsi-id.ns-id.vnf-id.vdu", - "/path/", + "simple", + ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0", + "path", {}, ) ) @@ -231,18 +232,18 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase): def test_exception( self, - mock_path, - mock_file_exists, ): - mock_file_exists.return_value = True - mock_path.return_value = "/path" + self.n2vc.fs.file_exists = MagicMock(create_autospec=True) + self.n2vc.fs.file_exists.return_value = True + self.n2vc.fs.path = MagicMock(create_autospec=True) + self.n2vc.fs.path.return_value = "path" self.n2vc.libjuju.deploy_charm.side_effect = Exception() with self.assertRaises(N2VCException): ee_id = self.loop.run_until_complete( self.n2vc.install_k8s_proxy_charm( - "charm", - "nsi-id.ns-id.vnf-id.vdu", - "path/", + "simple", + ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0", + "path", {}, ) ) @@ -377,3 +378,854 @@ class UpgradeCharmTest(N2VCJujuConnTestCase): model_name="sample_model", total_timeout=None, ) + + +class GenerateApplicationNameTest(N2VCJujuConnTestCase): + + vnf_id = "dbfbd751-3de4-4e68-bd40-ec5ae0a53898" + + def setUp(self): + super(GenerateApplicationNameTest, self).setUp() + self.db = MagicMock(DbMemory) + + @patch( + "n2vc.n2vc_juju_conn.generate_random_alfanum_string", + **{"return_value": "random"} + ) + def test_generate_backward_compatible_application_name( + self, mock_generate_random_alfanum + ): + vdu_id = "mgmtVM" + vdu_count = "0" + expected_result = "app-vnf-ec5ae0a53898-vdu-mgmtVM-cnt-0-random" + + application_name = self.n2vc._generate_backward_compatible_application_name( + GenerateApplicationNameTest.vnf_id, vdu_id, vdu_count + ) + self.assertEqual(application_name, expected_result) + + @patch( + "n2vc.n2vc_juju_conn.generate_random_alfanum_string", + **{"return_value": "random"} + ) + def test_generate_backward_compatible_application_name_without_vnf_id_vdu_id( + self, mock_generate_random_alfanum + ): + vnf_id = None + vdu_id = "" + vdu_count = None + expected_result = "app--random" + application_name = self.n2vc._generate_backward_compatible_application_name( + vnf_id, vdu_id, vdu_count + ) + + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + + def test_find_charm_level_with_vnf_id(self): + vdu_id = "" + expected_result = "vnf-level" + charm_level = self.n2vc._find_charm_level( + GenerateApplicationNameTest.vnf_id, vdu_id + ) + self.assertEqual(charm_level, expected_result) + + def test_find_charm_level_with_vdu_id(self): + vnf_id = "" + vdu_id = "mgmtVM" + with self.assertRaises(N2VCException): + self.n2vc._find_charm_level(vnf_id, vdu_id) + + def test_find_charm_level_with_vnf_id_and_vdu_id(self): + vdu_id = "mgmtVM" + expected_result = "vdu-level" + charm_level = self.n2vc._find_charm_level( + GenerateApplicationNameTest.vnf_id, vdu_id + ) + self.assertEqual(charm_level, expected_result) + + def test_find_charm_level_without_vnf_id_and_vdu_id(self): + vnf_id = "" + vdu_id = "" + expected_result = "ns-level" + charm_level = self.n2vc._find_charm_level(vnf_id, vdu_id) + self.assertEqual(charm_level, expected_result) + + def test_generate_application_name_ns_charm(self): + charm_level = "ns-level" + vnfrs = {} + vca_records = [ + { + "target_element": "ns", + "member-vnf-index": "", + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": None, + "vdu_name": None, + "type": "proxy_charm", + "ee_descriptor_id": None, + "charm_name": "simple-ns-charm-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh", + "ee_id": None, + "application": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vnf_count = "" + vdu_count = "" + expected_result = "simple-ns-charm-abc-000-rrrr-nnnn-4444-h-ns" + application_name = self.n2vc._generate_application_name( + charm_level, + vnfrs, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + + def test_generate_application_name_ns_charm_empty_vca_records(self): + charm_level = "ns-level" + vnfrs = {} + vca_records = [] + vnf_count = "" + vdu_count = "" + with self.assertRaises(N2VCException): + self.n2vc._generate_application_name( + charm_level, + vnfrs, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + + def test_generate_application_name_vnf_charm(self): + charm_level = "vnf-level" + vnfrs = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + } + vca_records = [ + { + "target_element": "vnf/vnf1", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vnf_count = "1" + vdu_count = "" + expected_result = "simple-ee-ab-1-vnf111-xxx-y-vnf" + application_name = self.n2vc._generate_application_name( + charm_level, + vnfrs, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + + def test_generate_application_name_vdu_charm(self): + charm_level = "vdu-level" + vnfrs = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + "vdur": [ + {"_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "mgmtVM"}, + {"_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "dataVM"}, + ], + } + vca_records = [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "vnf/vnf1/datavm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "datavm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-8888-hhh-3333-yyyy-888-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vnf_count = "2" + vdu_count = "0" + expected_result = "simple-ee-ab-2-vnf111-xxx-y-mgmtVM-0-vdu" + application_name = self.n2vc._generate_application_name( + charm_level, + vnfrs, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + + def test_generate_application_name_vdu_charm_wrong_vnfrs(self): + charm_level = "vdu-level" + vnfrs = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + } + vca_records = [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vnf_count = "2" + vdu_count = "0" + with self.assertRaises(KeyError): + self.n2vc._generate_application_name( + charm_level, + vnfrs, + vca_records, + vnf_count=vnf_count, + vdu_count=vdu_count, + ) + + def test_get_vnf_count_db_vnfr_ns_charm(self): + self.db.get_one.return_value = {"member-vnf-index-ref": "sample-ref"} + charm_level = "ns-level" + vnf_id_and_count = "m7fbd751-3de4-4e68-bd40-ec5ae0a53898-4" + with patch.object(self.n2vc, "db", self.db): + vnf_count, db_vnfr = self.n2vc._get_vnf_count_and_record( + charm_level, vnf_id_and_count + ) + self.assertEqual(vnf_count, "") + self.assertEqual(db_vnfr, {}) + + def test_get_vnf_count_db_vnfr_vnf_charm(self): + self.db.get_one.return_value = {"member-vnf-index-ref": "sample-ref"} + charm_level = "vnf-level" + vnf_id_and_count = "m7fbd751-3de4-4e68-bd40-ec5ae0a53898-4" + with patch.object(self.n2vc, "db", self.db): + vnf_count, db_vnfr = self.n2vc._get_vnf_count_and_record( + charm_level, vnf_id_and_count + ) + self.assertEqual(vnf_count, "4") + self.assertEqual(db_vnfr, {"member-vnf-index-ref": "sample-ref"}) + + def test_get_vnf_count_db_vnfr_vdu_charm(self): + self.db.get_one.return_value = {"member-vnf-index-ref": "sample-ref"} + charm_level = "vdu-level" + vnf_id_and_count = "m7fbd751-3de4-4e68-bd40-ec5ae0a53898-2" + with patch.object(self.n2vc, "db", self.db): + vnf_count, db_vnfr = self.n2vc._get_vnf_count_and_record( + charm_level, vnf_id_and_count + ) + self.assertEqual(vnf_count, "2") + self.assertEqual(db_vnfr, {"member-vnf-index-ref": "sample-ref"}) + + def test_get_vca_records_vdu_charm(self): + charm_level = "vdu-level" + db_vnfr = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + "vdur": [ + {"_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "mgmtVM"}, + {"_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "dataVM"}, + ], + } + db_nsr = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "vnf/vnf2/datavm", + "member-vnf-index": "vnf222-xxx-yyy-zzz", + "vdu_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "datavm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-8888-hhh-3333-yyyy-888-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + expected_result = [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vca_records = self.n2vc._get_vca_records(charm_level, db_nsr, db_vnfr) + self.assertEqual(vca_records, expected_result) + + def test_get_vca_records_vnf_charm_member_vnf_index_mismatch(self): + charm_level = "vnf-level" + db_vnfr = { + "member-vnf-index-ref": "vnf222-xxx-yyy-zzz", + } + db_nsr = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "datavm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-8888-hhh-3333-yyyy-888-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + expected_result = [] + vca_records = self.n2vc._get_vca_records(charm_level, db_nsr, db_vnfr) + self.assertEqual(vca_records, expected_result) + + def test_get_vca_records_ns_charm(self): + charm_level = "ns-level" + db_vnfr = { + "member-vnf-index-ref": "vnf222-xxx-yyy-zzz", + } + db_nsr = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "simple-ns-charm-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + expected_result = [ + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "simple-ns-charm-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vca_records = self.n2vc._get_vca_records(charm_level, db_nsr, db_vnfr) + self.assertEqual(vca_records, expected_result) + + def test_get_vca_records_ns_charm_empty_charm_name(self): + charm_level = "ns-level" + db_vnfr = { + "member-vnf-index-ref": "vnf222-xxx-yyy-zzz", + } + db_nsr = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + expected_result = [ + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + vca_records = self.n2vc._get_vca_records(charm_level, db_nsr, db_vnfr) + self.assertEqual(vca_records, expected_result) + + def test_get_application_name_vnf_charm(self): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + } + vnf_count = "0" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "simple-ee-ab-z0-vnf111-xxx-y-vnf" + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + mock_vnf_count_and_record.assert_called_once_with( + "vnf-level", "1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + ) + self.db.get_one.assert_called_once() + + @patch( + "n2vc.n2vc_juju_conn.generate_random_alfanum_string", + **{"return_value": "random"} + ) + def test_get_application_name_vnf_charm_old_naming( + self, mock_generate_random_alfanum + ): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + } + vnf_count = "0" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "app-vnf-eb3161eec0-z0-random" + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + mock_vnf_count_and_record.assert_called_once_with( + "vnf-level", "1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + ) + self.db.get_one.assert_called_once() + + def test_get_application_name_vnf_charm_vnf_index_ref_mismatch(self): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = { + "member-vnf-index-ref": "vnf222-xxx-yyy-zzz", + } + vnf_count = "0" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + with self.assertRaises(N2VCException): + self.n2vc._get_application_name(namespace) + mock_vnf_count_and_record.assert_called_once_with( + "vnf-level", "1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + ) + self.db.get_one.assert_called_once() + + def test_get_application_name_vdu_charm(self): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0.mgmtVM-0" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ] + } + } + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + "vdur": [ + {"_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "mgmtVM"}, + {"_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "dataVM"}, + ], + } + vnf_count = "0" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "simple-ee-ab-z0-vnf111-xxx-y-mgmtvm-z0-vdu" + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + mock_vnf_count_and_record.assert_called_once_with( + "vdu-level", "1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + ) + self.db.get_one.assert_called_once() + + @patch( + "n2vc.n2vc_juju_conn.generate_random_alfanum_string", + **{"return_value": "random"} + ) + def test_get_application_name_vdu_charm_old_naming( + self, mock_generate_random_alfanum + ): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898.1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0.mgmtVM-0" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "vnf/vnf1/mgmtvm", + "member-vnf-index": "vnf111-xxx-yyy-zzz", + "vdu_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "r7fbd751-3de4-4e68-bd40-ec5ae0a53898", + "vdu_name": "mgmtvm", + "ee_descriptor_id": "simple-ee-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = { + "member-vnf-index-ref": "vnf111-xxx-yyy-zzz", + "vdur": [ + {"_id": "38912ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "mgmtVM"}, + {"_id": "45512ff7-5bdd-4228-911f-c2bee259c44a", "vdu-id-ref": "dataVM"}, + ], + } + vnf_count = "0" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "app-vnf-eb3161eec0-z0-vdu-mgmtvm-cnt-z0-random" + + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + mock_vnf_count_and_record.assert_called_once_with( + "vdu-level", "1b6a4eb3-4fbf-415e-985c-4aeb3161eec0-0" + ) + self.db.get_one.assert_called_once() + + def test_get_application_name_ns_charm(self): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "simple-ns-charm-abc-000-rrrr-nnnn-4444-hhh-3333-yyyy-333-hhh-ttt-444", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = {} + vnf_count = "" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "simple-ns-charm-abc-z000-rrrr-nnnn-z4444-h-ns" + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + mock_vnf_count_and_record.assert_called_once_with("ns-level", None) + self.db.get_one.assert_called_once() + + def test_get_application_name_ns_charm_empty_charm_name(self): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "charm_name": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = {} + vnf_count = "" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + with self.assertRaises(N2VCException): + self.n2vc._get_application_name(namespace) + mock_vnf_count_and_record.assert_called_once_with("ns-level", None) + self.db.get_one.assert_called_once() + + @patch( + "n2vc.n2vc_juju_conn.generate_random_alfanum_string", + **{"return_value": "random"} + ) + def test_get_application_name_ns_charm_old_naming( + self, mock_generate_random_alfanum + ): + namespace = ".dbfbd751-3de4-4e68-bd40-ec5ae0a53898" + self.db.get_one.return_value = { + "_admin": { + "deployed": { + "VCA": [ + { + "target_element": "ns", + "member-vnf-index": None, + "vdu_id": None, + "kdu_name": None, + "vdu_count_index": None, + "vnfd_id": "", + "vdu_name": "", + "ee_descriptor_id": "", + "model": "dbfbd751-3de4-4e68-bd40-ec5ae0a53898", + }, + ], + }, + }, + } + mock_vnf_count_and_record = MagicMock() + db_vnfr = {} + vnf_count = "" + mock_vnf_count_and_record.return_value = (vnf_count, db_vnfr) + expected_result = "app-random" + with patch.object(self.n2vc, "db", self.db), patch.object( + self.n2vc, "_get_vnf_count_and_record", mock_vnf_count_and_record + ): + application_name = self.n2vc._get_application_name(namespace) + self.assertEqual(application_name, expected_result) + self.assertLess(len(application_name), 50) + mock_vnf_count_and_record.assert_called_once_with("ns-level", None) + self.db.get_one.assert_called_once() diff --git a/n2vc/tests/unit/testdata/test_db_descriptors.py b/n2vc/tests/unit/testdata/test_db_descriptors.py new file mode 100644 index 0000000..c6f3670 --- /dev/null +++ b/n2vc/tests/unit/testdata/test_db_descriptors.py @@ -0,0 +1,414 @@ +# Copyright 2022 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. + +db_nsrs_text = """ +--- +- _id: dbfbd751-3de4-4e68-bd40-ec5ae0a53898 + name: k8s-ns + name-ref: k8s-ns + short-name: k8s-ns + admin-status: ENABLED + nsState: READY + currentOperation: IDLE + currentOperationID: null + errorDescription: null + errorDetail: null + deploymentStatus: null + configurationStatus: + - elementType: VNF + elementUnderConfiguration: 1b6a4eb3-4fbf-415e-985c-4aeb3161eec0 + status: READY + - elementType: VNF + elementUnderConfiguration: 17892d73-aa19-4b87-9a00-1d094f07a6b3 + status: READY + vcaStatus: null + nsd: + _id: 12f320b5-2a57-40f4-82b5-020a6b1171d7 + id: k8s_proxy_charm-ns + version: '1.0' + name: k8s_proxy_charm-ns + vnfd-id: + - k8s_proxy_charm-vnf + virtual-link-desc: + - id: mgmtnet + mgmt-network: true + - id: datanet + df: + - id: default-df + vnf-profile: + - id: vnf1 + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: vnf1 + constituent-cpd-id: vnf-mgmt-ext + virtual-link-profile-id: mgmtnet + - constituent-cpd-id: + - constituent-base-element-id: vnf1 + constituent-cpd-id: vnf-data-ext + virtual-link-profile-id: datanet + vnfd-id: k8s_proxy_charm-vnf + - id: vnf2 + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: vnf2 + constituent-cpd-id: vnf-mgmt-ext + virtual-link-profile-id: mgmtnet + - constituent-cpd-id: + - constituent-base-element-id: vnf2 + constituent-cpd-id: vnf-data-ext + virtual-link-profile-id: datanet + vnfd-id: k8s_proxy_charm-vnf + description: NS with 2 VNFs with cloudinit connected by datanet and mgmtnet VLs + _admin: + userDefinedData: {} + revision: 1 + created: 1658990740.88281 + modified: 1658990741.09266 + projects_read: + - 51e0e80fe533469d98766caa16552a3e + projects_write: + - 51e0e80fe533469d98766caa16552a3e + onboardingState: ONBOARDED + operationalState: ENABLED + usageState: NOT_IN_USE + storage: + fs: mongo + path: /app/storage/ + folder: '12f320b5-2a57-40f4-82b5-020a6b1171d7:1' + pkg-dir: k8s_proxy_charm_ns + descriptor: k8s_proxy_charm_ns/k8s_proxy_charm_nsd.yaml + zipfile: k8s_proxy_charm_ns.tar.gz + datacenter: bad7338b-ae46-43d4-a434-c3337a8054ac + resource-orchestrator: osmopenmano + description: default description + constituent-vnfr-ref: + - 1b6a4eb3-4fbf-415e-985c-4aeb3161eec0 + - 17892d73-aa19-4b87-9a00-1d094f07a6b3 + operational-status: running + config-status: configured + detailed-status: Done + orchestration-progress: {} + create-time: 1658998097.57611 + nsd-name-ref: k8s_proxy_charm-ns + operational-events: [] + nsd-ref: k8s_proxy_charm-ns + nsd-id: 12f320b5-2a57-40f4-82b5-020a6b1171d7 + vnfd-id: + - 6d9e1ca1-f387-4d01-9876-066fc7311e0f + instantiate_params: + nsdId: 12f320b5-2a57-40f4-82b5-020a6b1171d7 + nsName: k8s-ns + nsDescription: default description + vimAccountId: bad7338b-ae46-43d4-a434-c3337a8054ac + vld: + - name: mgmtnet + vim-network-name: osm-ext + additionalParamsForNs: null + ns-instance-config-ref: dbfbd751-3de4-4e68-bd40-ec5ae0a53898 + id: dbfbd751-3de4-4e68-bd40-ec5ae0a53898 + ssh-authorized-key: null + flavor: + - id: '0' + memory-mb: 1024 + name: mgmtVM-flv + storage-gb: '10' + vcpu-count: 1 + vim_info: + 'vim:bad7338b-ae46-43d4-a434-c3337a8054ac': + vim_details: null + vim_id: 17a9ba76-beb7-4ad4-a481-97de37174866 + vim_status: DONE + - vcpu-count: 1 + memory-mb: 1024 + storage-gb: '10' + name: mgmtVM-flv + id: '1' + image: + - id: '0' + image: ubuntu18.04 + vim_info: + 'vim:bad7338b-ae46-43d4-a434-c3337a8054ac': + vim_details: null + vim_id: 919fc71a-6acd-4ee3-8123-739a9abbc2e7 + vim_status: DONE + - image: 'Canonical:UbuntuServer:18.04-LTS:latest' + vim-type: azure + id: '1' + - image: 'ubuntu-os-cloud:image-family:ubuntu-1804-lts' + vim-type: gcp + id: '2' + - image: ubuntu/images/hvm-ssd/ubuntu-artful-17.10-amd64-server-20180509 + vim-type: aws + id: '3' + affinity-or-anti-affinity-group: [] + revision: 1 + vld: + - id: mgmtnet + mgmt-network: true + name: mgmtnet + type: null + vim_info: + 'vim:bad7338b-ae46-43d4-a434-c3337a8054ac': + vim_account_id: bad7338b-ae46-43d4-a434-c3337a8054ac + vim_network_name: osm-ext + vim_details: > + {admin_state_up: true, availability_zone_hints: [], + availability_zones: [nova], created_at: '2019-10-17T23:44:03Z', + description: '', encapsulation: vlan, encapsulation_id: 2148, + encapsulation_type: vlan, id: 21ea5d92-24f1-40ab-8d28-83230e277a49, + ipv4_address_scope: null, + ipv6_address_scope: null, is_default: false, mtu: 1500, name: osm-ext, port_security_enabled: true, project_id: 456b6471010b4737b47a0dd599c920c5, 'provider:network_type': vlan, 'provider:physical_network': physnet1, 'provider:segmentation_id': 2148, revision_number: 1009, + 'router:external': true, segmentation_id: 2148, shared: true, status: ACTIVE, subnets: [{subnet: {allocation_pools: [{end: 172.21.249.255, start: 172.21.248.1}], cidr: 172.21.248.0/22, created_at: '2019-10-17T23:44:07Z', description: '', dns_nameservers: [], + enable_dhcp: true, gateway_ip: 172.21.251.254, host_routes: [], id: d14f68b7-8287-41fe-b533-dafb2240680a, ip_version: 4, ipv6_address_mode: null, ipv6_ra_mode: null, name: osm-ext-subnet, network_id: 21ea5d92-24f1-40ab-8d28-83230e277a49, project_id: 456b6471010b4737b47a0dd599c920c5, + revision_number: 5, service_types: [], subnetpool_id: null, tags: [], tenant_id: 456b6471010b4737b47a0dd599c920c5, updated_at: '2020-09-14T15:15:06Z'}}], tags: [], tenant_id: 456b6471010b4737b47a0dd599c920c5, type: data, updated_at: '2022-07-05T18:39:02Z'} + vim_id: 21ea5d92-24f1-40ab-8d28-83230e277a49 + vim_status: ACTIVE + - id: datanet + mgmt-network: false + name: datanet + type: null + vim_info: + 'vim:bad7338b-ae46-43d4-a434-c3337a8054ac': + vim_account_id: bad7338b-ae46-43d4-a434-c3337a8054ac + vim_network_name: null + vim_details: > + {admin_state_up: true, availability_zone_hints: [], + availability_zones: [nova], created_at: '2022-07-28T08:41:59Z', + description: '', encapsulation: vxlan, encapsulation_id: 27, + encapsulation_type: vxlan, id: 34056287-3cd5-42cb-92d3-413382b50813, + ipv4_address_scope: null, + ipv6_address_scope: null, mtu: 1450, name: k8s-ns-datanet, port_security_enabled: true, project_id: 71c7971a7cab4b72bd5c10dbe6617f1e, 'provider:network_type': vxlan, 'provider:physical_network': null, 'provider:segmentation_id': 27, revision_number: 2, 'router:external': false, + segmentation_id: 27, shared: false, status: ACTIVE, subnets: [{subnet: {allocation_pools: [{end: 192.168.181.254, start: 192.168.181.1}], cidr: 192.168.181.0/24, created_at: '2022-07-28T08:41:59Z', description: '', dns_nameservers: [], enable_dhcp: true, gateway_ip: null, + host_routes: [], id: ab2920f8-881b-4bef-82a5-9582a7930786, ip_version: 4, ipv6_address_mode: null, ipv6_ra_mode: null, name: k8s-ns-datanet-subnet, network_id: 34056287-3cd5-42cb-92d3-413382b50813, project_id: 71c7971a7cab4b72bd5c10dbe6617f1e, revision_number: 0, + service_types: [], subnetpool_id: null, tags: [], tenant_id: 71c7971a7cab4b72bd5c10dbe6617f1e, updated_at: '2022-07-28T08:41:59Z'}}], tags: [], tenant_id: 71c7971a7cab4b72bd5c10dbe6617f1e, type: bridge, updated_at: '2022-07-28T08:41:59Z'} + vim_id: 34056287-3cd5-42cb-92d3-413382b50813 + vim_status: ACTIVE + _admin: + created: 1658998097.58182 + modified: 1658998193.42562 + projects_read: + - 51e0e80fe533469d98766caa16552a3e + projects_write: + - 51e0e80fe533469d98766caa16552a3e + nsState: INSTANTIATED + current-operation: null + nslcmop: null + operation-type: null + deployed: + RO: + vnfd: [] + operational-status: running + VCA: + - target_element: vnf/vnf1 + member-vnf-index: vnf1 + vdu_id: null + kdu_name: null + vdu_count_index: 0 + operational-status: init + detailed-status: '' + step: initial-deploy + vnfd_id: k8s_proxy_charm-vnf + vdu_name: null + type: k8s_proxy_charm + ee_descriptor_id: simple-ee + charm_name: '' + ee_id: dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s.simple-ee-z0-vnf1-vnf.k8s + application: simple-ee-z0-vnf1-vnf + model: dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s + config_sw_installed: true + - target_element: vnf/vnf2 + member-vnf-index: vnf2 + vdu_id: null + kdu_name: null + vdu_count_index: 0 + operational-status: init + detailed-status: '' + step: initial-deploy + vnfd_id: k8s_proxy_charm-vnf + vdu_name: null + type: k8s_proxy_charm + ee_descriptor_id: simple-ee + charm_name: '' + ee_id: dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s.simple-ee-z0-vnf2-vnf.k8s + application: simple-ee-z0-vnf2-vnf + model: dbfbd751-3de4-4e68-bd40-ec5ae0a53898-k8s + config_sw_installed: true + K8s: [] +""" + +db_vnfrs_text = """ +- _id: 1b6a4eb3-4fbf-415e-985c-4aeb3161eec0 + id: 1b6a4eb3-4fbf-415e-985c-4aeb3161eec0 + nsr-id-ref: dbfbd751-3de4-4e68-bd40-ec5ae0a53898 + member-vnf-index-ref: vnf1 + additionalParamsForVnf: null + created-time: 1658998097.58036 + vnfd-ref: k8s_proxy_charm-vnf + vnfd-id: 6d9e1ca1-f387-4d01-9876-066fc7311e0f + vim-account-id: bad7338b-ae46-43d4-a434-c3337a8054ac + vca-id: null + vdur: + - _id: 38912ff7-5bdd-4228-911f-c2bee259c44a + additionalParams: + OSM: + count_index: 0 + member_vnf_index: vnf1 + ns_id: dbfbd751-3de4-4e68-bd40-ec5ae0a53898 + vdu: + mgmtVM-0: + count_index: 0 + interfaces: + dataVM-xe0: + name: dataVM-xe0 + mgmtVM-eth0: + name: mgmtVM-eth0 + vdu_id: mgmtVM + vdu_id: mgmtVM + vim_account_id: bad7338b-ae46-43d4-a434-c3337a8054ac + vnf_id: 1b6a4eb3-4fbf-415e-985c-4aeb3161eec0 + vnfd_id: 6d9e1ca1-f387-4d01-9876-066fc7311e0f + vnfd_ref: k8s_proxy_charm-vnf + affinity-or-anti-affinity-group-id: [] + alt-image-ids: + - '1' + - '2' + - '3' + cloud-init: '6d9e1ca1-f387-4d01-9876-066fc7311e0f:file:cloud-config.txt' + count-index: 0 + id: 38912ff7-5bdd-4228-911f-c2bee259c44a + interfaces: + - external-connection-point-ref: vnf-mgmt-ext + internal-connection-point-ref: mgmtVM-eth0-int + mgmt-interface: true + mgmt-vnf: true + name: mgmtVM-eth0 + ns-vld-id: mgmtnet + position: 1 + type: PARAVIRT + compute_node: nfvisrv11 + ip-address: 172.21.248.199 + mac-address: 'fa:16:3e:4d:65:e9' + pci: null + vlan: 2148 + - external-connection-point-ref: vnf-data-ext + internal-connection-point-ref: dataVM-xe0-int + name: dataVM-xe0 + ns-vld-id: datanet + position: 2 + type: PARAVIRT + compute_node: nfvisrv11 + ip-address: 192.168.181.179 + mac-address: 'fa:16:3e:ca:b5:d3' + pci: null + vlan: null + internal-connection-point: + - connection-point-id: mgmtVM-eth0-int + id: mgmtVM-eth0-int + name: mgmtVM-eth0-int + - connection-point-id: dataVM-xe0-int + id: dataVM-xe0-int + name: dataVM-xe0-int + ip-address: 172.21.248.199 + ns-flavor-id: '0' + ns-image-id: '0' + ssh-access-required: true + ssh-keys: + - > + ssh-rsa + AAAAB3NzaC1yc2EAAAADAQABAAACAQDW3dtEDKfwZL0WZp6LeJUZFlZzYAHP7M4AsJwl2YFO/wmblfrTpWZ8tRyGwyjQacB7Zb7J07wD5AZACE71A3Nc9zjI22/gWN7N8X+ZxH6ywcr1GdXBqZDBeOdzD4pRb11E9mydGZ9l++KtFRtlF4G7IFYuxkOiSCJrkgiKuVDGodtQ/6VUKwxuI8U6N7MxtIBN2L3IfvMwuNyTo1daiUabQMwQKt/Q8Zpp78zsZ6SoxU+eYAHzbeTjAfNwhA88nRzRZn7tQW+gWl9wbSINbr2+JetTN+BTot/CMPmKzzul9tZrzhSzck1QSM3UDrD36ctRdaLABnWCoxpm0wJthNt693xVrFP+bMgK2BR0fyu9WwVEcHkC9CZ8yoi37k5rGVtoDw6sW6lxQ5QKS+Plv/YjGKqK3Ro/UoIEhgxcW53uz4PveyMBss4geB9ad/1T8dtugd288qfCWJRBpJBrE497EalhHolF3L/2bEu3uCKN0TY4POzqP/5cuAUc/uTJ2mjZewJdlJtrn7IyFtSUypeuVmXRx5LwByQw9EwPhUZlKVjYEHYmu5YTKlFSWyorWgRLBBIK7LLPj+bCGgLeT+fXmip6eFquAyVtoQfDofQ/gc0OXEA1uKfK2VFKg1le+joz1WA/XieGSvKRQ4aZorYgi/FzbpxKj2a60cZubJMq5w== + root@lcm-7b6bcf7cdd-5h2ql + - >- + ssh-rsa + AAAAB3NzaC1yc2EAAAADAQABAAABAQDtg65/Jh3KDWC9+YzkTz8Md/uhalkjPo15DSxlUNWzYQNFUzaG5Pt0trDwQ29UOQIUy1CB9HpWSZMTA1ESet/+cyXWkZ9MznAmGLQBdnwqWU792UQf6rv74Zpned8MbnKQXfs8gog1ZFFKRMcwitNRqs8xs8XsPLE/l1Jo2QemhM0fIRofjJiLKYaKeGP59Fb8UlIeGDaxmIFgLs8bAZvrmjbae3o4b1fZDNboqlQbHb9rakxI9uCnsaBrCmelXpP9EFmENx85vdHEwCAfCRvSWKnbXuOojJJzFM5odoWFZo8AuIhEb5ZiLkGet3CvCfWZZPpQc4TuNDaY0t1XUegH + juju-client-key + vdu-id-ref: mgmtVM + vdu-name: mgmtVM + vim_info: + 'vim:bad7338b-ae46-43d4-a434-c3337a8054ac': + interfaces: + - vim_info: > + {admin_state_up: true, allowed_address_pairs: [], + 'binding:host_id': nfvisrv11, 'binding:profile': {}, + 'binding:vif_details': {bridge_name: br-int, connectivity: l2, + datapath_type: system, ovs_hybrid_plug: true, port_filter: true}, + 'binding:vif_type': ovs, 'binding:vnic_type': normal, + created_at: '2022-07-28T08:42:04Z', description: '', device_id: 1fabddca-0dcf-4702-a5f3-5cc028c2aba7, device_owner: 'compute:nova', extra_dhcp_opts: [], fixed_ips: [{ip_address: 172.21.248.199, subnet_id: d14f68b7-8287-41fe-b533-dafb2240680a}], id: e053d44f-1d67-4274-b85d-1cef243353d6, + mac_address: 'fa:16:3e:4d:65:e9', name: mgmtVM-eth0, network_id: 21ea5d92-24f1-40ab-8d28-83230e277a49, port_security_enabled: true, project_id: 71c7971a7cab4b72bd5c10dbe6617f1e, revision_number: 4, security_groups: [1de4b2c2-e4be-4e91-985c-d887e2715949], status: ACTIVE, + tags: [], tenant_id: 71c7971a7cab4b72bd5c10dbe6617f1e, updated_at: '2022-07-28T08:42:16Z'} + mac_address: 'fa:16:3e:4d:65:e9' + vim_net_id: 21ea5d92-24f1-40ab-8d28-83230e277a49 + vim_interface_id: e053d44f-1d67-4274-b85d-1cef243353d6 + compute_node: nfvisrv11 + pci: null + vlan: 2148 + ip_address: 172.21.248.199 + mgmt_vnf_interface: true + mgmt_vdu_interface: true + - vim_info: > + {admin_state_up: true, allowed_address_pairs: [], + 'binding:host_id': nfvisrv11, 'binding:profile': {}, + 'binding:vif_details': {bridge_name: br-int, connectivity: l2, + datapath_type: system, ovs_hybrid_plug: true, port_filter: true}, + 'binding:vif_type': ovs, 'binding:vnic_type': normal, + created_at: '2022-07-28T08:42:04Z', description: '', device_id: 1fabddca-0dcf-4702-a5f3-5cc028c2aba7, device_owner: 'compute:nova', extra_dhcp_opts: [], fixed_ips: [{ip_address: 192.168.181.179, subnet_id: ab2920f8-881b-4bef-82a5-9582a7930786}], id: 8a34c944-0fc1-41ae-9dbc-9743e5988162, + mac_address: 'fa:16:3e:ca:b5:d3', name: dataVM-xe0, network_id: 34056287-3cd5-42cb-92d3-413382b50813, port_security_enabled: true, project_id: 71c7971a7cab4b72bd5c10dbe6617f1e, revision_number: 4, security_groups: [1de4b2c2-e4be-4e91-985c-d887e2715949], status: ACTIVE, + tags: [], tenant_id: 71c7971a7cab4b72bd5c10dbe6617f1e, updated_at: '2022-07-28T08:42:15Z'} + mac_address: 'fa:16:3e:ca:b5:d3' + vim_net_id: 34056287-3cd5-42cb-92d3-413382b50813 + vim_interface_id: 8a34c944-0fc1-41ae-9dbc-9743e5988162 + compute_node: nfvisrv11 + pci: null + vlan: null + ip_address: 192.168.181.179 + vim_details: > + {'OS-DCF:diskConfig': MANUAL, 'OS-EXT-AZ:availability_zone': nova, + 'OS-EXT-SRV-ATTR:host': nfvisrv11, + 'OS-EXT-SRV-ATTR:hypervisor_hostname': nfvisrv11, + 'OS-EXT-SRV-ATTR:instance_name': instance-0002967a, + 'OS-EXT-STS:power_state': 1, 'OS-EXT-STS:task_state': null, + 'OS-EXT-STS:vm_state': active, 'OS-SRV-USG:launched_at': '2022-07-28T08:42:17.000000', 'OS-SRV-USG:terminated_at': null, accessIPv4: '', accessIPv6: '', addresses: {k8s-ns-datanet: [{'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:ca:b5:d3', 'OS-EXT-IPS:type': fixed, + addr: 192.168.181.179, version: 4}], osm-ext: [{'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:4d:65:e9', 'OS-EXT-IPS:type': fixed, addr: 172.21.248.199, version: 4}]}, config_drive: '', created: '2022-07-28T08:42:06Z', flavor: {id: 17a9ba76-beb7-4ad4-a481-97de37174866, + links: [{href: 'http://172.21.247.1:8774/flavors/17a9ba76-beb7-4ad4-a481-97de37174866', rel: bookmark}]}, hostId: 2aa7155bd281bd308d8e3776af56d428210c21aab788a8cbdf5ef500, id: 1fabddca-0dcf-4702-a5f3-5cc028c2aba7, image: {id: 919fc71a-6acd-4ee3-8123-739a9abbc2e7, + links: [{href: 'http://172.21.247.1:8774/images/919fc71a-6acd-4ee3-8123-739a9abbc2e7', rel: bookmark}]}, key_name: null, links: [{href: 'http://172.21.247.1:8774/v2.1/servers/1fabddca-0dcf-4702-a5f3-5cc028c2aba7', rel: self}, {href: 'http://172.21.247.1:8774/servers/1fabddca-0dcf-4702-a5f3-5cc028c2aba7', + rel: bookmark}], metadata: {}, name: k8s-ns-vnf1-mgmtVM-0, 'os-extended-volumes:volumes_attached': [], progress: 0, security_groups: [{name: default}, {name: default}], status: ACTIVE, tenant_id: 71c7971a7cab4b72bd5c10dbe6617f1e, updated: '2022-07-28T08:42:17Z', + user_id: f043c84f940b4fc8a01a98714ea97c80} + vim_id: 1fabddca-0dcf-4702-a5f3-5cc028c2aba7 + vim_status: ACTIVE + vim_name: k8s-ns-vnf1-mgmtVM-0 + virtual-storages: + - id: mgmtVM-storage + size-of-storage: '10' + status: ACTIVE + vim-id: 1fabddca-0dcf-4702-a5f3-5cc028c2aba7 + name: k8s-ns-vnf1-mgmtVM-0 + connection-point: + - name: vnf-mgmt-ext + connection-point-id: mgmtVM-eth0-int + connection-point-vdu-id: mgmtVM + id: vnf-mgmt-ext + - name: vnf-data-ext + connection-point-id: dataVM-xe0-int + connection-point-vdu-id: mgmtVM + id: vnf-data-ext + ip-address: 172.21.248.199 + revision: 1 + _admin: + created: 1658998097.58048 + modified: 1658998097.58048 + projects_read: + - 51e0e80fe533469d98766caa16552a3e + projects_write: + - 51e0e80fe533469d98766caa16552a3e + nsState: INSTANTIATED +""" diff --git a/tox.ini b/tox.ini index 2e1199f..5ae56bd 100644 --- a/tox.ini +++ b/tox.ini @@ -121,7 +121,8 @@ ignore = E125, E203, E226, - E241 + E241, + E501 exclude = .git, __pycache__, -- 2.17.1