From 9bc63ac2c1365535af344954b951b1ff04868ea1 Mon Sep 17 00:00:00 2001 From: aticig Date: Wed, 27 Jul 2022 09:32:06 +0300 Subject: [PATCH 1/1] Feature 10944 Change naming of charms Adding find_charm_name method and changing _deploy_n2vc and _heal_n2vc methods in LCM Change-Id: I62fdf3e66493c26e07e80ba7874badbe7c74c95e Signed-off-by: aticig --- osm_lcm/lcm_utils.py | 133 +++++++++++++ osm_lcm/ns.py | 18 ++ osm_lcm/tests/test_db_descriptors.py | 248 +++++++++++++++++++++++++ osm_lcm/tests/test_lcm.py | 1 - osm_lcm/tests/test_lcm_utils.py | 267 +++++++++++++++++++++++++++ osm_lcm/tests/test_ns.py | 2 +- 6 files changed, 667 insertions(+), 2 deletions(-) create mode 100644 osm_lcm/tests/test_lcm_utils.py diff --git a/osm_lcm/lcm_utils.py b/osm_lcm/lcm_utils.py index 1854da7..6d20318 100644 --- a/osm_lcm/lcm_utils.py +++ b/osm_lcm/lcm_utils.py @@ -20,9 +20,15 @@ import asyncio import checksumdir from collections import OrderedDict import os +import shutil +import traceback from time import time + +from osm_common.fsbase import FsException from osm_lcm.data_utils.database.database import Database from osm_lcm.data_utils.filesystem.filesystem import Filesystem +import yaml +from zipfile import ZipFile, BadZipfile # from osm_common.dbbase import DbException @@ -217,6 +223,133 @@ class LcmBase: ) ) + @staticmethod + def get_charm_name(charm_metadata_file: str) -> str: + """Get the charm name from metadata file. + + Args: + charm_metadata_file (str): charm metadata file full path + + Returns: + charm_name (str): charm name + + """ + # Read charm metadata.yaml to get the charm name + with open(charm_metadata_file, "r") as metadata_file: + content = yaml.safe_load(metadata_file) + charm_name = content["name"] + return str(charm_name) + + def _get_charm_path( + self, nsd_package_path: str, nsd_package_name: str, charm_folder_name: str + ) -> str: + """Get the full path of charm folder. + + Args: + nsd_package_path (str): NSD package full path + nsd_package_name (str): NSD package name + charm_folder_name (str): folder name + + Returns: + charm_path (str): charm folder full path + """ + charm_path = ( + self.fs.path + + nsd_package_path + + "/" + + nsd_package_name + + "/charms/" + + charm_folder_name + ) + return charm_path + + def _get_charm_metadata_file( + self, + charm_folder_name: str, + nsd_package_path: str, + nsd_package_name: str, + charm_path: str = None, + ) -> str: + """Get the path of charm metadata file. + + Args: + charm_folder_name (str): folder name + nsd_package_path (str): NSD package full path + nsd_package_name (str): NSD package name + charm_path (str): Charm full path + + Returns: + charm_metadata_file_path (str): charm metadata file full path + + """ + # Locate the charm metadata.yaml + if charm_folder_name.endswith(".charm"): + extract_path = ( + self.fs.path + + nsd_package_path + + "/" + + nsd_package_name + + "/charms/" + + charm_folder_name.split(".")[0] + ) + # Extract .charm to extract path + with ZipFile(charm_path, "r") as zipfile: + zipfile.extractall(extract_path) + return extract_path + "/metadata.yaml" + else: + return charm_path + "/metadata.yaml" + + def find_charm_name(self, db_nsr: dict, charm_folder_name: str) -> str: + """Get the charm name from metadata.yaml of charm package. + + Args: + db_nsr (dict): NS record as a dictionary + charm_folder_name (str): charm folder name + + Returns: + charm_name (str): charm name + """ + try: + if not charm_folder_name: + raise LcmException("charm_folder_name should be provided.") + + # Find nsd_package details: path, name + revision = db_nsr.get("revision", "") + nsd_package_path = ( + db_nsr["nsd-id"] + ":" + str(revision) if revision else db_nsr["nsd-id"] + ) + nsd_package_name = os.listdir(self.fs.path + nsd_package_path)[0] + + # Remove the existing nsd package and sync from FsMongo + shutil.rmtree(self.fs.path + nsd_package_path, ignore_errors=True) + self.fs.sync(from_path=nsd_package_path) + + # Get the charm path + charm_path = self._get_charm_path( + nsd_package_path, nsd_package_name, charm_folder_name + ) + + # Find charm metadata file full path + charm_metadata_file = self._get_charm_metadata_file( + charm_folder_name, nsd_package_path, nsd_package_name, charm_path + ) + + # Return charm name + return self.get_charm_name(charm_metadata_file) + + except ( + yaml.YAMLError, + IOError, + FsException, + KeyError, + TypeError, + FileNotFoundError, + BadZipfile, + ) as error: + self.logger.debug(traceback.format_exc()) + self.logger.error(f"{error} occured while getting the charm name") + raise LcmException(error) + class TaskRegistry(LcmBase): """ diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index 118b31e..b1c027a 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -3735,10 +3735,16 @@ class NsLcm(LcmBase): self.logger.debug( logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id) ) + + charm_name = "" + get_charm_name = False if "execution-environment-list" in descriptor_config: ee_list = descriptor_config.get("execution-environment-list", []) elif "juju" in descriptor_config: ee_list = [descriptor_config] # ns charms + if "execution-environment-list" not in descriptor_config: + # charm name is only required for ns charms + get_charm_name = True else: # other types as script are not supported ee_list = [] @@ -3752,6 +3758,8 @@ class NsLcm(LcmBase): ee_descriptor_id = ee_item.get("id") if ee_item.get("juju"): vca_name = ee_item["juju"].get("charm") + if get_charm_name: + charm_name = self.find_charm_name(db_nsr, str(vca_name)) vca_type = ( "lxc_proxy_charm" if ee_item["juju"].get("charm") is not None @@ -3810,6 +3818,7 @@ class NsLcm(LcmBase): "vdu_name": vdu_name, "type": vca_type, "ee_descriptor_id": ee_descriptor_id, + "charm_name": charm_name, } vca_index += 1 @@ -7832,10 +7841,16 @@ class NsLcm(LcmBase): self.logger.debug( logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id) ) + + charm_name = "" + get_charm_name = False if "execution-environment-list" in descriptor_config: ee_list = descriptor_config.get("execution-environment-list", []) elif "juju" in descriptor_config: ee_list = [descriptor_config] # ns charms + if "execution-environment-list" not in descriptor_config: + # charm name is only required for ns charms + get_charm_name = True else: # other types as script are not supported ee_list = [] @@ -7849,6 +7864,8 @@ class NsLcm(LcmBase): ee_descriptor_id = ee_item.get("id") if ee_item.get("juju"): vca_name = ee_item["juju"].get("charm") + if get_charm_name: + charm_name = self.find_charm_name(db_nsr, str(vca_name)) vca_type = ( "lxc_proxy_charm" if ee_item["juju"].get("charm") is not None @@ -7907,6 +7924,7 @@ class NsLcm(LcmBase): "vdu_name": vdu_name, "type": vca_type, "ee_descriptor_id": ee_descriptor_id, + "charm_name": charm_name, } vca_index += 1 diff --git a/osm_lcm/tests/test_db_descriptors.py b/osm_lcm/tests/test_db_descriptors.py index 9304908..d02b011 100644 --- a/osm_lcm/tests/test_db_descriptors.py +++ b/osm_lcm/tests/test_db_descriptors.py @@ -1235,6 +1235,254 @@ db_nsrs_text = """ vim-network-name: mgmt vnfd-id: - d96b1cdf-5ad6-49f7-bf65-907ada989293 + +- _id: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + name: ha_charm-ns2 + name-ref: ha_charm-ns2 + short-name: ha_charm-ns2 + admin-status: ENABLED + nsState: BROKEN + currentOperation: IDLE + currentOperationID: + errorDescription: 'Operation: INSTANTIATING.8e72f2b5-f466-4382-88a4-4575c9e07eb8, + Stage 5/5: running Day-1 primitives for NS.' + deploymentStatus: + configurationStatus: + - elementType: VDU + elementUnderConfiguration: userVM-0 + status: READY + - elementType: VDU + elementUnderConfiguration: policyVM-0 + status: READY + - elementType: NS + elementUnderConfiguration: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + status: BROKEN + vcaStatus: + nsd: + _id: a557cb0f-0dc9-494c-a9bd-69e8079767e7 + id: nscharm-ns + version: '1.0' + name: nscharm-ns + vnfd-id: + - nscharm-user-vnf + - nscharm-policy-vnf + virtual-link-desc: + - id: mgmtnet + mgmt-network: true + vim-network-name: osm-ext + df: + - id: default-df + vnf-profile: + - id: '1' + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: '1' + constituent-cpd-id: vnf-mgmt-ext + virtual-link-profile-id: mgmtnet + vnfd-id: nscharm-user-vnf + - id: '2' + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: '2' + constituent-cpd-id: vnf-mgmt-ext + virtual-link-profile-id: mgmtnet + vnfd-id: nscharm-policy-vnf + ns-configuration: + juju: + charm: ns_ubuntu-18.04-amd64.charm + config-primitive: + - name: add-user + parameter: + - name: username + data-type: STRING + initial-config-primitive: + - seq: '1' + name: config + parameter: + - name: juju-username + value: admin + - name: juju-password + value: a5611fc6452349cc6e45705d34c501d4 + - seq: '2' + name: add-user + parameter: + - name: username + value: root + description: NS with 2 VNFs + _admin: + userDefinedData: {} + revision: 1 + created: 1658868548.2641 + modified: 1658868548.89253 + projects_read: + - 51e0e80fe533469d98766caa16552a3e + projects_write: + - 51e0e80fe533469d98766caa16552a3e + onboardingState: ONBOARDED + operationalState: ENABLED + usageState: NOT_IN_USE + storage: + fs: mongo + path: "/app/storage/" + folder: a557cb0f-0dc9-494c-a9bd-69e8079767e7:1 + pkg-dir: nscharm_ns + descriptor: nscharm_ns/nscharm_nsd.yaml + zipfile: nscharm_ns.tar.gz + datacenter: bad7338b-ae46-43d4-a434-c3337a8054ac + resource-orchestrator: osmopenmano + description: default description + constituent-vnfr-ref: + - 303a6ccd-e6f2-4127-96a4-1e3b97956850 + - 0d0cd621-47db-4eef-a9e8-8edb71a34ea1 + operational-status: running + config-status: failed + orchestration-progress: {} + create-time: 1658868607.27119 + nsd-name-ref: nscharm-ns + operational-events: [] + nsd-ref: nscharm-ns + nsd-id: a557cb0f-0dc9-494c-a9bd-69e8079767e7 + vnfd-id: + - b5068dc9-a3cd-4a1e-b051-e36c3a9f10a4 + - 4aa63021-c816-456b-9998-804c5285a85d + instantiate_params: + nsdId: a557cb0f-0dc9-494c-a9bd-69e8079767e7 + nsName: ha_charm-ns2 + nsDescription: default description + vimAccountId: bad7338b-ae46-43d4-a434-c3337a8054ac + vld: + - name: mgmtnet + vim-network-name: osm-ext + additionalParamsForNs: + ns-instance-config-ref: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + id: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + ssh-authorized-key: + flavor: + - id: '0' + memory-mb: 1024 + name: userVM-flv + storage-gb: '10' + vcpu-count: 1 + vim_info: + vim:bad7338b-ae46-43d4-a434-c3337a8054ac: + vim_details: + vim_id: 17a9ba76-beb7-4ad4-a481-97de37174866 + vim_message: + vim_status: DONE + - id: '1' + memory-mb: 1024 + name: policyVM-flv + storage-gb: '10' + vcpu-count: 1 + vim_info: + vim:bad7338b-ae46-43d4-a434-c3337a8054ac: + vim_details: + vim_id: 17a9ba76-beb7-4ad4-a481-97de37174866 + vim_message: + vim_status: DONE + image: + - id: '0' + image: ubuntu18.04 + vim_info: + vim:bad7338b-ae46-43d4-a434-c3337a8054ac: + vim_details: + vim_id: 919fc71a-6acd-4ee3-8123-739a9abbc2e7 + vim_message: + vim_status: DONE + - image: ubuntu/images/hvm-ssd/ubuntu-artful-17.10-amd64-server-20180509 + vim-type: aws + id: '1' + - image: Canonical:UbuntuServer:18.04-LTS:latest + vim-type: azure + id: '2' + - image: ubuntu-os-cloud:image-family:ubuntu-1804-lts + vim-type: gcp + id: '3' + affinity-or-anti-affinity-group: [] + revision: 1 + vld: + - id: mgmtnet + mgmt-network: true + name: mgmtnet + type: + 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_message: + vim_status: ACTIVE + _admin: + created: 1658868607.2804 + modified: 1658868966.10105 + projects_read: + - 51e0e80fe533469d98766caa16552a3e + projects_write: + - 51e0e80fe533469d98766caa16552a3e + nsState: INSTANTIATED + current-operation: + nslcmop: + operation-type: + deployed: + RO: + vnfd: [] + operational-status: running + VCA: + - target_element: vnf/1/vdu/userVM/0 + member-vnf-index: '1' + vdu_id: userVM + kdu_name: + vdu_count_index: 0 + operational-status: init + detailed-status: '' + step: initial-deploy + vnfd_id: nscharm-user-vnf + vdu_name: + type: lxc_proxy_charm + ee_descriptor_id: vnf-user-ee + ee_id: b63aa1ba-996e-43a7-921a-1aca5ccbc63f.app-vnf-3b97956850-z0-vdu-uservm-cnt-z0-eh2hc.2 + application: app-vnf-3b97956850-z0-vdu-uservm-cnt-z0-eh2hc + model: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + config_sw_installed: true + - target_element: vnf/2/vdu/policyVM/0 + member-vnf-index: '2' + vdu_id: policyVM + kdu_name: + vdu_count_index: 0 + operational-status: init + detailed-status: '' + step: initial-deploy + vnfd_id: nscharm-policy-vnf + vdu_name: + type: lxc_proxy_charm + ee_descriptor_id: vnf-policy-ee + ee_id: b63aa1ba-996e-43a7-921a-1aca5ccbc63f.app-vnf-db71a34ea1-z0-vdu-policyvm-cnt-z0-tr1oc.0 + application: app-vnf-db71a34ea1-z0-vdu-policyvm-cnt-z0-tr1oc + model: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + config_sw_installed: true + - target_element: ns + member-vnf-index: + vdu_id: + kdu_name: + vdu_count_index: 0 + operational-status: init + detailed-status: '' + step: initial-deploy + vnfd_id: + vdu_name: + type: lxc_proxy_charm + ee_descriptor_id: + ee_id: b63aa1ba-996e-43a7-921a-1aca5ccbc63f.app-qmfbp.1 + application: app-qmfbp + model: b63aa1ba-996e-43a7-921a-1aca5ccbc63f + config_sw_installed: true + K8s: [] """ ro_ns_text = """ diff --git a/osm_lcm/tests/test_lcm.py b/osm_lcm/tests/test_lcm.py index af6f81d..bdd9a8d 100644 --- a/osm_lcm/tests/test_lcm.py +++ b/osm_lcm/tests/test_lcm.py @@ -63,7 +63,6 @@ def check_file_content(health_check_file: str) -> str: class TestLcm(TestCase): - def setUp(self): self.config_file = os.getcwd() + "/osm_lcm/tests/test_lcm_config_file.yaml" self.config_file_without_storage_path = tempfile.mkstemp()[1] diff --git a/osm_lcm/tests/test_lcm_utils.py b/osm_lcm/tests/test_lcm_utils.py new file mode 100644 index 0000000..13788e2 --- /dev/null +++ b/osm_lcm/tests/test_lcm_utils.py @@ -0,0 +1,267 @@ +# 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. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact: alfonso.tiernosepulveda@telefonica.com +## +import logging +import os +from unittest.mock import Mock, patch, MagicMock +from unittest import TestCase + +from osm_common.msgkafka import MsgKafka +from osm_common import fslocal +from osm_lcm.data_utils.database.database import Database +from osm_lcm.data_utils.filesystem.filesystem import Filesystem +from osm_lcm.lcm_utils import LcmBase, LcmException +from osm_lcm.tests import test_db_descriptors as descriptors +import yaml +from zipfile import BadZipfile + + +class TestLcmBase(TestCase): + + test_nsr_id = "b63aa1ba-996e-43a7-921a-1aca5ccbc63f" + nsd_package_path = "/" + test_nsr_id + nsd_package_name = "test_nsd" + charm_metadata_file = "/path/charm/metadata.yaml" + + def setUp(self): + # DB + Database.instance = None + self.db = Database({"database": {"driver": "memory"}}).instance.db + self.db.create_list("nsds", yaml.safe_load(descriptors.db_nsds_text)) + self.db.create_list("nsrs", yaml.safe_load(descriptors.db_nsrs_text)) + # Filesystem + self.fs = Filesystem({"storage": {"driver": "local", "path": "/"}}).instance.fs + # Create LCMBase class + self.msg = Mock(MsgKafka()) + self.logger = Mock(logging) + self.my_ns = LcmBase(self.msg, self.logger) + self.my_ns.fs = self.fs + self.my_ns.db = self.db + + def test_get_charm_name_successfully(self): + instance = self.my_ns + mock_open = MagicMock(open) + mock_yaml = MagicMock(yaml) + mock_yaml.safe_load.return_value = {"name": "test_charm"} + expected_result = "test_charm" + + with patch("osm_lcm.lcm_utils.open", mock_open), patch( + "osm_lcm.lcm_utils.yaml.safe_load", mock_yaml.safe_load + ): + result = instance.get_charm_name(TestLcmBase.charm_metadata_file) + self.assertEqual(result, expected_result, "wrong charm name") + self.assertEqual(mock_yaml.safe_load.call_count, 1) + self.assertEqual(mock_open.call_count, 1) + + def test_get_charm_name_can_not_open_metadata_file(self): + instance = self.my_ns + mock_open = MagicMock(open) + mock_open.side_effect = IOError + mock_yaml = MagicMock(create_autospec=True) + + with patch("osm_lcm.lcm_utils.open", mock_open), patch( + "osm_lcm.lcm_utils.yaml.safe_load", mock_yaml.safe_load + ): + with self.assertRaises(IOError): + instance.get_charm_name(TestLcmBase.charm_metadata_file) + mock_yaml.safe_load.assert_not_called() + self.assertEqual(mock_open.call_count, 1) + + def test_get_charm_name_wrong_metadata_file_format(self): + instance = self.my_ns + mock_open = MagicMock(open) + mock_yaml = MagicMock(create_autospec=True) + mock_yaml.safe_load.return_value = {} + + with patch("osm_lcm.lcm_utils.open", mock_open), patch( + "osm_lcm.lcm_utils.yaml.safe_load", mock_yaml.safe_load + ): + with self.assertRaises(KeyError): + instance.get_charm_name(TestLcmBase.charm_metadata_file) + self.assertEqual(mock_open.call_count, 1) + self.assertEqual(mock_yaml.safe_load.call_count, 1) + + def test_get_charm_path_successfully(self): + instance = self.my_ns + fs = fslocal.FsLocal() + fs.path = "/app/storage" + instance.fs = fs + charm_folder_name = "simple_charm" + expected_result = "/app/storage/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple_charm" + result = instance._get_charm_path( + TestLcmBase.nsd_package_path, TestLcmBase.nsd_package_name, charm_folder_name + ) + self.assertEqual(result, expected_result, "wrong_charm_path") + + def test_get_charm_metadata_file_charm_is_not_zipped(self): + instance = self.my_ns + fs = fslocal.FsLocal() + fs.path = "/app/storage" + instance.fs = fs + mock_zipfile = MagicMock(create_autospec=True) + charm_folder_name = "simple_charm" + charm_path = "/app/storage/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple_charm" + expected_result = "/app/storage/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple_charm/metadata.yaml" + + with patch("osm_lcm.lcm_utils.ZipFile", mock_zipfile): + result = instance._get_charm_metadata_file( + charm_folder_name, + TestLcmBase.nsd_package_path, + TestLcmBase.nsd_package_name, + charm_path=charm_path, + ) + self.assertEqual(result, expected_result, "wrong charm metadata path") + mock_zipfile.assert_not_called() + + def test_get_charm_metadata_file_charm_is_zipped(self): + instance = self.my_ns + fs = fslocal.FsLocal() + fs.path = "/app/storage" + instance.fs = fs + mock_zipfile = MagicMock(create_autospec=True) + mock_zipfile.side_effect = None + charm_folder_name = "simple_charm2.charm" + charm_path = "/app/storage/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple_charm" + expected_result = "/app/storage/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple_charm2/metadata.yaml" + + with patch("osm_lcm.lcm_utils.ZipFile", mock_zipfile): + result = instance._get_charm_metadata_file( + charm_folder_name, + TestLcmBase.nsd_package_path, + TestLcmBase.nsd_package_name, + charm_path=charm_path, + ) + self.assertEqual(result, expected_result, "wrong charm metadata path") + self.assertEqual(mock_zipfile.call_count, 1) + + def test_find_charm_name_successfully(self): + db_nsr = self.db.get_one("nsrs", {"_id": TestLcmBase.test_nsr_id}) + instance = self.my_ns + mock_listdir = MagicMock(os.listdir()) + mock_listdir.side_effect = None + mock_charm_path = MagicMock() + mock_metadata_file = MagicMock() + mock_metadata_file.return_value = ( + "/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple/metadata.yaml" + ) + mock_charm_name = MagicMock() + mock_charm_name.return_value = "test_charm" + expected_result = "test_charm" + + with patch("osm_lcm.lcm_utils.LcmBase._get_charm_path", mock_charm_path), patch( + "osm_lcm.lcm_utils.LcmBase._get_charm_metadata_file", mock_metadata_file + ), patch("osm_lcm.lcm_utils.LcmBase.get_charm_name", mock_charm_name), patch( + "osm_lcm.lcm_utils.os.listdir", mock_listdir + ): + + result = instance.find_charm_name(db_nsr, "simple") + self.assertEqual(result, expected_result, "Wrong charm name") + mock_charm_path.assert_called_once() + mock_metadata_file.assert_called_once() + mock_charm_name.assert_called_once_with( + "/b63aa1ba-996e-43a7-921a-1aca5ccbc63f/test_nsd/charms/simple/metadata.yaml" + ) + self.assertEqual(mock_listdir.call_count, 1) + + def test_find_charm_name_charm_bad_zipfile(self): + db_nsr = self.db.get_one("nsrs", {"_id": TestLcmBase.test_nsr_id}) + instance = self.my_ns + mock_listdir = MagicMock(os.listdir()) + mock_listdir.side_effect = None + mock_charm_path = MagicMock() + mock_metadata_file = MagicMock() + mock_metadata_file.side_effect = BadZipfile + mock_charm_name = MagicMock() + + with patch("osm_lcm.lcm_utils.LcmBase._get_charm_path", mock_charm_path), patch( + "osm_lcm.lcm_utils.LcmBase._get_charm_metadata_file", mock_metadata_file + ), patch("osm_lcm.lcm_utils.LcmBase.get_charm_name", mock_charm_name), patch( + "osm_lcm.lcm_utils.os.listdir", mock_listdir + ): + + with self.assertRaises(LcmException): + + instance.find_charm_name(db_nsr, "simple") + self.assertEqual(mock_listdir.call_count, 1) + self.assertEqual(mock_charm_path.call_count, 1) + self.assertEqual(mock_metadata_file.call_count, 1) + mock_charm_name.assert_not_called() + + def test_find_charm_name_charm_nsd_package_does_not_exist(self): + db_nsr = self.db.get_one("nsrs", {"_id": TestLcmBase.test_nsr_id}) + instance = self.my_ns + mock_listdir = MagicMock(os.listdir()) + mock_listdir.side_effect = FileNotFoundError + mock_charm_path = MagicMock() + mock_metadata_file = MagicMock() + mock_charm_name = MagicMock() + + with patch("osm_lcm.lcm_utils.LcmBase._get_charm_path", mock_charm_path), patch( + "osm_lcm.lcm_utils.LcmBase._get_charm_metadata_file", mock_metadata_file + ), patch("osm_lcm.lcm_utils.LcmBase.get_charm_name", mock_charm_name), patch( + "osm_lcm.lcm_utils.os.listdir", mock_listdir + ): + + with self.assertRaises(LcmException): + instance.find_charm_name(db_nsr, "simple") + self.assertEqual(mock_listdir.call_count, 1) + mock_charm_path.assert_not_called() + mock_metadata_file.assert_not_called() + mock_charm_name.assert_not_called() + + def test_find_charm_name_missing_input_charm_folder_name(self): + db_nsr = self.db.get_one("nsrs", {"_id": TestLcmBase.test_nsr_id}) + instance = self.my_ns + mock_listdir = MagicMock(os.listdir()) + mock_charm_path = MagicMock() + mock_metadata_file = MagicMock() + mock_charm_name = MagicMock() + + with patch("osm_lcm.lcm_utils.LcmBase._get_charm_path", mock_charm_path), patch( + "osm_lcm.lcm_utils.LcmBase._get_charm_metadata_file", mock_metadata_file + ), patch("osm_lcm.lcm_utils.LcmBase.get_charm_name", mock_charm_name), patch( + "osm_lcm.lcm_utils.os.listdir", mock_listdir + ): + + with self.assertRaises(LcmException): + instance.find_charm_name(db_nsr, "") + mock_charm_path.assert_not_called() + mock_metadata_file.assert_not_called() + mock_charm_name.assert_not_called() + mock_listdir.assert_not_called() + + def test_find_charm_name_can_not_open_metadata_file(self): + db_nsr = self.db.get_one("nsrs", {"_id": TestLcmBase.test_nsr_id}) + instance = self.my_ns + mock_listdir = MagicMock(os.listdir()) + mock_charm_path = MagicMock() + mock_metadata_file = MagicMock() + mock_charm_name = MagicMock() + mock_charm_name.side_effect = yaml.YAMLError + + with patch("osm_lcm.lcm_utils.LcmBase._get_charm_path", mock_charm_path), patch( + "osm_lcm.lcm_utils.LcmBase._get_charm_metadata_file", mock_metadata_file + ), patch("osm_lcm.lcm_utils.LcmBase.get_charm_name", mock_charm_name), patch( + "osm_lcm.lcm_utils.os.listdir", mock_listdir + ): + + with self.assertRaises(LcmException): + instance.find_charm_name(db_nsr, "simple") + self.assertEqual(mock_charm_path.call_count, 1) + self.assertEqual(mock_metadata_file.call_count, 1) + self.assertEqual(mock_charm_name.call_count, 1) + self.assertEqual(mock_listdir.call_count, 1) diff --git a/osm_lcm/tests/test_ns.py b/osm_lcm/tests/test_ns.py index 1441e72..560edc9 100644 --- a/osm_lcm/tests/test_ns.py +++ b/osm_lcm/tests/test_ns.py @@ -1557,7 +1557,7 @@ class TestMyNS(asynctest.TestCase): result = find_software_version(db_vnfd) self.assertEqual(result, expected_result, "VNFD software version is wrong") - with self.subTest(i=3, t="Check charm hash, Hash has did not change"): + with self.subTest(i=3, t="Check charm hash, Hash did not change"): # Testing method check_charm_hash_changed current_path, target_path = "/tmp/charm1", "/tmp/charm1" -- 2.25.1