From a9e7278d00d95a5376a895069624517429c7671b Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Wed, 4 Sep 2013 10:44:39 +0200 Subject: [PATCH] Update nested stacks in parallel This parallelises updates for AWS::CloudFormation::Stack resources, but not for autoscaling groups. Other types of nested stacks (the old LoadBalancer and DBInstance resources, and provider templates) have not yet implemented stack updates. Change-Id: I86e1d5289487b34712c248bc5e68e62cc4651ec6 --- heat/engine/resources/autoscaling.py | 4 +++- heat/engine/resources/stack.py | 6 +++--- heat/engine/stack_resource.py | 13 ++++++++++++- heat/tests/test_nested_stack.py | 4 +++- heat/tests/test_stack_resource.py | 24 ++++++++++++++++-------- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/heat/engine/resources/autoscaling.py b/heat/engine/resources/autoscaling.py index 7bdfbd04..12f79127 100644 --- a/heat/engine/resources/autoscaling.py +++ b/heat/engine/resources/autoscaling.py @@ -214,7 +214,9 @@ class InstanceGroup(stack_resource.StackResource): """ new_template = self._create_template(new_capacity) try: - self.update_with_template(new_template, {}) + updater = self.update_with_template(new_template, {}) + updater.run_to_completion() + self.check_update_complete(updater) finally: # Reload the LB in any case, so it's only pointing at healthy # nodes. diff --git a/heat/engine/resources/stack.py b/heat/engine/resources/stack.py index dc031ab6..3879935b 100644 --- a/heat/engine/resources/stack.py +++ b/heat/engine/resources/stack.py @@ -73,9 +73,9 @@ class NestedStack(stack_resource.StackResource): template_data = urlfetch.get(self.properties[PROP_TEMPLATE_URL]) template = template_format.parse(template_data) - self.update_with_template(template, - self.properties[PROP_PARAMETERS], - self.properties[PROP_TIMEOUT_MINS]) + return self.update_with_template(template, + self.properties[PROP_PARAMETERS], + self.properties[PROP_TIMEOUT_MINS]) def resource_mapping(): diff --git a/heat/engine/stack_resource.py b/heat/engine/stack_resource.py index 6743ff2b..b95088c0 100644 --- a/heat/engine/stack_resource.py +++ b/heat/engine/stack_resource.py @@ -136,12 +136,23 @@ class StackResource(resource.Resource): self.attributes = None self._outputs_to_attribs(child_template) - nested_stack.update(stack) + updater = scheduler.TaskRunner(nested_stack.update_task, stack) + updater.start() + return updater + def check_update_complete(self, updater): + if updater is None: + return True + + if not updater.step(): + return False + + nested_stack = self.nested() if nested_stack.state != (nested_stack.UPDATE, nested_stack.COMPLETE): raise exception.Error("Nested stack update failed: %s" % nested_stack.status_reason) + return True def delete_nested(self): ''' diff --git a/heat/tests/test_nested_stack.py b/heat/tests/test_nested_stack.py index 574d406f..cd8b13bb 100644 --- a/heat/tests/test_nested_stack.py +++ b/heat/tests/test_nested_stack.py @@ -122,7 +122,9 @@ Outputs: new_res['Properties']['TemplateURL'] = ( 'https://server.test/new.template') prop_diff = {'TemplateURL': 'https://server.test/new.template'} - rsrc.handle_update(new_res, {}, prop_diff) + updater = rsrc.handle_update(new_res, {}, prop_diff) + updater.run_to_completion() + self.assertEqual(True, rsrc.check_update_complete(updater)) # Expect the physical resource name staying the same after update, # so that the nested was actually updated instead of replaced. diff --git a/heat/tests/test_stack_resource.py b/heat/tests/test_stack_resource.py index 5e3bf2c9..bf3dff3b 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -159,8 +159,11 @@ class StackResourceTest(HeatTestCase): new_templ = self.simple_template.copy() inst_snippet = new_templ["Resources"]["WebServer"].copy() new_templ["Resources"]["WebServer2"] = inst_snippet - update_result = self.parent_resource.update_with_template( + updater = self.parent_resource.update_with_template( new_templ, {}) + updater.run_to_completion() + self.assertEqual(True, + self.parent_resource.check_update_complete(updater)) self.assertEqual(self.stack.state, ('UPDATE', 'COMPLETE')) self.assertEqual(set(self.stack.resources.keys()), set(["WebServer", "WebServer2"])) @@ -185,17 +188,22 @@ class StackResourceTest(HeatTestCase): inst_snippet = new_templ["Resources"]["WebServer"].copy() new_templ["Resources"]["WebServer2"] = inst_snippet - def change_state(stack): + def update_task(): + yield self.stack.state_set(parser.Stack.UPDATE, parser.Stack.FAILED, '') - self.m.StubOutWithMock(self.stack, 'update') - self.stack.update(mox.IgnoreArg()).WithSideEffects(change_state) + self.m.StubOutWithMock(self.stack, 'update_task') + self.stack.update_task(mox.IgnoreArg()).AndReturn(update_task()) self.m.ReplayAll() - try: - self.parent_resource.update_with_template(new_templ, {}) - except exception.Error as ex: - self.assertEqual('Nested stack update failed: ', ex.message) + updater = self.parent_resource.update_with_template(new_templ, {}) + updater.run_to_completion() + self.assertEqual((self.stack.UPDATE, self.stack.FAILED), + self.stack.state) + ex = self.assertRaises(exception.Error, + self.parent_resource.check_update_complete, + updater) + self.assertEqual('Nested stack update failed: ', str(ex)) self.m.VerifyAll() -- 2.45.2