Backup new resource as soon as possible

The root cause came discussion in
https://review.openstack.org/#/c/175868/.
It is better to copy a new resources that appears during
stack-update to backup stack as soon as possible because
it reduces time when backup stack is not synchronized with
the existing stack.

Change-Id: If104037225905dc9c504972864270d6e68e08d73
This commit is contained in:
kairat_kushaev 2015-05-27 11:56:31 +03:00
parent bc4255fe07
commit 3786262aed
2 changed files with 90 additions and 8 deletions

View File

@ -119,6 +119,19 @@ class StackUpdate(object):
existing_res.state_set(existing_res.UPDATE, existing_res.COMPLETE)
self.existing_stack.add_resource(new_res)
# Save new resource definition to backup stack if it is not
# present in backup stack template already
# it allows to resolve all dependencies that existing resource
# can have if it was copied to backup stack
if (res_name not in
self.previous_stack.t[self.previous_stack.t.RESOURCES]):
LOG.debug("Backing up new Resource %s" % res_name)
definition = new_res.t.reparse(self.previous_stack,
new_res.stack.t)
self.previous_stack.t.add_resource(definition)
self.previous_stack.t.store(self.previous_stack.context)
yield new_res.create()
@scheduler.wrappertask
@ -135,14 +148,13 @@ class StackUpdate(object):
except resource.UpdateReplace:
pass
else:
# Save resource definition to backup stack if it is not
# present in backup stack template already
if res_name not in self.previous_stack.t[
self.previous_stack.t.RESOURCES]:
definition = existing_res.t.reparse(self.previous_stack,
existing_res.stack.t)
self.previous_stack.t.add_resource(definition)
self.previous_stack.t.store(self.previous_stack.context)
# Save updated resource definition to backup stack
# cause it allows the backup stack resources to be synchronized
LOG.debug("Backing up updated Resource %s" % res_name)
definition = existing_res.t.reparse(self.previous_stack,
existing_res.stack.t)
self.previous_stack.t.add_resource(definition)
self.previous_stack.t.store(self.previous_stack.context)
LOG.info(_LI("Resource %(res_name)s for stack %(stack_name)s "
"updated"),

View File

@ -1603,3 +1603,73 @@ class StackUpdateTest(common.HeatTestCase):
self.stack.delete()
self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE),
self.stack.state)
def test_backup_stack_synchronized_after_update(self):
"""Test when backup stack updated correctly during stack update.
Test checks the following scenario:
1. Create stack
2. Update stack (failed - so the backup should not be deleted)
3. Update stack (failed - so the backup from step 2 should be updated)
The test checks that backup stack is synchronized with the main stack.
"""
# create a stack
tmpl_create = {
'heat_template_version': '2013-05-23',
'resources': {
'Ares': {'type': 'GenericResourceType'}
}
}
self.stack = stack.Stack(self.ctx, 'test_update_stack_backup',
template.Template(tmpl_create),
disable_rollback=True)
self.stack.store()
self.stack.create()
self.assertEqual((stack.Stack.CREATE, stack.Stack.COMPLETE),
self.stack.state)
# try to update a stack with a new resource that should be backed up
tmpl_update = {
'heat_template_version': '2013-05-23',
'resources': {
'Ares': {'type': 'GenericResourceType'},
'Bres': {
'type': 'ResWithComplexPropsAndAttrs',
'properties': {
'an_int': 0,
}
},
'Cres': {
'type': 'ResourceWithPropsType',
'properties': {
'Foo': {'get_resource': 'Bres'},
}
}
}
}
self.patchobject(generic_rsrc.ResourceWithProps,
'handle_create',
side_effect=[Exception, Exception])
stack_with_new_resource = stack.Stack(
self.ctx,
'test_update_stack_backup',
template.Template(tmpl_update))
self.stack.update(stack_with_new_resource)
self.assertEqual((stack.Stack.UPDATE, stack.Stack.FAILED),
self.stack.state)
# assert that backup stack has been updated correctly
self.assertIn('Bres', self.stack._backup_stack())
# update the stack with resource that updated in-place
tmpl_update['resources']['Bres']['properties']['an_int'] = 1
updated_stack_second = stack.Stack(self.ctx,
'test_update_stack_backup',
template.Template(tmpl_update))
self.stack.update(updated_stack_second)
self.assertEqual((stack.Stack.UPDATE, stack.Stack.FAILED),
self.stack.state)
# assert that resource in backup stack also has been updated
backup = self.stack._backup_stack()
self.assertEqual(1, backup['Bres'].properties['an_int'])