summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZane Bitter <zbitter@redhat.com>2017-02-17 13:33:06 -0500
committerZane Bitter <zbitter@redhat.com>2017-04-05 12:39:46 -0400
commit666930d1958cc34a85da9712a7e09200ad0ec030 (patch)
tree8d33938fc43af24734c04b9a91e8ffea43dc4e34
parentb5359cedf10dab59a11effb0ebed383ad23c73a6 (diff)
downloadheat-666930d1958cc34a85da9712a7e09200ad0ec030.tar.gz
Update NodeData in legacy path
In convergence stacks, we obtain the NodeData for the resources the current resource depends on from the RPC message triggering the resource check. For the legacy path, this change updates the NodeData in the StackDefinition after each resource is created or updated. This means that the legacy and convergence paths will be able to access data about other resources in essentially the same way. Change-Id: I61c61745d864de99b0127f4103a6c3a83379c516 Partially-Implements: blueprint stack-definition
-rw-r--r--heat/engine/stack.py6
-rw-r--r--heat/engine/stk_defn.py11
-rw-r--r--heat/engine/update.py9
-rw-r--r--heat/tests/test_metadata_refresh.py9
4 files changed, 33 insertions, 2 deletions
diff --git a/heat/engine/stack.py b/heat/engine/stack.py
index 097af9667..f89cfc9f4 100644
--- a/heat/engine/stack.py
+++ b/heat/engine/stack.py
@@ -1092,11 +1092,15 @@ class Stack(collections.Mapping):
lambda x: {})
@functools.wraps(getattr(resource.Resource, action_method))
+ @scheduler.wrappertask
def resource_action(r):
# Find e.g resource.create and call it
handle = getattr(r, action_method)
- return handle(**handle_kwargs(r))
+ yield handle(**handle_kwargs(r))
+
+ if action == self.CREATE:
+ stk_defn.update_resource_data(self.defn, r.name, r.node_data())
def get_error_wait_time(resource):
return resource.cancel_grace_period()
diff --git a/heat/engine/stk_defn.py b/heat/engine/stk_defn.py
index bc96d7c0f..c07039bdb 100644
--- a/heat/engine/stk_defn.py
+++ b/heat/engine/stk_defn.py
@@ -219,6 +219,17 @@ class ResourceProxy(status.ResourceStatus):
if k != attributes.SHOW_ATTR)
+def update_resource_data(stack_definition, resource_name, resource_data):
+ """Store new resource state data for the specified resource.
+
+ This function enables the legacy (non-convergence) path to store updated
+ NodeData as resources are created/updated in a single StackDefinition
+ that lasts for the entire lifetime of the stack operation.
+ """
+ stack_definition._resource_data[resource_name] = resource_data
+ stack_definition._resources.pop(resource_name, None)
+
+
def add_resource(stack_definition, resource_definition):
"""Insert the given resource definition into the stack definition.
diff --git a/heat/engine/update.py b/heat/engine/update.py
index de1599ccc..d6faeadf7 100644
--- a/heat/engine/update.py
+++ b/heat/engine/update.py
@@ -19,6 +19,7 @@ from heat.common.i18n import repr_wrapper
from heat.engine import dependencies
from heat.engine import resource
from heat.engine import scheduler
+from heat.engine import stk_defn
from heat.objects import resource as resource_objects
LOG = logging.getLogger(__name__)
@@ -173,12 +174,20 @@ class StackUpdate(object):
"%(stack_name)s updated",
{'res_name': res_name,
'stack_name': self.existing_stack.name})
+
+ stk_defn.update_resource_data(self.existing_stack.defn,
+ res_name,
+ existing_res.node_data())
return
else:
self._check_replace_restricted(new_res)
yield self._create_resource(new_res)
+ node_data = self.existing_stack[res_name].node_data()
+ stk_defn.update_resource_data(self.existing_stack.defn, res_name,
+ node_data)
+
def _update_in_place(self, existing_res, new_res, is_substituted=False):
existing_snippet = self.existing_snippets[existing_res.name]
prev_res = self.previous_stack.get(new_res.name)
diff --git a/heat/tests/test_metadata_refresh.py b/heat/tests/test_metadata_refresh.py
index 0675b735f..23720f4c0 100644
--- a/heat/tests/test_metadata_refresh.py
+++ b/heat/tests/test_metadata_refresh.py
@@ -150,7 +150,7 @@ class MetadataRefreshTest(common.HeatTestCase):
@mock.patch.object(glance.GlanceClientPlugin, 'find_image_by_name_or_id')
@mock.patch.object(instance.Instance, 'handle_create')
@mock.patch.object(instance.Instance, 'check_create_complete')
- @mock.patch.object(instance.Instance, 'FnGetAtt')
+ @mock.patch.object(instance.Instance, '_resolve_attribute')
def test_FnGetAtt_metadata_updated(self, mock_get, mock_check,
mock_handle, *args):
"""Tests that metadata gets updated when FnGetAtt return changes."""
@@ -172,6 +172,7 @@ class MetadataRefreshTest(common.HeatTestCase):
# Initial resolution of the metadata
stack.create()
+ self.assertEqual((stack.CREATE, stack.COMPLETE), stack.state)
# Sanity check on S2
s2 = stack['S2']
@@ -182,6 +183,12 @@ class MetadataRefreshTest(common.HeatTestCase):
content = self._get_metadata_content(s1.metadata_get())
self.assertEqual('s2-ip=10.0.0.1', content)
+ # This is not a terribly realistic test - the metadata updates below
+ # happen in run_alarm_action() in service_stack_watch, and actually
+ # operate on a freshly loaded stack so there's no cached attributes.
+ # Clear the attributes cache here to keep it passing.
+ s2.attributes.reset_resolved_values()
+
# Run metadata update to pick up the new value from S2
s1.metadata_update()
s2.metadata_update()