Support snapshot/restore for remote stack
Support snapshot and restore actions for OS::Heat::Stack. Blueprint: support-actions-for-remote-stack Change-Id: I3108e63ed35cb3b04f43fd992c2ca0986ee1a5aa
This commit is contained in:
parent
c03c9cfcbf
commit
eaaa717fed
@ -12,6 +12,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
|
||||
from heat.common import context
|
||||
@ -24,6 +25,7 @@ from heat.engine import environment
|
||||
from heat.engine import function
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine import template
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -185,6 +187,24 @@ class RemoteStack(resource.Resource):
|
||||
% self.name)
|
||||
self.heat().actions.suspend(stack_id=self.resource_id)
|
||||
|
||||
def handle_snapshot(self):
|
||||
snapshot = self.heat().stacks.snapshot(stack_id=self.resource_id)
|
||||
self.data_set('snapshot_id', snapshot['id'])
|
||||
|
||||
def handle_restore(self, defn, restore_data):
|
||||
snapshot_id = restore_data['resource_data']['snapshot_id']
|
||||
snapshot = self.heat().stacks.snapshot_show(self.resource_id,
|
||||
snapshot_id)
|
||||
s_data = snapshot['snapshot']['data']
|
||||
env = environment.Environment(s_data['environment'])
|
||||
files = s_data['files']
|
||||
tmpl = template.Template(s_data['template'], env=env, files=files)
|
||||
props = function.resolve(self.properties.data)
|
||||
props[self.TEMPLATE] = jsonutils.dumps(tmpl.t)
|
||||
props[self.PARAMETERS] = env.params
|
||||
|
||||
return defn.freeze(properties=props)
|
||||
|
||||
def _needs_update(self, after, before, after_props, before_props,
|
||||
prev_resource):
|
||||
# Always issue an update to the remote stack and let the individual
|
||||
@ -257,6 +277,9 @@ class RemoteStack(resource.Resource):
|
||||
def check_update_complete(self, *args):
|
||||
return self._check_action_complete(action=self.UPDATE)
|
||||
|
||||
def check_snapshot_complete(self, *args):
|
||||
return self._check_action_complete(action=self.SNAPSHOT)
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
try:
|
||||
stack = self.heat().stacks.get(stack_id=self.resource_id)
|
||||
|
@ -11,6 +11,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import copy
|
||||
|
||||
from heatclient import exc
|
||||
@ -392,6 +393,70 @@ class RemoteStackTest(tests_common.HeatTestCase):
|
||||
'incorrect.',
|
||||
six.text_type(error))
|
||||
|
||||
def test_snapshot(self):
|
||||
stacks = [get_stack(stack_status='SNAPSHOT_IN_PROGRESS'),
|
||||
get_stack(stack_status='SNAPSHOT_COMPLETE')]
|
||||
snapshot = {
|
||||
'id': 'a29bc9e25aa44f99a9a3d59cd5b0e263',
|
||||
'status': 'IN_PROGRESS'
|
||||
}
|
||||
|
||||
rsrc = self.create_remote_stack()
|
||||
|
||||
self.heat.stacks.get = mock.MagicMock(side_effect=stacks)
|
||||
self.heat.stacks.snapshot = mock.MagicMock(return_value=snapshot)
|
||||
scheduler.TaskRunner(rsrc.snapshot)()
|
||||
|
||||
self.assertEqual((rsrc.SNAPSHOT, rsrc.COMPLETE), rsrc.state)
|
||||
self.assertEqual('a29bc9e25aa44f99a9a3d59cd5b0e263',
|
||||
rsrc.data().get('snapshot_id'))
|
||||
self.heat.stacks.snapshot.assert_called_with(
|
||||
stack_id=rsrc.resource_id)
|
||||
|
||||
def test_restore(self):
|
||||
snapshot = {
|
||||
'id': 'a29bc9e25aa44f99a9a3d59cd5b0e263',
|
||||
'status': 'IN_PROGRESS'
|
||||
}
|
||||
remote_stack = mock.MagicMock()
|
||||
remote_stack.action = 'SNAPSHOT'
|
||||
remote_stack.status = 'COMPLETE'
|
||||
|
||||
parent, rsrc = self.create_parent_stack()
|
||||
rsrc.action = rsrc.SNAPSHOT
|
||||
|
||||
heat = rsrc._context().clients.client("heat")
|
||||
heat.stacks.snapshot = mock.MagicMock(return_value=snapshot)
|
||||
heat.stacks.get = mock.MagicMock(return_value=remote_stack)
|
||||
scheduler.TaskRunner(parent.snapshot, None)()
|
||||
self.assertEqual((parent.SNAPSHOT, parent.COMPLETE), parent.state)
|
||||
|
||||
data = parent.prepare_abandon()
|
||||
remote_stack_snapshot = {
|
||||
'snapshot': {
|
||||
'id': 'a29bc9e25aa44f99a9a3d59cd5b0e263',
|
||||
'status': 'COMPLETE',
|
||||
'data': {
|
||||
'files': data['files'],
|
||||
'environment': data['environment'],
|
||||
'template': template_format.parse(
|
||||
data['files']['remote_template.yaml'])
|
||||
}
|
||||
}
|
||||
}
|
||||
fake_snapshot = collections.namedtuple(
|
||||
'Snapshot', ('data', 'stack_id'))(data, parent.id)
|
||||
heat.stacks.snapshot_show = mock.MagicMock(
|
||||
return_value=remote_stack_snapshot)
|
||||
self.patchobject(rsrc, 'update').return_value = None
|
||||
rsrc.action = rsrc.UPDATE
|
||||
rsrc.status = rsrc.COMPLETE
|
||||
remote_stack.action = 'UPDATE'
|
||||
|
||||
parent.restore(fake_snapshot)
|
||||
|
||||
self.assertEqual((parent.RESTORE, parent.COMPLETE), parent.state)
|
||||
|
||||
def test_resume(self):
|
||||
stacks = [get_stack(stack_status='RESUME_IN_PROGRESS'),
|
||||
get_stack(stack_status='RESUME_COMPLETE')]
|
||||
|
Loading…
Reference in New Issue
Block a user