heat engine : store stack on failed update

Store the stack even when the update fails, otherwise we
lose track of the resources which failed on create so they
are not removed on stack delete

fixes bug 1151989

Change-Id: Ic8aa5ef92e188fb704ed25563aa9b86aa69232b4
This commit is contained in:
Steven Hardy
2013-03-08 17:23:17 +00:00
parent da6d6787a7
commit b8aad78cc5
2 changed files with 41 additions and 7 deletions

View File

@@ -426,13 +426,6 @@ class Stack(object):
raise exception.ResourceUpdateFailed(
resource_name=res.name)
# flip the template & parameters to the newstack values
self.t = newstack.t
self.parameters = newstack.parameters
template_outputs = self.t[template.OUTPUTS]
self.outputs = self.resolve_static_data(template_outputs)
self.store()
if action == self.UPDATE:
stack_status = self.UPDATE_COMPLETE
reason = 'Stack successfully updated'
@@ -469,6 +462,16 @@ class Stack(object):
self.state_set(stack_status, reason)
# flip the template & parameters to the newstack values
# Note we do this on success and failure, so the current
# stack resources are stored, even if one is in a failed
# state (otherwise we won't remove them on delete)
self.t = newstack.t
self.parameters = newstack.parameters
template_outputs = self.t[template.OUTPUTS]
self.outputs = self.resolve_static_data(template_outputs)
self.store()
def delete(self, action=DELETE):
'''
Delete all of the resources, and then the stack itself.

View File

@@ -674,6 +674,37 @@ class StackTest(unittest.TestCase):
self.assertEqual(self.stack.state, parser.Stack.UPDATE_FAILED)
self.m.VerifyAll()
@stack_delete_after
def test_update_add_failed_create(self):
tmpl = {'Resources': {'AResource': {'Type': 'GenericResourceType'}}}
self.stack = parser.Stack(self.ctx, 'update_test_stack',
template.Template(tmpl))
self.stack.store()
self.stack.create()
self.assertEqual(self.stack.state, parser.Stack.CREATE_COMPLETE)
tmpl2 = {'Resources': {
'AResource': {'Type': 'GenericResourceType'},
'BResource': {'Type': 'GenericResourceType'}}}
updated_stack = parser.Stack(self.ctx, 'updated_stack',
template.Template(tmpl2))
# patch in a dummy handle_create making BResource fail creating
self.m.StubOutWithMock(generic_rsrc.GenericResource, 'handle_create')
generic_rsrc.GenericResource.handle_create().AndRaise(Exception)
self.m.ReplayAll()
self.stack.update(updated_stack)
self.assertEqual(self.stack.state, parser.Stack.UPDATE_FAILED)
self.assertTrue('BResource' in self.stack)
# Reload the stack from the DB and prove that it contains the failed
# resource (to ensure it will be deleted on stack delete)
re_stack = parser.Stack.load(self.ctx, stack_id=self.stack.id)
self.assertTrue('BResource' in re_stack)
self.m.VerifyAll()
@stack_delete_after
def test_update_rollback(self):
# patch in a dummy property schema for GenericResource