+ async def test_deploy_kdus(self):
+ nsr_id = descriptors.test_ids["TEST-KDU"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-KDU"]["instantiate"]
+ db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
+ db_vnfr = self.db.get_one(
+ "vnfrs", {"nsr-id-ref": nsr_id, "member-vnf-index-ref": "multikdu"}
+ )
+ db_vnfrs = {"multikdu": db_vnfr}
+ db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
+ db_vnfds = [db_vnfd]
+ task_register = {}
+ logging_text = "KDU"
+ self.my_ns.k8sclusterhelm3.generate_kdu_instance_name = asynctest.mock.Mock()
+ self.my_ns.k8sclusterhelm3.generate_kdu_instance_name.return_value = "k8s_id"
+ self.my_ns.k8sclusterhelm3.install = asynctest.CoroutineMock()
+ self.my_ns.k8sclusterhelm3.synchronize_repos = asynctest.CoroutineMock(
+ return_value=("", "")
+ )
+ self.my_ns.k8sclusterhelm3.get_services = asynctest.CoroutineMock(
+ return_value=([])
+ )
+ await self.my_ns.deploy_kdus(
+ logging_text, nsr_id, nslcmop_id, db_vnfrs, db_vnfds, task_register
+ )
+ await asyncio.wait(list(task_register.keys()), timeout=100)
+ db_nsr = self.db.get_list("nsrs")[1]
+ self.assertIn(
+ "K8s",
+ db_nsr["_admin"]["deployed"],
+ "K8s entry not created at '_admin.deployed'",
+ )
+ self.assertIsInstance(
+ db_nsr["_admin"]["deployed"]["K8s"], list, "K8s entry is not of type list"
+ )
+ self.assertEqual(
+ len(db_nsr["_admin"]["deployed"]["K8s"]), 2, "K8s entry is not of type list"
+ )
+ k8s_instace_info = {
+ "kdu-instance": "k8s_id",
+ "k8scluster-uuid": "73d96432-d692-40d2-8440-e0c73aee209c",
+ "k8scluster-type": "helm-chart-v3",
+ "kdu-name": "ldap",
+ "member-vnf-index": "multikdu",
+ "namespace": None,
+ "kdu-deployment-name": None,
+ }
+
+ nsr_result = copy.deepcopy(db_nsr["_admin"]["deployed"]["K8s"][0])
+ nsr_kdu_model_result = nsr_result.pop("kdu-model")
+ expected_kdu_model = "stable/openldap:1.2.1"
+ self.assertEqual(nsr_result, k8s_instace_info)
+ self.assertTrue(
+ nsr_kdu_model_result in expected_kdu_model
+ or expected_kdu_model in nsr_kdu_model_result
+ )
+ nsr_result = copy.deepcopy(db_nsr["_admin"]["deployed"]["K8s"][1])
+ nsr_kdu_model_result = nsr_result.pop("kdu-model")
+ k8s_instace_info["kdu-name"] = "mongo"
+ expected_kdu_model = "stable/mongodb"
+ self.assertEqual(nsr_result, k8s_instace_info)
+ self.assertTrue(
+ nsr_kdu_model_result in expected_kdu_model
+ or expected_kdu_model in nsr_kdu_model_result
+ )
+
+ # Test remove_vnf() and related methods
+ @asynctest.fail_on(active_handles=True) # all async tasks must be completed
+ async def test_remove_vnf(self):
+ # Test REMOVE_VNF
+ nsr_id = descriptors.test_ids["TEST-UPDATE"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-UPDATE"]["removeVnf"]
+ vnf_instance_id = descriptors.test_ids["TEST-UPDATE"]["vnf"]
+ mock_wait_ng_ro = asynctest.CoroutineMock()
+ with patch("osm_lcm.ns.NsLcm._wait_ng_ro", mock_wait_ng_ro):
+ await self.my_ns.update(nsr_id, nslcmop_id)
+ expected_value = "COMPLETED"
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ self.assertEqual(return_value, expected_value)
+ with self.assertRaises(Exception) as context:
+ self.db.get_one("vnfrs", {"_id": vnf_instance_id})
+ self.assertTrue(
+ "database exception Not found entry with filter"
+ in str(context.exception)
+ )
+
+ # test vertical scale executes sucessfully
+ # @patch("osm_lcm.ng_ro.status.response")
+ @asynctest.fail_on(active_handles=True)
+ async def test_vertical_scaling(self):
+ nsr_id = descriptors.test_ids["TEST-V-SCALE"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-V-SCALE"]["instantiate"]
+
+ # calling the vertical scale fucntion
+ # self.my_ns.RO.status = asynctest.CoroutineMock(self.my_ns.RO.status, side_effect=self._ro_status("update"))
+ mock_wait_ng_ro = asynctest.CoroutineMock()
+ with patch("osm_lcm.ns.NsLcm._wait_ng_ro", mock_wait_ng_ro):
+ await self.my_ns.vertical_scale(nsr_id, nslcmop_id)
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ expected_value = "COMPLETED"
+ self.assertEqual(return_value, expected_value)
+
+ # test vertical scale executes fail
+ @asynctest.fail_on(active_handles=True)
+ async def test_vertical_scaling_fail(self):
+ # get th nsr nad nslcmops id from descriptors
+ nsr_id = descriptors.test_ids["TEST-V-SCALE"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-V-SCALE"]["instantiate-1"]
+
+ # calling the vertical scale fucntion
+ await self.my_ns.vertical_scale(nsr_id, nslcmop_id)
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ expected_value = "FAILED"
+ self.assertEqual(return_value, expected_value)
+
+ # async def test_instantiate_pdu(self):
+ # nsr_id = descriptors.test_ids["TEST-A"]["ns"]
+ # nslcmop_id = descriptors.test_ids["TEST-A"]["instantiate"]
+ # # Modify vnfd/vnfr to change KDU for PDU. Adding keys that NBI will already set
+ # self.db.set_one("vnfrs", {"nsr-id-ref": nsr_id, "member-vnf-index-ref": "1"},
+ # update_dict={"ip-address": "10.205.1.46",
+ # "vdur.0.pdu-id": "53e1ec21-2464-451e-a8dc-6e311d45b2c8",
+ # "vdur.0.pdu-type": "PDU-TYPE-1",
+ # "vdur.0.ip-address": "10.205.1.46",
+ # },
+ # unset={"vdur.status": None})
+ # self.db.set_one("vnfrs", {"nsr-id-ref": nsr_id, "member-vnf-index-ref": "2"},
+ # update_dict={"ip-address": "10.205.1.47",
+ # "vdur.0.pdu-id": "53e1ec21-2464-451e-a8dc-6e311d45b2c8",
+ # "vdur.0.pdu-type": "PDU-TYPE-1",
+ # "vdur.0.ip-address": "10.205.1.47",
+ # },
+ # unset={"vdur.status": None})
+
+ # await self.my_ns.instantiate(nsr_id, nslcmop_id)
+ # db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
+ # self.assertEqual(db_nsr.get("nsState"), "READY", str(db_nsr.get("errorDescription ")))
+ # self.assertEqual(db_nsr.get("currentOperation"), "IDLE", "currentOperation different than 'IDLE'")
+ # self.assertEqual(db_nsr.get("currentOperationID"), None, "currentOperationID different than None")
+ # self.assertEqual(db_nsr.get("errorDescription "), None, "errorDescription different than None")
+ # self.assertEqual(db_nsr.get("errorDetail"), None, "errorDetail different than None")
+
+ # @asynctest.fail_on(active_handles=True) # all async tasks must be completed
+ # async def test_terminate_without_configuration(self):
+ # nsr_id = descriptors.test_ids["TEST-A"]["ns"]
+ # nslcmop_id = descriptors.test_ids["TEST-A"]["terminate"]
+ # # set instantiation task as completed
+ # self.db.set_list("nslcmops", {"nsInstanceId": nsr_id, "_id.ne": nslcmop_id},
+ # update_dict={"operationState": "COMPLETED"})
+ # self.db.set_one("nsrs", {"_id": nsr_id},
+ # update_dict={"_admin.deployed.VCA.0": None, "_admin.deployed.VCA.1": None})
+
+ # await self.my_ns.terminate(nsr_id, nslcmop_id)
+ # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
+ # self.assertEqual(db_nslcmop.get("operationState"), 'COMPLETED', db_nslcmop.get("detailed-status"))
+ # db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
+ # self.assertEqual(db_nsr.get("nsState"), "NOT_INSTANTIATED", str(db_nsr.get("errorDescription ")))
+ # self.assertEqual(db_nsr["_admin"].get("nsState"), "NOT_INSTANTIATED", str(db_nsr.get("errorDescription ")))
+ # self.assertEqual(db_nsr.get("currentOperation"), "IDLE", "currentOperation different than 'IDLE'")
+ # self.assertEqual(db_nsr.get("currentOperationID"), None, "currentOperationID different than None")
+ # self.assertEqual(db_nsr.get("errorDescription "), None, "errorDescription different than None")
+ # self.assertEqual(db_nsr.get("errorDetail"), None, "errorDetail different than None")
+ # db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
+ # for vnfr in db_vnfrs_list:
+ # self.assertEqual(vnfr["_admin"].get("nsState"), "NOT_INSTANTIATED", "Not instantiated")
+
+ # @asynctest.fail_on(active_handles=True) # all async tasks must be completed
+ # async def test_terminate_primitive(self):
+ # nsr_id = descriptors.test_ids["TEST-A"]["ns"]
+ # nslcmop_id = descriptors.test_ids["TEST-A"]["terminate"]
+ # # set instantiation task as completed
+ # self.db.set_list("nslcmops", {"nsInstanceId": nsr_id, "_id.ne": nslcmop_id},
+ # update_dict={"operationState": "COMPLETED"})
+
+ # # modify vnfd descriptor to include terminate_primitive
+ # terminate_primitive = [{
+ # "name": "touch",
+ # "parameter": [{"name": "filename", "value": "terminate_filename"}],
+ # "seq": '1'
+ # }]
+ # db_vnfr = self.db.get_one("vnfrs", {"nsr-id-ref": nsr_id, "member-vnf-index-ref": "1"})
+ # self.db.set_one("vnfds", {"_id": db_vnfr["vnfd-id"]},
+ # {"vnf-configuration.0.terminate-config-primitive": terminate_primitive})
+
+ # await self.my_ns.terminate(nsr_id, nslcmop_id)
+ # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
+ # self.assertEqual(db_nslcmop.get("operationState"), 'COMPLETED', db_nslcmop.get("detailed-status"))
+ # db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
+ # self.assertEqual(db_nsr.get("nsState"), "NOT_INSTANTIATED", str(db_nsr.get("errorDescription ")))
+ # self.assertEqual(db_nsr["_admin"].get("nsState"), "NOT_INSTANTIATED", str(db_nsr.get("errorDescription ")))
+ # self.assertEqual(db_nsr.get("currentOperation"), "IDLE", "currentOperation different than 'IDLE'")
+ # self.assertEqual(db_nsr.get("currentOperationID"), None, "currentOperationID different than None")
+ # self.assertEqual(db_nsr.get("errorDescription "), None, "errorDescription different than None")
+ # self.assertEqual(db_nsr.get("errorDetail"), None, "errorDetail different than None")
+
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ @patch("osm_lcm.data_utils.vnfd.find_software_version")
+ @patch("osm_lcm.lcm_utils.check_juju_bundle_existence")
+ async def test_update_change_vnfpkg_sw_version_not_changed(
+ self,
+ mock_juju_bundle,
+ mock_software_version,
+ mock_charm_upgrade,
+ mock_charm_hash,
+ ):
+ """Update type: CHANGE_VNFPKG, latest_vnfd revision changed,
+ Charm package changed, sw-version is not changed"""
+ self.db.set_one(
+ "vnfds",
+ q_filter={"_id": vnfd_id},
+ update_dict={"_admin.revision": 3, "kdu": []},
+ )
+
+ self.db.set_one(
+ "vnfds_revisions",
+ 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})
+
+ mock_charm_hash.return_value = True
+ mock_software_version.side_effect = ["1.0", "1.0"]
+
+ task = asyncio.Future()
+ task.set_result(("COMPLETED", "some_output"))
+ mock_charm_upgrade.return_value = task
+
+ instance = self.my_ns
+ fs = deepcopy(update_fs)
+ instance.fs = fs
+
+ expected_operation_state = "COMPLETED"
+ expected_operation_error = ""
+ expected_vnfr_revision = 3
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_operation_state = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ return_operation_error = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "errorMessage"
+ )
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ mock_charm_hash.assert_called_with(
+ f"{vnfd_id}:1/hackfest_3charmed_vnfd/charms/simple",
+ f"{vnfd_id}:3/hackfest_3charmed_vnfd/charms/simple",
+ )
+ self.assertEqual(fs.sync.call_count, 2)
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_operation_state, expected_operation_state)
+ self.assertEqual(return_operation_error, expected_operation_error)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ @patch("osm_lcm.data_utils.vnfd.find_software_version")
+ @patch("osm_lcm.lcm_utils.check_juju_bundle_existence")
+ async def test_update_change_vnfpkg_vnfd_revision_not_changed(
+ self,
+ mock_juju_bundle,
+ mock_software_version,
+ mock_charm_upgrade,
+ mock_charm_hash,
+ ):
+ """Update type: CHANGE_VNFPKG, latest_vnfd revision not changed"""
+ self.db.set_one(
+ "vnfds", q_filter={"_id": vnfd_id}, update_dict={"_admin.revision": 1}
+ )
+ self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1})
+
+ mock_charm_hash.return_value = True
+
+ task = asyncio.Future()
+ task.set_result(("COMPLETED", "some_output"))
+ mock_charm_upgrade.return_value = task
+
+ instance = self.my_ns
+
+ expected_operation_state = "COMPLETED"
+ expected_operation_error = ""
+ expected_vnfr_revision = 1
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_operation_state = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ return_operation_error = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "errorMessage"
+ )
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ mock_charm_hash.assert_not_called()
+ mock_software_version.assert_not_called()
+ mock_juju_bundle.assert_not_called()
+ mock_charm_upgrade.assert_not_called()
+ update_fs.sync.assert_not_called()
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_operation_state, expected_operation_state)
+ self.assertEqual(return_operation_error, expected_operation_error)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ @patch("osm_lcm.data_utils.vnfd.find_software_version")
+ @patch("osm_lcm.lcm_utils.check_juju_bundle_existence")
+ async def test_update_change_vnfpkg_charm_is_not_changed(
+ self,
+ mock_juju_bundle,
+ mock_software_version,
+ mock_charm_upgrade,
+ mock_charm_hash,
+ ):
+ """Update type: CHANGE_VNFPKG, latest_vnfd revision changed
+ Charm package is not changed, sw-version is not changed"""
+ self.db.set_one(
+ "vnfds",
+ q_filter={"_id": vnfd_id},
+ update_dict={"_admin.revision": 3, "kdu": []},
+ )
+ self.db.set_one(
+ "vnfds_revisions",
+ 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})
+
+ mock_charm_hash.return_value = False
+ mock_software_version.side_effect = ["1.0", "1.0"]
+
+ instance = self.my_ns
+ fs = deepcopy(update_fs)
+ instance.fs = fs
+ expected_operation_state = "COMPLETED"
+ expected_operation_error = ""
+ expected_vnfr_revision = 3
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_operation_state = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ return_operation_error = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "errorMessage"
+ )
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ mock_charm_hash.assert_called_with(
+ f"{vnfd_id}:1/hackfest_3charmed_vnfd/charms/simple",
+ f"{vnfd_id}:3/hackfest_3charmed_vnfd/charms/simple",
+ )
+ self.assertEqual(fs.sync.call_count, 2)
+ self.assertEqual(mock_charm_hash.call_count, 1)
+ mock_juju_bundle.assert_not_called()
+ mock_charm_upgrade.assert_not_called()
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_operation_state, expected_operation_state)
+ self.assertEqual(return_operation_error, expected_operation_error)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ @patch("osm_lcm.lcm_utils.check_juju_bundle_existence")
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ @patch("osm_lcm.lcm_utils.get_charm_artifact_path")
+ async def test_update_change_vnfpkg_sw_version_changed(
+ self, mock_charm_artifact, mock_charm_upgrade, mock_charm_hash, mock_juju_bundle
+ ):
+ """Update type: CHANGE_VNFPKG, latest_vnfd revision changed
+ Charm package exists, sw-version changed."""
+ self.db.set_one(
+ "vnfds",
+ q_filter={"_id": vnfd_id},
+ update_dict={"_admin.revision": 3, "software-version": "3.0", "kdu": []},
+ )
+ self.db.set_one(
+ "vnfds_revisions",
+ 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},
+ )
+ mock_charm_hash.return_value = False
+
+ mock_charm_artifact.side_effect = [
+ f"{vnfd_id}:1/hackfest_3charmed_vnfd/charms/simple",
+ f"{vnfd_id}:3/hackfest_3charmed_vnfd/charms/simple",
+ ]
+
+ instance = self.my_ns
+ fs = deepcopy(update_fs)
+ instance.fs = fs
+ expected_operation_state = "FAILED"
+ expected_operation_error = "FAILED Checking if existing VNF has charm: Software version change is not supported as VNF instance 6421c7c9-d865-4fb4-9a13-d4275d243e01 has charm."
+ expected_vnfr_revision = 1
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_operation_state = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ return_operation_error = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "errorMessage"
+ )
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ self.assertEqual(fs.sync.call_count, 2)
+ mock_charm_hash.assert_not_called()
+ mock_juju_bundle.assert_not_called()
+ mock_charm_upgrade.assert_not_called()
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_operation_state, expected_operation_state)
+ self.assertEqual(return_operation_error, expected_operation_error)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ @patch("osm_lcm.lcm_utils.check_juju_bundle_existence")
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ @patch("osm_lcm.data_utils.vnfd.find_software_version")
+ async def test_update_change_vnfpkg_juju_bundle_exists(
+ self,
+ mock_software_version,
+ mock_charm_upgrade,
+ mock_charm_hash,
+ mock_juju_bundle,
+ ):
+ """Update type: CHANGE_VNFPKG, latest_vnfd revision changed
+ Charm package exists, sw-version not changed, juju-bundle exists"""
+ # Upgrade is not allowed with juju bundles, this will cause TypeError
+ self.db.set_one(
+ "vnfds",
+ q_filter={"_id": vnfd_id},
+ update_dict={
+ "_admin.revision": 5,
+ "software-version": "1.0",
+ "kdu": [{"kdu_name": "native-kdu", "juju-bundle": "stable/native-kdu"}],
+ },
+ )
+ self.db.set_one(
+ "vnfds_revisions",
+ q_filter={"_id": vnfd_id + ":1"},
+ update_dict={
+ "_admin.revision": 1,
+ "software-version": "1.0",
+ "kdu": [{"kdu_name": "native-kdu", "juju-bundle": "stable/native-kdu"}],
+ },
+ )
+ self.db.set_one(
+ "nsrs",
+ q_filter={"_id": nsr_id},
+ update_dict={
+ "_admin.deployed.VCA.0.kdu_name": "native-kdu",
+ },
+ )
+ self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1})
+
+ mock_charm_hash.side_effect = [True]
+ mock_software_version.side_effect = ["1.0", "1.0"]
+ mock_juju_bundle.return_value = True
+ instance = self.my_ns
+ fs = deepcopy(update_fs)
+ instance.fs = fs
+
+ expected_vnfr_revision = 1
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ self.assertEqual(fs.sync.call_count, 2)
+ mock_charm_upgrade.assert_not_called()
+ mock_charm_hash.assert_not_called()
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ @patch("osm_lcm.lcm_utils.LcmBase.check_charm_hash_changed")
+ @patch(
+ "osm_lcm.ns.NsLcm._ns_charm_upgrade", new_callable=asynctest.Mock(autospec=True)
+ )
+ async def test_update_change_vnfpkg_charm_upgrade_failed(
+ self, mock_charm_upgrade, mock_charm_hash
+ ):
+ """ "Update type: CHANGE_VNFPKG, latest_vnfd revision changed"
+ Charm package exists, sw-version not changed, charm-upgrade failed"""
+ self.db.set_one(
+ "vnfds",
+ q_filter={"_id": vnfd_id},
+ 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": [],
+ },
+ )
+ self.db.set_one("vnfrs", q_filter={"_id": vnfr_id}, update_dict={"revision": 1})
+
+ mock_charm_hash.return_value = True
+
+ task = asyncio.Future()
+ task.set_result(("FAILED", "some_error"))
+ mock_charm_upgrade.return_value = task
+
+ instance = self.my_ns
+ fs = deepcopy(update_fs)
+ instance.fs = fs
+ expected_operation_state = "FAILED"
+ expected_operation_error = "some_error"
+ expected_vnfr_revision = 1
+ expected_ns_state = "INSTANTIATED"
+ expected_ns_operational_state = "running"
+
+ await instance.update(nsr_id, nslcmop_id)
+ return_operation_state = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ return_operation_error = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "errorMessage"
+ )
+ return_ns_operational_state = self.db.get_one("nsrs", {"_id": nsr_id}).get(
+ "operational-status"
+ )
+ return_vnfr_revision = self.db.get_one("vnfrs", {"_id": vnfr_id}).get(
+ "revision"
+ )
+ return_ns_state = self.db.get_one("nsrs", {"_id": nsr_id}).get("nsState")
+ self.assertEqual(fs.sync.call_count, 2)
+ self.assertEqual(mock_charm_hash.call_count, 1)
+ self.assertEqual(mock_charm_upgrade.call_count, 1)
+ self.assertEqual(return_ns_state, expected_ns_state)
+ self.assertEqual(return_operation_state, expected_operation_state)
+ self.assertEqual(return_operation_error, expected_operation_error)
+ self.assertEqual(return_ns_operational_state, expected_ns_operational_state)
+ self.assertEqual(return_vnfr_revision, expected_vnfr_revision)
+
+ def test_ns_update_find_sw_version_vnfd_not_includes(self):
+ """Find software version, VNFD does not have software version"""
+
+ db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
+ expected_result = "1.0"
+ result = find_software_version(db_vnfd)
+ self.assertEqual(result, expected_result, "Default sw version should be 1.0")
+
+ def test_ns_update_find_sw_version_vnfd_includes(self):
+ """Find software version, VNFD includes software version"""
+
+ db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
+ db_vnfd["software-version"] = "3.1"
+ expected_result = "3.1"
+ result = find_software_version(db_vnfd)
+ self.assertEqual(result, expected_result, "VNFD software version is wrong")
+
+ @patch("os.path.exists")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charmdir_hash")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charm_hash")
+ def test_ns_update_check_charm_hash_not_changed(
+ self, mock_compare_charm_hash, mock_compare_charmdir_hash, mock_path_exists
+ ):
+ """Check charm hash, Hash did not change"""
+
+ current_path, target_path = "/tmp/charm1", "/tmp/charm1"
+
+ fs = Mock()
+ fs.path.__add__ = Mock()
+ fs.path.side_effect = [current_path, target_path]
+ fs.path.__add__.side_effect = [current_path, target_path]
+
+ mock_path_exists.side_effect = [True, True]
+
+ mock_compare_charmdir_hash.return_value = callable(False)
+ mock_compare_charm_hash.return_value = callable(False)
+
+ instance = self.my_ns
+ instance.fs = fs
+ expected_result = False
+
+ result = instance.check_charm_hash_changed(current_path, target_path)
+ self.assertEqual(result, expected_result, "Wrong charm hash control value")
+ self.assertEqual(mock_path_exists.call_count, 2)
+ self.assertEqual(mock_compare_charmdir_hash.call_count, 1)
+ self.assertEqual(mock_compare_charm_hash.call_count, 0)
+
+ @patch("os.path.exists")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charmdir_hash")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charm_hash")
+ def test_ns_update_check_charm_hash_changed(
+ self, mock_compare_charm_hash, mock_compare_charmdir_hash, mock_path_exists
+ ):
+ """Check charm hash, Hash has changed"""
+
+ current_path, target_path = "/tmp/charm1", "/tmp/charm2"
+
+ fs = Mock()
+ fs.path.__add__ = Mock()
+ fs.path.side_effect = [current_path, target_path, current_path, target_path]
+ fs.path.__add__.side_effect = [
+ current_path,
+ target_path,
+ current_path,
+ target_path,
+ ]
+
+ mock_path_exists.side_effect = [True, True]
+ mock_compare_charmdir_hash.return_value = callable(True)
+ mock_compare_charm_hash.return_value = callable(True)
+
+ instance = self.my_ns
+ instance.fs = fs
+ expected_result = True
+
+ result = instance.check_charm_hash_changed(current_path, target_path)
+ self.assertEqual(result, expected_result, "Wrong charm hash control value")
+ self.assertEqual(mock_path_exists.call_count, 2)
+ self.assertEqual(mock_compare_charmdir_hash.call_count, 1)
+ self.assertEqual(mock_compare_charm_hash.call_count, 0)
+
+ @patch("os.path.exists")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charmdir_hash")
+ @patch("osm_lcm.lcm_utils.LcmBase.compare_charm_hash")
+ def test_ns_update_check_no_charm_path(
+ self, mock_compare_charm_hash, mock_compare_charmdir_hash, mock_path_exists
+ ):
+ """Check charm hash, Charm path does not exist"""
+
+ current_path, target_path = "/tmp/charm1", "/tmp/charm2"
+
+ fs = Mock()
+ fs.path.__add__ = Mock()
+ fs.path.side_effect = [current_path, target_path, current_path, target_path]
+ fs.path.__add__.side_effect = [
+ current_path,
+ target_path,
+ current_path,
+ target_path,
+ ]
+
+ mock_path_exists.side_effect = [True, False]
+
+ mock_compare_charmdir_hash.return_value = callable(False)
+ mock_compare_charm_hash.return_value = callable(False)
+ instance = self.my_ns
+ instance.fs = fs
+
+ with self.assertRaises(LcmException):
+ instance.check_charm_hash_changed(current_path, target_path)
+ self.assertEqual(mock_path_exists.call_count, 2)
+ self.assertEqual(mock_compare_charmdir_hash.call_count, 0)
+ self.assertEqual(mock_compare_charm_hash.call_count, 0)
+
+ def test_ns_update_check_juju_bundle_existence_bundle_exists(self):
+ """Check juju bundle existence"""
+ test_vnfd2 = self.db.get_one(
+ "vnfds", {"_id": "d96b1cdf-5ad6-49f7-bf65-907ada989293"}
+ )
+ expected_result = "stable/native-kdu"
+ result = check_juju_bundle_existence(test_vnfd2)
+ self.assertEqual(result, expected_result, "Wrong juju bundle name")
+
+ def test_ns_update_check_juju_bundle_existence_bundle_does_not_exist(self):
+ """Check juju bundle existence"""
+ test_vnfd1 = self.db.get_one("vnfds", {"_id": vnfd_id})
+ expected_result = None
+ result = check_juju_bundle_existence(test_vnfd1)
+ self.assertEqual(result, expected_result, "Wrong juju bundle name")
+
+ def test_ns_update_check_juju_bundle_existence_empty_vnfd(self):
+ """Check juju bundle existence"""
+ test_vnfd1 = {}
+ expected_result = None
+ result = check_juju_bundle_existence(test_vnfd1)
+ self.assertEqual(result, expected_result, "Wrong juju bundle name")
+
+ def test_ns_update_check_juju_bundle_existence_invalid_vnfd(self):
+ """Check juju bundle existence"""
+ test_vnfd1 = [{"_id": vnfd_id}]
+ with self.assertRaises(AttributeError):
+ check_juju_bundle_existence(test_vnfd1)
+
+ 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",
+ }
+ charm_name = "simple"
+ charm_type = "lxc_proxy_charm"
+ revision = 3
+ expected_result = f"{vnfd_id}:3/hackfest_3charmed_vnfd/charms/simple"
+ result = get_charm_artifact_path(base_folder, charm_name, charm_type, revision)
+ self.assertEqual(result, expected_result, "Wrong charm artifact path")
+
+ def test_ns_update_check_juju_charm_artifacts_base_folder_wthout_pkgdir(self):
+ """Check charm artifacts, SOL004 packages"""
+ base_folder = {
+ "folder": vnfd_id,
+ }
+ charm_name = "basic"
+ charm_type, revision = "", ""
+ expected_result = f"{vnfd_id}/Scripts/helm-charts/basic"
+ result = get_charm_artifact_path(base_folder, charm_name, charm_type, revision)
+ self.assertEqual(result, expected_result, "Wrong charm artifact path")
+