From: Liang Chen Date: Thu, 22 Aug 2013 05:41:52 +0000 (+0800) Subject: Enhance StackResource update for more use cases X-Git-Tag: 2014.1~135^2 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=112283f1352010d44cbebc1b7ac76f997abc3a21;p=openstack-build%2Fheat-build.git Enhance StackResource update for more use cases Enhance StackResource.update_with_template to accommodate more possible use cases. This will take care of the nested stack update failure by raising an exception in such case, so the the concrete nested stack resource implementations will have a chance to take some actions upon nested stack update failure. blueprint nested-stack-updates Change-Id: Id31ef67e1d7c4928704c6e169bce13f0f7232932 --- diff --git a/heat/engine/resources/autoscaling.py b/heat/engine/resources/autoscaling.py index 79ad56ae..2eaf4090 100644 --- a/heat/engine/resources/autoscaling.py +++ b/heat/engine/resources/autoscaling.py @@ -174,12 +174,15 @@ class InstanceGroup(stack_resource.StackResource): When shrinking, the newest instances will be removed. """ new_template = self._create_template(new_capacity) - result = self.update_with_template(new_template, {}) - for resource in self.nested(): - if resource.state == ('CREATE', 'FAILED'): - resource.destroy() + try: + self.update_with_template(new_template, {}) + except exception.Error as ex: + logger.error('Failed to resize instance group %s. Error: %s' % + (self.name, ex)) + for resource in self.nested(): + if resource.state == ('CREATE', 'FAILED'): + resource.destroy() self._lb_reload() - return result def _lb_reload(self): ''' diff --git a/heat/engine/stack_resource.py b/heat/engine/stack_resource.py index 6ff3339b..b4ff15ad 100644 --- a/heat/engine/stack_resource.py +++ b/heat/engine/stack_resource.py @@ -113,9 +113,25 @@ class StackResource(resource.Resource): environment.Environment(user_params), timeout_mins=timeout_mins, disable_rollback=True, - parent_resource=self) + parent_resource=self, + owner_id=self.stack.id) stack.validate() - return self._nested.update(stack) + + nested_stack = self.nested() + if nested_stack is None: + raise exception.Error(_('Cannot update %s, stack not created') + % self.name) + + if not hasattr(type(self), 'attributes_schema'): + self.attributes = None + self._outputs_to_attribs(child_template) + + nested_stack.update(stack) + + if nested_stack.state != (nested_stack.UPDATE, + nested_stack.COMPLETE): + raise exception.Error("Nested stack update failed: %s" % + nested_stack.status_reason) def delete_nested(self): ''' diff --git a/heat/tests/test_stack_resource.py b/heat/tests/test_stack_resource.py index 83465263..5e3bf2c9 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -12,6 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. + +import mox + from heat.common import template_format from heat.common import exception from heat.engine import environment @@ -167,6 +170,35 @@ class StackResourceTest(HeatTestCase): self.parent_stack.context, self.stack.id) self.assertEqual(saved_stack.owner_id, self.parent_stack.id) + @utils.stack_delete_after + def test_update_with_template_state_err(self): + """ + update_with_template_state_err method should raise error when update + task is done but the nested stack is in (UPDATE, FAILED) state. + """ + create_creator = self.parent_resource.create_with_template( + self.simple_template, {}) + create_creator.run_to_completion() + self.stack = self.parent_resource.nested() + + new_templ = self.simple_template.copy() + inst_snippet = new_templ["Resources"]["WebServer"].copy() + new_templ["Resources"]["WebServer2"] = inst_snippet + + def change_state(stack): + 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.ReplayAll() + + try: + self.parent_resource.update_with_template(new_templ, {}) + except exception.Error as ex: + self.assertEqual('Nested stack update failed: ', ex.message) + + self.m.VerifyAll() + @utils.stack_delete_after def test_load_nested_ok(self): self.parent_resource.create_with_template(self.templ,