# Copyright 2017 99cloud, Inc. # All Rights Reserved. # # 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 importlib import json import os import tempfile from unittest import mock import ddt import requests import yaml from tacker.common import exceptions from tacker import context from tacker.extensions import vnfm from tacker import objects from tacker.tests.common import helpers from tacker.tests import constants from tacker.tests.unit import base from tacker.tests.unit.db import utils 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 from tacker.tests import uuidsentinel from tacker.vnfm.infra_drivers.openstack import openstack @ddt.ddt class TestOpenStack(base.FixturedTestCase): client_fixture_class = client.ClientFixture sdk_connection_fixure_class = client.SdkConnectionFixture def setUp(self): super(TestOpenStack, self).setUp() self.openstack = openstack.OpenStack() self.context = context.get_admin_context() self.heat_url = client.HEAT_URL self.glance_url = client.GLANCE_URL self.instance_uuid = uuidsentinel.instance_id self.stack_id = uuidsentinel.stack_id self.auth_attr = None self.plugin = None self.json_headers = {'content-type': 'application/json', 'location': 'http://heat-api/stacks/' + self.instance_uuid + '/myStack/60f83b5e'} self._mock('tacker.common.clients.OpenstackClients.heat', self.cs) mock.patch('tacker.common.clients.OpenstackSdkConnection.' 'openstack_connection', return_value=self.sdk_conn).start() self.mock_log = mock.patch('tacker.vnfm.infra_drivers.openstack.' 'openstack.LOG').start() mock.patch('time.sleep', return_value=None).start() def _response_in_wait_until_stack_ready(self, status_list, stack_outputs=True): # response for heat_client's get() for status in status_list: url = self.heat_url + '/stacks/' + self.instance_uuid json = {'stack': fd_utils.get_dummy_stack(stack_outputs, status=status)} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def _response_in_resource_get(self, id, res_name=None): # response for heat_client's resource_get() if res_name: url = self.heat_url + '/stacks/' + id + ('/myStack/60f83b5e/' 'resources/') + res_name else: url = self.heat_url + '/stacks/' + id json = {'resource': fd_utils.get_dummy_resource()} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def _response_in_stack_get(self, id, stack_status='CREATE_COMPLETE'): # response for heat_client's stack_get() url = self.heat_url + '/stacks/' + id json = {'stack': fd_utils.get_dummy_stack(status=stack_status)} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def _response_in_stack_update(self, id): # response for heat_client's stack_patch() url = self.heat_url + '/stacks/' + id self.requests_mock.register_uri('PATCH', url, headers=self.json_headers) def _response_resource_mark_unhealthy(self, id, resources, raise_exception=False): # response for heat_client's heatclient.resource_mark_unhealthy if not resources: return class MyException(Exception): pass for resource in resources: url = os.path.join(self.heat_url, 'stacks', id, 'myStack/60f83b5e/resources', resource['resource_name']) if raise_exception: self.requests_mock.register_uri('PATCH', url, exc=MyException("Any stuff")) else: self.requests_mock.register_uri('PATCH', url) def _json_load(self, input_file): json_file = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../etc/samples/lcm_instantiate_request/", str(input_file))) with open(json_file) as f: json_dict = json.load(f) return json_dict def _read_file(self): yaml_file = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../etc/samples/", "hot_lcm_user_data.yaml")) with open(yaml_file, 'r') as f: yaml_file_dict = yaml.safe_load(f) return yaml_file_dict @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack' '.OpenStack._format_base_hot') @mock.patch('tacker.vnflcm.utils._get_vnflcm_interface') @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_normal(self, mock_OpenstackClients_heat, mock_get_base_hot_dict, mock_get_vnflcm_interface, mock_format_base_hot): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] vnf_resource = type('', (), {}) vnf_resource.resource_identifier = constants.INVALID_UUID grant_info_test = {'vdu_name': {vnf_resource}} nested_hot_dict = {'parameters': {'vnf': 'test'}} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.openstack.create(self.plugin, self.context, vnf, self.auth_attr, inst_req_info=inst_req_info_test, vnf_package_path=vnf_package_path_test, base_hot_dict=base_hot_dict_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.common.clients.OpenstackClients') def test_create_heat_stack(self, mock_OpenstackClients_heat): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict = None vnf_package_path = None self.openstack.create(self.plugin, self.context, vnf, self.auth_attr, base_hot_dict, vnf_package_path) @mock.patch('tacker.common.clients.OpenstackClients') def test_create_userdata_none(self, mock_OpenstackClients_heat): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # delete lcm-operation-user-data from additionalParams del test_json['additionalParams']['lcm-operation-user-data'] inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None grant_info_test = None self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test) @mock.patch('tacker.common.clients.OpenstackClients') def test_create_userdataclass_none(self, mock_OpenstackClients_heat): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # delete lcm-operation-user-data-class from additionalParams del test_json['additionalParams']['lcm-operation-user-data-class'] inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None grant_info_test = None self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_userdata_null(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # set null to setlcm-operation-user-data from additionalParams test_json['additionalParams']['lcm-operation-user-data'] = '' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_userdataclass_null(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # set null to setlcm-operation-user-data-class from additionalParams test_json['additionalParams']['lcm-operation-user-data-class'] = '' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_import_module_exception(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() with mock.patch.object(importlib, 'import_module') as mock_importlib: mock_importlib.side_effect = Exception('Test Exception') self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_getattr_none(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() with mock.patch.object(importlib, 'import_module') as mock_importlib: mock_importlib.return_value = None self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_missing_file(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_none")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] vnf_resource = type('', (), {}) vnf_resource.resource_identifier = constants.INVALID_UUID grant_info_test = {'vdu_name': {vnf_resource}} nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, inst_req_info=inst_req_info_test, vnf_package_path=vnf_package_path_test, base_hot_dict=base_hot_dict_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_return_none_dict(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_non_dict")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') test_json['additionalParams']['lcm-operation-user-data'] = \ 'UserData/lcm_user_data_non_dict.py' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] vnf_resource = type('', (), {}) vnf_resource.resource_identifier = constants.INVALID_UUID grant_info_test = {'vdu_name': {vnf_resource}} nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, inst_req_info=inst_req_info_test, vnf_package_path=vnf_package_path_test, base_hot_dict=base_hot_dict_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_none_base_hot_dict(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.flavour_id = test_json['flavourId'] base_hot_dict_test = None vnf_package_path_test = None grant_info_test = None nested_hot_dict = {} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_invalid_user_data(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # set dummy to setlcm-operation-user-data-class from additionalParams test_json['additionalParams']['lcm-operation-user-data-class'] = \ 'DummyUserData' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_invalid_user_data_class(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # set dummy to setlcm-operation-user-data-class from additionalParams test_json['additionalParams']['lcm-operation-user-data-class'] = \ 'DummyUserData' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] grant_info_test = None nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict_test, vnf_package_path_test, inst_req_info=inst_req_info_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_lcm_user_data_and_user_data_class_no_value(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # set null to setlcm-operation-user-data and # lcm-operation-user-data-class from additionalParams test_json['additionalParams']['lcm-operation-user-data'] = '' test_json['additionalParams']['lcm-operation-user-data-class'] = '' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = test_json['extVirtualLinks'] inst_req_info_test.flavour_id = test_json['flavourId'] vnf_resource = type('', (), {}) vnf_resource.resource_identifier = constants.INVALID_UUID grant_info_test = {'vdu_name': {vnf_resource}} nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, inst_req_info=inst_req_info_test, vnf_package_path=vnf_package_path_test, base_hot_dict=base_hot_dict_test, grant_info=grant_info_test, vnf_instance=vnf_instance) @mock.patch('tacker.common.clients.OpenstackClients') def test_create_lcm_user_data_and_user_data_class_none(self, mock_OpenstackClients_heat): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_normal")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') # delete lcm-operation-user-data and # lcm-operation-user-data-class from additionalParams del test_json['additionalParams']['lcm-operation-user-data'] del test_json['additionalParams']['lcm-operation-user-data-class'] inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = test_json['extVirtualLinks'] base_hot_dict = None self.assertRaises(BaseException, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict, vnf_package_path=vnf_package_path_test, inst_req_info=inst_req_info_test) @mock.patch('tacker.common.clients.OpenstackClients') def test_create_no_additionalparams(self, mock_OpenstackClients_heat): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_normal")) vnf['placement_attr'] = {'region_name': 'dummy_region'} inst_req_info_test = type('', (), {}) inst_req_info_test.additional_params = None inst_req_info_test.ext_virtual_links = None base_hot_dict = None self.assertRaises(BaseException, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, base_hot_dict, vnf_package_path=vnf_package_path_test, inst_req_info=inst_req_info_test) @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch('tacker.common.clients.OpenstackClients') def test_create_instance_exception(self, mock_OpenstackClients_heat, mock_get_base_hot_dict): vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid) vnf['placement_attr'] = {'region_name': 'dummy_region'} base_hot_dict_test = self._read_file() vnf_package_path_test = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../etc/samples/etsi/nfv", "user_data_sample_userdata_invalid_script")) inst_req_info_test = type('', (), {}) test_json = self._json_load( 'instantiate_vnf_request_lcm_userdata.json') test_json['additionalParams']['lcm-operation-user-data'] = \ 'UserData/lcm_user_data_invalid_script.py' inst_req_info_test.additional_params = test_json['additionalParams'] inst_req_info_test.ext_virtual_links = None inst_req_info_test.flavour_id = test_json['flavourId'] vnf_resource = type('', (), {}) vnf_resource.resource_identifier = constants.INVALID_UUID grant_info_test = {'vdu_name': {vnf_resource}} nested_hot_dict = {'test': 'test'} mock_get_base_hot_dict.return_value = \ self._read_file(), nested_hot_dict vnf_instance = fd_utils.get_vnf_instance_object() self.assertRaises(vnfm.LCMUserDataFailed, self.openstack.create, self.plugin, self.context, vnf, self.auth_attr, inst_req_info=inst_req_info_test, vnf_package_path=vnf_package_path_test, base_hot_dict=base_hot_dict_test, grant_info=grant_info_test, vnf_instance=vnf_instance) def test_create_wait(self): self._response_in_wait_until_stack_ready(["CREATE_IN_PROGRESS", "CREATE_COMPLETE"]) vnf_dict = utils.get_dummy_vnf(instance_id=self.instance_uuid) self.openstack.create_wait(None, None, vnf_dict, self.instance_uuid, None) self.mock_log.debug.assert_called_with('outputs %s', fd_utils.get_dummy_stack()['outputs']) self.assertEqual(helpers.compact_byte('{"VDU1": "192.168.120.216"}'), vnf_dict['mgmt_ip_address']) def test_create_wait_without_mgmt_ips(self): self._response_in_wait_until_stack_ready(["CREATE_IN_PROGRESS", "CREATE_COMPLETE"], stack_outputs=False) vnf_dict = utils.get_dummy_vnf(instance_id=self.instance_uuid) self.openstack.create_wait(None, None, vnf_dict, self.instance_uuid, None) self.mock_log.debug.assert_called_with('outputs %s', fd_utils.get_dummy_stack(outputs=False)['outputs']) self.assertIsNone(vnf_dict['mgmt_ip_address']) def test_create_wait_with_scaling_group_names(self): self._response_in_wait_until_stack_ready(["CREATE_IN_PROGRESS", "CREATE_COMPLETE"]) self._response_in_resource_get(self.instance_uuid, res_name='SP1_group') url = self.heat_url + '/stacks/' + self.stack_id + '/resources' json = {'resources': [fd_utils.get_dummy_resource()]} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) self._response_in_resource_get(self.stack_id) vnf_dict = utils.get_dummy_vnf(scaling_group=True) self.openstack.create_wait(None, None, vnf_dict, self.instance_uuid, None) self.assertEqual(helpers.compact_byte('{"vdu1": ["test1"]}'), vnf_dict['mgmt_ip_address']) def test_create_wait_failed_with_stack_retries_0(self): self._response_in_wait_until_stack_ready(["CREATE_IN_PROGRESS"]) vnf_dict = utils.get_dummy_vnf(instance_id=self.instance_uuid) self.assertRaises(vnfm.VNFCreateWaitFailed, self.openstack.create_wait, None, None, vnf_dict, self.instance_uuid, None) def test_create_wait_failed_with_stack_retries_not_0(self): self._response_in_wait_until_stack_ready(["CREATE_IN_PROGRESS", "FAILED"]) vnf_dict = utils.get_dummy_vnf(instance_id=self.instance_uuid) self.assertRaises(vnfm.VNFCreateWaitFailed, self.openstack.create_wait, None, None, vnf_dict, self.instance_uuid, {}) def _exception_response(self): url = self.heat_url + '/stacks/' + self.instance_uuid body = {"error": Exception("any stuff")} self.requests_mock.register_uri('GET', url, body=body, status_code=404, headers=self.json_headers) def test_create_wait_with_exception(self): self._exception_response() vnf_dict = utils.get_dummy_vnf(instance_id=self.instance_uuid) self.assertRaises(vnfm.VNFCreateWaitFailed, self.openstack.create_wait, None, None, vnf_dict, self.instance_uuid, None) def test_delete_wait_failed_with_stack_retries_0(self): self._response_in_wait_until_stack_ready(["DELETE_IN_PROGRESS"]) self.assertRaises(vnfm.VNFDeleteWaitFailed, self.openstack.delete_wait, None, None, self.instance_uuid, None, None) def test_delete_wait_stack_retries_not_0(self): self._response_in_wait_until_stack_ready(["DELETE_IN_PROGRESS", "FAILED"]) self.assertRaises(vnfm.VNFDeleteWaitFailed, self.openstack.delete_wait, None, None, self.instance_uuid, None, None) self.mock_log.warning.assert_called_once() def test_update_wait(self): self._response_in_wait_until_stack_ready(["CREATE_COMPLETE"]) vnf_dict = utils.get_dummy_vnf(status='PENDING_UPDATE', instance_id=self.instance_uuid) self.openstack.update_wait(None, None, vnf_dict, None) self.mock_log.debug.assert_called_with('outputs %s', fd_utils.get_dummy_stack()['outputs']) self.assertEqual(helpers.compact_byte('{"VDU1": "192.168.120.216"}'), vnf_dict['mgmt_ip_address']) def test_heal_wait(self): self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS", "UPDATE_COMPLETE"]) vnf_dict = utils.get_dummy_vnf(status='PENDING_HEAL', instance_id=self.instance_uuid) self.openstack.heal_wait(None, None, vnf_dict, None) self.mock_log.debug.assert_called_with('outputs %s', fd_utils.get_dummy_stack()['outputs']) self.assertEqual(helpers.compact_byte('{"VDU1": "192.168.120.216"}'), vnf_dict['mgmt_ip_address']) def test_heal_wait_without_mgmt_ips(self): self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS", "UPDATE_COMPLETE"], stack_outputs=False) vnf_dict = utils.get_dummy_vnf(status='PENDING_HEAL', instance_id=self.instance_uuid) self.openstack.heal_wait(None, None, vnf_dict, None) self.mock_log.debug.assert_called_with('outputs %s', fd_utils.get_dummy_stack(outputs=False)['outputs']) self.assertIsNone(vnf_dict['mgmt_ip_address']) def test_heal_wait_failed_with_retries_0(self): self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS"]) vnf_dict = utils.get_dummy_vnf(status='PENDING_HEAL', instance_id=self.instance_uuid) self.assertRaises(vnfm.VNFHealWaitFailed, self.openstack.heal_wait, None, None, vnf_dict, None) def test_heal_wait_failed_stack_retries_not_0(self): self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS", "FAILED"]) vnf_dict = utils.get_dummy_vnf(status='PENDING_HEAL', instance_id=self.instance_uuid) self.assertRaises(vnfm.VNFHealWaitFailed, self.openstack.heal_wait, None, None, vnf_dict, None) def _responses_in_resource_event_list(self, dummy_event): # response for heat_client's resource_event_list() url = self.heat_url + '/stacks/' + self.instance_uuid json = {'stack': [fd_utils.get_dummy_stack()]} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) url = self.heat_url + '/stacks/' + self.instance_uuid + ( '/myStack/60f83b5e/resources/SP1_scale_out/events?limit=1&sort_dir' '=desc&sort_keys=event_time') json = {'events': [dummy_event]} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def test_scale(self): dummy_event = fd_utils.get_dummy_event() self._responses_in_resource_event_list(dummy_event) # response for heat_client's resource_signal() url = self.heat_url + '/stacks/' + self.instance_uuid + ( '/myStack/60f83b5e/resources/SP1_scale_out/signal') self.requests_mock.register_uri('POST', url, json={}, headers=self.json_headers) event_id = self.openstack.scale(plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None) self.assertEqual(dummy_event['id'], event_id) def _response_in_resource_get_list(self, stack_id=None, resources=None): # response for heat_client's resource_get_list() if stack_id: url = self.heat_url + '/stacks/' + stack_id + '/resources' else: url = self.heat_url + '/stacks/' + self.stack_id + '/resources' resources = resources or [fd_utils.get_dummy_resource()] json = {'resources': resources} self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def _test_scale(self, resource_status): dummy_event = fd_utils.get_dummy_event(resource_status) self._responses_in_resource_event_list(dummy_event) self._response_in_resource_get(self.instance_uuid, res_name='G1') self._response_in_resource_get_list() self._response_in_resource_get(self.stack_id) self._response_in_resource_get(self.instance_uuid, res_name='SP1_group') def test_scale_wait_with_different_last_event_id(self): self._test_scale("SIGNAL_COMPLETE") mgmt_ip = self.openstack.scale_wait(plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None, last_event_id=uuidsentinel. non_last_event_id) self.assertEqual(helpers.compact_byte('{"vdu1": ["test1"]}'), mgmt_ip) @ddt.data("SIGNAL_COMPLETE", "CREATE_COMPLETE") def test_scale_wait_with_same_last_event_id(self, resource_status): self._test_scale(resource_status) mgmt_ip = self.openstack.scale_wait(plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None, last_event_id=fd_utils.get_dummy_event()['id']) self.assertEqual(helpers.compact_byte('{"vdu1": ["test1"]}'), mgmt_ip) @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack.LOG') def test_scale_wait_failed_with_exception(self, mock_log): self._exception_response() self.assertRaises(vnfm.VNFScaleWaitFailed, self.openstack.scale_wait, plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None, last_event_id=fd_utils.get_dummy_event()['id']) mock_log.warning.assert_called_once() def _response_in_resource_metadata(self, metadata=None): # response for heat_client's resource_metadata() url = self.heat_url + '/stacks/' + self.instance_uuid + \ '/myStack/60f83b5e/resources/SP1_scale_out/metadata' json = {'metadata': {'scaling_in_progress': metadata}} return self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def test_scale_wait_failed_with_stack_retries_0(self): dummy_event = fd_utils.get_dummy_event("CREATE_IN_PROGRESS") self._responses_in_resource_event_list(dummy_event) self._response_in_resource_metadata(True) self.assertRaises(vnfm.VNFScaleWaitFailed, self.openstack.scale_wait, plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None, last_event_id=dummy_event['id']) self.mock_log.warning.assert_called_once() def test_scale_wait_without_resource_metadata(self): dummy_event = fd_utils.get_dummy_event("CREATE_IN_PROGRESS") self._responses_in_resource_event_list(dummy_event) self._response_in_resource_metadata() self._response_in_resource_get(self.instance_uuid, res_name='G1') self._response_in_resource_get_list() self._response_in_resource_get(self.stack_id) self._response_in_resource_get(self.instance_uuid, res_name='SP1_group') mgmt_ip = self.openstack.scale_wait(plugin=self, context=self.context, auth_attr=None, policy=fd_utils.get_dummy_policy_dict(), region_name=None, last_event_id=fd_utils.get_dummy_event() ['id']) error_reason = ('When signal occurred within cool down ' 'window, no events generated from heat, ' 'so ignore it') self.mock_log.warning.assert_called_once_with(error_reason) self.assertEqual(b'{"vdu1": ["test1"]}', mgmt_ip) def _responses_in_create_image(self, multiple_responses=False): # response for glance_client's create() json = fd_utils.get_fake_glance_image_dict() url = os.path.join(self.glance_url, 'images') if multiple_responses: return self.requests_mock.register_uri( 'POST', url, [{'json': json, 'status_code': 201, 'headers': self.json_headers}, {'exc': requests.exceptions.ConnectTimeout}]) else: return self.requests_mock.register_uri('POST', url, json=json, headers=self.json_headers) def _responses_in_import_image(self, raise_exception=False): # response for glance_client's import() json = fd_utils.get_fake_glance_image_dict() url = os.path.join( self.glance_url, 'images', uuidsentinel.image_id, 'import') if raise_exception: return self.requests_mock.register_uri('POST', url, exc=requests.exceptions.ConnectTimeout) else: return self.requests_mock.register_uri('POST', url, json=json, headers=self.json_headers) def _responses_in_get_image(self, image_path=None, status='active', hash_value='hash'): # response for glance_client's import() json = fd_utils.get_fake_glance_image_dict(image_path=image_path, status=status, hash_value=hash_value) url = os.path.join( self.glance_url, 'images', uuidsentinel.image_id) return self.requests_mock.register_uri('GET', url, json=json, headers=self.json_headers) def _responses_in_upload_image(self, image_path=None, status='active', hash_value='hash'): # response for glance_client's upload() json = fd_utils.get_fake_glance_image_dict(image_path=image_path, status=status, hash_value=hash_value) url = os.path.join( self.glance_url, 'images', uuidsentinel.image_id, 'file') return self.requests_mock.register_uri('PUT', url, json=json, headers=self.json_headers) def test_pre_instantiation_vnf_image_with_file(self): vnf_instance = fd_utils.get_vnf_instance_object() # Create a temporary file as the openstacksdk will access it for # calculating the hash value. image_fd, image_path = tempfile.mkstemp() vnf_software_image = fd_utils.get_vnf_software_image_object( image_path=image_path) vnf_software_images = {'node_name': vnf_software_image} upload_image_url = self._responses_in_upload_image(image_path) create_image_url = self._responses_in_create_image() get_image_url = self._responses_in_get_image(image_path) vnf_resources = self.openstack.pre_instantiation_vnf( self.context, vnf_instance, None, vnf_software_images) image_resource = vnf_resources['node_name'][0] os.close(image_fd) os.remove(image_path) # Asserting the response as per the data given in the fake objects. self.assertEqual(image_resource.resource_name, 'test-image') self.assertEqual(image_resource.resource_status, 'CREATED') self.assertEqual(image_resource.resource_type, 'image') self.assertEqual(image_resource.vnf_instance_id, vnf_instance.id) self.assertEqual(upload_image_url.call_count, 1) self.assertEqual(create_image_url.call_count, 1) self.assertTrue(get_image_url.call_count >= 1) @mock.patch('tacker.common.utils.is_url', mock.MagicMock( return_value=True)) def test_pre_instantiation_vnf_image_with_url(self): image_path = "http://fake-url.net" vnf_instance = fd_utils.get_vnf_instance_object() vnf_software_image = fd_utils.get_vnf_software_image_object( image_path=image_path) vnf_software_images = {'node_name': vnf_software_image} create_image_url = self._responses_in_create_image(image_path) import_image_url = self._responses_in_import_image() get_image_url = self._responses_in_get_image(image_path) vnf_resources = self.openstack.pre_instantiation_vnf( self.context, vnf_instance, None, vnf_software_images) image_resource = vnf_resources['node_name'][0] # Asserting the response as per the data given in the fake objects. self.assertEqual(image_resource.resource_name, 'test-image') self.assertEqual(image_resource.resource_status, 'CREATED') self.assertEqual(image_resource.resource_type, 'image') self.assertEqual(image_resource.vnf_instance_id, vnf_instance.id) self.assertEqual(create_image_url.call_count, 1) self.assertEqual(import_image_url.call_count, 1) self.assertEqual(get_image_url.call_count, 1) @ddt.data(False, True) def test_pre_instantiation_vnf_failed_in_image_creation( self, exception_in_delete_image): vnf_instance = fd_utils.get_vnf_instance_object() vnf_software_image = fd_utils.get_vnf_software_image_object() vnf_software_images = {'node_name1': vnf_software_image, 'node_name2': vnf_software_image} # exception will occur in second iteration of image creation. create_image_url = self._responses_in_create_image( multiple_responses=True) import_image_url = self._responses_in_import_image() get_image_url = self._responses_in_get_image() delete_image_url = self._response_in_delete_image( uuidsentinel.image_id, exception=exception_in_delete_image) self.assertRaises(exceptions.VnfPreInstantiationFailed, self.openstack.pre_instantiation_vnf, self.context, vnf_instance, None, vnf_software_images) self.assertEqual(create_image_url.call_count, 3) self.assertEqual(import_image_url.call_count, 1) self.assertEqual(get_image_url.call_count, 1) delete_call_count = 2 if exception_in_delete_image else 1 self.assertEqual(delete_image_url.call_count, delete_call_count) @ddt.data(False, True) def test_pre_instantiation_vnf_failed_in_image_upload( self, exception_in_delete_image): vnf_instance = fd_utils.get_vnf_instance_object() image_path = '/non/existent/file' software_image_update = {'image_path': image_path} vnf_software_image = fd_utils.get_vnf_software_image_object( **software_image_update) vnf_software_images = {'node_name1': vnf_software_image, 'node_name2': vnf_software_image} # exception will occur in second iteration of image creation. # No urls are accessed in this case because openstacksdk fails to # access the file when it wants to calculate the hash. self._responses_in_create_image(multiple_responses=True) self._responses_in_upload_image(image_path) self._responses_in_get_image() self._response_in_delete_image(uuidsentinel.image_id, exception=exception_in_delete_image) self.assertRaises(exceptions.VnfPreInstantiationFailed, self.openstack.pre_instantiation_vnf, self.context, vnf_instance, None, vnf_software_images) def test_pre_instantiation_vnf_failed_with_mismatch_in_hash_value(self): vnf_instance = fd_utils.get_vnf_instance_object() vnf_software_image = fd_utils.get_vnf_software_image_object() vnf_software_images = {'node_name1': vnf_software_image, 'node_name2': vnf_software_image} # exception will occur in second iteration of image creation. create_image_url = self._responses_in_create_image( multiple_responses=True) import_image_url = self._responses_in_import_image() get_image_url = self._responses_in_get_image( hash_value='diff-hash-value') delete_image_url = self._response_in_delete_image( uuidsentinel.image_id) self.assertRaises(exceptions.VnfPreInstantiationFailed, self.openstack.pre_instantiation_vnf, self.context, vnf_instance, None, vnf_software_images) self.assertEqual(create_image_url.call_count, 1) self.assertEqual(import_image_url.call_count, 1) self.assertEqual(get_image_url.call_count, 1) self.assertEqual(delete_image_url.call_count, 1) def test_pre_instantiation_vnf_with_image_create_wait_failed(self): vnf_instance = fd_utils.get_vnf_instance_object() vnf_software_image = fd_utils.get_vnf_software_image_object() vnf_software_images = {'node_name1': vnf_software_image, 'node_name2': vnf_software_image} # exception will occurs in second iteration of image creation. create_image_url = self._responses_in_create_image() import_image_url = self._responses_in_import_image() get_image_url = self._responses_in_get_image(status='pending_create') self.assertRaises(exceptions.VnfPreInstantiationFailed, self.openstack.pre_instantiation_vnf, self.context, vnf_instance, None, vnf_software_images) self.assertEqual(create_image_url.call_count, 1) self.assertEqual(import_image_url.call_count, 1) self.assertEqual(get_image_url.call_count, 10) def _response_in_delete_image(self, resource_id, exception=False): # response for glance_client's delete() url = os.path.join( self.glance_url, 'images', resource_id) if exception: return self.requests_mock.register_uri( 'DELETE', url, exc=requests.exceptions.ConnectTimeout) else: return self.requests_mock.register_uri('DELETE', url, json={}, status_code=200, headers=self.json_headers) @ddt.data(True, False) def test_pre_instantiation_vnf_failed_in_image_import( self, exception_in_delete): vnf_instance = fd_utils.get_vnf_instance_object() vnf_software_image = fd_utils.get_vnf_software_image_object() vnf_software_images = {'node_name': vnf_software_image} create_image_url = self._responses_in_create_image() import_image_exc_url = self._responses_in_import_image( raise_exception=True) delete_image_url = self._response_in_delete_image( uuidsentinel.image_id, exception_in_delete) self.assertRaises(exceptions.VnfPreInstantiationFailed, self.openstack.pre_instantiation_vnf, self.context, vnf_instance, None, vnf_software_images) self.assertEqual(create_image_url.call_count, 1) self.assertEqual(import_image_exc_url.call_count, 2) delete_call_count = 2 if exception_in_delete else 1 self.assertEqual(delete_image_url.call_count, delete_call_count) @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack.LOG') def test_delete_vnf_instance_resource(self, mock_log): vnf_instance = fd_utils.get_vnf_instance_object() vnf_resource = fd_utils.get_vnf_resource_object() delete_image_url = self._response_in_delete_image( vnf_resource.resource_identifier) self.openstack.delete_vnf_instance_resource( self.context, vnf_instance, None, vnf_resource) mock_log.info.assert_called() self.assertEqual(delete_image_url.call_count, 1) @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack.LOG') def test_delete_vnf_instance_resource_failed_with_exception( self, mock_log): vnf_instance = fd_utils.get_vnf_instance_object() vnf_resource = fd_utils.get_vnf_resource_object() delete_image_url = self._response_in_delete_image( vnf_resource.resource_identifier, exception=True) self.openstack.delete_vnf_instance_resource( self.context, vnf_instance, None, vnf_resource) mock_log.info.assert_called() self.assertEqual(delete_image_url.call_count, 2) @mock.patch('tacker.vnfm.infra_drivers.openstack.translate_template.' 'TOSCAToHOT._get_unsupported_resource_props') def test_instantiate_vnf(self, mock_get_unsupported_resource_props): vim_connection_info = fd_utils.get_vim_connection_info_object() inst_req_info = fd_utils.get_instantiate_vnf_request() vnfd_dict = fd_utils.get_vnfd_dict() grant_response = fd_utils.get_grant_response_dict() url = os.path.join(self.heat_url, 'stacks') self.requests_mock.register_uri( 'POST', url, json={'stack': fd_utils.get_dummy_stack()}, headers=self.json_headers) vnf_instance = fd_utils.get_vnf_instance_object() instance_id = self.openstack.instantiate_vnf( self.context, vnf_instance, vnfd_dict, vim_connection_info, inst_req_info, grant_response, self.plugin) self.assertEqual(uuidsentinel.instance_id, instance_id) def _responses_in_stack_list(self, instance_id, resources=None): resources = resources or [] url = os.path.join(self.heat_url, 'stacks', instance_id, 'resources') self.requests_mock.register_uri('GET', url, json={'resources': resources}, headers=self.json_headers) response_list = [{'json': {'stacks': [fd_utils.get_dummy_stack( attrs={'parent': uuidsentinel.instance_id})]}}, {'json': {'stacks': [fd_utils.get_dummy_stack()]}}] url = os.path.join(self.heat_url, 'stacks?owner_id=' + instance_id + '&show_nested=True') self.requests_mock.register_uri('GET', url, response_list) def test_post_vnf_instantiation(self): v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1", set_resource_id=False) storage_resource_ids = [v_s_resource_info.id] vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF", storage_resource_ids=storage_resource_ids, set_resource_id=False) v_l_resource_info = fd_utils.get_virtual_link_resource_info( vnfc_resource_info.vnfc_cp_info[0].vnf_link_port_id, vnfc_resource_info.vnfc_cp_info[0].id) inst_vnf_info = fd_utils.get_vnf_instantiated_info( virtual_storage_resource_info=[v_s_resource_info], vnf_virtual_link_resource_info=[v_l_resource_info], vnfc_resource_info=[vnfc_resource_info]) vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() resources = [{'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.vdu_resource_id}, {'resource_name': v_s_resource_info.virtual_storage_desc_id, 'resource_type': v_s_resource_info.storage_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.storage_resource_id}, {'resource_name': vnfc_resource_info.vnfc_cp_info[0].cpd_id, 'resource_type': inst_vnf_info.vnf_virtual_link_resource_info[0]. vnf_link_ports[0].resource_handle.vim_level_resource_type, 'physical_resource_id': uuidsentinel.cp1_resource_id}] self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) self.openstack.post_vnf_instantiation( self.context, vnf_instance, vim_connection_info) self.assertEqual(vnf_instance.instantiated_vnf_info. vnfc_resource_info[0].metadata['stack_id'], inst_vnf_info.instance_id) # Check if vnfc resource "VDU_VNF" is set with resource_id self.assertEqual(uuidsentinel.vdu_resource_id, vnf_instance.instantiated_vnf_info.vnfc_resource_info[0]. compute_resource.resource_id) # Check if virtual storage resource "storage1" is set with resource_id self.assertEqual(uuidsentinel.storage_resource_id, vnf_instance.instantiated_vnf_info. virtual_storage_resource_info[0].storage_resource.resource_id) # Check if virtual link port "CP1" is set with resource_id self.assertEqual(uuidsentinel.cp1_resource_id, vnf_instance.instantiated_vnf_info. vnf_virtual_link_resource_info[0].vnf_link_ports[0]. resource_handle.resource_id) def test_post_vnf_instantiation_with_ext_managed_virtual_link(self): v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1", set_resource_id=False) storage_resource_ids = [v_s_resource_info.id] vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF", storage_resource_ids=storage_resource_ids, set_resource_id=False) v_l_resource_info = fd_utils.get_virtual_link_resource_info( vnfc_resource_info.vnfc_cp_info[0].vnf_link_port_id, vnfc_resource_info.vnfc_cp_info[0].id, desc_id='ExternalVL1') ext_managed_v_l_resource_info = \ fd_utils.get_ext_managed_virtual_link_resource_info( uuidsentinel.virtual_link_port_id, uuidsentinel.vnfc_cp_info_id, desc_id='ExternalVL1') inst_vnf_info = fd_utils.get_vnf_instantiated_info( virtual_storage_resource_info=[v_s_resource_info], vnf_virtual_link_resource_info=[v_l_resource_info], vnfc_resource_info=[vnfc_resource_info], ext_managed_virtual_link_info=[ext_managed_v_l_resource_info]) vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() resources = [{'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.vdu_resource_id}, {'resource_name': v_s_resource_info.virtual_storage_desc_id, 'resource_type': v_s_resource_info.storage_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.storage_resource_id}, {'resource_name': vnfc_resource_info.vnfc_cp_info[0].cpd_id, 'resource_type': inst_vnf_info.vnf_virtual_link_resource_info[0]. vnf_link_ports[0].resource_handle.vim_level_resource_type, 'physical_resource_id': uuidsentinel.cp1_resource_id}, {'resource_name': v_l_resource_info.vnf_virtual_link_desc_id, 'resource_type': v_l_resource_info.network_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.v_l_resource_info_id}] self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) self.openstack.post_vnf_instantiation( self.context, vnf_instance, vim_connection_info) self.assertEqual(vnf_instance.instantiated_vnf_info. vnfc_resource_info[0].metadata['stack_id'], inst_vnf_info.instance_id) # Check if vnfc resource "VDU_VNF" is set with resource_id self.assertEqual(uuidsentinel.vdu_resource_id, vnf_instance.instantiated_vnf_info.vnfc_resource_info[0]. compute_resource.resource_id) # Check if virtual storage resource "storage1" is set with resource_id self.assertEqual(uuidsentinel.storage_resource_id, vnf_instance.instantiated_vnf_info. virtual_storage_resource_info[0].storage_resource.resource_id) # Check if virtual link port "CP1" is set with resource_id self.assertEqual(uuidsentinel.cp1_resource_id, vnf_instance.instantiated_vnf_info. vnf_virtual_link_resource_info[0].vnf_link_ports[0]. resource_handle.resource_id) # Check if ext managed virtual link port is set with resource_id self.assertEqual(uuidsentinel.cp1_resource_id, vnf_instance.instantiated_vnf_info. ext_managed_virtual_link_info[0].vnf_link_ports[0]. resource_handle.resource_id) def test_heal_vnf_instance(self): v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1") storage_resource_ids = [v_s_resource_info.id] vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF", storage_resource_ids=storage_resource_ids) inst_vnf_info = fd_utils.get_vnf_instantiated_info( virtual_storage_resource_info=[v_s_resource_info], vnfc_resource_info=[vnfc_resource_info]) vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() heal_vnf_request = objects.HealVnfRequest( vnfc_instance_id=[vnfc_resource_info.id], cause="healing request") # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. resources = [{ 'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': vnfc_resource_info.compute_resource. resource_id}, { 'resource_name': v_s_resource_info.virtual_storage_desc_id, 'resource_type': v_s_resource_info.storage_resource. vim_level_resource_type, 'physical_resource_id': v_s_resource_info.storage_resource. resource_id}] self._response_in_stack_get(inst_vnf_info.instance_id) self._response_in_resource_get_list(inst_vnf_info.instance_id, resources=resources) self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) self._response_in_stack_update(inst_vnf_info.instance_id) self._response_resource_mark_unhealthy(inst_vnf_info.instance_id, resources=resources) self.openstack.heal_vnf( self.context, vnf_instance, vim_connection_info, heal_vnf_request) history = self.requests_mock.request_history patch_req = [req.url for req in history if req.method == 'PATCH'] # Total 3 times patch should be called, 2 for marking resources # as unhealthy, and 1 for updating stack self.assertEqual(3, len(patch_req)) def test_heal_vnf_instance_resource_mark_unhealthy_error(self): vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF") inst_vnf_info = fd_utils.get_vnf_instantiated_info( vnfc_resource_info=[vnfc_resource_info]) vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() heal_vnf_request = objects.HealVnfRequest( vnfc_instance_id=[vnfc_resource_info.id], cause="healing request") # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. resources = [{ 'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': vnfc_resource_info.compute_resource. resource_id}] self._response_in_stack_get(inst_vnf_info.instance_id) self._response_in_resource_get_list(inst_vnf_info.instance_id, resources=resources) self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) self._response_resource_mark_unhealthy(inst_vnf_info.instance_id, resources=resources, raise_exception=True) result = self.assertRaises(exceptions.VnfHealFailed, self.openstack.heal_vnf, self.context, vnf_instance, vim_connection_info, heal_vnf_request) expected_msg = ("Failed to mark stack '%(id)s' resource as unhealthy " "for resource '%(resource_name)s'") % { 'id': inst_vnf_info.instance_id, 'resource_name': resources[0]['resource_name']} self.assertIn(expected_msg, str(result)) history = self.requests_mock.request_history patch_req = [req.url for req in history if req.method == 'PATCH'] # only one time patch method be called for marking vdu resource # as unhealthy self.assertEqual(1, len(patch_req)) def test_heal_vnf_instance_incorrect_stack_status(self): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() heal_vnf_request = objects.HealVnfRequest( vnfc_instance_id=[uuidsentinel.vnfc_resource_id], cause="healing request") # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. self._response_in_stack_get(inst_vnf_info.instance_id, stack_status='UPDATE_IN_PROGRESS') result = self.assertRaises(exceptions.VnfHealFailed, self.openstack.heal_vnf, self.context, vnf_instance, vim_connection_info, heal_vnf_request) expected_msg = ("Healing of vnf instance %s is possible only when " "stack %s status is CREATE_COMPLETE,UPDATE_COMPLETE, " "current stack status is UPDATE_IN_PROGRESS") self.assertIn(expected_msg % (vnf_instance.id, inst_vnf_info.instance_id), str(result)) def test_heal_vnf_wait(self): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf_wait. self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS", "UPDATE_COMPLETE"]) stack = self.openstack.heal_vnf_wait( self.context, vnf_instance, vim_connection_info) self.assertEqual('UPDATE_COMPLETE', stack.stack_status) def test_heal_vnf_wait_fail(self): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf_wait. self._response_in_wait_until_stack_ready(["UPDATE_IN_PROGRESS"]) self.openstack.STACK_RETRIES = 1 result = self.assertRaises(vnfm.VNFHealWaitFailed, self.openstack.heal_vnf_wait, self.context, vnf_instance, vim_connection_info) expected_msg = ("VNF Heal action is not completed within 10 seconds " "on stack %s") % inst_vnf_info.instance_id self.assertIn(expected_msg, str(result)) def test_post_heal_vnf(self): v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1") storage_resource_ids = [v_s_resource_info.id] vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF", storage_resource_ids=storage_resource_ids) inst_vnf_info = fd_utils.get_vnf_instantiated_info( virtual_storage_resource_info=[v_s_resource_info], vnfc_resource_info=[vnfc_resource_info]) vnfc_resource_info.metadata['stack_id'] = inst_vnf_info.instance_id vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() heal_vnf_request = objects.HealVnfRequest( vnfc_instance_id=[vnfc_resource_info.id], cause="healing request") # Change the physical_resource_id of both the resources, so # that we can check it's updated in vnf instance after # post_heal_vnf call. resources = [{ 'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.compute_resource_id_new}, { 'resource_name': v_s_resource_info.virtual_storage_desc_id, 'resource_type': v_s_resource_info.storage_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.storage_resource_id_new}] # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) v_s_resource_info_old = v_s_resource_info.obj_clone() vnfc_resource_info_old = vnfc_resource_info.obj_clone() self.openstack.post_heal_vnf(self.context, vnf_instance, vim_connection_info, heal_vnf_request) vnfc_resource_info_new = vnf_instance.instantiated_vnf_info.\ vnfc_resource_info[0] v_s_resource_info_new = vnf_instance.instantiated_vnf_info.\ virtual_storage_resource_info[0] # Compare the resource_id, it should be updated with the new ones. self.assertNotEqual(vnfc_resource_info_old.compute_resource. resource_id, vnfc_resource_info_new.compute_resource.resource_id) self.assertEqual(uuidsentinel.compute_resource_id_new, vnfc_resource_info_new.compute_resource.resource_id) self.assertNotEqual(v_s_resource_info_old.storage_resource.resource_id, v_s_resource_info_new.storage_resource.resource_id) self.assertEqual(uuidsentinel.storage_resource_id_new, v_s_resource_info_new.storage_resource.resource_id) def test_post_heal_vnf_fail(self): vnfc_resource_info = fd_utils.get_vnfc_resource_info() inst_vnf_info = fd_utils.get_vnf_instantiated_info( vnfc_resource_info=[vnfc_resource_info]) vnfc_resource_info.metadata['stack_id'] = uuidsentinel.stack_id vnf_instance = fd_utils.get_vnf_instance_object( instantiated_vnf_info=inst_vnf_info) vim_connection_info = fd_utils.get_vim_connection_info_object() heal_vnf_request = objects.HealVnfRequest( vnfc_instance_id=[vnfc_resource_info.id], cause="healing request") # Change the physical_resource_id of both the resources, so # that we can check it's updated in vnf instance after # post_heal_vnf call. resources = [{ 'resource_name': vnfc_resource_info.vdu_id, 'resource_type': vnfc_resource_info.compute_resource. vim_level_resource_type, 'physical_resource_id': uuidsentinel.compute_resource_id_new}] # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. self._responses_in_stack_list(inst_vnf_info.instance_id, resources=resources) result = self.assertRaises(exceptions.VnfHealFailed, self.openstack.post_heal_vnf, self.context, vnf_instance, vim_connection_info, heal_vnf_request) expected_msg = ("Heal Vnf failed for vnf %s, error: Failed to find " "stack_id %s") % (vnf_instance.id, uuidsentinel.stack_id) self.assertEqual(expected_msg, str(result))