Use stored properties values during signal

When we signal a resource, we want the signal to be interpreted in the
context of the properties of the resource as they were set at the last
stack update, not based on any attributes of other resources that may have
changed.

We already store the properties for comparison during updates. This patch
freezes the properties while we call handle_signal(), in a similar way to
how we freeze the properties during handle_update() (see bug 1584623).

Also make sure that when a ScalingPolicy adjusts an autoscaling group, it
also uses the group's stored properties so that e.g. the definitions of
existing members cannot change on a scale up.

Change-Id: I7e248ad82f2334b1a580655efa3a302e7d84fbd8
Partially-Implements: blueprint stack-definition
This commit is contained in:
Zane Bitter 2017-07-19 17:35:39 -04:00
parent 9a21b8a5f3
commit efd51f4525
2 changed files with 32 additions and 5 deletions

View File

@ -553,12 +553,35 @@ class Resource(status.ResourceStatus):
**self.stack.identifier())
def frozen_definition(self):
"""Return a frozen ResourceDefinition with stored property values.
The returned definition will contain the property values read from the
database, and will have all intrinsic functions resolved (note that
this makes it useless for calculating dependencies).
"""
if self._stored_properties_data is not None:
args = {'properties': self._stored_properties_data}
else:
args = {}
return self.t.freeze(**args)
@contextlib.contextmanager
def frozen_properties(self):
"""Context manager to use the frozen property values from the database.
The live property values are always substituted back when the context
ends.
"""
live_props = self.properties
props = self.frozen_definition().properties(self.properties_schema,
self.context)
try:
self.properties = props
yield props
finally:
self.properties = live_props
def update_template_diff(self, after, before):
"""Returns the difference between the before and after json snippets.
@ -2344,7 +2367,10 @@ class Resource(status.ResourceStatus):
return False
if need_check:
self._signal_check_action()
self._handle_signal(details)
with self.frozen_properties():
self._handle_signal(details)
return self.signal_needs_metadata_updates
def handle_update(self, json_snippet, tmpl_diff, prop_diff):

View File

@ -182,10 +182,11 @@ class AutoScalingPolicy(cooldown.CooldownMixin,
size_changed = False
try:
group.adjust(
self.properties[self.SCALING_ADJUSTMENT],
self.properties[self.ADJUSTMENT_TYPE],
self.properties[self.MIN_ADJUSTMENT_STEP])
with group.frozen_properties():
group.adjust(
self.properties[self.SCALING_ADJUSTMENT],
self.properties[self.ADJUSTMENT_TYPE],
self.properties[self.MIN_ADJUSTMENT_STEP])
size_changed = True
except resource.NoActionRequired:
raise