Cancel nested stack updates when appropriate

If a stack update is cancelled while the update of a nested stack is being
processed, the nested stack update is no longer stopped since the
implementation changed in Kilo to use the RPC API to control nested stacks.

To alleviate this, use the RPC API to cancel the (nested) stack update when
the resource update is cancelled. This results in a rollback of the nested
stack, so if a subsequent attempt to roll back the ensted stack by doing a
stack update fails due to the rollback already being in progress, just
ignore the error and wait for the existing operation to complete.

Change-Id: I3eacf216194517c995732a3f4de876551b70fe91
Closes-Bug: #1446252
This commit is contained in:
Zane Bitter 2015-04-20 19:12:07 -04:00
parent ecccf66f7e
commit ad4c00e672
1 changed files with 22 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import json
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import excutils
import six
from heat.common import exception
@ -84,6 +85,20 @@ class StackResource(resource.Resource):
# resources in it decide if they need updating.
return True
@scheduler.wrappertask
def update(self, after, before=None, prev_resource=None):
try:
yield super(StackResource, self).update(after, before,
prev_resource)
except StopIteration:
with excutils.save_and_reraise_exception():
stack_identity = identifier.HeatIdentifier(
self.context.tenant_id,
self.physical_resource_name(),
self.resource_id)
self.rpc_client().stack_cancel_update(self.context,
stack_identity)
def nested(self, force_reload=False, show_deleted=False):
'''Return a Stack object representing the nested (child) stack.
@ -278,6 +293,13 @@ class StackResource(resource.Resource):
else:
message = full_message
if (isinstance(ex, exception.ActionInProgress) and
self.stack.action == self.stack.ROLLBACK):
# The update was interrupted and the rollback is already in
# progress, so just ignore the error and wait for the rollback to
# finish
return
if isinstance(ex, exception.HeatException):
message = ex.message
local_ex = copy.copy(getattr(exception, ex_type))