From 33cb3ba5753c7487f6e8ef7e7d30359a5df2f30d Mon Sep 17 00:00:00 2001 From: Aldinson Esto Date: Wed, 28 Apr 2021 14:56:08 +0900 Subject: [PATCH] Fix Healing so image is updated after Healing This patch will fix the issue about Healing not being able to update to the new image. Closes-Bug: #1924215 Change-Id: I3de1a532e33ae25638a452db4b9e18626de8df42 --- tacker/conductor/conductor_server.py | 20 ++++++ tacker/tests/functional/sol/vnflcm/base.py | 12 ++++ .../test_vnf_instance_with_user_data.py | 13 ++++ ...f_instance_with_user_data_nfvo_separate.py | 2 +- .../unit/conductor/test_conductor_server.py | 43 ++++++++++-- .../openstack/test_openstack_driver.py | 66 +++++++++++++++++-- tacker/vnflcm/utils.py | 61 +++++++++++++++++ .../vnfm/infra_drivers/openstack/openstack.py | 35 +++++++++- 8 files changed, 238 insertions(+), 14 deletions(-) diff --git a/tacker/conductor/conductor_server.py b/tacker/conductor/conductor_server.py index 6a52d8d28..43b6fbea4 100644 --- a/tacker/conductor/conductor_server.py +++ b/tacker/conductor/conductor_server.py @@ -1953,6 +1953,21 @@ class Conductor(manager.Manager): error_point=vnf_dict['current_error_point'] ) + def _update_vnf_attributes_stack_param(self, context, vnf_dict, vnf_id, + heal_vnf_request, inst_vnf_info): + stack_param = vnflcm_utils.get_stack_param( + context, vnf_dict, heal_vnf_request, inst_vnf_info) + + # update vnf_attribute in DB + with context.session.begin(subtransactions=True): + vnf_attr_model = (context.session.query( + vnfm_db.VNFAttribute). + filter_by(vnf_id=vnf_id). + filter_by(key='stack_param').first()) + + if vnf_attr_model: + vnf_attr_model.update({'value': str(stack_param)}) + @coordination.synchronized('{vnf_instance[id]}') def heal(self, context, @@ -1998,6 +2013,11 @@ class Conductor(manager.Manager): self._update_instantiated_vnf_info(context, vnf_instance, heal_vnf_request) + # update stack_param in vnf_attribute table + self._update_vnf_attributes_stack_param( + context, vnf_dict, vnf_instance.id, heal_vnf_request, + vnf_instance.instantiated_vnf_info) + # update instance_in in vnf_table self._add_additional_vnf_info(context, vnf_instance) diff --git a/tacker/tests/functional/sol/vnflcm/base.py b/tacker/tests/functional/sol/vnflcm/base.py index d1ab0b6fb..9c9555a0a 100644 --- a/tacker/tests/functional/sol/vnflcm/base.py +++ b/tacker/tests/functional/sol/vnflcm/base.py @@ -10,6 +10,7 @@ # 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 json import os import tempfile import time @@ -1253,3 +1254,14 @@ class BaseVnfLcmTest(base.BaseTackerTest): return [ h for h in notify_histories if h.request_body.get('vnfInstanceId') == vnf_instance_id] + + def _get_heat_stack_show(self, vnf_instance_id, resource_name): + """Retrieve image name of the resource from stack""" + try: + stack = self._get_heat_stack(vnf_instance_id) + stack_info = self.h_client.stacks.get(stack.id) + stack_dict = stack_info.to_dict() + resource_dict = json.loads(stack_dict['parameters']['nfv']) + except Exception: + return None + return resource_dict['VDU'][resource_name]['image'] diff --git a/tacker/tests/functional/sol/vnflcm/test_vnf_instance_with_user_data.py b/tacker/tests/functional/sol/vnflcm/test_vnf_instance_with_user_data.py index 6dd03efc6..cf385e22b 100644 --- a/tacker/tests/functional/sol/vnflcm/test_vnf_instance_with_user_data.py +++ b/tacker/tests/functional/sol/vnflcm/test_vnf_instance_with_user_data.py @@ -374,6 +374,13 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): resp, vnf_instance = self._show_vnf_instance(vnf_instance_id) self.assertEqual(200, resp.status_code) + # Get VNF image after instantiate VDU2 + image_before_update = self._get_heat_stack_show( + vnf_instance_id, 'VDU2') + self.assertIsNotNone( + image_before_update, + "failed to retrieve image") + # Update vnf (vnfdId) sample_name = 'functional2' csar_package_path = os.path.abspath( @@ -409,6 +416,12 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) self.assert_heal_vnf(resp, vnf_instance_id, vnf_package_id) + # Check of Image changes after heal + image_after_heal = self._get_heat_stack_show(vnf_instance_id, 'VDU2') + self.assertIsNotNone( + image_after_heal, "failed to retrieve image") + self.assertNotEqual(image_before_update, image_after_heal) + # Terminate VNF stack = self._get_heat_stack(vnf_instance_id) resources_list = self._get_heat_resource_list(stack.id) diff --git a/tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py b/tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py index 53ab325f7..afbcf5487 100644 --- a/tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py +++ b/tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py @@ -541,5 +541,5 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest): physical_resource_id = [r.physical_resource_id for r in resources_list if stack_name_wd in r.stack_name] template = self._get_heat_stack_template(physical_resource_id[0]) - template_count = str(template).count("zone") + template_count = str(template).count("flavor") self.assertEqual(template_count, 3) diff --git a/tacker/tests/unit/conductor/test_conductor_server.py b/tacker/tests/unit/conductor/test_conductor_server.py index eb7696ab4..b1db431bc 100644 --- a/tacker/tests/unit/conductor/test_conductor_server.py +++ b/tacker/tests/unit/conductor/test_conductor_server.py @@ -1344,6 +1344,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_log.error.assert_called_once_with(expected_msg, vnf_package_vnfd.package_uuid) + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_add_additional_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' @@ -1355,7 +1357,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): @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): + mock_update_insta_vnf_info, mock_add_additional_vnf_info, + mock_update_vnf_attributes_stack_param): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, @@ -1380,7 +1383,12 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 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_update_vnf_attributes_stack_param.assert_called_once_with( + self.context, vnf_dict, vnf_instance.id, heal_vnf_req, + vnf_instance.instantiated_vnf_info) + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_add_additional_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' @@ -1393,7 +1401,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): def test_heal_vnf_instance_error_point_notify_processing( self, mock_vnf_by_id, mock_get_lock, mock_save, mock_change_vnf_status, mock_update_insta_vnf_info, - mock_add_additional_vnf_info): + mock_add_additional_vnf_info, + mock_update_vnf_attributes_stack_param): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, @@ -1418,7 +1427,12 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 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_update_vnf_attributes_stack_param.assert_called_once_with( + self.context, vnf_dict, vnf_instance.id, heal_vnf_req, + vnf_instance.instantiated_vnf_info) + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_add_additional_vnf_info') @mock.patch('tacker.conductor.conductor_server.Conductor.' @@ -1431,7 +1445,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): def test_heal_vnf_instance_error_point_internal_processing( self, mock_vnf_by_id, mock_get_lock, mock_save, mock_change_vnf_status, mock_update_insta_vnf_info, - mock_add_additional_vnf_info): + mock_add_additional_vnf_info, + mock_update_vnf_attributes_stack_param): lcm_op_occs_data = fakes.get_lcm_op_occs_data() mock_vnf_by_id.return_value = \ objects.VnfLcmOpOcc(context=self.context, @@ -1456,6 +1471,9 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 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_update_vnf_attributes_stack_param.assert_called_once_with( + self.context, vnf_dict, vnf_instance.id, heal_vnf_req, + vnf_instance.instantiated_vnf_info) @mock.patch('tacker.vnflcm.vnflcm_driver.VnfLcmDriver' '.heal_vnf') @@ -1496,6 +1514,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): self.assertEqual(mock_update_insta_vnf_info.call_count, 0) self.assertEqual(mock_add_additional_vnf_info.call_count, 0) + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch('tacker.conductor.conductor_server.Conductor' @@ -1528,7 +1548,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_save, mock_add_vnf_info, mock_update_vnf_info, - mock_change_status): + mock_change_status, + mock_update_vnf_attributes_stack_param): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) @@ -1581,9 +1602,12 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): heal_vnf_req, vnf_lcm_op_occs_id) mock_add_vnf_info.assert_called_once() mock_update_vnf_info.assert_called_once() + mock_update_vnf_attributes_stack_param.assert_called_once() self.vnflcm_driver.heal_vnf.assert_called_once_with( self.context, mock.ANY, vnf_dict, heal_vnf_req) + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor' '._change_vnf_status') @mock.patch('tacker.conductor.conductor_server.Conductor' @@ -1619,7 +1643,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_save, mock_add_vnf_info, mock_update_vnf_info, - mock_change_status): + mock_change_status, + mock_update_vnf_attribute_stack_param): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) @@ -1746,6 +1771,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): heal_vnf_req, vnf_lcm_op_occs_id) mock_add_vnf_info.assert_called_once() mock_update_vnf_info.assert_called_once() + mock_update_vnf_attribute_stack_param.assert_called_once() self.vnflcm_driver.heal_vnf.assert_called_once_with( self.context, mock.ANY, vnf_dict, heal_vnf_req) @@ -1916,6 +1942,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_send.call_args[0][1].get('operationState'), 'ROLLED_BACK') + @mock.patch('tacker.conductor.conductor_server.Conductor.' + '_update_vnf_attributes_stack_param') @mock.patch('tacker.conductor.conductor_server.Conductor.' '_send_lcm_op_occ_notification') @mock.patch('tacker.conductor.conductor_server.Conductor.' @@ -1929,7 +1957,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 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): + mock_send_notification, mock_update_vnf_attributes_stack_param): vnf_package_vnfd = self._create_and_upload_vnf_package() vnf_instance_data = fake_obj.get_vnf_instance_data( vnf_package_vnfd.vnfd_id) @@ -1951,6 +1979,9 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): vnf_instance.id, mock.ANY, constants.ERROR, "") mock_update_insta_vnf_info.assert_called_with(self.context, vnf_instance, heal_vnf_req) + mock_update_vnf_attributes_stack_param.assert_called_once_with( + self.context, vnf_dict, vnf_instance.id, heal_vnf_req, + vnf_instance.instantiated_vnf_info) self.assertEqual(mock_send_notification.call_count, 2) @unittest.skip("Such test is no longer feasible.") diff --git a/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py b/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py index 3c90373bb..cabb4a5ac 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py +++ b/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py @@ -49,6 +49,29 @@ vnf_dict = { } +class FakeVNFMPlugin(mock.Mock): + def __init__(self): + super(FakeVNFMPlugin, self).__init__() + + def get_vnf(self, context, vnf_id): + return { + 'attributes': {}, + 'status': 'ACTIVE', + 'vnfd_id': 'e889e4fe-52fe-437d-b1e1-a690dc95e3f8', + 'tenant_id': '13d2ca8de70d48b2a2e0dbac2c327c0b', + 'vim_id': '3f41faa7-5630-47d2-9d4a-1216953c8887', + 'instance_id': 'd1121d3c-368b-4ac2-b39d-835aa3e4ccd8', + 'placement_attr': {'vim_name': 'kubernetes-vim'}, + 'id': '436aaa6e-2db6-4d6e-a3fc-e728b2f0ac56', + 'name': 'cnf_create_1', + 'vnfd': { + 'attributes': { + 'vnfd_simple': 'dummy' + } + } + } + + class FakeAlarmPlugin(): def add_alarm_url_to_vnf(self, context, vnf): return @@ -66,6 +89,10 @@ class TestOpenStack(base.FixturedTestCase): def setUp(self): super(TestOpenStack, self).setUp() + self.patcher = mock.patch( + 'tacker.manager.TackerManager.get_service_plugins', + return_value={'VNFM': FakeVNFMPlugin()}) + self.mock_manager = self.patcher.start() self.openstack = openstack.OpenStack() self.context = context.get_admin_context() self.heat_url = client.HEAT_URL @@ -1787,8 +1814,16 @@ class TestOpenStack(base.FixturedTestCase): ext_managed_virtual_link_info[0].vnf_link_ports[0]. resource_handle.resource_id) + @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') + @mock.patch('tacker.vnflcm.utils._get_vnf_package_path') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_vnf_instance_id") - def test_heal_vnf_instance(self, mock_get_vnflcm_op_occs): + def test_heal_vnf_instance(self, mock_get_vnflcm_op_occs, + mock_get_vnf_package_path, + mock_get_base_hot_dict): + nested_hot_dict = {'parameters': {'vnf': 'test'}} + mock_get_base_hot_dict.return_value = \ + self._read_file(), nested_hot_dict + v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1") @@ -1836,7 +1871,8 @@ class TestOpenStack(base.FixturedTestCase): error_point=fields.ErrorPoint.PRE_VIM_CONTROL) mock_get_vnflcm_op_occs.return_value = vnf_lcm_op_occs self.openstack.heal_vnf( - self.context, vnf_instance, vim_connection_info, heal_vnf_request) + 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'] @@ -1844,9 +1880,16 @@ class TestOpenStack(base.FixturedTestCase): # as unhealthy, and 1 for updating stack self.assertEqual(3, len(patch_req)) + @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') + @mock.patch('tacker.vnflcm.utils._get_vnf_package_path') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_vnf_instance_id") def test_heal_vnf_instance_error_point_post_vim_control( - self, mock_get_vnflcm_op_occs): + self, mock_get_vnflcm_op_occs, mock_get_vnf_package_path, + mock_get_base_hot_dict): + nested_hot_dict = {'parameters': {'vnf': 'test'}} + mock_get_base_hot_dict.return_value = \ + self._read_file(), nested_hot_dict + v_s_resource_info = fd_utils.get_virtual_storage_resource_info( desc_id="storage1") @@ -1892,16 +1935,18 @@ class TestOpenStack(base.FixturedTestCase): error_point=fields.ErrorPoint.POST_VIM_CONTROL) mock_get_vnflcm_op_occs.return_value = vnf_lcm_op_occs self.openstack.heal_vnf( - self.context, vnf_instance, vim_connection_info, heal_vnf_request) + 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 of 1 times for updating stack self.assertEqual(1, len(patch_req)) + @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_vnf_instance_id") def test_heal_vnf_instance_resource_mark_unhealthy_error( - self, mock_get_vnflcm_op_occs): + self, mock_get_vnflcm_op_occs, mock_get_base_hot_dict): vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF") inst_vnf_info = fd_utils.get_vnf_instantiated_info( @@ -1916,6 +1961,10 @@ class TestOpenStack(base.FixturedTestCase): vnfc_instance_id=[vnfc_resource_info.id], cause="healing request") + nested_hot_dict = {'parameters': {'vnf': 'test'}} + mock_get_base_hot_dict.return_value = ( + self._read_file(), nested_hot_dict) + # Mock various heat APIs that will be called by heatclient # during the process of heal_vnf. resources = [{ @@ -1952,9 +2001,10 @@ class TestOpenStack(base.FixturedTestCase): # as unhealthy self.assertEqual(1, len(patch_req)) + @mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict') @mock.patch.object(objects.VnfLcmOpOcc, "get_by_vnf_instance_id") def test_heal_vnf_instance_incorrect_stack_status( - self, mock_get_vnflcm_op_occs): + self, mock_get_vnflcm_op_occs, mock_get_base_hot_dict): inst_vnf_info = fd_utils.get_vnf_instantiated_info() vnf_instance = fd_utils.get_vnf_instance_object( @@ -1966,6 +2016,10 @@ class TestOpenStack(base.FixturedTestCase): vnfc_instance_id=[uuidsentinel.vnfc_resource_id], cause="healing request") + nested_hot_dict = {'parameters': {'vnf': 'test'}} + mock_get_base_hot_dict.return_value = ( + self._read_file(), nested_hot_dict) + # 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, diff --git a/tacker/vnflcm/utils.py b/tacker/vnflcm/utils.py index 0b8ed8d3c..05ef8936f 100644 --- a/tacker/vnflcm/utils.py +++ b/tacker/vnflcm/utils.py @@ -28,6 +28,7 @@ from tacker.extensions import nfvo from tacker import objects from tacker.objects import fields from tacker.tosca import utils as toscautils +from tacker.vnfm.lcm_user_data import utils as userdata_utils from tacker.vnfm import vim_client LOG = logging.getLogger(__name__) @@ -1314,3 +1315,63 @@ def _get_changed_ext_connectivity( LOG.debug('changed_ext_connectivities: {}'.format( changed_ext_connectivities)) return changed_ext_connectivities + + +def get_stack_param(context, vnf_dict, heal_vnf_request, inst_vnf_info): + stack_param = {} + vnfc_resources = [] + + # get vnfc resources + if not heal_vnf_request.vnfc_instance_id: + # include all vnfc resources + vnfc_resources = [ + resource for resource in inst_vnf_info.vnfc_resource_info] + else: + for vnfc_resource in inst_vnf_info.vnfc_resource_info: + if vnfc_resource.id in heal_vnf_request.vnfc_instance_id: + vnfc_resources.append(vnfc_resource) + + def _update_stack_params( + context, base_hot_dict, nested_hot_dict, vnfd_dict): + param_base_hot_dict = copy.deepcopy(nested_hot_dict) + param_base_hot_dict['heat_template'] = base_hot_dict + + initial_param_dict = ( + userdata_utils.create_initial_param_server_port_dict( + param_base_hot_dict) + ) + del initial_param_dict['nfv']['CP'] + + vdu_flavor_dict = ( + userdata_utils.create_vdu_flavor_capability_name_dict(vnfd_dict) + ) + vdu_image_dict = userdata_utils.create_sw_image_dict(vnfd_dict) + + final_param_dict = userdata_utils.create_final_param_dict( + initial_param_dict, vdu_flavor_dict, vdu_image_dict, {}) + + return final_param_dict['nfv']['VDU'] + + # get HOT dict + base_hot_dict, nested_hot_dict = get_base_nest_hot_dict( + context, inst_vnf_info.flavour_id, vnf_dict['vnfd_id']) + + vnfd_dict = yaml.safe_load( + vnf_dict['vnfd']['attributes']['vnfd_' + inst_vnf_info.flavour_id]) + + if 'stack_param' in vnf_dict['attributes'].keys(): + stack_param = yaml.safe_load( + vnf_dict['attributes']['stack_param']) + + updated_vdu_params = _update_stack_params( + context, base_hot_dict, nested_hot_dict, vnfd_dict) + + for vnfc_resource in vnfc_resources: + vdu_id = vnfc_resource.vdu_id + if (updated_vdu_params.get(vdu_id) and + stack_param['nfv']['VDU'].get(vdu_id)): + stack_param['nfv']['VDU'].update({ + vdu_id: updated_vdu_params.get(vdu_id) + }) + + return stack_param diff --git a/tacker/vnfm/infra_drivers/openstack/openstack.py b/tacker/vnfm/infra_drivers/openstack/openstack.py index cb3a1342e..6a01de820 100644 --- a/tacker/vnfm/infra_drivers/openstack/openstack.py +++ b/tacker/vnfm/infra_drivers/openstack/openstack.py @@ -37,6 +37,7 @@ from tacker.common import utils from tacker.db.common_services import common_services_db_plugin from tacker.extensions import vnflcm from tacker.extensions import vnfm +from tacker import manager from tacker import objects from tacker.objects import fields from tacker.plugins.common import constants @@ -1264,6 +1265,10 @@ class OpenStack(abstract_driver.VnfAbstractDriver, heatclient = hc.HeatClient(access_info, region_name=region_name) vnf_lcm_op_occs = objects.VnfLcmOpOcc.get_by_vnf_instance_id( context, vnf_instance.id) + stack_param = {} + + vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM'] + vnf_dict = vnfm_plugin.get_vnf(context, vnf_instance.id) def _get_storage_resources(vnfc_resource): # Prepare list of storage resources to be marked unhealthy @@ -1350,10 +1355,38 @@ class OpenStack(abstract_driver.VnfAbstractDriver, _get_stack_status() _resource_mark_unhealthy() + # get HOT dict + base_hot_dict, nested_hot_dict = \ + vnflcm_utils.get_base_nest_hot_dict( + context, + inst_vnf_info.flavour_id, + vnf_dict['vnfd_id']) + + stack_param = vnflcm_utils.get_stack_param( + context, vnf_dict, heal_vnf_request, inst_vnf_info) + + # update stack with latest HOT + stack_update_param = { + 'existing': True} + + if base_hot_dict: + stack_update_param['template'] = \ + self._format_base_hot(base_hot_dict) + + if nested_hot_dict: + files_dict = {} + for name, value in nested_hot_dict.items(): + files_dict[name] = self._format_base_hot(value) + stack_update_param['files'] = files_dict + + if stack_param: + stack_update_param['parameters'] = stack_param + LOG.info("Updating stack %(stack)s for vnf instance %(id)s", {"stack": inst_vnf_info.instance_id, "id": vnf_instance.id}) - heatclient.update(stack_id=inst_vnf_info.instance_id, existing=True) + heatclient.update( + stack_id=inst_vnf_info.instance_id, **stack_update_param) @log.log def heal_vnf_wait(self, context, vnf_instance, vim_connection_info,