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:
parent
bc4255fe07
commit
3786262aed
@ -119,6 +119,19 @@ class StackUpdate(object):
|
|||||||
existing_res.state_set(existing_res.UPDATE, existing_res.COMPLETE)
|
existing_res.state_set(existing_res.UPDATE, existing_res.COMPLETE)
|
||||||
|
|
||||||
self.existing_stack.add_resource(new_res)
|
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()
|
yield new_res.create()
|
||||||
|
|
||||||
@scheduler.wrappertask
|
@scheduler.wrappertask
|
||||||
@ -135,14 +148,13 @@ class StackUpdate(object):
|
|||||||
except resource.UpdateReplace:
|
except resource.UpdateReplace:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# Save resource definition to backup stack if it is not
|
# Save updated resource definition to backup stack
|
||||||
# present in backup stack template already
|
# cause it allows the backup stack resources to be synchronized
|
||||||
if res_name not in self.previous_stack.t[
|
LOG.debug("Backing up updated Resource %s" % res_name)
|
||||||
self.previous_stack.t.RESOURCES]:
|
definition = existing_res.t.reparse(self.previous_stack,
|
||||||
definition = existing_res.t.reparse(self.previous_stack,
|
existing_res.stack.t)
|
||||||
existing_res.stack.t)
|
self.previous_stack.t.add_resource(definition)
|
||||||
self.previous_stack.t.add_resource(definition)
|
self.previous_stack.t.store(self.previous_stack.context)
|
||||||
self.previous_stack.t.store(self.previous_stack.context)
|
|
||||||
|
|
||||||
LOG.info(_LI("Resource %(res_name)s for stack %(stack_name)s "
|
LOG.info(_LI("Resource %(res_name)s for stack %(stack_name)s "
|
||||||
"updated"),
|
"updated"),
|
||||||
|
@ -1603,3 +1603,73 @@ class StackUpdateTest(common.HeatTestCase):
|
|||||||
self.stack.delete()
|
self.stack.delete()
|
||||||
self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE),
|
self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE),
|
||||||
self.stack.state)
|
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'])
|
||||||
|
Loading…
Reference in New Issue
Block a user