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
)
)
+ @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):
"""
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 = """
--- /dev/null
+# 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)