Merge "Convergence rollback implementation"

This commit is contained in:
Jenkins 2015-06-29 01:52:09 +00:00 committed by Gerrit Code Review
commit 2ed0b7ddcb
2 changed files with 57 additions and 3 deletions

View File

@ -28,6 +28,7 @@ from heat.engine import dependencies
from heat.engine import resource
from heat.engine import stack as parser
from heat.engine import sync_point
from heat.engine import template as templatem
from heat.objects import resource as resource_objects
from heat.rpc import listener_client
from heat.rpc import worker_client as rpc_client
@ -99,8 +100,18 @@ class WorkerService(service.Service):
return False
def _trigger_rollback(self, cnxt, stack):
# TODO(ananta) convergence-rollback implementation
pass
LOG.info(_LI("Triggering rollback of %(stack_name)s %(action)s "),
{'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,
failure_reason):
@ -110,6 +121,7 @@ class WorkerService(service.Service):
return
stack.state_set(stack.action, stack.FAILED, failure_reason)
if (not stack.disable_rollback and
stack.action in (stack.CREATE, stack.UPDATE)):
self._trigger_rollback(cnxt, stack)
@ -148,7 +160,6 @@ class WorkerService(service.Service):
if (rsrc.replaced_by is not None and
rsrc.current_template_id != tmpl.id):
return
try:
check_resource_update(rsrc, tmpl.id, data, self.engine_id)
except resource.UpdateReplace:

View File

@ -16,9 +16,11 @@
import mock
from heat.common import exception
from heat.common import template_format
from heat.engine import resource
from heat.engine import stack
from heat.engine import sync_point
from heat.engine import template as templatem
from heat.engine import worker
from heat.rpc import worker_client
from heat.tests import common
@ -288,6 +290,47 @@ class CheckWorkflowUpdateTest(common.HeatTestCase):
self.is_update)
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(
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
self.stack.disable_rollback = True