From ee9f0354ec7c0084c0f8cfe2b670589e0d326421 Mon Sep 17 00:00:00 2001 From: John Griffith Date: Mon, 1 Jul 2013 21:17:30 -0600 Subject: [PATCH] Enable ability to reset state on snapshots. Implement the ability to reset-state on snapshots, exposes os-reset_status from snapshot actions. Change-Id: I605f41e39fde46ccfe6a53222b798f32c14bc1f8 --- cinderclient/tests/v1/fakes.py | 11 +++++++++++ cinderclient/tests/v1/test_shell.py | 10 ++++++++++ cinderclient/tests/v2/fakes.py | 11 +++++++++++ cinderclient/tests/v2/test_shell.py | 10 ++++++++++ cinderclient/v1/shell.py | 15 +++++++++++++++ cinderclient/v1/volume_snapshots.py | 15 +++++++++++++++ cinderclient/v2/shell.py | 15 +++++++++++++++ cinderclient/v2/volume_snapshots.py | 15 +++++++++++++++ 8 files changed, 102 insertions(+) diff --git a/cinderclient/tests/v1/fakes.py b/cinderclient/tests/v1/fakes.py index a223d16be..2a33ba830 100644 --- a/cinderclient/tests/v1/fakes.py +++ b/cinderclient/tests/v1/fakes.py @@ -231,6 +231,17 @@ class FakeHTTPClient(base_client.HTTPClient): snapshot.update(kw['body']['snapshot']) return (200, {}, {'snapshot': snapshot}) + def post_snapshots_1234_action(self, body, **kw): + _body = None + resp = 202 + assert len(body.keys()) == 1 + action = body.keys()[0] + if action == 'os-reset_status': + assert 'status' in body['os-reset_status'] + else: + raise AssertionError('Unexpected action: %s" % action') + return (resp, {}, _body) + # # Volumes # diff --git a/cinderclient/tests/v1/test_shell.py b/cinderclient/tests/v1/test_shell.py index 8b23d6f8c..a8c9425e3 100644 --- a/cinderclient/tests/v1/test_shell.py +++ b/cinderclient/tests/v1/test_shell.py @@ -189,3 +189,13 @@ class ShellTest(utils.TestCase): self.run_command('reset-state --state error 1234') expected = {'os-reset_status': {'status': 'error'}} self.assert_called('POST', '/volumes/1234/action', body=expected) + + def test_snapshot_reset_state(self): + self.run_command('snapshot-reset-state 1234') + expected = {'os-reset_status': {'status': 'available'}} + self.assert_called('POST', '/snapshots/1234/action', body=expected) + + def test_snapshot_reset_state_with_flag(self): + self.run_command('snapshot-reset-state --state error 1234') + expected = {'os-reset_status': {'status': 'error'}} + self.assert_called('POST', '/snapshots/1234/action', body=expected) diff --git a/cinderclient/tests/v2/fakes.py b/cinderclient/tests/v2/fakes.py index e888a8b2c..c1b5be582 100644 --- a/cinderclient/tests/v2/fakes.py +++ b/cinderclient/tests/v2/fakes.py @@ -238,6 +238,17 @@ class FakeHTTPClient(base_client.HTTPClient): snapshot.update(kw['body']['snapshot']) return (200, {}, {'snapshot': snapshot}) + def post_snapshots_1234_action(self, body, **kw): + _body = None + resp = 202 + assert len(body.keys()) == 1 + action = body.keys()[0] + if action == 'os-reset_status': + assert 'status' in body['os-reset_status'] + else: + raise AssertionError('Unexpected action: %s" % action') + return (resp, {}, _body) + # # Volumes # diff --git a/cinderclient/tests/v2/test_shell.py b/cinderclient/tests/v2/test_shell.py index ce7842cf6..eabf13476 100644 --- a/cinderclient/tests/v2/test_shell.py +++ b/cinderclient/tests/v2/test_shell.py @@ -167,3 +167,13 @@ class ShellTest(utils.TestCase): self.run_command('reset-state --state error 1234') expected = {'os-reset_status': {'status': 'error'}} self.assert_called('POST', '/volumes/1234/action', body=expected) + + def test_snapshot_reset_state(self): + self.run_command('snapshot-reset-state 1234') + expected = {'os-reset_status': {'status': 'available'}} + self.assert_called('POST', '/snapshots/1234/action', body=expected) + + def test_snapshot_reset_state_with_flag(self): + self.run_command('snapshot-reset-state --state error 1234') + expected = {'os-reset_status': {'status': 'error'}} + self.assert_called('POST', '/snapshots/1234/action', body=expected) diff --git a/cinderclient/v1/shell.py b/cinderclient/v1/shell.py index f42d74e5d..684728b5d 100644 --- a/cinderclient/v1/shell.py +++ b/cinderclient/v1/shell.py @@ -443,6 +443,21 @@ def do_snapshot_rename(cs, args): _find_volume_snapshot(cs, args.snapshot).update(**kwargs) +@utils.arg('snapshot', metavar='', + help='ID of the snapshot to modify.') +@utils.arg('--state', metavar='', + default='available', + help=('Indicate which state to assign the snapshot. ' + 'Options include available, error, creating, deleting, ' + 'error_deleting. If no state is provided, ' + 'available will be used.')) +@utils.service_type('volume') +def do_snapshot_reset_state(cs, args): + """Explicitly update the state of a snapshot.""" + snapshot = _find_volume_snapshot(cs, args.snapshot) + snapshot.reset_state(args.state) + + def _print_volume_type_list(vtypes): utils.print_list(vtypes, ['ID', 'Name']) diff --git a/cinderclient/v1/volume_snapshots.py b/cinderclient/v1/volume_snapshots.py index 66237a515..63e92c836 100644 --- a/cinderclient/v1/volume_snapshots.py +++ b/cinderclient/v1/volume_snapshots.py @@ -53,6 +53,10 @@ class Snapshot(base.Resource): def project_id(self): return self._info.get('os-extended-snapshot-attributes:project_id') + def reset_state(self, state): + """Update the snapshot with the privided state.""" + self.manager.reset_state(self, state) + class SnapshotManager(base.ManagerWithFind): """ @@ -133,3 +137,14 @@ class SnapshotManager(base.ManagerWithFind): body = {"snapshot": kwargs} self._update("/snapshots/%s" % base.getid(snapshot), body) + + def reset_state(self, snapshot, state): + """Update the specified volume with the provided state.""" + return self._action('os-reset_status', snapshot, {'status': state}) + + def _action(self, action, snapshot, info=None, **kwargs): + """Perform a snapshot action.""" + body = {action: info} + self.run_hooks('modify_body_for_action', body, **kwargs) + url = '/snapshots/%s/action' % base.getid(snapshot) + return self.api.client.post(url, body=body) diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index b86f7f9be..70b259ae0 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -512,6 +512,21 @@ def do_snapshot_rename(cs, args): _find_volume_snapshot(cs, args.snapshot).update(**kwargs) +@utils.arg('snapshot', metavar='', + help='ID of the snapshot to modify.') +@utils.arg('--state', metavar='', + default='available', + help=('Indicate which state to assign the snapshot. ' + 'Options include available, error, creating, ' + 'deleting, error_deleting. If no state is provided, ' + 'available will be used.')) +@utils.service_type('snapshot') +def do_snapshot_reset_state(cs, args): + """Explicitly update the state of a snapshot.""" + snapshot = _find_volume_snapshot(cs, args.snapshot) + snapshot.reset_state(args.state) + + def _print_volume_type_list(vtypes): utils.print_list(vtypes, ['ID', 'Name']) diff --git a/cinderclient/v2/volume_snapshots.py b/cinderclient/v2/volume_snapshots.py index b16383c67..ef529eb39 100644 --- a/cinderclient/v2/volume_snapshots.py +++ b/cinderclient/v2/volume_snapshots.py @@ -45,6 +45,10 @@ class Snapshot(base.Resource): def project_id(self): return self._info.get('os-extended-snapshot-attributes:project_id') + def reset_state(self, state): + """Update the snapshot with the provided state.""" + self.manager.reset_state(self, state) + class SnapshotManager(base.ManagerWithFind): """Manage :class:`Snapshot` resources.""" @@ -118,3 +122,14 @@ class SnapshotManager(base.ManagerWithFind): body = {"snapshot": kwargs} self._update("/snapshots/%s" % base.getid(snapshot), body) + + def reset_state(self, snapshot, state): + """Update the specified snapshot with the provided state.""" + return self._action('os-reset_status', snapshot, {'status': state}) + + def _action(self, action, snapshot, info=None, **kwargs): + """Perform a snapshot action.""" + body = {action: info} + self.run_hooks('modify_body_for_action', body, **kwargs) + url = '/snapshots/%s/action' % base.getid(snapshot) + return self.api.client.post(url, body=body)