Support pagination for volume list
Since v2 api supports pagination, we should add this support in cinderclient too. Change-Id: I9d4cb9e192523c14cf7df043deabe156dbb8e216 Closes-bug: 1325773
This commit is contained in:
@@ -102,6 +102,24 @@ class ShellTest(utils.TestCase):
|
|||||||
self.run_command('list --all-tenants=1')
|
self.run_command('list --all-tenants=1')
|
||||||
self.assert_called('GET', '/volumes/detail?all_tenants=1')
|
self.assert_called('GET', '/volumes/detail?all_tenants=1')
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
def test_list_marker(self):
|
||||||
|
self.register_keystone_auth_fixture()
|
||||||
|
self.run_command('list --marker=1234')
|
||||||
|
self.assert_called('GET', '/volumes/detail?marker=1234')
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
def test_list_limit(self):
|
||||||
|
self.register_keystone_auth_fixture()
|
||||||
|
self.run_command('list --limit=10')
|
||||||
|
self.assert_called('GET', '/volumes/detail?limit=10')
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
def test_list_sort(self):
|
||||||
|
self.register_keystone_auth_fixture()
|
||||||
|
self.run_command('list --sort_key=name --sort_dir=asc')
|
||||||
|
self.assert_called('GET', '/volumes/detail?sort_dir=asc&sort_key=name')
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_list_availability_zone(self):
|
def test_list_availability_zone(self):
|
||||||
self.register_keystone_auth_fixture()
|
self.register_keystone_auth_fixture()
|
||||||
|
@@ -23,6 +23,22 @@ cs = fakes.FakeClient()
|
|||||||
|
|
||||||
class VolumesTest(utils.TestCase):
|
class VolumesTest(utils.TestCase):
|
||||||
|
|
||||||
|
def test_list_volumes_with_marker_limit(self):
|
||||||
|
cs.volumes.list(marker=1234, limit=2)
|
||||||
|
cs.assert_called('GET', '/volumes/detail?limit=2&marker=1234')
|
||||||
|
|
||||||
|
def test_list_volumes_with_sort_key_dir(self):
|
||||||
|
cs.volumes.list(sort_key='id', sort_dir='asc')
|
||||||
|
cs.assert_called('GET', '/volumes/detail?sort_dir=asc&sort_key=id')
|
||||||
|
|
||||||
|
def test_list_volumes_with_invalid_sort_key(self):
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
cs.volumes.list, sort_key='invalid', sort_dir='asc')
|
||||||
|
|
||||||
|
def test_list_volumes_with_invalid_sort_dir(self):
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
cs.volumes.list, sort_key='id', sort_dir='invalid')
|
||||||
|
|
||||||
def test_delete_volume(self):
|
def test_delete_volume(self):
|
||||||
v = cs.volumes.list()[0]
|
v = cs.volumes.list()[0]
|
||||||
v.delete()
|
v.delete()
|
||||||
|
@@ -156,6 +156,27 @@ def _extract_metadata(args):
|
|||||||
help='Filters results by a metadata key and value pair. '
|
help='Filters results by a metadata key and value pair. '
|
||||||
'OPTIONAL: Default=None.',
|
'OPTIONAL: Default=None.',
|
||||||
default=None)
|
default=None)
|
||||||
|
@utils.arg('--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
default=None,
|
||||||
|
help='Begin returning volumes that appear later in the volume '
|
||||||
|
'list than that represented by this volume id. '
|
||||||
|
'OPTIONAL: Default=None.')
|
||||||
|
@utils.arg('--limit',
|
||||||
|
metavar='<limit>',
|
||||||
|
default=None,
|
||||||
|
help='Maximum number of volumes to return. OPTIONAL: Default=None.')
|
||||||
|
@utils.arg('--sort_key',
|
||||||
|
metavar='<sort_key>',
|
||||||
|
default=None,
|
||||||
|
help='Key to be sorted, should be (`id`, `status`, `size`, '
|
||||||
|
'`availability_zone`, `name`, `bootable`, `created_at`). '
|
||||||
|
'OPTIONAL: Default=None.')
|
||||||
|
@utils.arg('--sort_dir',
|
||||||
|
metavar='<sort_dir>',
|
||||||
|
default=None,
|
||||||
|
help='Sort direction, should be `desc` or `asc`. '
|
||||||
|
'OPTIONAL: Default=None.')
|
||||||
@utils.service_type('volumev2')
|
@utils.service_type('volumev2')
|
||||||
def do_list(cs, args):
|
def do_list(cs, args):
|
||||||
"""Lists all volumes."""
|
"""Lists all volumes."""
|
||||||
@@ -170,7 +191,9 @@ def do_list(cs, args):
|
|||||||
'status': args.status,
|
'status': args.status,
|
||||||
'metadata': _extract_metadata(args) if args.metadata else None,
|
'metadata': _extract_metadata(args) if args.metadata else None,
|
||||||
}
|
}
|
||||||
volumes = cs.volumes.list(search_opts=search_opts)
|
volumes = cs.volumes.list(search_opts=search_opts, marker=args.marker,
|
||||||
|
limit=args.limit, sort_key=args.sort_key,
|
||||||
|
sort_dir=args.sort_dir)
|
||||||
_translate_volume_keys(volumes)
|
_translate_volume_keys(volumes)
|
||||||
|
|
||||||
# Create a list of servers to which the volume is attached
|
# Create a list of servers to which the volume is attached
|
||||||
|
@@ -24,6 +24,11 @@ except ImportError:
|
|||||||
from cinderclient import base
|
from cinderclient import base
|
||||||
|
|
||||||
|
|
||||||
|
SORT_DIR_VALUES = ('asc', 'desc')
|
||||||
|
SORT_KEY_VALUES = ('id', 'status', 'size', 'availability_zone', 'name',
|
||||||
|
'bootable', 'created_at')
|
||||||
|
|
||||||
|
|
||||||
class Volume(base.Resource):
|
class Volume(base.Resource):
|
||||||
"""A volume is an extra block level storage to the OpenStack instances."""
|
"""A volume is an extra block level storage to the OpenStack instances."""
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -208,9 +213,17 @@ class VolumeManager(base.ManagerWithFind):
|
|||||||
"""
|
"""
|
||||||
return self._get("/volumes/%s" % volume_id, "volume")
|
return self._get("/volumes/%s" % volume_id, "volume")
|
||||||
|
|
||||||
def list(self, detailed=True, search_opts=None):
|
def list(self, detailed=True, search_opts=None, marker=None, limit=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
"""Lists all volumes.
|
"""Lists all volumes.
|
||||||
|
|
||||||
|
:param detailed: Whether to return detailed volume info.
|
||||||
|
:param search_opts: Search options to filter out volumes.
|
||||||
|
:param marker: Begin returning volumes that appear later in the volume
|
||||||
|
list than that represented by this volume id.
|
||||||
|
:param limit: Maximum number of volumes to return.
|
||||||
|
:param sort_key: Key to be sorted.
|
||||||
|
:param sort_dir: Sort direction, should be 'desc' or 'asc'.
|
||||||
:rtype: list of :class:`Volume`
|
:rtype: list of :class:`Volume`
|
||||||
"""
|
"""
|
||||||
if search_opts is None:
|
if search_opts is None:
|
||||||
@@ -222,7 +235,33 @@ class VolumeManager(base.ManagerWithFind):
|
|||||||
if val:
|
if val:
|
||||||
qparams[opt] = val
|
qparams[opt] = val
|
||||||
|
|
||||||
query_string = "?%s" % urlencode(qparams) if qparams else ""
|
if marker:
|
||||||
|
qparams['marker'] = marker
|
||||||
|
|
||||||
|
if limit:
|
||||||
|
qparams['limit'] = limit
|
||||||
|
|
||||||
|
if sort_key is not None:
|
||||||
|
if sort_key in SORT_KEY_VALUES:
|
||||||
|
qparams['sort_key'] = sort_key
|
||||||
|
else:
|
||||||
|
raise ValueError('sort_key must be one of the following: %s.'
|
||||||
|
% ', '.join(SORT_KEY_VALUES))
|
||||||
|
|
||||||
|
if sort_dir is not None:
|
||||||
|
if sort_dir in SORT_DIR_VALUES:
|
||||||
|
qparams['sort_dir'] = sort_dir
|
||||||
|
else:
|
||||||
|
raise ValueError('sort_dir must be one of the following: %s.'
|
||||||
|
% ', '.join(SORT_DIR_VALUES))
|
||||||
|
|
||||||
|
# Transform the dict to a sequence of two-element tuples in fixed
|
||||||
|
# order, then the encoded string will be consistent in Python 2&3.
|
||||||
|
if qparams:
|
||||||
|
new_qparams = sorted(qparams.items(), key=lambda x: x[0])
|
||||||
|
query_string = "?%s" % urlencode(new_qparams)
|
||||||
|
else:
|
||||||
|
query_string = ""
|
||||||
|
|
||||||
detail = ""
|
detail = ""
|
||||||
if detailed:
|
if detailed:
|
||||||
|
Reference in New Issue
Block a user