diff options
author | Zuul <zuul@review.openstack.org> | 2018-02-20 19:19:23 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2018-02-20 19:19:24 +0000 |
commit | a2e26ffb71995c78fda9a91e01558600ea063274 (patch) | |
tree | 72e7f1fae54121a006b6af1cefb08bc9255f7615 | |
parent | 2bf19f54503fc1b5311fa441c2aa65a95f7d37bb (diff) | |
parent | 9ef06ccead321fcc224ba4c33b168d2e7e746de1 (diff) | |
download | heat-a2e26ffb71995c78fda9a91e01558600ea063274.tar.gz |
Merge "Fix non-destructive upgrade for deprecated res types in convergence" into stable/ocata
-rw-r--r-- | heat/engine/resource.py | 39 | ||||
-rw-r--r-- | heat_integrationtests/functional/test_replace_deprecated.py | 12 |
2 files changed, 33 insertions, 18 deletions
diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 0d173090a..cd4909bdd 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -337,11 +337,28 @@ class Resource(object): resource_owning_stack = stack_mod.Stack.load(context, stack=db_stack) - # Load only the resource in question; don't load all resources - # by invoking stack.resources. Maintain light-weight stack. res_defn = resource_owning_stack.t.resource_definitions( resource_owning_stack)[db_res.name] - resource = cls(db_res.name, res_defn, resource_owning_stack) + res_type = resource_owning_stack.env.registry.get_class_to_instantiate( + res_defn.resource_type, resource_name=db_res.name) + + # If the resource type has changed and the new one is a valid + # substitution, use that as the class to instantiate. + if is_update and (curr_stack is not resource_owning_stack): + new_res_defns = curr_stack.t.resource_definitions( + resource_owning_stack) + if db_res.name in new_res_defns: + new_res_defn = new_res_defns[db_res.name] + new_registry = curr_stack.env.registry + new_res_type = new_registry.get_class_to_instantiate( + new_res_defn.resource_type, resource_name=db_res.name) + + if res_type.check_is_substituted(new_res_type): + res_type = new_res_type + + # Load only the resource in question; don't load all resources + # by invoking stack.resources. Maintain light-weight stack. + resource = res_type(db_res.name, res_defn, resource_owning_stack) resource._load_data(db_res) # assign current stack to the resource for updates @@ -1164,6 +1181,9 @@ class Resource(object): ) with self.lock(engine_id): + # Check that the resource type matches. If the type has changed by + # a legitimate substitution, the load()ed resource will already be + # of the new type. registry = new_stack.env.registry new_res_def = new_stack.t.resource_definitions( new_stack)[self.name] @@ -1171,8 +1191,7 @@ class Resource(object): new_res_def.resource_type, resource_name=self.name) restricted_actions = registry.get_rsrc_restricted_actions( self.name) - is_substituted = self.check_is_substituted(new_res_type) - if type(self) is not new_res_type and not is_substituted: + if type(self) is not new_res_type: self._check_for_convergence_replace(restricted_actions) action_rollback = self.stack.action == self.stack.ROLLBACK @@ -1186,15 +1205,7 @@ class Resource(object): six.text_type(failure)) raise failure - # Use new resource as update method if existing resource - # need to be substituted. - if is_substituted: - substitute = new_res_type(self.name, self.t, self.stack) - self.stack.resources[self.name] = substitute - updater = substitute.update - else: - updater = self.update - runner = scheduler.TaskRunner(updater, new_res_def) + runner = scheduler.TaskRunner(self.update, new_res_def) try: runner(timeout=timeout, progress_callback=progress_callback) update_tmpl_id_and_requires() diff --git a/heat_integrationtests/functional/test_replace_deprecated.py b/heat_integrationtests/functional/test_replace_deprecated.py index 5e7fdc67e..bbf2e66cc 100644 --- a/heat_integrationtests/functional/test_replace_deprecated.py +++ b/heat_integrationtests/functional/test_replace_deprecated.py @@ -69,24 +69,28 @@ properties: parameters=parms, template=deployments_template, enable_cleanup=self.enable_cleanup) + expected_resources = {'config': 'OS::Heat::SoftwareConfig', 'dep': 'OS::Heat::SoftwareDeployments', 'server': 'OS::Nova::Server'} - resource = self.client.resources.get(stack_identifier, 'server') self.assertEqual(expected_resources, self.list_resources(stack_identifier)) + + resource = self.client.resources.get(stack_identifier, 'dep') initial_phy_id = resource.physical_resource_id + resources = deployments_template['resources'] resources['dep'] = yaml.safe_load(self.deployment_group_snippet) self.update_stack( stack_identifier, deployments_template, parameters=parms) - resource = self.client.resources.get(stack_identifier, 'server') - self.assertEqual(initial_phy_id, - resource.physical_resource_id) + expected_new_resources = {'config': 'OS::Heat::SoftwareConfig', 'dep': 'OS::Heat::SoftwareDeploymentGroup', 'server': 'OS::Nova::Server'} self.assertEqual(expected_new_resources, self.list_resources(stack_identifier)) + + resource = self.client.resources.get(stack_identifier, 'dep') + self.assertEqual(initial_phy_id, resource.physical_resource_id) |