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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user