]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat engine : store stack on failed update
authorSteven Hardy <shardy@redhat.com>
Fri, 8 Mar 2013 17:23:17 +0000 (17:23 +0000)
committerSteven Hardy <shardy@redhat.com>
Fri, 8 Mar 2013 17:48:19 +0000 (17:48 +0000)
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

heat/engine/parser.py
heat/tests/test_parser.py

index f4ff716ede3b2502c4230ce9d16ab2f8950cbecd..16dbec51bdaaa8c9fac7f23fb3d59e00b2935da8 100644 (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.
index 7b0186bf119b54376667c5f20f3dd288a83129dd..1f2b90919b16f50460f71cfda96cb11973bbbfdd 100644 (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