Correct reset_state_on_error() handling

The change Ic948c2fe5baf23c9c4ced33060f672ca9c278a19 aim
to prevent the stacks hanging in IN_PROGRESS, but the code
is incorrect, this patch fix them.

Change-Id: I0e9655b5a931452d810c38b7ddf6a2ce742bb7ed
Closes-Bug: #1521881
Related-Bug: #1492433
This commit is contained in:
huangtianhua 2015-12-02 16:02:41 +08:00
parent c8eccf374b
commit 63141b20bc
2 changed files with 14 additions and 13 deletions

View File

@ -84,9 +84,11 @@ def reset_state_on_error(func):
LOG.error(_LE('Unexpected exception in %(func)s: %(msg)s'),
{'func': func.__name__, 'msg': errmsg})
finally:
if stack.state == stack.IN_PROGRESS:
stack.set_state(stack.action, stack.FAILED, errmsg)
assert errmsg is not None, "Returned while IN_PROGRESS"
if stack.status == stack.IN_PROGRESS:
msg = _("Unexpected returning while IN_PROGRESS.")
stack.state_set(stack.action, stack.FAILED,
errmsg if errmsg is not None else msg)
assert errmsg is not None, "Returned while IN_PROGRESS."
return handle_exceptions
@ -1663,7 +1665,6 @@ class Stack(collections.Mapping):
sus_task(timeout=self.timeout_secs())
@profiler.trace('Stack.delete_snapshot', hide_args=False)
@reset_state_on_error
def delete_snapshot(self, snapshot):
"""Remove a snapshot from the backends."""
for name, rsrc in six.iteritems(self.resources):

View File

@ -2542,19 +2542,19 @@ class ResetStateOnErrorTest(common.HeatTestCase):
(COMPLETE, IN_PROGRESS, FAILED) = range(3)
action = 'something'
state = COMPLETE
status = COMPLETE
def __init__(self):
self.set_state = mock.MagicMock()
self.state_set = mock.MagicMock()
@stack.reset_state_on_error
def raise_exception(self):
self.state = self.IN_PROGRESS
self.status = self.IN_PROGRESS
raise ValueError('oops')
@stack.reset_state_on_error
def raise_exit_exception(self):
self.state = self.IN_PROGRESS
self.status = self.IN_PROGRESS
raise BaseException('bye')
@stack.reset_state_on_error
@ -2563,31 +2563,31 @@ class ResetStateOnErrorTest(common.HeatTestCase):
@stack.reset_state_on_error
def fail(self):
self.state = self.FAILED
self.status = self.FAILED
return 'Hello world'
def test_success(self):
dummy = self.DummyStack()
self.assertEqual('Hello world', dummy.succeed())
self.assertFalse(dummy.set_state.called)
self.assertFalse(dummy.state_set.called)
def test_failure(self):
dummy = self.DummyStack()
self.assertEqual('Hello world', dummy.fail())
self.assertFalse(dummy.set_state.called)
self.assertFalse(dummy.state_set.called)
def test_reset_state_exception(self):
dummy = self.DummyStack()
exc = self.assertRaises(ValueError, dummy.raise_exception)
self.assertIn('oops', str(exc))
self.assertTrue(dummy.set_state.called)
self.assertTrue(dummy.state_set.called)
def test_reset_state_exit_exception(self):
dummy = self.DummyStack()
exc = self.assertRaises(BaseException, dummy.raise_exit_exception)
self.assertIn('bye', str(exc))
self.assertTrue(dummy.set_state.called)
self.assertTrue(dummy.state_set.called)