Convergence: Fix duplicate events for stack actions
When stack actions such as suspend/resume/snapshot/restore are completed, two events are logged in DB. The above stack actions still use stack lock even under convergence. Hence when setting the stack action as complete/failed, state_set should not persist state. Sending notification, events and saving Complete/Failed state in DB is done at the time of releasing lock for these stack actions. Change-Id: Ib3e6c1de2f2f17502049e06ae484cb2e50867fab Closes-Bug: #1516089
This commit is contained in:
parent
2ceaca1cb8
commit
ccf8464531
|
@ -743,8 +743,10 @@ class Stack(collections.Mapping):
|
||||||
self.status = status
|
self.status = status
|
||||||
self.status_reason = reason
|
self.status_reason = reason
|
||||||
|
|
||||||
if cfg.CONF.convergence_engine:
|
if self.convergence and action in (self.UPDATE, self.DELETE,
|
||||||
# for convergence stack lock is not used, hence persist state
|
self.CREATE):
|
||||||
|
# if convergence and stack operation is create/update/delete,
|
||||||
|
# stack lock is not used, hence persist state
|
||||||
self._persist_state()
|
self._persist_state()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -446,7 +446,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
|
||||||
@mock.patch.object(parser.Stack, '_converge_create_or_update')
|
@mock.patch.object(parser.Stack, '_converge_create_or_update')
|
||||||
def test_updated_time_stack_create(self, mock_ccu, mock_cr):
|
def test_updated_time_stack_create(self, mock_ccu, mock_cr):
|
||||||
stack = parser.Stack(utils.dummy_context(), 'convg_updated_time_test',
|
stack = parser.Stack(utils.dummy_context(), 'convg_updated_time_test',
|
||||||
templatem.Template.create_empty_template())
|
templatem.Template.create_empty_template(),
|
||||||
|
convergence=True)
|
||||||
stack.converge_stack(template=stack.t, action=stack.CREATE)
|
stack.converge_stack(template=stack.t, action=stack.CREATE)
|
||||||
self.assertIsNone(stack.updated_time)
|
self.assertIsNone(stack.updated_time)
|
||||||
self.assertTrue(mock_ccu.called)
|
self.assertTrue(mock_ccu.called)
|
||||||
|
@ -456,12 +457,71 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
|
||||||
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
|
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
|
||||||
'Resources': {'R1': {'Type': 'GenericResourceType'}}}
|
'Resources': {'R1': {'Type': 'GenericResourceType'}}}
|
||||||
stack = parser.Stack(utils.dummy_context(), 'updated_time_test',
|
stack = parser.Stack(utils.dummy_context(), 'updated_time_test',
|
||||||
templatem.Template(tmpl))
|
templatem.Template(tmpl), convergence=True)
|
||||||
stack.converge_stack(template=stack.t, action=stack.UPDATE)
|
stack.converge_stack(template=stack.t, action=stack.UPDATE)
|
||||||
self.assertIsNotNone(stack.updated_time)
|
self.assertIsNotNone(stack.updated_time)
|
||||||
self.assertTrue(mock_ccu.called)
|
self.assertTrue(mock_ccu.called)
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch.object(parser.Stack, '_persist_state')
|
||||||
|
class TestConvgStackStateSet(common.HeatTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestConvgStackStateSet, self).setUp()
|
||||||
|
cfg.CONF.set_override('convergence_engine', True)
|
||||||
|
self.stack = tools.get_stack(
|
||||||
|
'test_stack', utils.dummy_context(),
|
||||||
|
template=tools.wp_template, convergence=True)
|
||||||
|
|
||||||
|
def test_state_set_create_update_delete_complete(self, mock_ps):
|
||||||
|
self.stack.state_set(self.stack.CREATE, self.stack.COMPLETE,
|
||||||
|
'Create complete')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.UPDATE, self.stack.COMPLETE,
|
||||||
|
'Update complete')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.DELETE, self.stack.COMPLETE,
|
||||||
|
'Delete complete')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
|
||||||
|
def test_state_set_stack_suspend(self, mock_ps):
|
||||||
|
self.stack.state_set(self.stack.SUSPEND, self.stack.IN_PROGRESS,
|
||||||
|
'Suspend started')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.SUSPEND, self.stack.COMPLETE,
|
||||||
|
'Suspend complete')
|
||||||
|
self.assertFalse(mock_ps.called)
|
||||||
|
|
||||||
|
def test_state_set_stack_resume(self, mock_ps):
|
||||||
|
self.stack.state_set(self.stack.RESUME, self.stack.IN_PROGRESS,
|
||||||
|
'Resume started')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.RESUME, self.stack.COMPLETE,
|
||||||
|
'Resume complete')
|
||||||
|
self.assertFalse(mock_ps.called)
|
||||||
|
|
||||||
|
def test_state_set_stack_snapshot(self, mock_ps):
|
||||||
|
self.stack.state_set(self.stack.SNAPSHOT, self.stack.IN_PROGRESS,
|
||||||
|
'Snapshot started')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.SNAPSHOT, self.stack.COMPLETE,
|
||||||
|
'Snapshot complete')
|
||||||
|
self.assertFalse(mock_ps.called)
|
||||||
|
|
||||||
|
def test_state_set_stack_restore(self, mock_ps):
|
||||||
|
self.stack.state_set(self.stack.RESTORE, self.stack.IN_PROGRESS,
|
||||||
|
'Restore started')
|
||||||
|
self.assertTrue(mock_ps.called)
|
||||||
|
mock_ps.reset_mock()
|
||||||
|
self.stack.state_set(self.stack.RESTORE, self.stack.COMPLETE,
|
||||||
|
'Restore complete')
|
||||||
|
self.assertFalse(mock_ps.called)
|
||||||
|
|
||||||
|
|
||||||
class TestConvgStackRollback(common.HeatTestCase):
|
class TestConvgStackRollback(common.HeatTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Reference in New Issue