summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-02-20 19:19:23 +0000
committerGerrit Code Review <review@openstack.org>2018-02-20 19:19:24 +0000
commita2e26ffb71995c78fda9a91e01558600ea063274 (patch)
tree72e7f1fae54121a006b6af1cefb08bc9255f7615
parent2bf19f54503fc1b5311fa441c2aa65a95f7d37bb (diff)
parent9ef06ccead321fcc224ba4c33b168d2e7e746de1 (diff)
downloadheat-a2e26ffb71995c78fda9a91e01558600ea063274.tar.gz
Merge "Fix non-destructive upgrade for deprecated res types in convergence" into stable/ocata
-rw-r--r--heat/engine/resource.py39
-rw-r--r--heat_integrationtests/functional/test_replace_deprecated.py12
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)