From 154a22b18f8e5ef40b326633c91310405de68b8f Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Thu, 25 Jun 2015 12:40:56 +1000 Subject: [PATCH] Convergence: Fix Resource Replacement. - Set the appropriate states for the resource and it's replacement. - Serialize input_data before calling check_resource for a replacement. - Make replacement should take the current template ID being provisioned and assign it to the new replacement being created. Otherwise, the replacement has reference to old template id, from the resource it is replacing, and properties don't get updated. Change-Id: I49da2fcfdce7510dd58716ba2050cfb529114997 Co-Authored-By: Sirushti Murugesan Co-Authored-By: Anant Patil --- heat/engine/resource.py | 9 ++++++--- heat/engine/worker.py | 4 +++- heat/tests/test_resource.py | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 74d72dc99b..1f41a29b5a 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -254,7 +254,7 @@ class Resource(object): resource._load_data(db_res) return resource, stack - def make_replacement(self): + def make_replacement(self, new_tmpl_id): # 1. create the replacement with "replaces" = self.id # Don't set physical_resource_id so that a create is triggered. rs = {'stack_id': self.stack.id, @@ -263,14 +263,17 @@ class Resource(object): 'needed_by': self.needed_by, 'requires': self.requires, 'replaces': self.id, - 'current_template_id': self.current_template_id, + 'action': self.INIT, + 'status': self.COMPLETE, + 'current_template_id': new_tmpl_id, 'stack_name': self.stack.name} new_rs = resource_objects.Resource.create(self.context, rs) # 2. update the current resource to be replaced_by the one above. rs = resource_objects.Resource.get_obj(self.context, self.id) self.replaced_by = new_rs.id - rs.update_and_save({'replaced_by': self.replaced_by}) + rs.update_and_save({'status': self.COMPLETE, + 'replaced_by': self.replaced_by}) return new_rs.id def reparse(self): diff --git a/heat/engine/worker.py b/heat/engine/worker.py index eafe354a7f..2c9b1947aa 100644 --- a/heat/engine/worker.py +++ b/heat/engine/worker.py @@ -163,7 +163,9 @@ class WorkerService(service.Service): try: check_resource_update(rsrc, tmpl.id, data, self.engine_id) except resource.UpdateReplace: - new_res_id = rsrc.make_replacement() + new_res_id = rsrc.make_replacement(tmpl.id) + LOG.info("Replacing resource with new id %s", new_res_id) + data = sync_point.serialize_input_data(data) self._rpc_client.check_resource(cnxt, new_res_id, current_traversal, diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index 0329120dce..8603e19e10 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -382,13 +382,15 @@ class ResourceTest(common.HeatTestCase): tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo') res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack) res._store() + new_tmpl_id = 2 self.assertIsNotNone(res.id) - new_id = res.make_replacement() + new_id = res.make_replacement(new_tmpl_id) new_res = resource_objects.Resource.get_obj(res.context, new_id) self.assertEqual(new_id, res.replaced_by) self.assertEqual(res.id, new_res.replaces) self.assertIsNone(new_res.nova_instance) + self.assertEqual(new_tmpl_id, new_res.current_template_id) def test_parsed_template(self): join_func = cfn_funcs.Join(None,