Keep old files in file map for rolling update

We would need old resource definitions when doing rolling update of certain
group resources like RG/ASG. Therefore update the file map with the files
from old template.

Change-Id: I8f880e5b23c25159ecab1c63b594329d8df33973
Closes-Bug: #1765454
Task: #17360
Story: #1765454
This commit is contained in:
rabi 2018-05-09 10:26:03 +05:30
parent 7c55b25375
commit d42f863dc5
7 changed files with 79 additions and 3 deletions

View File

@ -197,3 +197,21 @@ def get_member_definitions(group, include_failed=False):
return [(name, definitions[name]) return [(name, definitions[name])
for name in inspector.member_names(include_failed=include_failed) for name in inspector.member_names(include_failed=include_failed)
if name in definitions] if name in definitions]
def get_child_template_files(context, stack,
is_rolling_update,
old_template_id):
"""Return a merged map of old and new template files.
For rolling update files for old and new defintions are required as the
nested stack is updated in batches of scaled units.
"""
if not stack.convergence:
old_template_id = stack.t.id
if is_rolling_update and old_template_id:
prev_files = template.Template.load(context, old_template_id).files
prev_files.update(dict(stack.t.files))
return prev_files
return stack.t.files

View File

@ -247,6 +247,7 @@ class Resource(status.ResourceStatus):
self.replaces = None self.replaces = None
self.replaced_by = None self.replaced_by = None
self.current_template_id = None self.current_template_id = None
self.old_template_id = None
self.root_stack_id = None self.root_stack_id = None
self._calling_engine_id = None self._calling_engine_id = None
self._atomic_key = None self._atomic_key = None
@ -1659,7 +1660,7 @@ class Resource(status.ResourceStatus):
after_props.validate() after_props.validate()
self.properties = before_props self.properties = before_props
tmpl_diff = self.update_template_diff(after.freeze(), before) tmpl_diff = self.update_template_diff(after.freeze(), before)
old_template_id = self.current_template_id self.old_template_id = self.current_template_id
try: try:
if tmpl_diff and self.needs_replace_with_tmpl_diff(tmpl_diff): if tmpl_diff and self.needs_replace_with_tmpl_diff(tmpl_diff):
@ -1676,7 +1677,8 @@ class Resource(status.ResourceStatus):
prop_diff]) prop_diff])
except UpdateReplace: except UpdateReplace:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
self.current_template_id = old_template_id self.current_template_id = self.old_template_id
self.old_template_id = None
self._prepare_update_replace(action) self._prepare_update_replace(action)
self.t = after self.t = after

View File

@ -186,6 +186,12 @@ class AutoScalingResourceGroup(aws_asg.AutoScalingGroup):
resource_def)) resource_def))
return rsrc_defn.ResourceDefinition(None, **defn_data) return rsrc_defn.ResourceDefinition(None, **defn_data)
def child_template_files(self, child_env):
is_update = self.action == self.UPDATE
return grouputils.get_child_template_files(self.context, self.stack,
is_update,
self.old_template_id)
def _try_rolling_update(self, prop_diff): def _try_rolling_update(self, prop_diff):
if self.RESOURCE in prop_diff: if self.RESOURCE in prop_diff:
policy = self.properties[self.ROLLING_UPDATES] policy = self.properties[self.ROLLING_UPDATES]

View File

@ -478,6 +478,13 @@ class InstanceGroup(stack_resource.StackResource):
num_instances = int(self.properties[self.SIZE]) num_instances = int(self.properties[self.SIZE])
return self._create_template(num_instances) return self._create_template(num_instances)
def child_template_files(self, child_env):
is_rolling_update = (self.action == self.UPDATE and
self.update_policy[self.ROLLING_UPDATE])
return grouputils.get_child_template_files(self.context, self.stack,
is_rolling_update,
self.old_template_id)
def child_params(self): def child_params(self):
"""Return the environment for the nested stack.""" """Return the environment for the nested stack."""
return { return {

View File

@ -668,6 +668,14 @@ class ResourceGroup(stack_resource.StackResource):
self._add_output_defns_to_template(tmpl, [k for k, d in definitions]) self._add_output_defns_to_template(tmpl, [k for k, d in definitions])
return tmpl return tmpl
def child_template_files(self, child_env):
is_rolling_update = (self.action == self.UPDATE
and self.update_policy[self.ROLLING_UPDATE])
return grouputils.get_child_template_files(self.context,
self.stack,
is_rolling_update,
self.old_template_id)
def _assemble_for_rolling_update(self, total_capacity, max_updates, def _assemble_for_rolling_update(self, total_capacity, max_updates,
include_all=False, include_all=False,
template_version=('heat_template_version', template_version=('heat_template_version',

View File

@ -222,7 +222,12 @@ class StackResource(resource.Resource):
if isinstance(parsed_child_template, template.Template): if isinstance(parsed_child_template, template.Template):
parsed_child_template = parsed_child_template.t parsed_child_template = parsed_child_template.t
return template.Template(parsed_child_template, return template.Template(parsed_child_template,
files=self.stack.t.files, env=child_env) files=self.child_template_files(child_env),
env=child_env)
def child_template_files(self, child_env):
"""Default implementation to get the files map for child template."""
return self.stack.t.files
def _parse_nested_stack(self, stack_name, child_template, def _parse_nested_stack(self, stack_name, child_template,
child_params, timeout_mins=None, child_params, timeout_mins=None,

View File

@ -612,6 +612,36 @@ resources:
created=10, created=10,
deleted=10) deleted=10)
def test_resource_group_update_replace_template_changed(self):
"""Test rolling update(replace)with child template path changed.
Simple rolling update replace with child template path changed.
"""
nested_templ = '''
heat_template_version: "2013-05-23"
resources:
oops:
type: OS::Heat::TestResource
'''
create_template = yaml.safe_load(copy.deepcopy(self.template))
grp = create_template['resources']['random_group']
grp['properties']['resource_def'] = {'type': '/opt/provider.yaml'}
files = {'/opt/provider.yaml': nested_templ}
policy = grp['update_policy']['rolling_update']
policy['min_in_service'] = '1'
policy['max_batch_size'] = '3'
stack_identifier = self.stack_create(template=create_template,
files=files)
update_template = create_template.copy()
grp = update_template['resources']['random_group']
grp['properties']['resource_def'] = {'type': '/opt1/provider.yaml'}
files = {'/opt1/provider.yaml': nested_templ}
self.update_stack(stack_identifier, update_template, files=files)
def test_resource_group_update_scaledown(self): def test_resource_group_update_scaledown(self):
"""Test rolling update with scaledown. """Test rolling update with scaledown.