Merge "Convergence rollback implementation"
This commit is contained in:
commit
2ed0b7ddcb
|
@ -28,6 +28,7 @@ from heat.engine import dependencies
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine import stack as parser
|
from heat.engine import stack as parser
|
||||||
from heat.engine import sync_point
|
from heat.engine import sync_point
|
||||||
|
from heat.engine import template as templatem
|
||||||
from heat.objects import resource as resource_objects
|
from heat.objects import resource as resource_objects
|
||||||
from heat.rpc import listener_client
|
from heat.rpc import listener_client
|
||||||
from heat.rpc import worker_client as rpc_client
|
from heat.rpc import worker_client as rpc_client
|
||||||
|
@ -99,8 +100,18 @@ class WorkerService(service.Service):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _trigger_rollback(self, cnxt, stack):
|
def _trigger_rollback(self, cnxt, stack):
|
||||||
# TODO(ananta) convergence-rollback implementation
|
LOG.info(_LI("Triggering rollback of %(stack_name)s %(action)s "),
|
||||||
pass
|
{'action': stack.action, 'stack_name': stack.name})
|
||||||
|
old_tmpl_id = stack.prev_raw_template_id
|
||||||
|
if old_tmpl_id is None:
|
||||||
|
rollback_tmpl = templatem.Template.create_empty_template(
|
||||||
|
version=stack.t.version)
|
||||||
|
else:
|
||||||
|
rollback_tmpl = templatem.Template.load(cnxt, old_tmpl_id)
|
||||||
|
stack.prev_raw_template_id = None
|
||||||
|
stack.store()
|
||||||
|
|
||||||
|
stack.converge_stack(rollback_tmpl, action=stack.ROLLBACK)
|
||||||
|
|
||||||
def _handle_resource_failure(self, cnxt, stack_id, traversal_id,
|
def _handle_resource_failure(self, cnxt, stack_id, traversal_id,
|
||||||
failure_reason):
|
failure_reason):
|
||||||
|
@ -110,6 +121,7 @@ class WorkerService(service.Service):
|
||||||
return
|
return
|
||||||
|
|
||||||
stack.state_set(stack.action, stack.FAILED, failure_reason)
|
stack.state_set(stack.action, stack.FAILED, failure_reason)
|
||||||
|
|
||||||
if (not stack.disable_rollback and
|
if (not stack.disable_rollback and
|
||||||
stack.action in (stack.CREATE, stack.UPDATE)):
|
stack.action in (stack.CREATE, stack.UPDATE)):
|
||||||
self._trigger_rollback(cnxt, stack)
|
self._trigger_rollback(cnxt, stack)
|
||||||
|
@ -148,7 +160,6 @@ class WorkerService(service.Service):
|
||||||
if (rsrc.replaced_by is not None and
|
if (rsrc.replaced_by is not None and
|
||||||
rsrc.current_template_id != tmpl.id):
|
rsrc.current_template_id != tmpl.id):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
check_resource_update(rsrc, tmpl.id, data, self.engine_id)
|
check_resource_update(rsrc, tmpl.id, data, self.engine_id)
|
||||||
except resource.UpdateReplace:
|
except resource.UpdateReplace:
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
|
from heat.common import template_format
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine import stack
|
from heat.engine import stack
|
||||||
from heat.engine import sync_point
|
from heat.engine import sync_point
|
||||||
|
from heat.engine import template as templatem
|
||||||
from heat.engine import worker
|
from heat.engine import worker
|
||||||
from heat.rpc import worker_client
|
from heat.rpc import worker_client
|
||||||
from heat.tests import common
|
from heat.tests import common
|
||||||
|
@ -288,6 +290,47 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
|
||||||
self.is_update)
|
self.is_update)
|
||||||
self.assertFalse(self.worker._trigger_rollback.called)
|
self.assertFalse(self.worker._trigger_rollback.called)
|
||||||
|
|
||||||
|
def test_trigger_rollback_uses_old_template_if_available(
|
||||||
|
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
|
||||||
|
# create a template and assign to stack as previous template
|
||||||
|
t = template_format.parse(tools.wp_template)
|
||||||
|
prev_tmpl = templatem.Template(t)
|
||||||
|
prev_tmpl.store(context=self.ctx)
|
||||||
|
self.stack.prev_raw_template_id = prev_tmpl.id
|
||||||
|
# mock failure
|
||||||
|
self.stack.action = self.stack.UPDATE
|
||||||
|
self.stack.status = self.stack.FAILED
|
||||||
|
self.stack.store()
|
||||||
|
# mock converge_stack()
|
||||||
|
self.stack.converge_stack = mock.Mock()
|
||||||
|
# call trigger_rollbac
|
||||||
|
self.worker._trigger_rollback(self.ctx, self.stack)
|
||||||
|
|
||||||
|
# Make sure stack converge is called with previous template
|
||||||
|
self.assertTrue(self.stack.converge_stack.called)
|
||||||
|
self.assertIsNone(self.stack.prev_raw_template_id)
|
||||||
|
call_args, call_kwargs = self.stack.converge_stack.call_args
|
||||||
|
template_used_for_rollback = call_args[0]
|
||||||
|
self.assertEqual(prev_tmpl.id, template_used_for_rollback.id)
|
||||||
|
|
||||||
|
def test_trigger_rollback_uses_empty_template_if_prev_tmpl_not_available(
|
||||||
|
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
|
||||||
|
# mock create failure with no previous template
|
||||||
|
self.stack.prev_raw_template_id = None
|
||||||
|
self.stack.action = self.stack.CREATE
|
||||||
|
self.stack.status = self.stack.FAILED
|
||||||
|
self.stack.store()
|
||||||
|
# mock converge_stack()
|
||||||
|
self.stack.converge_stack = mock.Mock()
|
||||||
|
# call trigger_rollback
|
||||||
|
self.worker._trigger_rollback(self.ctx, self.stack)
|
||||||
|
|
||||||
|
# Make sure stack converge is called with empty template
|
||||||
|
self.assertTrue(self.stack.converge_stack.called)
|
||||||
|
call_args, call_kwargs = self.stack.converge_stack.call_args
|
||||||
|
template_used_for_rollback = call_args[0]
|
||||||
|
self.assertEqual({}, template_used_for_rollback['resources'])
|
||||||
|
|
||||||
def test_resource_update_failure_purges_db_for_stack_failure(
|
def test_resource_update_failure_purges_db_for_stack_failure(
|
||||||
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
|
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
|
||||||
self.stack.disable_rollback = True
|
self.stack.disable_rollback = True
|
||||||
|
|
Loading…
Reference in New Issue