Merge "Handle exceptions in initial convergence traversal setup"
This commit is contained in:
commit
99cbff3803
|
@ -92,27 +92,9 @@ class CheckResource(object):
|
|||
LOG.debug('Resource id=%d modified by another traversal', rsrc.id)
|
||||
return False
|
||||
|
||||
def _trigger_rollback(self, stack):
|
||||
LOG.info("Triggering rollback of %(stack_name)s %(action)s ",
|
||||
{'action': stack.action, 'stack_name': stack.name})
|
||||
stack.rollback()
|
||||
|
||||
def _handle_failure(self, cnxt, stack, failure_reason):
|
||||
updated = stack.state_set(stack.action, stack.FAILED, failure_reason)
|
||||
if not updated:
|
||||
return False
|
||||
|
||||
if (not stack.disable_rollback and
|
||||
stack.action in (stack.CREATE, stack.ADOPT, stack.UPDATE,
|
||||
stack.RESTORE)):
|
||||
self._trigger_rollback(stack)
|
||||
else:
|
||||
stack.purge_db()
|
||||
return True
|
||||
|
||||
def _handle_resource_failure(self, cnxt, is_update, rsrc_id,
|
||||
stack, failure_reason):
|
||||
failure_handled = self._handle_failure(cnxt, stack, failure_reason)
|
||||
failure_handled = stack.mark_failed(failure_reason)
|
||||
if not failure_handled:
|
||||
# Another concurrent update has taken over. But there is a
|
||||
# possibility for that update to be waiting for this rsrc to
|
||||
|
@ -131,7 +113,7 @@ class CheckResource(object):
|
|||
|
||||
def _handle_stack_timeout(self, cnxt, stack):
|
||||
failure_reason = u'Timed out'
|
||||
self._handle_failure(cnxt, stack, failure_reason)
|
||||
stack.mark_failed(failure_reason)
|
||||
|
||||
def _handle_resource_replacement(self, cnxt,
|
||||
current_traversal, new_tmpl_id, requires,
|
||||
|
|
|
@ -90,10 +90,10 @@ def reset_state_on_error(func):
|
|||
LOG.info('Stopped due to %(msg)s in %(func)s',
|
||||
{'func': func.__name__, 'msg': errmsg})
|
||||
finally:
|
||||
if stack.status == stack.IN_PROGRESS:
|
||||
if ((not stack.convergence or errmsg is not None) and
|
||||
stack.status == stack.IN_PROGRESS):
|
||||
rtnmsg = _("Unexpected exit while IN_PROGRESS.")
|
||||
stack.state_set(stack.action, stack.FAILED,
|
||||
errmsg if errmsg is not None else rtnmsg)
|
||||
stack.mark_failed(errmsg if errmsg is not None else rtnmsg)
|
||||
assert errmsg is not None, "Returned while IN_PROGRESS."
|
||||
|
||||
return handle_exceptions
|
||||
|
@ -1306,6 +1306,7 @@ class Stack(collections.Mapping):
|
|||
updater()
|
||||
|
||||
@profiler.trace('Stack.converge_stack', hide_args=False)
|
||||
@reset_state_on_error
|
||||
def converge_stack(self, template, action=UPDATE, new_stack=None,
|
||||
pre_converge=None):
|
||||
"""Update the stack template and trigger convergence for resources."""
|
||||
|
@ -1364,6 +1365,7 @@ class Stack(collections.Mapping):
|
|||
self.thread_group_mgr.start(self.id, self._converge_create_or_update,
|
||||
pre_converge=pre_converge)
|
||||
|
||||
@reset_state_on_error
|
||||
def _converge_create_or_update(self, pre_converge=None):
|
||||
current_resources = self._update_or_store_resources()
|
||||
self._compute_convg_dependencies(self.ext_rsrcs_db, self.dependencies,
|
||||
|
@ -2107,13 +2109,31 @@ class Stack(collections.Mapping):
|
|||
'tags': self.tags,
|
||||
}
|
||||
|
||||
def mark_complete(self):
|
||||
"""Mark the update as complete.
|
||||
def mark_failed(self, failure_reason):
|
||||
"""Mark the convergence update as failed."""
|
||||
updated = self.state_set(self.action, self.FAILED, failure_reason)
|
||||
if not updated:
|
||||
return False
|
||||
|
||||
This currently occurs when all resources have been updated; there may
|
||||
still be resources being cleaned up, but the Stack should now be in
|
||||
service.
|
||||
"""
|
||||
if not self.convergence:
|
||||
# This function is not generally used in the legacy path, but to
|
||||
# allow it to be used by any kind of stack in the
|
||||
# reset_state_on_error decorator, bail out before the
|
||||
# convergence-specific part in legacy stacks.
|
||||
return
|
||||
|
||||
if (not self.disable_rollback and
|
||||
self.action in (self.CREATE, self.ADOPT, self.UPDATE,
|
||||
self.RESTORE)):
|
||||
LOG.info("Triggering rollback of %(stack_name)s %(action)s ",
|
||||
{'action': self.action, 'stack_name': self.name})
|
||||
self.rollback()
|
||||
else:
|
||||
self.purge_db()
|
||||
return True
|
||||
|
||||
def mark_complete(self):
|
||||
"""Mark the convergence update as complete."""
|
||||
|
||||
LOG.info('[%(name)s(%(id)s)] update traversal %(tid)s complete',
|
||||
{'name': self.name, 'id': self.id,
|
||||
|
|
|
@ -42,6 +42,7 @@ class StackCreateTest(common.HeatTestCase):
|
|||
self.ctx = utils.dummy_context()
|
||||
self.man = service.EngineService('a-host', 'a-topic')
|
||||
self.man.thread_group_mgr = service.ThreadGroupManager()
|
||||
cfg.CONF.set_override('convergence_engine', False)
|
||||
|
||||
@mock.patch.object(threadgroup, 'ThreadGroup')
|
||||
@mock.patch.object(stack.Stack, 'validate')
|
||||
|
@ -53,7 +54,8 @@ class StackCreateTest(common.HeatTestCase):
|
|||
params = {'foo': 'bar'}
|
||||
template = '{ "Template": "data" }'
|
||||
|
||||
stk = tools.get_stack(stack_name, self.ctx)
|
||||
stk = tools.get_stack(stack_name, self.ctx,
|
||||
convergence=cfg.CONF.convergence_engine)
|
||||
|
||||
files = None
|
||||
if files_container:
|
||||
|
|
|
@ -205,7 +205,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
self.assertFalse(res)
|
||||
mock_ss.assert_not_called()
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_resource_update_failure_sets_stack_state_as_failed(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self.stack.state_set(self.stack.UPDATE, self.stack.IN_PROGRESS, '')
|
||||
|
@ -224,7 +224,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
'ResourceNotAvailable: resources.A: The Resource (A)'
|
||||
' is not available.', s.status_reason)
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_resource_cleanup_failure_sets_stack_state_as_failed(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self.is_update = False # invokes check_resource_cleanup
|
||||
|
@ -244,9 +244,9 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
'ResourceNotAvailable: resources.A: The Resource (A)'
|
||||
' is not available.', s.status_reason)
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
def test_resource_update_failure_triggers_rollback_if_enabled(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
mock_tr = self.stack.rollback = mock.Mock(return_value=None)
|
||||
self.stack.disable_rollback = False
|
||||
self.stack.store()
|
||||
dummy_ex = exception.ResourceNotAvailable(
|
||||
|
@ -257,14 +257,11 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
self.stack.current_traversal, {},
|
||||
self.is_update, None)
|
||||
self.assertTrue(mock_tr.called)
|
||||
# make sure the rollback is called on given stack
|
||||
call_args, call_kwargs = mock_tr.call_args
|
||||
called_stack = call_args[0]
|
||||
self.assertEqual(self.stack.id, called_stack.id)
|
||||
mock_tr.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
def test_resource_cleanup_failure_triggers_rollback_if_enabled(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
mock_tr = self.stack.rollback = mock.Mock(return_value=None)
|
||||
self.is_update = False # invokes check_resource_cleanup
|
||||
self.stack.disable_rollback = False
|
||||
self.stack.store()
|
||||
|
@ -275,13 +272,9 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
self.worker.check_resource(self.ctx, self.resource.id,
|
||||
self.stack.current_traversal, {},
|
||||
self.is_update, None)
|
||||
self.assertTrue(mock_tr.called)
|
||||
# make sure the rollback is called on given stack
|
||||
call_args, call_kwargs = mock_tr.call_args
|
||||
called_stack = call_args[0]
|
||||
self.assertEqual(self.stack.id, called_stack.id)
|
||||
mock_tr.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_rollback_is_not_triggered_on_rollback_disabled_stack(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self.stack.disable_rollback = True
|
||||
|
@ -295,7 +288,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
self.is_update, None)
|
||||
self.assertFalse(mock_tr.called)
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_rollback_not_re_triggered_for_a_rolling_back_stack(
|
||||
self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self.stack.disable_rollback = False
|
||||
|
@ -435,23 +428,23 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
@mock.patch.object(stack.Stack, 'purge_db')
|
||||
def test_handle_failure(self, mock_purgedb, mock_cru, mock_crc, mock_pcr,
|
||||
mock_csc):
|
||||
self.cr._handle_failure(self.ctx, self.stack, 'dummy-reason')
|
||||
self.stack.mark_failed('dummy-reason')
|
||||
mock_purgedb.assert_called_once_with()
|
||||
self.assertEqual('dummy-reason', self.stack.status_reason)
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
def test_handle_failure_rollback(self, mock_tr, mock_cru, mock_crc,
|
||||
def test_handle_failure_rollback(self, mock_cru, mock_crc,
|
||||
mock_pcr, mock_csc):
|
||||
mock_tr = self.stack.rollback = mock.Mock(return_value=None)
|
||||
self.stack.disable_rollback = False
|
||||
self.stack.state_set(self.stack.UPDATE, self.stack.IN_PROGRESS, '')
|
||||
self.cr._handle_failure(self.ctx, self.stack, 'dummy-reason')
|
||||
mock_tr.assert_called_once_with(self.stack)
|
||||
self.stack.mark_failed('dummy-reason')
|
||||
mock_tr.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(stack.Stack, 'purge_db')
|
||||
@mock.patch.object(stack.Stack, 'state_set')
|
||||
@mock.patch.object(check_resource.CheckResource,
|
||||
'retrigger_check_resource')
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_handle_rsrc_failure_when_update_fails(
|
||||
self, mock_tr, mock_rcr, mock_ss, mock_pdb, mock_cru, mock_crc,
|
||||
mock_pcr, mock_csc):
|
||||
|
@ -469,7 +462,7 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
@mock.patch.object(stack.Stack, 'state_set')
|
||||
@mock.patch.object(check_resource.CheckResource,
|
||||
'retrigger_check_resource')
|
||||
@mock.patch.object(check_resource.CheckResource, '_trigger_rollback')
|
||||
@mock.patch.object(stack.Stack, 'rollback')
|
||||
def test_handle_rsrc_failure_when_update_fails_different_traversal(
|
||||
self, mock_tr, mock_rcr, mock_ss, mock_pdb, mock_cru, mock_crc,
|
||||
mock_pcr, mock_csc):
|
||||
|
@ -492,22 +485,21 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
|||
self.assertFalse(mock_pdb.called)
|
||||
self.assertFalse(mock_tr.called)
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource, '_handle_failure')
|
||||
def test_handle_stack_timeout(self, mock_hf, mock_cru, mock_crc, mock_pcr,
|
||||
def test_handle_stack_timeout(self, mock_cru, mock_crc, mock_pcr,
|
||||
mock_csc):
|
||||
mock_mf = self.stack.mark_failed = mock.Mock(return_value=True)
|
||||
self.cr._handle_stack_timeout(self.ctx, self.stack)
|
||||
mock_hf.assert_called_once_with(self.ctx, self.stack, u'Timed out')
|
||||
mock_mf.assert_called_once_with(u'Timed out')
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource,
|
||||
'_handle_failure')
|
||||
def test_do_check_resource_marks_stack_as_failed_if_stack_timesout(
|
||||
self, mock_hf, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
self, mock_cru, mock_crc, mock_pcr, mock_csc):
|
||||
mock_mf = self.stack.mark_failed = mock.Mock(return_value=True)
|
||||
mock_cru.side_effect = scheduler.Timeout(None, 60)
|
||||
self.is_update = True
|
||||
self.cr._do_check_resource(self.ctx, self.stack.current_traversal,
|
||||
self.stack.t, {}, self.is_update,
|
||||
self.resource, self.stack, {})
|
||||
mock_hf.assert_called_once_with(self.ctx, self.stack, u'Timed out')
|
||||
mock_mf.assert_called_once_with(u'Timed out')
|
||||
|
||||
@mock.patch.object(check_resource.CheckResource,
|
||||
'_handle_stack_timeout')
|
||||
|
|
|
@ -489,7 +489,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
|
|||
def test_sync_point_delete_stack_create(self, mock_syncpoint_del,
|
||||
mock_ccu, mock_cr):
|
||||
stack = parser.Stack(utils.dummy_context(), 'convg_updated_time_test',
|
||||
templatem.Template.create_empty_template())
|
||||
templatem.Template.create_empty_template(),
|
||||
convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.converge_stack(template=stack.t, action=stack.CREATE)
|
||||
self.assertFalse(mock_syncpoint_del.called)
|
||||
|
@ -503,7 +504,7 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
|
|||
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {'R1': {'Type': 'GenericResourceType'}}}
|
||||
stack = parser.Stack(utils.dummy_context(), 'updated_time_test',
|
||||
templatem.Template(tmpl))
|
||||
templatem.Template(tmpl), convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.current_traversal = 'prev_traversal'
|
||||
stack.converge_stack(template=stack.t, action=stack.UPDATE)
|
||||
|
@ -514,7 +515,7 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
|
|||
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
|
||||
'Resources': {'R1': {'Type': 'GenericResourceType'}}}
|
||||
stack = parser.Stack(utils.dummy_context(), 'updated_time_test',
|
||||
templatem.Template(tmpl))
|
||||
templatem.Template(tmpl), convergence=True)
|
||||
stack.current_traversal = 'prev_traversal'
|
||||
stack.action, stack.status = stack.CREATE, stack.COMPLETE
|
||||
stack.store()
|
||||
|
|
|
@ -2043,6 +2043,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self.assertEqual(atomic_key, rs.atomic_key)
|
||||
|
||||
def test_create_convergence(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.action = res.CREATE
|
||||
|
@ -2059,6 +2060,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self._assert_resource_lock(res.id, None, None)
|
||||
|
||||
def test_create_convergence_throws_timeout(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.action = res.CREATE
|
||||
|
@ -2074,6 +2076,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
Ensure that requires are computed correctly even if resource
|
||||
create fails.
|
||||
"""
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.store()
|
||||
|
@ -2089,6 +2092,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
|
||||
@mock.patch.object(resource.Resource, 'adopt')
|
||||
def test_adopt_convergence_ok(self, mock_adopt):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.action = res.ADOPT
|
||||
|
@ -2106,6 +2110,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self._assert_resource_lock(res.id, None, None)
|
||||
|
||||
def test_adopt_convergence_bad_data(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.action = res.ADOPT
|
||||
|
@ -2127,7 +2132,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
tmpl, convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
|
@ -2144,8 +2149,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
}}, env=self.env)
|
||||
new_temp.store(stack.context)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
res.stack.convergence = True
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
|
||||
tr = scheduler.TaskRunner(res.update_convergence, new_temp.id,
|
||||
{4, 3}, 'engine-007', 120, new_stack)
|
||||
|
@ -2163,7 +2168,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
tmpl, convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
|
@ -2177,7 +2182,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
}}, env=self.env)
|
||||
new_temp.store(stack.context)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
|
||||
tr = scheduler.TaskRunner(res.update_convergence, new_temp.id,
|
||||
set(), 'engine-007', -1, new_stack,
|
||||
|
@ -2185,6 +2191,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self.assertRaises(scheduler.Timeout, tr)
|
||||
|
||||
def test_update_convergence_with_substitute_class(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'GenericResourceType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
|
@ -2198,13 +2205,15 @@ class ResourceTest(common.HeatTestCase):
|
|||
}}, env=self.env)
|
||||
new_temp.store(self.stack.context)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
|
||||
self.assertRaises(resource.UpdateReplace, res.update_convergence,
|
||||
new_temp.id, set(), 'engine-007',
|
||||
-1, new_stack)
|
||||
|
||||
def test_update_convergence_checks_resource_class(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res',
|
||||
'GenericResourceType')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
|
@ -2219,7 +2228,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
ctx = utils.dummy_context()
|
||||
new_temp.store(ctx)
|
||||
new_stack = parser.Stack(ctx, 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
|
||||
tr = scheduler.TaskRunner(res.update_convergence, new_temp.id,
|
||||
set(), 'engine-007', -1, new_stack,
|
||||
|
@ -2245,7 +2255,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl, stack_id=self.stack.id)
|
||||
tmpl, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
tr = scheduler.TaskRunner(res.update_convergence, 'template_key',
|
||||
{4, 3}, 'engine-007', self.dummy_timeout,
|
||||
new_stack)
|
||||
|
@ -2268,7 +2279,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
tmpl, convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
|
@ -2285,7 +2296,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
new_temp.store(stack.context)
|
||||
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
|
||||
res.stack.convergence = True
|
||||
res._calling_engine_id = 'engine-9'
|
||||
|
@ -2309,7 +2321,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
'test_res': {'Type': 'ResourceWithPropsType'}
|
||||
}}, env=self.env)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
tmpl)
|
||||
tmpl, convergence=True)
|
||||
stack.thread_group_mgr = tools.DummyThreadGroupManager()
|
||||
stack.converge_stack(stack.t, action=stack.CREATE)
|
||||
res = stack.resources['test_res']
|
||||
|
@ -2341,6 +2353,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self._assert_resource_lock(res.id, None, 2)
|
||||
|
||||
def test_convergence_update_replace_rollback(self):
|
||||
self.stack.convergence = True
|
||||
rsrc_def = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
res = generic_rsrc.ResourceWithProps('test_res', rsrc_def, self.stack)
|
||||
|
@ -2354,7 +2367,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
'Properties': {'Foo': 'abc'}}
|
||||
}}, env=self.env)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
self.stack.state_set(self.stack.ROLLBACK, self.stack.IN_PROGRESS,
|
||||
'Simulate rollback')
|
||||
res.restore_prev_rsrc = mock.Mock()
|
||||
|
@ -2365,6 +2379,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self.assertTrue(res.restore_prev_rsrc.called)
|
||||
|
||||
def test_convergence_update_replace_rollback_restore_prev_rsrc_error(self):
|
||||
self.stack.convergence = True
|
||||
rsrc_def = rsrc_defn.ResourceDefinition('test_res',
|
||||
'ResourceWithPropsType')
|
||||
res = generic_rsrc.ResourceWithProps('test_res', rsrc_def, self.stack)
|
||||
|
@ -2378,7 +2393,8 @@ class ResourceTest(common.HeatTestCase):
|
|||
'Properties': {'Foo': 'abc'}}
|
||||
}}, env=self.env)
|
||||
new_stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
new_temp, stack_id=self.stack.id)
|
||||
new_temp, stack_id=self.stack.id,
|
||||
convergence=True)
|
||||
self.stack.state_set(self.stack.ROLLBACK, self.stack.IN_PROGRESS,
|
||||
'Simulate rollback')
|
||||
res.restore_prev_rsrc = mock.Mock(side_effect=Exception)
|
||||
|
@ -2390,6 +2406,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self.assertEqual((res.UPDATE, res.FAILED), res.state)
|
||||
|
||||
def test_delete_convergence_ok(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.current_template_id = 1
|
||||
|
@ -2409,6 +2426,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self._assert_resource_lock(res.id, None, None)
|
||||
|
||||
def test_delete_convergence_does_not_delete_same_template_resource(self):
|
||||
self.stack.convergence = True
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
|
||||
res.current_template_id = 'same-template'
|
||||
|
|
|
@ -2985,7 +2985,8 @@ class ResetStateOnErrorTest(common.HeatTestCase):
|
|||
status = COMPLETE
|
||||
|
||||
def __init__(self):
|
||||
self.state_set = mock.MagicMock()
|
||||
self.mark_failed = mock.MagicMock()
|
||||
self.convergence = False
|
||||
|
||||
@stack.reset_state_on_error
|
||||
def raise_exception(self):
|
||||
|
@ -3010,27 +3011,27 @@ class ResetStateOnErrorTest(common.HeatTestCase):
|
|||
dummy = self.DummyStack()
|
||||
|
||||
self.assertEqual('Hello world', dummy.succeed())
|
||||
self.assertFalse(dummy.state_set.called)
|
||||
self.assertFalse(dummy.mark_failed.called)
|
||||
|
||||
def test_failure(self):
|
||||
dummy = self.DummyStack()
|
||||
|
||||
self.assertEqual('Hello world', dummy.fail())
|
||||
self.assertFalse(dummy.state_set.called)
|
||||
self.assertFalse(dummy.mark_failed.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.state_set.called)
|
||||
self.assertTrue(dummy.mark_failed.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.state_set.called)
|
||||
self.assertTrue(dummy.mark_failed.called)
|
||||
|
||||
|
||||
class StackStateSetTest(common.HeatTestCase):
|
||||
|
|
Loading…
Reference in New Issue