# Copyright (c) 2019 NTT DATA # # 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. import base64 import fixtures import json import os import requests import shutil import six.moves.urllib.error as urlerr import sys import tacker.conf import yaml from glance_store import exceptions as store_exceptions from oslo_config import cfg from six.moves import urllib from tacker import auth from tacker.common import coordination from tacker.common import csar_utils from tacker.common import exceptions from tacker.conductor import conductor_server from tacker import context from tacker.glance_store import store as glance_store from tacker import objects from tacker.objects import fields from tacker.plugins.common import constants from tacker.tests.unit import base as unit_base from tacker.tests.unit.conductor import fakes from tacker.tests.unit.db.base import SqlTestCase from tacker.tests.unit.db import utils as db_utils from tacker.tests.unit.objects import fakes as fake_obj from tacker.tests.unit.vnflcm import fakes as vnflcm_fakes from tacker.tests.unit.vnfm.infra_drivers.openstack.fixture_data import client from tacker.tests.unit.vnfm.infra_drivers.openstack.fixture_data import \ fixture_data_utils as fd_utils import tacker.tests.unit.vnfm.test_nfvo_client as nfvo_client from tacker.tests import utils from tacker.tests import uuidsentinel import unittest from unittest import mock CONF = tacker.conf.CONF class FakeVnfLcmDriver(mock.Mock): pass class FakeVNFMPlugin(mock.Mock): pass class TestConductor(SqlTestCase, unit_base.FixturedTestCase): client_fixture_class = client.ClientFixture sdk_connection_fixure_class = client.SdkConnectionFixture def setUp(self): super(TestConductor, self).setUp() self.addCleanup(mock.patch.stopall) self.context = context.get_admin_context() self._mock_vnflcm_driver() self._mock_vnfm_plugin() self.conductor = conductor_server.Conductor('host') self.vnf_package = self._create_vnf_package() self.instance_uuid = uuidsentinel.instance_id self.temp_dir = self.useFixture(fixtures.TempDir()).path def _mock_vnfm_plugin(self): self.vnfm_plugin = mock.Mock(wraps=FakeVNFMPlugin()) fake_vnfm_plugin = mock.Mock() fake_vnfm_plugin.return_value = self.vnfm_plugin self._mock( 'tacker.vnfm.plugin.VNFMPlugin', fake_vnfm_plugin) def _mock_vnflcm_driver(self): self.vnflcm_driver = mock.Mock(wraps=FakeVnfLcmDriver()) fake_vnflcm_driver = mock.Mock() fake_vnflcm_driver.return_value = self.vnflcm_driver self._mock( 'tacker.vnflcm.vnflcm_driver.VnfLcmDriver', fake_vnflcm_driver) def _create_vnf_package(self): vnfpkgm = objects.VnfPackage(context=self.context, **fakes.VNF_PACKAGE_DATA) vnfpkgm.create() return vnfpkgm def _create_vnf_package_vnfd(self): return fakes.get_vnf_package_vnfd() def _create_subscriptions(self, auth_params=None): class DummyLcmSubscription: def __init__(self, auth_params=None): if auth_params: self.subscription_authentication = json.dumps( auth_params).encode() self.id = uuidsentinel.lcm_subscription_id.encode() self.callback_uri = 'https://localhost/callback'.encode() def __getattr__(self, name): try: return object.__getattr__(self, name) except AttributeError: return None return [DummyLcmSubscription(auth_params)] def assert_auth_basic( self, acutual_request, expected_user_name, expected_password): actual_auth = acutual_request._request.headers.get("Authorization") expected_auth = base64.b64encode( '{}:{}'.format( expected_user_name, expected_password).encode('utf-8')).decode() self.assertEqual("Basic " + expected_auth, actual_auth) def assert_auth_client_credentials(self, acutual_request, expected_token): actual_auth = acutual_request._request.headers.get( "Authorization") self.assertEqual("Bearer " + expected_token, actual_auth) @mock.patch.object(conductor_server.Conductor, '_onboard_vnf_package') @mock.patch.object(conductor_server, 'revert_upload_vnf_package') @mock.patch.object(csar_utils, 'load_csar_data') @mock.patch.object(glance_store, 'load_csar') def test_upload_vnf_package_content(self, mock_load_csar, mock_load_csar_data, mock_revert, mock_onboard): mock_load_csar_data.return_value = (mock.ANY, mock.ANY, mock.ANY) mock_load_csar.return_value = '/var/lib/tacker/5f5d99c6-844a-4c3' \ '1-9e6d-ab21b87dcfff.zip' self.conductor.upload_vnf_package_content( self.context, self.vnf_package) mock_load_csar.assert_called() mock_load_csar_data.assert_called() mock_onboard.assert_called() @mock.patch.object(conductor_server.Conductor, '_onboard_vnf_package') @mock.patch.object(glance_store, 'store_csar') @mock.patch.object(conductor_server, 'revert_upload_vnf_package') @mock.patch.object(csar_utils, 'load_csar_data') @mock.patch.object(glance_store, 'load_csar') def test_upload_vnf_package_from_uri(self, mock_load_csar, mock_load_csar_data, mock_revert, mock_store, mock_onboard): address_information = "http://test.zip" mock_load_csar_data.return_value = (mock.ANY, mock.ANY, mock.ANY) mock_load_csar.return_value = '/var/lib/tacker/5f5d99c6-844a' \ '-4c31-9e6d-ab21b87dcfff.zip' mock_store.return_value = 'location', 0, 'checksum',\ 'multihash', 'loc_meta' self.conductor.upload_vnf_package_from_uri(self.context, self.vnf_package, address_information, user_name=None, password=None) mock_load_csar.assert_called() mock_load_csar_data.assert_called() mock_store.assert_called() mock_onboard.assert_called() self.assertEqual('multihash', self.vnf_package.hash) self.assertEqual('location', self.vnf_package.location_glance_store) @mock.patch.object(glance_store, 'delete_csar') def test_delete_vnf_package(self, mock_delete_csar): self.vnf_package.__setattr__('onboarding_state', 'ONBOARDED') self.conductor.delete_vnf_package(self.context, self.vnf_package) mock_delete_csar.assert_called() def test_get_vnf_package_vnfd_with_tosca_meta_file_in_csar(self): fake_csar = fakes.create_fake_csar_dir(self.vnf_package.id, self.temp_dir) expected_data = fakes.get_expected_vnfd_data() result = self.conductor.get_vnf_package_vnfd(self.context, self.vnf_package) self.assertEqual(expected_data, result) shutil.rmtree(fake_csar) def test_get_vnf_package_vnfd_with_single_yaml_csar(self): fake_csar = fakes.create_fake_csar_dir( self.vnf_package.id, self.temp_dir, csar_without_tosca_meta=True) result = self.conductor.get_vnf_package_vnfd(self.context, self.vnf_package) # only one key present in the result shows that it contains only one # yaml file self.assertEqual(1, len(result.keys())) shutil.rmtree(fake_csar) @mock.patch.object(glance_store, 'load_csar') def test_get_vnf_package_vnfd_download_from_glance_store(self, mock_load_csar): fake_csar = os.path.join(self.temp_dir, self.vnf_package.id) cfg.CONF.set_override('vnf_package_csar_path', self.temp_dir, group='vnf_package') fake_csar_zip, _ = utils.create_csar_with_unique_vnfd_id( './tacker/tests/etc/samples/etsi/nfv/sample_vnfpkg_tosca_vnfd') mock_load_csar.return_value = fake_csar_zip expected_data = fakes.get_expected_vnfd_data(zip_file=fake_csar_zip) result = self.conductor.get_vnf_package_vnfd(self.context, self.vnf_package) self.assertEqual(expected_data, result) shutil.rmtree(fake_csar) os.remove(fake_csar_zip) @mock.patch.object(glance_store, 'load_csar') def test_get_vnf_package_vnfd_exception_from_glance_store(self, mock_load_csar): mock_load_csar.side_effect = store_exceptions.NotFound self.assertRaises(exceptions.FailedToGetVnfdData, self.conductor.get_vnf_package_vnfd, self.context, self.vnf_package) @mock.patch.object(conductor_server.Conductor, '_read_vnfd_files') def test_get_vnf_package_vnfd_exception_from_read_vnfd_files( self, mock_read_vnfd_files): fake_csar = fakes.create_fake_csar_dir(self.vnf_package.id, self.temp_dir) mock_read_vnfd_files.side_effect = yaml.YAMLError self.assertRaises(exceptions.FailedToGetVnfdData, self.conductor.get_vnf_package_vnfd, self.context, self.vnf_package) shutil.rmtree(fake_csar) def _create_and_upload_vnf_package(self): vnf_package = objects.VnfPackage(context=self.context, **fake_obj.vnf_package_data) vnf_package.create() vnf_pack_vnfd = fake_obj.get_vnf_package_vnfd_data( vnf_package.id, uuidsentinel.vnfd_id) vnf_pack_vnfd_obj = objects.VnfPackageVnfd( context=self.context, **vnf_pack_vnfd) vnf_pack_vnfd_obj.create() vnf_package.onboarding_state = "ONBOARDED" vnf_package.save() return vnf_pack_vnfd_obj @mock.patch('tacker.conductor.conductor_server.Conductor' '._update_vnf_attributes') @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch.object(objects.VnfLcmOpOcc, "save") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") def test_instantiate_vnf_instance(self, mock_vnf_by_id, mock_get_lock, mock_save, mock_change_vnf_status, mock_update_vnf_attributes): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, **lcm_op_occs_data) vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() instantiate_vnf_req = vnflcm_fakes.get_instantiate_vnf_request_obj() vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = {"status": "ACTIVE"} self.conductor.instantiate(self.context, vnf_instance, vnf_dict, instantiate_vnf_req, vnf_lcm_op_occs_id) self.vnflcm_driver.instantiate_vnf.assert_called_once_with( self.context, mock.ANY, vnf_dict, instantiate_vnf_req) self.vnflcm_driver._vnf_instance_update.assert_called_once() mock_change_vnf_status. \ assert_called_once_with(self.context, vnf_instance.id, mock.ANY, 'PENDING_CREATE') mock_update_vnf_attributes.assert_called_once() @unittest.skip("Such test is no longer feasible.") @mock.patch.object(objects.VnfLcmOpOcc, "save") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') @mock.patch('tacker.conductor.conductor_server.LOG') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") def test_instantiate_vnf_instance_already_instantiated(self, mock_vnf_by_id, mock_log, mock_package_in_use, mock_get_lock, mock_save): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, **lcm_op_occs_data) vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() instantiate_vnf_req = vnflcm_fakes.get_instantiate_vnf_request_obj() vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id self.conductor.instantiate(self.context, vnf_instance, instantiate_vnf_req, vnf_lcm_op_occs_id) self.vnflcm_driver.instantiate_vnf.assert_not_called() mock_package_in_use.assert_not_called() expected_log = 'Vnf instance %(id)s is already in %(state)s state.' mock_log.error.assert_called_once_with(expected_log, {'id': vnf_instance.id, 'state': fields.VnfInstanceState.INSTANTIATED}) @unittest.skip("Such test is no longer feasible.") @mock.patch.object(objects.VnfLcmOpOcc, "save") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") def test_instantiate_vnf_instance_with_vnf_package_in_use(self, mock_vnf_by_id, mock_vnf_lcm_subscriptions_get, mock_vnf_package_in_use, mock_get_lock, mock_save): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, **lcm_op_occs_data) vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) m_vnf_lcm_subscriptions = \ [mock.MagicMock(**fakes.get_vnf_lcm_subscriptions())] mock_vnf_lcm_subscriptions_get.return_value = \ m_vnf_lcm_subscriptions mock_vnf_package_in_use.return_value = True vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() instantiate_vnf_req = vnflcm_fakes.get_instantiate_vnf_request_obj() vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id self.conductor.instantiate(self.context, vnf_instance, instantiate_vnf_req, vnf_lcm_op_occs_id) self.vnflcm_driver.instantiate_vnf.assert_called_once_with( self.context, mock.ANY, instantiate_vnf_req) mock_vnf_package_in_use.assert_called_once() @mock.patch('tacker.conductor.conductor_server.Conductor' '._update_vnf_attributes') @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch.object(objects.VnfLcmOpOcc, "save") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') @mock.patch('tacker.conductor.conductor_server.LOG') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") @mock.patch('tacker.vnflcm.utils._get_affected_resources') def test_instantiate_vnf_instance_failed_with_exception( self, mock_res, mock_vnf_by_id, mock_log, mock_vnf_lcm_subscriptions_get, mock_get_lock, mock_save, mock_change_vnf_status, mock_update_vnf_attributes): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, **lcm_op_occs_data) vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() instantiate_vnf_req = vnflcm_fakes.get_instantiate_vnf_request_obj() vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = {"status": "ACTIVE"} m_vnf_lcm_subscriptions = \ [mock.MagicMock(**fakes.get_vnf_lcm_subscriptions())] mock_vnf_lcm_subscriptions_get.return_value = \ m_vnf_lcm_subscriptions mock_update_vnf_attributes.side_effect = Exception mock_res.return_value = {} self.conductor.instantiate(self.context, vnf_instance, vnf_dict, instantiate_vnf_req, vnf_lcm_op_occs_id) self.vnflcm_driver.instantiate_vnf.assert_called_once_with( self.context, vnf_instance, vnf_dict, instantiate_vnf_req) mock_change_vnf_status.assert_called_with(self.context, vnf_instance.id, mock.ANY, 'ERROR') mock_update_vnf_attributes.assert_called_once() @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch('tacker.conductor.conductor_server.Conductor' '._send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') def test_terminate_vnf_instance(self, mock_get_lock, mock_send_notification, mock_change_vnf_status): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils. \ get_vnf_instance_object(instantiated_vnf_info=inst_vnf_info) terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) self.vnflcm_driver.terminate_vnf.assert_called_once_with( self.context, vnf_instance, terminate_vnf_req) self.vnflcm_driver._vnf_instance_update.assert_called_once() self.assertEqual(mock_send_notification.call_count, 2) self.assertEqual(mock_change_vnf_status.call_count, 2) @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch('tacker.conductor.conductor_server.Conductor' '._send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') def test_terminate_vnf_instance_exception(self, mock_get_lock, mock_send_notification, mock_change_vnf_status): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils. \ get_vnf_instance_object(instantiated_vnf_info=inst_vnf_info) mock_send_notification.side_effect = Exception terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) try: self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) except Exception: pass self.vnflcm_driver.terminate_vnf.assert_not_called() mock_change_vnf_status.assert_called_once_with(self.context, vnf_instance.id, mock.ANY, 'ERROR') self.assertEqual(mock_send_notification.call_count, 2) @unittest.skip("Such test is no longer feasible.") @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') @mock.patch('tacker.conductor.conductor_server.LOG') def test_terminate_vnf_instance_already_not_instantiated(self, mock_log, mock_package_in_use, mock_get_lock, mock_send_notification): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) mock_package_in_use.return_value = True vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.NOT_INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) self.vnflcm_driver.terminate_vnf.assert_not_called() mock_package_in_use.assert_not_called() expected_log = ('Terminate action cannot be performed on vnf %(id)s ' 'which is in %(state)s state.') mock_log.error.assert_called_once_with(expected_log, {'id': vnf_instance.id, 'state': fields.VnfInstanceState.NOT_INSTANTIATED}) @unittest.skip("Such test is no longer feasible.") @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') def test_terminate_vnf_instance_with_usage_state_not_in_use(self, mock_vnf_package_is_package_in_use, mock_get_lock, mock_send_notification): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() mock_vnf_package_is_package_in_use.return_value = False terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) self.vnflcm_driver.terminate_vnf.assert_called_once_with( self.context, mock.ANY, terminate_vnf_req, vnf_lcm_op_occs_id) mock_vnf_package_is_package_in_use.assert_called_once() @unittest.skip("Such test is no longer feasible.") @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') def test_terminate_vnf_instance_with_usage_state_already_in_use(self, mock_vnf_package_is_package_in_use, mock_get_lock, mock_send_notification): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() mock_vnf_package_is_package_in_use.return_value = True terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) self.vnflcm_driver.terminate_vnf.assert_called_once_with( self.context, mock.ANY, terminate_vnf_req, vnf_lcm_op_occs_id) mock_vnf_package_is_package_in_use.assert_called_once() @unittest.skip("Such test is no longer feasible.") @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfPackage, 'is_package_in_use') @mock.patch('tacker.conductor.conductor_server.LOG') def test_terminate_vnf_instance_failed_to_update_usage_state( self, mock_log, mock_is_package_in_use, mock_get_lock, mock_send_notification): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, additional_params={"key": "value"}) mock_is_package_in_use.side_effect = Exception vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id vnf_dict = db_utils.get_dummy_vnf(instance_id=self.instance_uuid) self.conductor.terminate(self.context, vnf_lcm_op_occs_id, vnf_instance, terminate_vnf_req, vnf_dict) self.vnflcm_driver.terminate_vnf.assert_called_once_with( self.context, mock.ANY, terminate_vnf_req, vnf_lcm_op_occs_id) expected_msg = "Failed to update usage_state of vnf package %s" mock_log.error.assert_called_once_with(expected_msg, vnf_package_vnfd.package_uuid) @mock.patch('tacker.conductor.conductor_server.Conductor.' '_add_additional_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_update_instantiated_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_change_vnf_status') @mock.patch.object(objects.VnfLcmOpOcc, "save") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") def test_heal_vnf_instance(self, mock_vnf_by_id, mock_get_lock, mock_save, mock_change_vnf_status, mock_update_insta_vnf_info, mock_add_additional_vnf_info): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, **lcm_op_occs_data) vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() vnf_instance.instantiation_state = \ fields.VnfInstanceState.INSTANTIATED vnf_instance.save() heal_vnf_req = objects.HealVnfRequest(cause="healing request") vnf_dict = {"fake": "fake_dict"} vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id self.conductor.heal(self.context, vnf_instance, vnf_dict, heal_vnf_req, vnf_lcm_op_occs_id) self.assertEqual(mock_change_vnf_status.call_count, 2) mock_update_insta_vnf_info. \ assert_called_once_with(self.context, vnf_instance, heal_vnf_req) mock_add_additional_vnf_info. \ assert_called_once_with(self.context, vnf_instance) @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_update_instantiated_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_change_vnf_status') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_add_additional_vnf_info') @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch('tacker.conductor.conductor_server.LOG') def test_heal_vnf_instance_exception(self, mock_log, mock_get_lock, mock_add_additional_vnf_info, mock_change_vnf_status, mock_update_insta_vnf_info, mock_send_notification): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.NOT_INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() mock_add_additional_vnf_info.side_effect = Exception heal_vnf_req = objects.HealVnfRequest(cause="healing request") vnf_dict = {"fake": "fake_dict"} vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id self.conductor.heal(self.context, vnf_instance, vnf_dict, heal_vnf_req, vnf_lcm_op_occs_id) mock_change_vnf_status.assert_called_with(self.context, vnf_instance, mock.ANY, constants.ERROR, "") mock_update_insta_vnf_info.assert_called_with(self.context, vnf_instance, heal_vnf_req) self.assertEqual(mock_send_notification.call_count, 2) @unittest.skip("Such test is no longer feasible.") @mock.patch.object(coordination.Coordinator, 'get_lock') @mock.patch('tacker.conductor.conductor_server.LOG') def test_heal_vnf_instance_already_not_instantiated(self, mock_log, mock_get_lock): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) vnf_instance_data['instantiation_state'] =\ fields.VnfInstanceState.NOT_INSTANTIATED vnf_instance = objects.VnfInstance(context=self.context, **vnf_instance_data) vnf_instance.create() heal_vnf_req = objects.HealVnfRequest(cause="healing request") vnf_dict = {"fake": "fake_dict"} vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id self.conductor.heal(self.context, vnf_instance, vnf_dict, heal_vnf_req, vnf_lcm_op_occs_id) self.vnflcm_driver.heal_vnf.assert_not_called() expected_log = ('Heal action cannot be performed on vnf %(id)s ' 'which is in %(state)s state.') mock_log.error.assert_called_once_with(expected_log, {'id': vnf_instance.id, 'state': fields.VnfInstanceState.NOT_INSTANTIATED}) @mock.patch.object(os, 'remove') @mock.patch.object(shutil, 'rmtree') @mock.patch.object(os.path, 'exists') @mock.patch.object(objects.VnfPackagesList, 'get_by_filters') def test_run_cleanup_vnf_packages(self, mock_get_by_filter, mock_exists, mock_rmtree, mock_remove): vnf_package_data = {'algorithm': None, 'hash': None, 'location_glance_store': None, 'onboarding_state': 'CREATED', 'operational_state': 'DISABLED', 'tenant_id': uuidsentinel.tenant_id, 'usage_state': 'NOT_IN_USE', 'user_data': {'abc': 'xyz'} } vnfpkgm = objects.VnfPackage(context=self.context, **vnf_package_data) vnfpkgm.create() vnfpkgm.destroy(self.context) mock_get_by_filter.return_value = [vnfpkgm] mock_exists.return_value = True conductor_server.Conductor('host')._run_cleanup_vnf_packages( self.context) mock_get_by_filter.assert_called() mock_rmtree.assert_called() mock_remove.assert_called() @mock.patch.object(sys, 'exit') @mock.patch.object(conductor_server.LOG, 'error') @mock.patch.object(glance_store, 'initialize_glance_store') @mock.patch.object(os.path, 'isdir') def test_init_host(self, mock_isdir, mock_initialize_glance_store, mock_log_error, mock_exit): mock_isdir.return_value = False self.conductor.init_host() mock_log_error.assert_called() mock_exit.assert_called_with(1) self.assertIn("Config option 'vnf_package_csar_path' is not configured" " correctly. VNF package CSAR path directory %s doesn't" " exist", mock_log_error.call_args[0][0]) @mock.patch.object(urllib.request, 'urlopen') def test_upload_vnf_package_from_uri_with_invalid_auth(self, mock_url_open): address_information = "http://localhost/test.zip" user_name = "username" password = "password" mock_url_open.side_effect = urlerr.HTTPError( url='', code=401, msg='HTTP Error 401 Unauthorized', hdrs={}, fp=None) self.assertRaises(exceptions.VNFPackageURLInvalid, self.conductor.upload_vnf_package_from_uri, self.context, self.vnf_package, address_information, user_name=user_name, password=password) self.assertEqual('CREATED', self.vnf_package.onboarding_state) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_notFoundSubscription(self, mock_subscriptions_get): mock_subscriptions_get.return_value = None notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfLcmOperationOccurrenceNotification'} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, -1) mock_subscriptions_get.assert_called() @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_vnfLcmOperationOccurrence(self, mock_subscriptions_get): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={'Content-Type': 'application/json'}, status_code=204) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfLcmOperationOccurrenceNotification', 'operationTypes': 'SCALE', 'operationStates': 'RESULT', '_links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost") self.assertEqual(1, req_count) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_vnfIdentifierCreation(self, mock_subscriptions_get): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={'Content-Type': 'application/json'}, status_code=204) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost") self.assertEqual(1, req_count) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_with_auth_basic(self, mock_subscriptions_get): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={'Content-Type': 'application/json'}, status_code=204) auth_user_name = 'test_user' auth_password = 'test_password' mock_subscriptions_get.return_value = self._create_subscriptions( {'authType': ['BASIC'], 'paramsBasic': {'userName': auth_user_name, 'password': auth_password}}) notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost") self.assertEqual(1, req_count) self.assert_auth_basic( history[0], auth_user_name, auth_password) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_with_auth_client_credentials( self, mock_subscriptions_get): auth.auth_manager = auth._AuthManager() self.requests_mock.register_uri('POST', "https://localhost/callback", headers={'Content-Type': 'application/json'}, status_code=204) auth_user_name = 'test_user' auth_password = 'test_password' token_endpoint = 'https://oauth2/tokens' self.requests_mock.register_uri('GET', token_endpoint, json={'access_token': 'test_token', 'token_type': 'bearer'}, headers={'Content-Type': 'application/json'}, status_code=200) mock_subscriptions_get.return_value = self._create_subscriptions( {'authType': ['OAUTH2_CLIENT_CREDENTIALS'], 'paramsOauth2ClientCredentials': { 'clientId': auth_user_name, 'clientPassword': auth_password, 'tokenEndpoint': token_endpoint}}) notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost", 'https://oauth2') self.assertEqual(2, req_count) self.assert_auth_basic(history[0], auth_user_name, auth_password) self.assert_auth_client_credentials(history[1], "test_token") @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_retyNotification(self, mock_subscriptions_get): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={'Content-Type': 'application/json'}, status_code=400) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost") self.assertEqual(3, req_count) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_sendError(self, mock_subscriptions_get): self.requests_mock.register_uri('POST', "https://localhost/callback", exc=requests.exceptions.HTTPError("MockException")) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { 'vnfInstanceId': 'Test', 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) mock_subscriptions_get.assert_called() history = self.requests_mock.request_history req_count = nfvo_client._count_mock_history( history, "https://localhost") self.assertEqual(1, req_count) @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_sendNotification_internalServerError( self, mock_subscriptions_get): mock_subscriptions_get.side_effect = Exception("MockException") notification = { 'vnfInstanceId': 'Test', 'notificationTypes': 'VnfIdentifierCreationNotification', 'links': {}} result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 99) mock_subscriptions_get.assert_called()