X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_lcm%2Ftests%2Ftest_ns.py;h=91ad6a3c3cf5e562542b65ffd9dab108e1f605b9;hb=4c0e6805c44f9ed1d0bb35161bf69645f5b84151;hp=1082648432cc70961db3cca4ceb4bc5f9261dc55;hpb=afff693a2ae9757aee5f731ee12bca70cdb9a907;p=osm%2FLCM.git diff --git a/osm_lcm/tests/test_ns.py b/osm_lcm/tests/test_ns.py index 1082648..91ad6a3 100644 --- a/osm_lcm/tests/test_ns.py +++ b/osm_lcm/tests/test_ns.py @@ -21,6 +21,7 @@ import asyncio from copy import deepcopy import yaml import copy +from n2vc.exceptions import N2VCException from os import getenv from osm_lcm import ns from osm_common.msgkafka import MsgKafka @@ -30,6 +31,7 @@ from osm_lcm.lcm_utils import TaskRegistry from osm_lcm.ng_ro import NgRoClient from osm_lcm.data_utils.database.database import Database from osm_lcm.data_utils.filesystem.filesystem import Filesystem +from osm_lcm.data_utils.vca import Relation, EERelation, DeployedVCA from osm_lcm.data_utils.vnfd import find_software_version from osm_lcm.lcm_utils import check_juju_bundle_existence, get_charm_artifact_path from osm_lcm.lcm_utils import LcmException @@ -97,7 +99,7 @@ def callable(a): return a -class TestMyNS(asynctest.TestCase): +class TestBaseNS(asynctest.TestCase): async def _n2vc_DeployCharms( self, model_name, @@ -115,7 +117,7 @@ class TestMyNS(asynctest.TestCase): ("active", "Ready!"), ): # call callback after some time - asyncio.sleep(5, loop=self.loop) + asyncio.sleep(5) callback(model_name, application_name, status, message, *callback_args) @staticmethod @@ -185,8 +187,17 @@ class TestMyNS(asynctest.TestCase): return str(uuid4()) async def setUp(self): - - # Mock DB + self.mock_db() + self.mock_kafka() + self.mock_filesystem() + self.mock_task_registry() + self.mock_vca_k8s() + self.create_nslcm_class() + self.mock_logging() + self.mock_vca_n2vc() + self.mock_ro() + + def mock_db(self): if not getenv("OSMLCMTEST_DB_NOMOCK"): # Cleanup singleton Database instance Database.instance = None @@ -194,18 +205,15 @@ class TestMyNS(asynctest.TestCase): self.db = Database({"database": {"driver": "memory"}}).instance.db self.db.create_list("vnfds", yaml.safe_load(descriptors.db_vnfds_text)) self.db.create_list( - "vnfds_revisions", - yaml.safe_load(descriptors.db_vnfds_revisions_text), + "vnfds_revisions", yaml.safe_load(descriptors.db_vnfds_revisions_text) ) self.db.create_list("nsds", yaml.safe_load(descriptors.db_nsds_text)) self.db.create_list("nsrs", yaml.safe_load(descriptors.db_nsrs_text)) self.db.create_list( - "vim_accounts", - yaml.safe_load(descriptors.db_vim_accounts_text), + "vim_accounts", yaml.safe_load(descriptors.db_vim_accounts_text) ) self.db.create_list( - "k8sclusters", - yaml.safe_load(descriptors.db_k8sclusters_text), + "k8sclusters", yaml.safe_load(descriptors.db_k8sclusters_text) ) self.db.create_list( "nslcmops", yaml.safe_load(descriptors.db_nslcmops_text) @@ -213,10 +221,10 @@ class TestMyNS(asynctest.TestCase): self.db.create_list("vnfrs", yaml.safe_load(descriptors.db_vnfrs_text)) self.db_vim_accounts = yaml.safe_load(descriptors.db_vim_accounts_text) - # Mock kafka + def mock_kafka(self): self.msg = asynctest.Mock(MsgKafka()) - # Mock filesystem + def mock_filesystem(self): if not getenv("OSMLCMTEST_FS_NOMOCK"): self.fs = asynctest.Mock( Filesystem({"storage": {"driver": "local", "path": "/"}}).instance.fs @@ -228,13 +236,13 @@ class TestMyNS(asynctest.TestCase): # self.fs.file_open.return_value.__enter__.return_value = asynctest.MagicMock() # called on a python "with" # self.fs.file_open.return_value.__enter__.return_value.read.return_value = "" # empty file - # Mock TaskRegistry + def mock_task_registry(self): self.lcm_tasks = asynctest.Mock(TaskRegistry()) self.lcm_tasks.lock_HA.return_value = True self.lcm_tasks.waitfor_related_HA.return_value = None self.lcm_tasks.lookfor_related.return_value = ("", []) - # Mock VCA - K8s + def mock_vca_k8s(self): if not getenv("OSMLCMTEST_VCA_K8s_NOMOCK"): ns.K8sJujuConnector = asynctest.MagicMock(ns.K8sJujuConnector) ns.K8sHelmConnector = asynctest.MagicMock(ns.K8sHelmConnector) @@ -244,17 +252,17 @@ class TestMyNS(asynctest.TestCase): ns.N2VCJujuConnector = asynctest.MagicMock(ns.N2VCJujuConnector) ns.LCMHelmConn = asynctest.MagicMock(ns.LCMHelmConn) - # Create NsLCM class - self.my_ns = ns.NsLcm(self.msg, self.lcm_tasks, lcm_config, self.loop) + def create_nslcm_class(self): + self.my_ns = ns.NsLcm(self.msg, self.lcm_tasks, lcm_config) self.my_ns.fs = self.fs self.my_ns.db = self.db self.my_ns._wait_dependent_n2vc = asynctest.CoroutineMock() - # Mock logging + def mock_logging(self): if not getenv("OSMLCMTEST_LOGGING_NOMOCK"): self.my_ns.logger = asynctest.Mock(self.my_ns.logger) - # Mock VCA - N2VC + def mock_vca_n2vc(self): if not getenv("OSMLCMTEST_VCA_NOMOCK"): pub_key = getenv("OSMLCMTEST_NS_PUBKEY", "ssh-rsa test-pub-key t@osm.com") # self.my_ns.n2vc = asynctest.Mock(N2VC()) @@ -298,12 +306,13 @@ class TestMyNS(asynctest.TestCase): self.my_ns.n2vc.delete_namespace = asynctest.CoroutineMock( return_value=None ) + self.my_ns.n2vc.register_execution_environment = asynctest.CoroutineMock( + return_value="model-name.application-name.k8s" + ) - # Mock RO + def mock_ro(self): if not getenv("OSMLCMTEST_RO_NOMOCK"): - self.my_ns.RO = asynctest.Mock( - NgRoClient(self.loop, **lcm_config.RO.to_dict()) - ) + self.my_ns.RO = asynctest.Mock(NgRoClient(**lcm_config.RO.to_dict())) # TODO first time should be empty list, following should return a dict # self.my_ns.RO.get_list = asynctest.CoroutineMock(self.my_ns.RO.get_list, return_value=[]) self.my_ns.RO.deploy = asynctest.CoroutineMock( @@ -315,87 +324,8 @@ class TestMyNS(asynctest.TestCase): # "description": "done"}}) self.my_ns.RO.delete = asynctest.CoroutineMock(self.my_ns.RO.delete) - # @asynctest.fail_on(active_handles=True) # all async tasks must be completed - # async def test_instantiate(self): - # nsr_id = descriptors.test_ids["TEST-A"]["ns"] - # nslcmop_id = descriptors.test_ids["TEST-A"]["instantiate"] - # # print("Test instantiate started") - - # # delete deployed information of database - # if not getenv("OSMLCMTEST_DB_NOMOCK"): - # if self.db.get_list("nsrs")[0]["_admin"].get("deployed"): - # del self.db.get_list("nsrs")[0]["_admin"]["deployed"] - # for db_vnfr in self.db.get_list("vnfrs"): - # db_vnfr.pop("ip_address", None) - # for db_vdur in db_vnfr["vdur"]: - # db_vdur.pop("ip_address", None) - # db_vdur.pop("mac_address", None) - # if getenv("OSMLCMTEST_RO_VIMID"): - # self.db.get_list("vim_accounts")[0]["_admin"]["deployed"]["RO"] = getenv("OSMLCMTEST_RO_VIMID") - # if getenv("OSMLCMTEST_RO_VIMID"): - # self.db.get_list("nsrs")[0]["_admin"]["deployed"]["RO"] = getenv("OSMLCMTEST_RO_VIMID") - - # await self.my_ns.instantiate(nsr_id, nslcmop_id) - - # self.msg.aiowrite.assert_called_once_with("ns", "instantiated", - # {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id, - # "operationState": "COMPLETED"}, - # loop=self.loop) - # self.lcm_tasks.lock_HA.assert_called_once_with('ns', 'nslcmops', nslcmop_id) - # if not getenv("OSMLCMTEST_LOGGING_NOMOCK"): - # self.assertTrue(self.my_ns.logger.debug.called, "Debug method not called") - # self.my_ns.logger.error.assert_not_called() - # self.my_ns.logger.exception().assert_not_called() - - # if not getenv("OSMLCMTEST_DB_NOMOCK"): - # self.assertTrue(self.db.set_one.called, "db.set_one not called") - # db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) - # db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}) - # self.assertEqual(db_nsr["_admin"].get("nsState"), "INSTANTIATED", "Not instantiated") - # for vnfr in db_vnfrs_list: - # self.assertEqual(vnfr["_admin"].get("nsState"), "INSTANTIATED", "Not instantiated") - - # if not getenv("OSMLCMTEST_VCA_NOMOCK"): - # # check intial-primitives called - # self.assertTrue(self.my_ns.n2vc.exec_primitive.called, - # "Exec primitive not called for initial config primitive") - # for _call in self.my_ns.n2vc.exec_primitive.call_args_list: - # self.assertIn(_call[1]["primitive_name"], ("config", "touch"), - # "called exec primitive with a primitive different than config or touch") - - # # TODO add more checks of called methods - # # TODO add a terminate - - # async def test_instantiate_ee_list(self): - # # Using modern IM where configuration is in the new format of execution_environment_list - # ee_descriptor_id = "charm_simple" - # non_used_initial_primitive = { - # "name": "not_to_be_called", - # "seq": 3, - # "execution-environment-ref": "not_used_ee" - # } - # ee_list = [ - # { - # "id": ee_descriptor_id, - # "juju": {"charm": "simple"}, - - # }, - # ] - - # self.db.set_one( - # "vnfds", - # q_filter={"_id": "7637bcf8-cf14-42dc-ad70-c66fcf1e6e77"}, - # update_dict={"vnf-configuration.0.execution-environment-list": ee_list, - # "vnf-configuration.0.initial-config-primitive.0.execution-environment-ref": ee_descriptor_id, - # "vnf-configuration.0.initial-config-primitive.1.execution-environment-ref": ee_descriptor_id, - # "vnf-configuration.0.initial-config-primitive.2": non_used_initial_primitive, - # "vnf-configuration.0.config-primitive.0.execution-environment-ref": ee_descriptor_id, - # "vnf-configuration.0.config-primitive.0.execution-environment-primitive": "touch_charm", - # }, - # unset={"vnf-configuration.juju": None}) - # await self.test_instantiate() - # # this will check that the initial-congig-primitive 'not_to_be_called' is not called +class TestMyNS(TestBaseNS): @asynctest.fail_on(active_handles=True) async def test_start_stop_rebuild_pass(self): nsr_id = descriptors.test_ids["TEST-OP-VNF"]["ns"] @@ -501,13 +431,16 @@ class TestMyNS(asynctest.TestCase): ): if ( v.get("execution-environment-list") - and "juju" in v["execution-environment-list"][k] + and "juju" in v["execution-environment-list"][0] ): expected_value = self.db.get_list("nsrs")[i][ "vcaStatus" ] await self.my_ns._on_update_n2vc_db( - "nsrs", {"_id": nsr_id}, "_admin.deployed.VCA.0", {} + "nsrs", + {"_id": nsr_id}, + "_admin.deployed.VCA.{}".format(k), + {}, ) return_value = self.db.get_list("nsrs")[i]["vcaStatus"] self.assertEqual(return_value, expected_value) @@ -1180,11 +1113,7 @@ class TestMyNS(asynctest.TestCase): q_filter={"_id": vnfd_id + ":1"}, update_dict={"_admin.revision": 1, "kdu": []}, ) - self.db.set_one( - "vnfrs", - q_filter={"_id": vnfr_id}, - update_dict={"revision": 1}, - ) + self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1}) mock_charm_hash.return_value = False mock_charm_artifact.side_effect = [ @@ -1262,9 +1191,7 @@ class TestMyNS(asynctest.TestCase): self.db.set_one( "nsrs", q_filter={"_id": nsr_id}, - update_dict={ - "_admin.deployed.VCA.0.kdu_name": "native-kdu", - }, + update_dict={"_admin.deployed.VCA.0.kdu_name": "native-kdu"}, ) self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1}) @@ -1306,20 +1233,12 @@ class TestMyNS(asynctest.TestCase): self.db.set_one( "vnfds", q_filter={"_id": vnfd_id}, - update_dict={ - "_admin.revision": 3, - "software-version": "1.0", - "kdu": [], - }, + update_dict={"_admin.revision": 3, "software-version": "1.0", "kdu": []}, ) self.db.set_one( "vnfds_revisions", q_filter={"_id": vnfd_id + ":1"}, - update_dict={ - "_admin.revision": 1, - "software-version": "1.0", - "kdu": [], - }, + update_dict={"_admin.revision": 1, "software-version": "1.0", "kdu": []}, ) self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1}) @@ -1506,10 +1425,7 @@ class TestMyNS(asynctest.TestCase): def test_ns_update_check_juju_charm_artifacts_base_folder_wth_pkgdir(self): """Check charm artifacts""" - base_folder = { - "folder": vnfd_id, - "pkg-dir": "hackfest_3charmed_vnfd", - } + base_folder = {"folder": vnfd_id, "pkg-dir": "hackfest_3charmed_vnfd"} charm_name = "simple" charm_type = "lxc_proxy_charm" revision = 3 @@ -1519,9 +1435,7 @@ class TestMyNS(asynctest.TestCase): def test_ns_update_check_juju_charm_artifacts_base_folder_wthout_pkgdir(self): """Check charm artifacts, SOL004 packages""" - base_folder = { - "folder": vnfd_id, - } + base_folder = {"folder": vnfd_id} charm_name = "basic" charm_type, revision = "", "" expected_result = f"{vnfd_id}/Scripts/helm-charts/basic" @@ -1529,5 +1443,165 @@ class TestMyNS(asynctest.TestCase): self.assertEqual(result, expected_result, "Wrong charm artifact path") +class TestInstantiateN2VC(TestBaseNS): + async def setUp(self): + await super().setUp() + self.db_nsr = yaml.safe_load(descriptors.db_nsrs_text)[0] + self.db_vnfr = yaml.safe_load(descriptors.db_vnfrs_text)[0] + self.vca_index = 1 + self.my_ns._write_configuration_status = Mock() + + async def call_instantiate_N2VC(self): + logging_text = "N2VC Instantiation" + config_descriptor = {"config-access": {"ssh-access": {"default-user": "admin"}}} + base_folder = {"pkg-dir": "", "folder": "~"} + stage = ["Stage", "Message"] + + await self.my_ns.instantiate_N2VC( + logging_text=logging_text, + vca_index=self.vca_index, + nsi_id="nsi_id", + db_nsr=self.db_nsr, + db_vnfr=self.db_vnfr, + vdu_id=None, + kdu_name=None, + vdu_index=None, + kdu_index=None, + config_descriptor=config_descriptor, + deploy_params={}, + base_folder=base_folder, + nslcmop_id="nslcmop_id", + stage=stage, + vca_type="native_charm", + vca_name="vca_name", + ee_config_descriptor={}, + ) + + def check_config_status(self, expected_status): + self.my_ns._write_configuration_status.assert_called_with( + nsr_id=self.db_nsr["_id"], vca_index=self.vca_index, status=expected_status + ) + + async def call_ns_add_relation(self): + ee_relation = EERelation( + { + "nsr-id": self.db_nsr["_id"], + "vdu-profile-id": None, + "kdu-resource-profile-id": None, + "vnf-profile-id": "hackfest_vnf1", + "execution-environment-ref": "f48163a6-c807-47bc-9682-f72caef5af85.alf-c-ab", + "endpoint": "127.0.0.1", + } + ) + + relation = Relation("relation-name", ee_relation, ee_relation) + cached_vnfrs = {"hackfest_vnf1": self.db_vnfr} + + return await self.my_ns._add_relation( + relation=relation, + vca_type="native_charm", + db_nsr=self.db_nsr, + cached_vnfds={}, + cached_vnfrs=cached_vnfrs, + ) + + async def test_add_relation_ok(self): + await self.call_instantiate_N2VC() + self.check_config_status(expected_status="READY") + + async def test_add_relation_returns_false_raises_exception(self): + self.my_ns._add_vca_relations = asynctest.CoroutineMock(return_value=False) + + with self.assertRaises(LcmException) as exception: + await self.call_instantiate_N2VC() + + exception_msg = "Relations could not be added to VCA." + self.assertTrue(exception_msg in str(exception.exception)) + self.check_config_status(expected_status="BROKEN") + + async def test_add_relation_raises_lcm_exception(self): + exception_msg = "Relations FAILED" + self.my_ns._add_vca_relations = asynctest.CoroutineMock( + side_effect=LcmException(exception_msg) + ) + + with self.assertRaises(LcmException) as exception: + await self.call_instantiate_N2VC() + + self.assertTrue(exception_msg in str(exception.exception)) + self.check_config_status(expected_status="BROKEN") + + async def test_n2vc_add_relation_fails_raises_exception(self): + exception_msg = "N2VC failed to add relations" + self.my_ns.n2vc.add_relation = asynctest.CoroutineMock( + side_effect=N2VCException(exception_msg) + ) + with self.assertRaises(LcmException) as exception: + await self.call_ns_add_relation() + self.assertTrue(exception_msg in str(exception.exception)) + + async def test_n2vc_add_relation_ok_returns_true(self): + self.my_ns.n2vc.add_relation = asynctest.CoroutineMock(return_value=None) + self.assertTrue(await self.call_ns_add_relation()) + + +class TestGetVNFRelations(TestBaseNS): + async def setUp(self): + await super().setUp() + self.db_nsd = yaml.safe_load(descriptors.db_nsds_text)[0] + + def test_ns_charm_vca_returns_empty_relations(self): + ns_charm_vca = {"member-vnf-index": None, "target_element": "ns"} + nsr_id = self.db_nsd["id"] + deployed_vca = DeployedVCA(nsr_id, ns_charm_vca) + + expected_relations = [] + self.assertEqual( + expected_relations, + self.my_ns._get_vnf_relations( + nsr_id=nsr_id, nsd=self.db_nsd, vca=deployed_vca, cached_vnfds={} + ), + ) + + def test_vnf_returns_relation(self): + vnf_vca = { + "member-vnf-index": "1", + "target_element": "vnf/0", + "ee_descriptor_id": "simple-ee", + "vdu_id": "mgmtVM", + } + nsr_id = self.db_nsd["id"] + deployed_vca = DeployedVCA(nsr_id, vnf_vca) + + provider_dict = { + "nsr-id": nsr_id, + "vnf-profile-id": "1", + "vdu-profile-id": "mgmtVM", + "kdu-resource-profile-id": None, + "execution-environment-ref": "simple-ee", + "endpoint": "interface", + } + + requirer_dict = { + "nsr-id": nsr_id, + "vnf-profile-id": "1", + "vdu-profile-id": "dataVM", + "kdu-resource-profile-id": None, + "execution-environment-ref": "simple-ee", + "endpoint": "interface", + } + + provider = EERelation(provider_dict) + requirer = EERelation(requirer_dict) + relation = Relation("relation", provider, requirer) + + relations_found = self.my_ns._get_vnf_relations( + nsr_id=nsr_id, nsd=self.db_nsd, vca=deployed_vca, cached_vnfds={} + ) + + self.assertEqual(1, len(relations_found)) + self.assertEqual(relation, relations_found[0]) + + if __name__ == "__main__": asynctest.main()