Support list with 'with_count' in client
Add 'with_count' parameter in list volume, snapshot and backup APIs. Change-Id: I2b7b41b3579c24703a7a67ab5dc6f960a3ccbdc2 Partial-Implements: bp add-amount-info-in-list-api
This commit is contained in:
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
# key is a deprecated version and value is an alternative version.
|
# key is a deprecated version and value is an alternative version.
|
||||||
DEPRECATED_VERSIONS = {"1": "2"}
|
DEPRECATED_VERSIONS = {"1": "2"}
|
||||||
DEPRECATED_VERSION = "2.0"
|
DEPRECATED_VERSION = "2.0"
|
||||||
MAX_VERSION = "3.44"
|
MAX_VERSION = "3.45"
|
||||||
MIN_VERSION = "3.0"
|
MIN_VERSION = "3.0"
|
||||||
|
|
||||||
_SUBSTITUTIONS = {}
|
_SUBSTITUTIONS = {}
|
||||||
|
@@ -105,6 +105,9 @@ class Manager(common_base.HookableMixin):
|
|||||||
if margin <= len(items_new):
|
if margin <= len(items_new):
|
||||||
# If the limit is reached, return the items.
|
# If the limit is reached, return the items.
|
||||||
items = items + items_new[:margin]
|
items = items + items_new[:margin]
|
||||||
|
if "count" in body:
|
||||||
|
return common_base.ListWithMeta(items, resp), body['count']
|
||||||
|
else:
|
||||||
return common_base.ListWithMeta(items, resp)
|
return common_base.ListWithMeta(items, resp)
|
||||||
else:
|
else:
|
||||||
items = items + items_new
|
items = items + items_new
|
||||||
@@ -128,6 +131,9 @@ class Manager(common_base.HookableMixin):
|
|||||||
# till there is no more items.
|
# till there is no more items.
|
||||||
items = self._list(next, response_key, obj_class, None,
|
items = self._list(next, response_key, obj_class, None,
|
||||||
limit, items)
|
limit, items)
|
||||||
|
if "count" in body:
|
||||||
|
return common_base.ListWithMeta(items, resp), body['count']
|
||||||
|
else:
|
||||||
return common_base.ListWithMeta(items, resp)
|
return common_base.ListWithMeta(items, resp)
|
||||||
|
|
||||||
def _build_list_url(self, resource_type, detailed=True, search_opts=None,
|
def _build_list_url(self, resource_type, detailed=True, search_opts=None,
|
||||||
|
@@ -389,9 +389,12 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
#
|
#
|
||||||
|
|
||||||
def get_snapshots_detail(self, **kw):
|
def get_snapshots_detail(self, **kw):
|
||||||
|
if kw.get('with_count', False):
|
||||||
return (200, {}, {'snapshots': [
|
return (200, {}, {'snapshots': [
|
||||||
_stub_snapshot(),
|
_stub_snapshot(),
|
||||||
]})
|
], 'count': 1})
|
||||||
|
return (200, {}, {'snapshots': [
|
||||||
|
_stub_snapshot()]})
|
||||||
|
|
||||||
def get_snapshots_1234(self, **kw):
|
def get_snapshots_1234(self, **kw):
|
||||||
return (200, {}, {'snapshot': _stub_snapshot(id='1234')})
|
return (200, {}, {'snapshot': _stub_snapshot(id='1234')})
|
||||||
@@ -464,6 +467,10 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
]})
|
]})
|
||||||
|
|
||||||
def get_volumes_detail(self, **kw):
|
def get_volumes_detail(self, **kw):
|
||||||
|
if kw.get('with_count', False):
|
||||||
|
return (200, {}, {"volumes": [
|
||||||
|
_stub_volume(id=kw.get('id', 1234))
|
||||||
|
], "count": 1})
|
||||||
return (200, {}, {"volumes": [
|
return (200, {}, {"volumes": [
|
||||||
_stub_volume(id=kw.get('id', 1234))
|
_stub_volume(id=kw.get('id', 1234))
|
||||||
]})
|
]})
|
||||||
@@ -885,6 +892,12 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
backup1 = '76a17945-3c6f-435c-975b-b5685db10b62'
|
backup1 = '76a17945-3c6f-435c-975b-b5685db10b62'
|
||||||
backup2 = 'd09534c6-08b8-4441-9e87-8976f3a8f699'
|
backup2 = 'd09534c6-08b8-4441-9e87-8976f3a8f699'
|
||||||
|
if kw.get('with_count', False):
|
||||||
|
return (200, {},
|
||||||
|
{'backups': [
|
||||||
|
_stub_backup_full(backup1, base_uri, tenant_id),
|
||||||
|
_stub_backup_full(backup2, base_uri, tenant_id)],
|
||||||
|
'count': 2})
|
||||||
return (200, {},
|
return (200, {},
|
||||||
{'backups': [
|
{'backups': [
|
||||||
_stub_backup_full(backup1, base_uri, tenant_id),
|
_stub_backup_full(backup1, base_uri, tenant_id),
|
||||||
|
@@ -231,6 +231,10 @@ class ShellTest(utils.TestCase):
|
|||||||
# NOTE(jdg): we default to detail currently
|
# NOTE(jdg): we default to detail currently
|
||||||
self.assert_called('GET', '/volumes/detail')
|
self.assert_called('GET', '/volumes/detail')
|
||||||
|
|
||||||
|
def test_list_with_with_count(self):
|
||||||
|
self.run_command('--os-volume-api-version 3.45 list --with-count')
|
||||||
|
self.assert_called('GET', '/volumes/detail?with_count=True')
|
||||||
|
|
||||||
def test_summary(self):
|
def test_summary(self):
|
||||||
self.run_command('--os-volume-api-version 3.12 summary')
|
self.run_command('--os-volume-api-version 3.12 summary')
|
||||||
self.assert_called('GET', '/volumes/summary')
|
self.assert_called('GET', '/volumes/summary')
|
||||||
@@ -430,6 +434,11 @@ class ShellTest(utils.TestCase):
|
|||||||
expected = {'backup': {'name': 'new_name'}}
|
expected = {'backup': {'name': 'new_name'}}
|
||||||
self.assert_called('PUT', '/backups/1234', body=expected)
|
self.assert_called('PUT', '/backups/1234', body=expected)
|
||||||
|
|
||||||
|
def test_backup_list_with_with_count(self):
|
||||||
|
self.run_command(
|
||||||
|
'--os-volume-api-version 3.45 backup-list --with-count')
|
||||||
|
self.assert_called('GET', '/backups/detail?with_count=True')
|
||||||
|
|
||||||
def test_backup_update_with_description(self):
|
def test_backup_update_with_description(self):
|
||||||
self.run_command('--os-volume-api-version 3.9 '
|
self.run_command('--os-volume-api-version 3.9 '
|
||||||
'backup-update 1234 --description=new-description')
|
'backup-update 1234 --description=new-description')
|
||||||
@@ -742,6 +751,11 @@ class ShellTest(utils.TestCase):
|
|||||||
expected = {'os-reset_status': expected}
|
expected = {'os-reset_status': expected}
|
||||||
self.assert_called('POST', '/volumes/1234/action', body=expected)
|
self.assert_called('POST', '/volumes/1234/action', body=expected)
|
||||||
|
|
||||||
|
def test_snapshot_list_with_with_count(self):
|
||||||
|
self.run_command(
|
||||||
|
'--os-volume-api-version 3.45 snapshot-list --with-count')
|
||||||
|
self.assert_called('GET', '/snapshots/detail?with_count=True')
|
||||||
|
|
||||||
def test_snapshot_list_with_metadata(self):
|
def test_snapshot_list_with_metadata(self):
|
||||||
self.run_command('--os-volume-api-version 3.22 '
|
self.run_command('--os-volume-api-version 3.22 '
|
||||||
'snapshot-list --metadata key1=val1')
|
'snapshot-list --metadata key1=val1')
|
||||||
|
@@ -107,10 +107,21 @@ def do_list_filters(cs, args):
|
|||||||
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
||||||
"to check enabled filters from server. Use 'key~=value' for "
|
"to check enabled filters from server. Use 'key~=value' for "
|
||||||
"inexact filtering if the key supports. Default=None.")
|
"inexact filtering if the key supports. Default=None.")
|
||||||
|
@utils.arg('--with-count',
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
const=True,
|
||||||
|
nargs='?',
|
||||||
|
start_version='3.45',
|
||||||
|
metavar='<True|False>',
|
||||||
|
help="Show total number of backup entities. This is useful when "
|
||||||
|
"pagination is applied in the request.")
|
||||||
def do_backup_list(cs, args):
|
def do_backup_list(cs, args):
|
||||||
"""Lists all backups."""
|
"""Lists all backups."""
|
||||||
# pylint: disable=function-redefined
|
# pylint: disable=function-redefined
|
||||||
|
|
||||||
|
show_count = True if hasattr(
|
||||||
|
args, 'with_count') and args.with_count else False
|
||||||
search_opts = {
|
search_opts = {
|
||||||
'all_tenants': args.all_tenants,
|
'all_tenants': args.all_tenants,
|
||||||
'name': args.name,
|
'name': args.name,
|
||||||
@@ -122,6 +133,14 @@ def do_backup_list(cs, args):
|
|||||||
if hasattr(args, 'filters') and args.filters is not None:
|
if hasattr(args, 'filters') and args.filters is not None:
|
||||||
search_opts.update(shell_utils.extract_filters(args.filters))
|
search_opts.update(shell_utils.extract_filters(args.filters))
|
||||||
|
|
||||||
|
total_count = 0
|
||||||
|
if show_count:
|
||||||
|
search_opts['with_count'] = args.with_count
|
||||||
|
backups, total_count = cs.backups.list(search_opts=search_opts,
|
||||||
|
marker=args.marker,
|
||||||
|
limit=args.limit,
|
||||||
|
sort=args.sort)
|
||||||
|
else:
|
||||||
backups = cs.backups.list(search_opts=search_opts,
|
backups = cs.backups.list(search_opts=search_opts,
|
||||||
marker=args.marker,
|
marker=args.marker,
|
||||||
limit=args.limit,
|
limit=args.limit,
|
||||||
@@ -134,6 +153,8 @@ def do_backup_list(cs, args):
|
|||||||
else:
|
else:
|
||||||
sortby_index = 0
|
sortby_index = 0
|
||||||
utils.print_list(backups, columns, sortby_index=sortby_index)
|
utils.print_list(backups, columns, sortby_index=sortby_index)
|
||||||
|
if show_count:
|
||||||
|
print("Backup in total: %s" % total_count)
|
||||||
|
|
||||||
|
|
||||||
@utils.arg('--detail',
|
@utils.arg('--detail',
|
||||||
@@ -282,13 +303,23 @@ RESET_STATE_RESOURCES = {'volume': utils.find_volume,
|
|||||||
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
||||||
"to check enabled filters from server. Use 'key~=value' "
|
"to check enabled filters from server. Use 'key~=value' "
|
||||||
"for inexact filtering if the key supports. Default=None.")
|
"for inexact filtering if the key supports. Default=None.")
|
||||||
|
@utils.arg('--with-count',
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
const=True,
|
||||||
|
nargs='?',
|
||||||
|
start_version='3.45',
|
||||||
|
metavar='<True|False>',
|
||||||
|
help="Show total number of volume entities. This is useful when "
|
||||||
|
"pagination is applied in the request.")
|
||||||
def do_list(cs, args):
|
def do_list(cs, args):
|
||||||
"""Lists all volumes."""
|
"""Lists all volumes."""
|
||||||
# pylint: disable=function-redefined
|
# pylint: disable=function-redefined
|
||||||
# NOTE(thingee): Backwards-compatibility with v1 args
|
# NOTE(thingee): Backwards-compatibility with v1 args
|
||||||
if args.display_name is not None:
|
if args.display_name is not None:
|
||||||
args.name = args.display_name
|
args.name = args.display_name
|
||||||
|
show_count = True if hasattr(
|
||||||
|
args, 'with_count') and args.with_count else False
|
||||||
all_tenants = 1 if args.tenant else \
|
all_tenants = 1 if args.tenant else \
|
||||||
int(os.environ.get("ALL_TENANTS", args.all_tenants))
|
int(os.environ.get("ALL_TENANTS", args.all_tenants))
|
||||||
search_opts = {
|
search_opts = {
|
||||||
@@ -323,6 +354,14 @@ def do_list(cs, args):
|
|||||||
'The --sort_key and --sort_dir arguments are deprecated and are '
|
'The --sort_key and --sort_dir arguments are deprecated and are '
|
||||||
'not supported with --sort.')
|
'not supported with --sort.')
|
||||||
|
|
||||||
|
total_count = 0
|
||||||
|
if show_count:
|
||||||
|
search_opts['with_count'] = args.with_count
|
||||||
|
volumes, total_count = cs.volumes.list(
|
||||||
|
search_opts=search_opts, marker=args.marker,
|
||||||
|
limit=args.limit, sort_key=args.sort_key,
|
||||||
|
sort_dir=args.sort_dir, sort=args.sort)
|
||||||
|
else:
|
||||||
volumes = cs.volumes.list(search_opts=search_opts, marker=args.marker,
|
volumes = cs.volumes.list(search_opts=search_opts, marker=args.marker,
|
||||||
limit=args.limit, sort_key=args.sort_key,
|
limit=args.limit, sort_key=args.sort_key,
|
||||||
sort_dir=args.sort_dir, sort=args.sort)
|
sort_dir=args.sort_dir, sort=args.sort)
|
||||||
@@ -353,6 +392,8 @@ def do_list(cs, args):
|
|||||||
sortby_index = 0
|
sortby_index = 0
|
||||||
utils.print_list(volumes, key_list, exclude_unavailable=True,
|
utils.print_list(volumes, key_list, exclude_unavailable=True,
|
||||||
sortby_index=sortby_index)
|
sortby_index=sortby_index)
|
||||||
|
if show_count:
|
||||||
|
print("Volume in total: %s" % total_count)
|
||||||
|
|
||||||
|
|
||||||
@utils.arg('entity', metavar='<entity>', nargs='+',
|
@utils.arg('entity', metavar='<entity>', nargs='+',
|
||||||
@@ -1813,9 +1854,20 @@ def do_message_delete(cs, args):
|
|||||||
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
help="Filter key and value pairs. Please use 'cinder list-filters' "
|
||||||
"to check enabled filters from server. Use 'key~=value' "
|
"to check enabled filters from server. Use 'key~=value' "
|
||||||
"for inexact filtering if the key supports. Default=None.")
|
"for inexact filtering if the key supports. Default=None.")
|
||||||
|
@utils.arg('--with-count',
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
const=True,
|
||||||
|
nargs='?',
|
||||||
|
start_version='3.45',
|
||||||
|
metavar='<True|False>',
|
||||||
|
help="Show total number of snapshot entities. This is useful when "
|
||||||
|
"pagination is applied in the request.")
|
||||||
def do_snapshot_list(cs, args):
|
def do_snapshot_list(cs, args):
|
||||||
"""Lists all snapshots."""
|
"""Lists all snapshots."""
|
||||||
# pylint: disable=function-redefined
|
# pylint: disable=function-redefined
|
||||||
|
show_count = True if hasattr(
|
||||||
|
args, 'with_count') and args.with_count else False
|
||||||
all_tenants = (1 if args.tenant else
|
all_tenants = (1 if args.tenant else
|
||||||
int(os.environ.get("ALL_TENANTS", args.all_tenants)))
|
int(os.environ.get("ALL_TENANTS", args.all_tenants)))
|
||||||
|
|
||||||
@@ -1842,10 +1894,20 @@ def do_snapshot_list(cs, args):
|
|||||||
if hasattr(args, 'filters') and args.filters is not None:
|
if hasattr(args, 'filters') and args.filters is not None:
|
||||||
search_opts.update(shell_utils.extract_filters(args.filters))
|
search_opts.update(shell_utils.extract_filters(args.filters))
|
||||||
|
|
||||||
|
total_count = 0
|
||||||
|
if show_count:
|
||||||
|
search_opts['with_count'] = args.with_count
|
||||||
|
snapshots, total_count = cs.volume_snapshots.list(
|
||||||
|
search_opts=search_opts,
|
||||||
|
marker=args.marker,
|
||||||
|
limit=args.limit,
|
||||||
|
sort=args.sort)
|
||||||
|
else:
|
||||||
snapshots = cs.volume_snapshots.list(search_opts=search_opts,
|
snapshots = cs.volume_snapshots.list(search_opts=search_opts,
|
||||||
marker=args.marker,
|
marker=args.marker,
|
||||||
limit=args.limit,
|
limit=args.limit,
|
||||||
sort=args.sort)
|
sort=args.sort)
|
||||||
|
|
||||||
shell_utils.translate_volume_snapshot_keys(snapshots)
|
shell_utils.translate_volume_snapshot_keys(snapshots)
|
||||||
sortby_index = None if args.sort else 0
|
sortby_index = None if args.sort else 0
|
||||||
if cs.api_version >= api_versions.APIVersion("3.41"):
|
if cs.api_version >= api_versions.APIVersion("3.41"):
|
||||||
@@ -1857,6 +1919,8 @@ def do_snapshot_list(cs, args):
|
|||||||
utils.print_list(snapshots,
|
utils.print_list(snapshots,
|
||||||
['ID', 'Volume ID', 'Status', 'Name', 'Size'],
|
['ID', 'Volume ID', 'Status', 'Name', 'Size'],
|
||||||
sortby_index=sortby_index)
|
sortby_index=sortby_index)
|
||||||
|
if show_count:
|
||||||
|
print("Snapshot in total: %s" % total_count)
|
||||||
|
|
||||||
|
|
||||||
@api_versions.wraps('3.27')
|
@api_versions.wraps('3.27')
|
||||||
|
3
releasenotes/notes/list-with-count-78gtf45r66bf8912.yaml
Normal file
3
releasenotes/notes/list-with-count-78gtf45r66bf8912.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added ``with_count`` option in volume, snapshot and backup's list commands since 3.45.
|
Reference in New Issue
Block a user