Support revert to snapshot in client

This patch added revert to snapshot support in
cinder client, also fix two pylint errors.

Change-Id: I20d8df8d7bcf763f6651f44901a98f6d853b27ce
Partial-Implements: blueprint revert-volume-to-snapshot
Depends-On: cca9e1ac54d123da8859ff918b2355606bfa474e
This commit is contained in:
TommyLike 2017-05-16 09:52:08 +08:00 committed by xing-yang
parent b910f5bea3
commit 7dfbb239de
7 changed files with 73 additions and 1 deletions

View File

@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
# key is a deprecated version and value is an alternative version.
DEPRECATED_VERSIONS = {"1": "2"}
DEPRECATED_VERSION = "2.0"
MAX_VERSION = "3.33"
MAX_VERSION = "3.40"
MIN_VERSION = "3.0"
_SUBSTITUTIONS = {}

View File

@ -535,6 +535,8 @@ class FakeHTTPClient(base_client.HTTPClient):
elif action == 'os-volume_upload_image':
assert 'image_name' in body[action]
_body = body
elif action == 'revert':
assert 'snapshot_id' in body[action]
else:
raise AssertionError("Unexpected action: %s" % action)
return (resp, {}, _body)

View File

@ -23,6 +23,7 @@ from cinderclient import client
from cinderclient import exceptions
from cinderclient import shell
from cinderclient.v3 import volumes
from cinderclient.v3 import volume_snapshots
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v3 import fakes
from cinderclient.tests.unit.fixture_data import keystone_client
@ -278,6 +279,18 @@ class ShellTest(utils.TestCase):
self.run_command(command)
self.assert_called('GET', '/attachments%s' % expected)
@mock.patch('cinderclient.shell_utils.find_volume_snapshot')
def test_revert_to_snapshot(self, mock_snapshot):
mock_snapshot.return_value = volume_snapshots.Snapshot(
self, {'id': '5678', 'volume_id': '1234'})
self.run_command(
'--os-volume-api-version 3.40 revert-to-snapshot 5678')
self.assert_called('POST', '/volumes/1234/action',
body={'revert': {'snapshot_id': '5678'}})
def test_attachment_show(self):
self.run_command('--os-volume-api-version 3.27 attachment-show 1234')
self.assert_called('GET', '/attachments/1234')

View File

@ -18,9 +18,11 @@
import ddt
from cinderclient import api_versions
from cinderclient import exceptions
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v3 import fakes
from cinderclient.v3 import volumes
from cinderclient.v3 import volume_snapshots
from six.moves.urllib import parse
@ -48,6 +50,28 @@ class VolumesTest(utils.TestCase):
visibility='public', protected=True)
cs.assert_called_anytime('POST', '/volumes/1234/action', body=expected)
@ddt.data('3.39', '3.40')
def test_revert_to_snapshot(self, version):
api_version = api_versions.APIVersion(version)
cs = fakes.FakeClient(api_version)
manager = volumes.VolumeManager(cs)
fake_snapshot = volume_snapshots.Snapshot(
manager, {'id': 12345, 'name': 'fake-snapshot'}, loaded=True)
fake_volume = volumes.Volume(manager,
{'id': 1234, 'name': 'sample-volume'},
loaded=True)
expected = {'revert': {'snapshot_id': 12345}}
if version == '3.40':
fake_volume.revert_to_snapshot(fake_snapshot)
cs.assert_called_anytime('POST', '/volumes/1234/action',
body=expected)
else:
self.assertRaises(exceptions.VersionNotFoundForAPIMethod,
fake_volume.revert_to_snapshot, fake_snapshot)
def test_create_volume(self):
vol = cs.volumes.create(1, group_id='1234', volume_type='5678')
expected = {'volume': {'status': 'creating',

View File

@ -1371,6 +1371,19 @@ def do_api_version(cs, args):
utils.print_list(response, columns)
@api_versions.wraps("3.40")
@utils.arg(
'snapshot',
metavar='<snapshot>',
help='Name or ID of the snapshot to restore. The snapshot must be the '
'most recent one known to cinder.')
def do_revert_to_snapshot(cs, args):
"""Revert a volume to the specified snapshot."""
snapshot = shell_utils.find_volume_snapshot(cs, args.snapshot)
volume = utils.find_volume(cs, snapshot.volume_id)
volume.revert_to_snapshot(snapshot)
@api_versions.wraps("3.3")
@utils.arg('--marker',
metavar='<marker>',

View File

@ -45,6 +45,10 @@ class Volume(volumes.Volume):
return self.manager.upload_to_image(self, force, image_name,
container_format, disk_format)
def revert_to_snapshot(self, snapshot):
"""Revert a volume to a snapshot."""
self.manager.revert_to_snapshot(self, snapshot)
class VolumeManager(volumes.VolumeManager):
resource_class = Volume
@ -109,6 +113,17 @@ class VolumeManager(volumes.VolumeManager):
return self._create('/volumes', body, 'volume')
@api_versions.wraps('3.40')
def revert_to_snapshot(self, volume, snapshot):
"""Revert a volume to a snapshot.
The snapshot must be the most recent one known to cinder.
:param volume: volume object.
:param snapshot: snapshot object.
"""
return self._action('revert', volume,
info={'snapshot_id': base.getid(snapshot.id)})
@api_versions.wraps("3.0")
def delete_metadata(self, volume, keys):
"""Delete specified keys from volumes metadata.
@ -131,6 +146,7 @@ class VolumeManager(volumes.VolumeManager):
:param volume: The :class:`Volume`.
:param keys: A list of keys to be removed.
"""
# pylint: disable=function-redefined
data = self._get("/volumes/%s/metadata" % base.getid(volume))
metadata = data._info.get("metadata", {})
if set(keys).issubset(metadata.keys()):
@ -160,6 +176,7 @@ class VolumeManager(volumes.VolumeManager):
"""Upload volume to image service as image.
:param volume: The :class:`Volume` to upload.
"""
# pylint: disable=function-redefined
return self._action('os-volume_upload_image',
volume,
{'force': force,

View File

@ -0,0 +1,3 @@
---
features:
- Added support for the revert-to-snapshot feature.