Metadata based snapshop filtering
The snpapshot-list API for cinder gives a list of snapshots based on certain criteria to the user. From microversion 3.22 onwards the snapshot-list API has been enhanced to support snapshot list filtering based on metadata of snapshots. The metadata is stored as key-value pair for every snapshot. With this commit cinder will be queried based on metadata key and value specified in the API snaphot-list. All the snapshots which match the key, value provided by the user along with any other filter criteria will be returned. Added the test cases for the CLI and web requests. DocImpact: "Filters results by a metadata key and value pair. Default=None." on cinder snapshot-list APIImpact Closes-bug: #1569554 Change-Id: Idec0d0d02e7956843f202508e32c023c3cafbb0f
This commit is contained in:
@@ -26,6 +26,8 @@ from cinderclient.tests.unit import utils
|
||||
from cinderclient.tests.unit.v3 import fakes
|
||||
from cinderclient.tests.unit.fixture_data import keystone_client
|
||||
|
||||
from six.moves.urllib import parse
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@mock.patch.object(client, 'Client', fakes.FakeClient)
|
||||
@@ -344,6 +346,13 @@ class ShellTest(utils.TestCase):
|
||||
self.run_command('--os-volume-api-version 3.3 message-list')
|
||||
self.assert_called('GET', '/messages')
|
||||
|
||||
def test_snapshot_list_with_metadata(self):
|
||||
self.run_command('--os-volume-api-version 3.22 '
|
||||
'snapshot-list --metadata key1=val1')
|
||||
expected = ("/snapshots/detail?metadata=%s"
|
||||
% parse.quote_plus("{'key1': 'val1'}"))
|
||||
self.assert_called('GET', expected)
|
||||
|
||||
@ddt.data(('resource_type',), ('event_id',), ('resource_uuid',),
|
||||
('level', 'message_level'), ('request_id',))
|
||||
def test_list_messages_with_filters(self, filter):
|
||||
|
@@ -20,6 +20,8 @@ from cinderclient.tests.unit import utils
|
||||
from cinderclient.tests.unit.v3 import fakes
|
||||
from cinderclient.v3 import volumes
|
||||
|
||||
from six.moves.urllib import parse
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
@@ -84,3 +86,10 @@ class VolumesTest(utils.TestCase):
|
||||
cs = fakes.FakeClient(api_versions.APIVersion('3.8'))
|
||||
cs.volume_snapshots.list_manageable('host1', detailed=True)
|
||||
cs.assert_called('GET', '/manageable_snapshots/detail?host=host1')
|
||||
|
||||
def test_snapshot_list_with_metadata(self):
|
||||
cs = fakes.FakeClient(api_versions.APIVersion('3.22'))
|
||||
cs.volume_snapshots.list(search_opts={'metadata': {'key1': 'val1'}})
|
||||
expected = ("/snapshots/detail?metadata=%s"
|
||||
% parse.quote_plus("{'key1': 'val1'}"))
|
||||
cs.assert_called('GET', expected)
|
||||
|
@@ -1210,3 +1210,94 @@ def do_message_delete(cs, args):
|
||||
if failure_count == len(args.message):
|
||||
raise exceptions.CommandError("Unable to delete any of the specified "
|
||||
"messages.")
|
||||
|
||||
|
||||
@utils.arg('--all-tenants',
|
||||
dest='all_tenants',
|
||||
metavar='<0|1>',
|
||||
nargs='?',
|
||||
type=int,
|
||||
const=1,
|
||||
default=0,
|
||||
help='Shows details for all tenants. Admin only.')
|
||||
@utils.arg('--all_tenants',
|
||||
nargs='?',
|
||||
type=int,
|
||||
const=1,
|
||||
help=argparse.SUPPRESS)
|
||||
@utils.arg('--name',
|
||||
metavar='<name>',
|
||||
default=None,
|
||||
help='Filters results by a name. Default=None.')
|
||||
@utils.arg('--display-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@utils.arg('--display_name',
|
||||
help=argparse.SUPPRESS)
|
||||
@utils.arg('--status',
|
||||
metavar='<status>',
|
||||
default=None,
|
||||
help='Filters results by a status. Default=None.')
|
||||
@utils.arg('--volume-id',
|
||||
metavar='<volume-id>',
|
||||
default=None,
|
||||
help='Filters results by a volume ID. Default=None.')
|
||||
@utils.arg('--volume_id',
|
||||
help=argparse.SUPPRESS)
|
||||
@utils.arg('--marker',
|
||||
metavar='<marker>',
|
||||
default=None,
|
||||
help='Begin returning snapshots that appear later in the snapshot '
|
||||
'list than that represented by this id. '
|
||||
'Default=None.')
|
||||
@utils.arg('--limit',
|
||||
metavar='<limit>',
|
||||
default=None,
|
||||
help='Maximum number of snapshots to return. Default=None.')
|
||||
@utils.arg('--sort',
|
||||
metavar='<key>[:<direction>]',
|
||||
default=None,
|
||||
help=(('Comma-separated list of sort keys and directions in the '
|
||||
'form of <key>[:<asc|desc>]. '
|
||||
'Valid keys: %s. '
|
||||
'Default=None.') % ', '.join(base.SORT_KEY_VALUES)))
|
||||
@utils.arg('--tenant',
|
||||
type=str,
|
||||
dest='tenant',
|
||||
nargs='?',
|
||||
metavar='<tenant>',
|
||||
help='Display information from single tenant (Admin only).')
|
||||
@utils.arg('--metadata',
|
||||
nargs='*',
|
||||
metavar='<key=value>',
|
||||
default=None,
|
||||
start_version='3.22',
|
||||
help='Filters results by a metadata key and value pair. Require '
|
||||
'volume api version >=3.22. Default=None.')
|
||||
@utils.service_type('volumev3')
|
||||
def do_snapshot_list(cs, args):
|
||||
"""Lists all snapshots."""
|
||||
all_tenants = (1 if args.tenant else
|
||||
int(os.environ.get("ALL_TENANTS", args.all_tenants)))
|
||||
|
||||
if args.display_name is not None:
|
||||
args.name = args.display_name
|
||||
|
||||
search_opts = {
|
||||
'all_tenants': all_tenants,
|
||||
'name': args.name,
|
||||
'status': args.status,
|
||||
'volume_id': args.volume_id,
|
||||
'project_id': args.tenant,
|
||||
'metadata': shell_utils.extract_metadata(args)
|
||||
if args.metadata else None,
|
||||
}
|
||||
|
||||
snapshots = cs.volume_snapshots.list(search_opts=search_opts,
|
||||
marker=args.marker,
|
||||
limit=args.limit,
|
||||
sort=args.sort)
|
||||
shell_utils.translate_volume_snapshot_keys(snapshots)
|
||||
sortby_index = None if args.sort else 0
|
||||
utils.print_list(snapshots,
|
||||
['ID', 'Volume ID', 'Status', 'Name', 'Size'],
|
||||
sortby_index=sortby_index)
|
Reference in New Issue
Block a user