Add state check when suspend or resume stack

If suspend a stack which is already suspended,
some resource will throw exceptions.and you can't
suspend or resume that failed resource.

Add stack check when update or resume,if the
state of stack is expecter,return directly.

Change-Id: Ie6859c03168d9d18e88bbeb6df2c646541f2aa9d
Closes-Bug: 1284531
This commit is contained in:
Zhang Yang 2014-02-25 02:49:23 -08:00
parent 362e0332ca
commit 696ae2b251
2 changed files with 60 additions and 0 deletions

View File

@ -674,6 +674,11 @@ class Stack(collections.Mapping):
other than move to SUSPEND_COMPLETE, so the resources must implement
handle_suspend for this to have any effect.
'''
# No need to suspend if the stack has been suspended
if self.state == (self.SUSPEND, self.COMPLETE):
logger.info(_('%s is already suspended') % str(self))
return
sus_task = scheduler.TaskRunner(self.stack_task,
action=self.SUSPEND,
reverse=True)
@ -688,6 +693,11 @@ class Stack(collections.Mapping):
other than move to RESUME_COMPLETE, so the resources must implement
handle_resume for this to have any effect.
'''
# No need to resume if the stack has been resumed
if self.state == (self.RESUME, self.COMPLETE):
logger.info(_('%s is already resumed') % str(self))
return
sus_task = scheduler.TaskRunner(self.stack_task,
action=self.RESUME,
reverse=False)

View File

@ -1142,6 +1142,56 @@ class StackTest(HeatTestCase):
self.m.VerifyAll()
@utils.stack_delete_after
def test_suspend_stack_suspended_ok(self):
tmpl = {'Resources': {'AResource': {'Type': 'GenericResourceType'}}}
self.stack = parser.Stack(self.ctx, 'suspend_test',
parser.Template(tmpl))
self.stack.store()
self.stack.create()
self.assertEqual((self.stack.CREATE, self.stack.COMPLETE),
self.stack.state)
self.stack.suspend()
self.assertEqual((self.stack.SUSPEND, self.stack.COMPLETE),
self.stack.state)
# unexpected to call Resource.suspend
self.m.StubOutWithMock(generic_rsrc.GenericResource, 'suspend')
self.m.ReplayAll()
self.stack.suspend()
self.assertEqual((self.stack.SUSPEND, self.stack.COMPLETE),
self.stack.state)
self.m.VerifyAll()
@utils.stack_delete_after
def test_resume_stack_resumeed_ok(self):
tmpl = {'Resources': {'AResource': {'Type': 'GenericResourceType'}}}
self.stack = parser.Stack(self.ctx, 'suspend_test',
parser.Template(tmpl))
self.stack.store()
self.stack.create()
self.assertEqual((self.stack.CREATE, self.stack.COMPLETE),
self.stack.state)
self.stack.suspend()
self.assertEqual((self.stack.SUSPEND, self.stack.COMPLETE),
self.stack.state)
self.stack.resume()
self.assertEqual((self.stack.RESUME, self.stack.COMPLETE),
self.stack.state)
# unexpected to call Resource.resume
self.m.StubOutWithMock(generic_rsrc.GenericResource, 'resume')
self.m.ReplayAll()
self.stack.resume()
self.assertEqual((self.stack.RESUME, self.stack.COMPLETE),
self.stack.state)
self.m.VerifyAll()
@utils.stack_delete_after
def test_suspend_fail(self):
tmpl = {'Resources': {'AResource': {'Type': 'GenericResourceType'}}}