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
This commit is contained in:
Liang Chen 2013-08-22 13:41:52 +08:00
parent a4a823ac22
commit 112283f135
3 changed files with 58 additions and 7 deletions

View File

@ -174,12 +174,15 @@ class InstanceGroup(stack_resource.StackResource):
When shrinking, the newest instances will be removed. When shrinking, the newest instances will be removed.
""" """
new_template = self._create_template(new_capacity) new_template = self._create_template(new_capacity)
result = self.update_with_template(new_template, {}) 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(): for resource in self.nested():
if resource.state == ('CREATE', 'FAILED'): if resource.state == ('CREATE', 'FAILED'):
resource.destroy() resource.destroy()
self._lb_reload() self._lb_reload()
return result
def _lb_reload(self): def _lb_reload(self):
''' '''

View File

@ -113,9 +113,25 @@ class StackResource(resource.Resource):
environment.Environment(user_params), environment.Environment(user_params),
timeout_mins=timeout_mins, timeout_mins=timeout_mins,
disable_rollback=True, disable_rollback=True,
parent_resource=self) parent_resource=self,
owner_id=self.stack.id)
stack.validate() 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): def delete_nested(self):
''' '''

View File

@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mox
from heat.common import template_format from heat.common import template_format
from heat.common import exception from heat.common import exception
from heat.engine import environment from heat.engine import environment
@ -167,6 +170,35 @@ class StackResourceTest(HeatTestCase):
self.parent_stack.context, self.stack.id) self.parent_stack.context, self.stack.id)
self.assertEqual(saved_stack.owner_id, self.parent_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 @utils.stack_delete_after
def test_load_nested_ok(self): def test_load_nested_ok(self):
self.parent_resource.create_with_template(self.templ, self.parent_resource.create_with_template(self.templ,