Fix restore with convergence

Handle the restore operation as a normal convergence update instead of a
legacy one.

Change-Id: I6ee46cdf7a8fdf89c58c9812d08af21c97fb0f9e
Related-Bug: #1687006
This commit is contained in:
Thomas Herve 2017-05-17 16:06:33 +02:00
parent 53aff6561a
commit 42e3d02dbf
4 changed files with 29 additions and 16 deletions

View File

@ -77,7 +77,8 @@ class CheckResource(object):
return False return False
if (not stack.disable_rollback and if (not stack.disable_rollback and
stack.action in (stack.CREATE, stack.ADOPT, stack.UPDATE)): stack.action in (stack.CREATE, stack.ADOPT, stack.UPDATE,
stack.RESTORE)):
self._trigger_rollback(stack) self._trigger_rollback(stack)
else: else:
stack.purge_db() stack.purge_db()

View File

@ -2113,8 +2113,15 @@ class EngineService(service.ServiceBase):
# FIXME(pas-ha) has to be amended to deny restoring stacks # FIXME(pas-ha) has to be amended to deny restoring stacks
# that have disallowed for current user # that have disallowed for current user
self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id, if stack.convergence:
_stack_restore, stack, snapshot) new_stack, tmpl = stack.restore_data(snapshot)
stack.thread_group_mgr = self.thread_group_mgr
stack.converge_stack(template=tmpl,
action=stack.RESTORE,
new_stack=new_stack)
else:
self.thread_group_mgr.start_with_lock(
cnxt, stack, self.engine_id, _stack_restore, stack, snapshot)
@context.request_context @context.request_context
def stack_list_snapshots(self, cnxt, stack_identity): def stack_list_snapshots(self, cnxt, stack_identity):

View File

@ -922,7 +922,7 @@ class Stack(collections.Mapping):
if self.convergence and action in ( if self.convergence and action in (
self.UPDATE, self.DELETE, self.CREATE, self.UPDATE, self.DELETE, self.CREATE,
self.ADOPT, self.ROLLBACK): self.ADOPT, self.ROLLBACK, self.RESTORE):
# if convergence and stack operation is create/update/rollback/ # if convergence and stack operation is create/update/rollback/
# delete, stack lock is not used, hence persist state # delete, stack lock is not used, hence persist state
updated = self._persist_state() updated = self._persist_state()
@ -940,7 +940,7 @@ class Stack(collections.Mapping):
# or action == UPDATE/DELETE/ROLLBACK. Else, it would # or action == UPDATE/DELETE/ROLLBACK. Else, it would
# be done before releasing the stack lock. # be done before releasing the stack lock.
if status == self.IN_PROGRESS or action in ( if status == self.IN_PROGRESS or action in (
self.UPDATE, self.DELETE, self.ROLLBACK): self.UPDATE, self.DELETE, self.ROLLBACK, self.RESTORE):
self._persist_state() self._persist_state()
def _log_status(self): def _log_status(self):
@ -1908,14 +1908,7 @@ class Stack(collections.Mapping):
data = snapshot.data['resources'].get(name) data = snapshot.data['resources'].get(name)
scheduler.TaskRunner(rsrc.delete_snapshot, data)() scheduler.TaskRunner(rsrc.delete_snapshot, data)()
@profiler.trace('Stack.restore', hide_args=False) def restore_data(self, snapshot):
@reset_state_on_error
def restore(self, snapshot):
"""Restore the given snapshot.
Invokes handle_restore on all resources.
"""
self.updated_time = oslo_timeutils.utcnow()
env = environment.Environment(snapshot.data['environment']) env = environment.Environment(snapshot.data['environment'])
files = snapshot.data['files'] files = snapshot.data['files']
template = tmpl.Template(snapshot.data['template'], template = tmpl.Template(snapshot.data['template'],
@ -1935,6 +1928,17 @@ class Stack(collections.Mapping):
newstack.parameters.set_stack_id(self.identifier()) newstack.parameters.set_stack_id(self.identifier())
return newstack, template
@reset_state_on_error
def restore(self, snapshot):
"""Restore the given snapshot.
Invokes handle_restore on all resources.
"""
self.updated_time = oslo_timeutils.utcnow()
newstack = self.restore_data(snapshot)[0]
updater = scheduler.TaskRunner(self.update_task, newstack, updater = scheduler.TaskRunner(self.update_task, newstack,
action=self.RESTORE) action=self.RESTORE)
updater() updater()

View File

@ -663,15 +663,16 @@ class TestConvgStackStateSet(common.HeatTestCase):
self.assertIsNone(ret_val) self.assertIsNone(ret_val)
def test_state_set_stack_restore(self, mock_ps): def test_state_set_stack_restore(self, mock_ps):
mock_ps.return_value = 'updated'
ret_val = self.stack.state_set( ret_val = self.stack.state_set(
self.stack.RESTORE, self.stack.IN_PROGRESS, 'Restore started') self.stack.RESTORE, self.stack.IN_PROGRESS, 'Restore started')
self.assertTrue(mock_ps.called) self.assertTrue(mock_ps.called)
self.assertIsNone(ret_val) self.assertEqual('updated', ret_val)
mock_ps.reset_mock() mock_ps.reset_mock()
ret_val = self.stack.state_set( ret_val = self.stack.state_set(
self.stack.RESTORE, self.stack.COMPLETE, 'Restore complete') self.stack.RESTORE, self.stack.COMPLETE, 'Restore complete')
self.assertFalse(mock_ps.called) self.assertTrue(mock_ps.called)
self.assertIsNone(ret_val) self.assertEqual('updated', ret_val)
class TestConvgStackRollback(common.HeatTestCase): class TestConvgStackRollback(common.HeatTestCase):