cinder list now supports filter by tenant

Admin can now filter volumes on the basis of tenant.
Also updated help argument, to be consistent over the
v1 and v2 shell module.

Closes-Bug: #1341411
Change-Id: I647f0c9331ee4cd27acbfada6cdb9a56f80701b4
This commit is contained in:
yatin karel
2015-04-12 16:53:35 +05:30
parent de36755657
commit fa8c7e3d84
5 changed files with 186 additions and 145 deletions

View File

@@ -112,6 +112,16 @@ 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_filter_tenant_with_all_tenants(self):
self.run_command('list --tenant=123 --all-tenants 1')
self.assert_called('GET',
'/volumes/detail?all_tenants=1&project_id=123')
def test_list_filter_tenant_without_all_tenants(self):
self.run_command('list --tenant=123')
self.assert_called('GET',
'/volumes/detail?all_tenants=1&project_id=123')
def test_metadata_args_with_limiter(self): def test_metadata_args_with_limiter(self):
self.run_command('create --metadata key1="--test1" 1') self.run_command('create --metadata key1="--test1" 1')
expected = {'volume': {'snapshot_id': None, expected = {'volume': {'snapshot_id': None,

View File

@@ -85,6 +85,16 @@ 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_filter_tenant_with_all_tenants(self):
self.run_command('list --all-tenants=1 --tenant 123')
self.assert_called('GET',
'/volumes/detail?all_tenants=1&project_id=123')
def test_list_filter_tenant_without_all_tenants(self):
self.run_command('list --tenant 123')
self.assert_called('GET',
'/volumes/detail?all_tenants=1&project_id=123')
def test_metadata_args_with_limiter(self): def test_metadata_args_with_limiter(self):
self.run_command('create --metadata key1="--test1" 1') self.run_command('create --metadata key1="--test1" 1')
self.assert_called('GET', '/volumes/1234') self.assert_called('GET', '/volumes/1234')

View File

@@ -160,15 +160,24 @@ def _extract_metadata(args):
type=str, type=str,
nargs='*', nargs='*',
metavar='<key=value>', metavar='<key=value>',
default=None,
help='Filters list by metadata key and value pair. ' help='Filters list by metadata key and value pair. '
'Default=None.', 'Default=None.')
default=None) @utils.arg(
'--tenant',
type=str,
dest='tenant',
nargs='?',
metavar='<tenant>',
help='Display information from single tenant (Admin only).')
@utils.service_type('volume') @utils.service_type('volume')
def do_list(cs, args): def do_list(cs, args):
"""Lists all volumes.""" """Lists all volumes."""
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) all_tenants = 1 if args.tenant else \
int(os.environ.get("ALL_TENANTS", args.all_tenants))
search_opts = { search_opts = {
'all_tenants': all_tenants, 'all_tenants': all_tenants,
'project_id': args.tenant,
'display_name': args.display_name, 'display_name': args.display_name,
'status': args.status, 'status': args.status,
'metadata': _extract_metadata(args) if args.metadata else None, 'metadata': _extract_metadata(args) if args.metadata else None,
@@ -206,7 +215,7 @@ def do_show(cs, args):
metavar='<snapshot-id>', metavar='<snapshot-id>',
default=None, default=None,
help='Creates volume from snapshot ID. ' help='Creates volume from snapshot ID. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--snapshot_id', '--snapshot_id',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -215,7 +224,7 @@ def do_show(cs, args):
metavar='<source-volid>', metavar='<source-volid>',
default=None, default=None,
help='Creates volume from volume ID. ' help='Creates volume from volume ID. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--source_volid', '--source_volid',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -224,7 +233,7 @@ def do_show(cs, args):
metavar='<image-id>', metavar='<image-id>',
default=None, default=None,
help='Creates volume from image ID. ' help='Creates volume from image ID. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--image_id', '--image_id',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -233,7 +242,7 @@ def do_show(cs, args):
metavar='<display-name>', metavar='<display-name>',
default=None, default=None,
help='Volume name. ' help='Volume name. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--display_name', '--display_name',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -242,7 +251,7 @@ def do_show(cs, args):
metavar='<display-description>', metavar='<display-description>',
default=None, default=None,
help='Volume description. ' help='Volume description. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--display_description', '--display_description',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -251,7 +260,7 @@ def do_show(cs, args):
metavar='<volume-type>', metavar='<volume-type>',
default=None, default=None,
help='Volume type. ' help='Volume type. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--volume_type', '--volume_type',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -260,7 +269,7 @@ def do_show(cs, args):
metavar='<availability-zone>', metavar='<availability-zone>',
default=None, default=None,
help='Availability zone for volume. ' help='Availability zone for volume. '
'Default=None.') 'Default=None.')
@utils.arg( @utils.arg(
'--availability_zone', '--availability_zone',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@@ -268,9 +277,9 @@ def do_show(cs, args):
type=str, type=str,
nargs='*', nargs='*',
metavar='<key=value>', metavar='<key=value>',
default=None,
help='Metadata key and value pairs. ' help='Metadata key and value pairs. '
'Default=None.', 'Default=None.')
default=None)
@utils.service_type('volume') @utils.service_type('volume')
def do_create(cs, args): def do_create(cs, args):
"""Creates a volume.""" """Creates a volume."""
@@ -293,7 +302,7 @@ def do_create(cs, args):
@utils.arg('volume', metavar='<volume>', nargs='+', @utils.arg('volume', metavar='<volume>', nargs='+',
help='Name or ID of volume to delete. ' help='Name or ID of volume to delete. '
'Separate multiple volumes with a space.') 'Separate multiple volumes with a space.')
@utils.service_type('volume') @utils.service_type('volume')
def do_delete(cs, args): def do_delete(cs, args):
"""Removes one or more volumes.""" """Removes one or more volumes."""
@@ -311,7 +320,7 @@ def do_delete(cs, args):
@utils.arg('volume', metavar='<volume>', nargs='+', @utils.arg('volume', metavar='<volume>', nargs='+',
help='Name or ID of volume to delete. ' help='Name or ID of volume to delete. '
'Separate multiple volumes with a space.') 'Separate multiple volumes with a space.')
@utils.service_type('volume') @utils.service_type('volume')
def do_force_delete(cs, args): def do_force_delete(cs, args):
"""Attempts force-delete of volume, regardless of state.""" """Attempts force-delete of volume, regardless of state."""
@@ -329,7 +338,7 @@ def do_force_delete(cs, args):
@utils.arg('volume', metavar='<volume>', nargs='+', @utils.arg('volume', metavar='<volume>', nargs='+',
help='Name or ID of volume to modify. ' help='Name or ID of volume to modify. '
'Separate multiple volumes with a space.') 'Separate multiple volumes with a space.')
@utils.arg('--state', metavar='<state>', default='available', @utils.arg('--state', metavar='<state>', default='available',
help=('The state to assign to the volume. Valid values are ' help=('The state to assign to the volume. Valid values are '
'"available," "error," "creating," "deleting," "in-use," ' '"available," "error," "creating," "deleting," "in-use," '
@@ -360,8 +369,7 @@ def do_reset_state(cs, args):
@utils.arg('display_name', nargs='?', metavar='<display-name>', @utils.arg('display_name', nargs='?', metavar='<display-name>',
help='New display name for volume.') help='New display name for volume.')
@utils.arg('--display-description', metavar='<display-description>', @utils.arg('--display-description', metavar='<display-description>',
help='Volume description. Default=None.', default=None, help='Volume description. Default=None.')
default=None)
@utils.service_type('volume') @utils.service_type('volume')
def do_rename(cs, args): def do_rename(cs, args):
"""Renames a volume.""" """Renames a volume."""
@@ -384,14 +392,14 @@ def do_rename(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help='The metadata key and pair to set or unset. ' help='The metadata key and pair to set or unset. '
'For unset, specify only the key. ' 'For unset, specify only the key. '
'Default=[].') 'Default=[].')
@utils.service_type('volume') @utils.service_type('volume')
def do_metadata(cs, args): def do_metadata(cs, args):
"""Sets or deletes volume metadata.""" """Sets or deletes volume metadata."""
@@ -467,13 +475,13 @@ def do_snapshot_show(cs, args):
help='Name or ID of volume to snapshot.') help='Name or ID of volume to snapshot.')
@utils.arg('--force', @utils.arg('--force',
metavar='<True|False>', metavar='<True|False>',
default=False,
help='Allows or disallows snapshot of ' help='Allows or disallows snapshot of '
'a volume when the volume is attached to an instance. ' 'a volume when the volume is attached to an instance. '
'If set to True, ignores the current status of the ' 'If set to True, ignores the current status of the '
'volume when attempting to snapshot it rather ' 'volume when attempting to snapshot it rather '
'than forcing it to be available. ' 'than forcing it to be available. '
'Default=False.', 'Default=False.')
default=False)
@utils.arg( @utils.arg(
'--display-name', '--display-name',
metavar='<display-name>', metavar='<display-name>',
@@ -524,8 +532,7 @@ def do_snapshot_delete(cs, args):
@utils.arg('display_name', nargs='?', metavar='<display-name>', @utils.arg('display_name', nargs='?', metavar='<display-name>',
help='New display name for snapshot.') help='New display name for snapshot.')
@utils.arg('--display-description', metavar='<display-description>', @utils.arg('--display-description', metavar='<display-description>',
help='Snapshot description. Default=None.', default=None, help='Snapshot description. Default=None.')
default=None)
@utils.service_type('volume') @utils.service_type('volume')
def do_snapshot_rename(cs, args): def do_snapshot_rename(cs, args):
"""Renames a snapshot.""" """Renames a snapshot."""
@@ -594,7 +601,7 @@ def do_extra_specs_list(cs, args):
@utils.arg('name', @utils.arg('name',
metavar='<name>', metavar='<name>',
help="Name for the volume type.") help='Name for the volume type.')
@utils.service_type('volume') @utils.service_type('volume')
def do_type_create(cs, args): def do_type_create(cs, args):
"""Creates a volume type.""" """Creates a volume type."""
@@ -604,7 +611,7 @@ def do_type_create(cs, args):
@utils.arg('id', @utils.arg('id',
metavar='<id>', metavar='<id>',
help="ID of volume type to delete.") help='ID of volume type to delete.')
@utils.service_type('volume') @utils.service_type('volume')
def do_type_delete(cs, args): def do_type_delete(cs, args):
"""Deletes a specified volume type.""" """Deletes a specified volume type."""
@@ -614,17 +621,17 @@ def do_type_delete(cs, args):
@utils.arg('vtype', @utils.arg('vtype',
metavar='<vtype>', metavar='<vtype>',
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='*', nargs='*',
default=None, default=None,
help='The extra specs key and value pair to set or unset. ' help='The extra specs key and value pair to set or unset. '
'For unset, specify only the key. Default=None.') 'For unset, specify only the key. Default=None.')
@utils.service_type('volume') @utils.service_type('volume')
def do_type_key(cs, args): def do_type_key(cs, args):
"""Sets or unsets extra_spec for a volume type.""" """Sets or unsets extra_spec for a volume type."""
@@ -829,20 +836,20 @@ def _find_volume_type(cs, vtype):
help='Name or ID of volume to upload to an image.') help='Name or ID of volume to upload to an image.')
@utils.arg('--force', @utils.arg('--force',
metavar='<True|False>', metavar='<True|False>',
default=False,
help='Enables or disables upload of ' help='Enables or disables upload of '
'a volume that is attached to an instance. ' 'a volume that is attached to an instance. '
'Default=False.', 'Default=False.')
default=False)
@utils.arg('--container-format', @utils.arg('--container-format',
metavar='<container-format>', metavar='<container-format>',
default='bare',
help='Container format type. ' help='Container format type. '
'Default is bare.', 'Default is bare.')
default='bare')
@utils.arg('--disk-format', @utils.arg('--disk-format',
metavar='<disk-format>', metavar='<disk-format>',
default='raw',
help='Disk format type. ' help='Disk format type. '
'Default is raw.', 'Default is raw.')
default='raw')
@utils.arg('image_name', @utils.arg('image_name',
metavar='<image-name>', metavar='<image-name>',
help='The new image name.') help='The new image name.')
@@ -859,14 +866,14 @@ def do_upload_to_image(cs, args):
@utils.arg('volume', metavar='<volume>', @utils.arg('volume', metavar='<volume>',
help='Name or ID of volume to back up.') help='Name or ID of volume to back up.')
@utils.arg('--container', metavar='<container>', @utils.arg('--container', metavar='<container>',
help='Backup container name. Default=None.', default=None,
default=None) help='Backup container name. Default=None.')
@utils.arg('--display-name', metavar='<display-name>', @utils.arg('--display-name', metavar='<display-name>',
help='Backup name. Default=None.', default=None,
default=None) help='Backup name. Default=None.')
@utils.arg('--display-description', metavar='<display-description>', @utils.arg('--display-description', metavar='<display-description>',
help='Backup description. Default=None.', default=None,
default=None) help='Backup description. Default=None.')
@utils.service_type('volume') @utils.service_type('volume')
def do_backup_create(cs, args): def do_backup_create(cs, args):
"""Creates a volume backup.""" """Creates a volume backup."""
@@ -920,9 +927,9 @@ def do_backup_delete(cs, args):
@utils.arg('backup', metavar='<backup>', @utils.arg('backup', metavar='<backup>',
help='ID of backup to restore.') help='ID of backup to restore.')
@utils.arg('--volume-id', metavar='<volume>', @utils.arg('--volume-id', metavar='<volume>',
default=None,
help='ID or name of backup volume to ' help='ID or name of backup volume to '
'which to restore. Default=None.', 'which to restore. Default=None.')
default=None)
@utils.service_type('volume') @utils.service_type('volume')
def do_backup_restore(cs, args): def do_backup_restore(cs, args):
"""Restores a backup.""" """Restores a backup."""
@@ -936,8 +943,8 @@ def do_backup_restore(cs, args):
@utils.arg('volume', metavar='<volume>', @utils.arg('volume', metavar='<volume>',
help='Name or ID of volume to transfer.') help='Name or ID of volume to transfer.')
@utils.arg('--display-name', metavar='<display-name>', @utils.arg('--display-name', metavar='<display-name>',
help='Transfer name. Default=None.', default=None,
default=None) help='Transfer name. Default=None.')
@utils.service_type('volume') @utils.service_type('volume')
def do_transfer_create(cs, args): def do_transfer_create(cs, args):
"""Creates a volume transfer.""" """Creates a volume transfer."""
@@ -1159,7 +1166,7 @@ def do_encryption_type_list(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.service_type('volume') @utils.service_type('volume')
def do_encryption_type_show(cs, args): def do_encryption_type_show(cs, args):
"""Shows encryption type details for volume type. Admin only.""" """Shows encryption type details for volume type. Admin only."""
@@ -1177,26 +1184,26 @@ def do_encryption_type_show(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.arg('provider', @utils.arg('provider',
metavar='<provider>', metavar='<provider>',
type=str, type=str,
help='The class that provides encryption support. ' help='The class that provides encryption support. '
'For example, a volume driver class path.') 'For example, a volume driver class path.')
@utils.arg('--cipher', @utils.arg('--cipher',
metavar='<cipher>', metavar='<cipher>',
type=str, type=str,
required=False, required=False,
default=None, default=None,
help='The encryption algorithm and mode. ' help='The encryption algorithm and mode. '
'For example, aes-xts-plain64. Default=None.') 'For example, aes-xts-plain64. Default=None.')
@utils.arg('--key_size', @utils.arg('--key_size',
metavar='<key_size>', metavar='<key_size>',
type=int, type=int,
required=False, required=False,
default=None, default=None,
help='Size of encryption key, in bits. ' help='Size of encryption key, in bits. '
'For example, 128 or 256. Default=None.') 'For example, 128 or 256. Default=None.')
@utils.arg('--control_location', @utils.arg('--control_location',
metavar='<control_location>', metavar='<control_location>',
choices=['front-end', 'back-end'], choices=['front-end', 'back-end'],
@@ -1204,9 +1211,9 @@ def do_encryption_type_show(cs, args):
required=False, required=False,
default='front-end', default='front-end',
help='Notional service where encryption is performed. ' help='Notional service where encryption is performed. '
'Valid values are "front-end" or "back-end." ' 'Valid values are "front-end" or "back-end." '
'For example, front-end=Nova. ' 'For example, front-end=Nova. '
'Default is "front-end."') 'Default is "front-end."')
@utils.service_type('volume') @utils.service_type('volume')
def do_encryption_type_create(cs, args): def do_encryption_type_create(cs, args):
"""Creates encryption type for a volume type. Admin only.""" """Creates encryption type for a volume type. Admin only."""
@@ -1225,7 +1232,7 @@ def do_encryption_type_create(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.service_type('volume') @utils.service_type('volume')
def do_encryption_type_delete(cs, args): def do_encryption_type_delete(cs, args):
"""Deletes encryption type for a volume type. Admin only.""" """Deletes encryption type for a volume type. Admin only."""
@@ -1237,10 +1244,10 @@ def do_encryption_type_delete(cs, args):
@utils.arg('host', metavar='<host>', help='Destination host.') @utils.arg('host', metavar='<host>', help='Destination host.')
@utils.arg('--force-host-copy', metavar='<True|False>', @utils.arg('--force-host-copy', metavar='<True|False>',
choices=['True', 'False'], required=False, choices=['True', 'False'], required=False,
default=False,
help='Enables or disables generic host-based ' help='Enables or disables generic host-based '
'force-migration, which bypasses driver ' 'force-migration, which bypasses driver '
'optimizations. Default=False.', 'optimizations. Default=False.')
default=False)
@utils.service_type('volume') @utils.service_type('volume')
def do_migrate(cs, args): def do_migrate(cs, args):
"""Migrates volume to a new host.""" """Migrates volume to a new host."""
@@ -1267,7 +1274,7 @@ def _print_associations_list(associations):
@utils.arg('name', @utils.arg('name',
metavar='<name>', metavar='<name>',
help="Name of new QoS specifications.") help='Name of new QoS specifications.')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
@@ -1347,12 +1354,12 @@ def do_qos_disassociate_all(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', metavar='key=value', @utils.arg('metadata', metavar='key=value',
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair to set or unset. ' help='Metadata key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
def do_qos_key(cs, args): def do_qos_key(cs, args):
"""Sets or unsets specifications for a qos spec.""" """Sets or unsets specifications for a qos spec."""
keypair = _extract_metadata(args) keypair = _extract_metadata(args)
@@ -1378,13 +1385,13 @@ def do_qos_get_association(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help='The metadata key and value pair to set or unset. ' help='The metadata key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
@utils.service_type('volume') @utils.service_type('volume')
def do_snapshot_metadata(cs, args): def do_snapshot_metadata(cs, args):
"""Sets or deletes snapshot metadata.""" """Sets or deletes snapshot metadata."""
@@ -1424,7 +1431,7 @@ def do_metadata_show(cs, args):
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair or pairs to update. ' help='Metadata key and value pair or pairs to update. '
'Default=[].') 'Default=[].')
@utils.service_type('volume') @utils.service_type('volume')
def do_metadata_update_all(cs, args): def do_metadata_update_all(cs, args):
"""Updates volume metadata.""" """Updates volume metadata."""
@@ -1442,7 +1449,7 @@ def do_metadata_update_all(cs, args):
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair or pairs to update. ' help='Metadata key and value pair or pairs to update. '
'Default=[].') 'Default=[].')
@utils.service_type('volume') @utils.service_type('volume')
def do_snapshot_metadata_update_all(cs, args): def do_snapshot_metadata_update_all(cs, args):
"""Updates snapshot metadata.""" """Updates snapshot metadata."""
@@ -1457,7 +1464,7 @@ def do_snapshot_metadata_update_all(cs, args):
metavar='<True|true|False|false>', metavar='<True|true|False|false>',
choices=['True', 'true', 'False', 'false'], choices=['True', 'true', 'False', 'false'],
help='Enables or disables update of volume to ' help='Enables or disables update of volume to '
'read-only access mode.') 'read-only access mode.')
@utils.service_type('volume') @utils.service_type('volume')
def do_readonly_mode_update(cs, args): def do_readonly_mode_update(cs, args):
"""Updates volume read-only access-mode flag.""" """Updates volume read-only access-mode flag."""

View File

@@ -205,7 +205,13 @@ class VolumeManager(base.ManagerWithFind):
if val: if val:
qparams[opt] = val qparams[opt] = val
query_string = "?%s" % urlencode(qparams) if qparams else "" # 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:

View File

@@ -164,15 +164,15 @@ def _extract_metadata(args):
type=str, type=str,
nargs='*', nargs='*',
metavar='<key=value>', metavar='<key=value>',
default=None,
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)
@utils.arg('--marker', @utils.arg('--marker',
metavar='<marker>', metavar='<marker>',
default=None, default=None,
help='Begin returning volumes that appear later in the volume ' help='Begin returning volumes that appear later in the volume '
'list than that represented by this volume id. ' 'list than that represented by this volume id. '
'OPTIONAL: Default=None.') 'OPTIONAL: Default=None.')
@utils.arg('--limit', @utils.arg('--limit',
metavar='<limit>', metavar='<limit>',
default=None, default=None,
@@ -189,9 +189,15 @@ def _extract_metadata(args):
metavar='<key>[:<direction>]', metavar='<key>[:<direction>]',
default=None, default=None,
help=(('Comma-separated list of sort keys and directions in the ' help=(('Comma-separated list of sort keys and directions in the '
'form of <key>[:<asc|desc>]. ' 'form of <key>[:<asc|desc>]. '
'Valid keys: %s. ' 'Valid keys: %s. OPTIONAL: '
'OPTIONAL: Default=None.') % ', '.join(volumes.SORT_KEY_VALUES))) 'Default=None.') % ', '.join(volumes.SORT_KEY_VALUES)))
@utils.arg('--tenant',
type=str,
dest='tenant',
nargs='?',
metavar='<tenant>',
help='Display information from single tenant (Admin only).')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_list(cs, args): def do_list(cs, args):
"""Lists all volumes.""" """Lists all volumes."""
@@ -199,9 +205,11 @@ def do_list(cs, 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
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) all_tenants = 1 if args.tenant else \
int(os.environ.get("ALL_TENANTS", args.all_tenants))
search_opts = { search_opts = {
'all_tenants': all_tenants, 'all_tenants': all_tenants,
'project_id': args.tenant,
'name': args.name, 'name': args.name,
'status': args.status, 'status': args.status,
'metadata': _extract_metadata(args) if args.metadata else None, 'metadata': _extract_metadata(args) if args.metadata else None,
@@ -332,8 +340,8 @@ class CheckSizeArgForCreate(argparse.Action):
type=str, type=str,
nargs='*', nargs='*',
metavar='<key=value>', metavar='<key=value>',
help='Metadata key and value pairs. Default=None.', default=None,
default=None) help='Metadata key and value pairs. Default=None.')
@utils.arg('--hint', @utils.arg('--hint',
metavar='<key=value>', metavar='<key=value>',
dest='scheduler_hints', dest='scheduler_hints',
@@ -502,13 +510,13 @@ def do_rename(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair to set or unset. ' help='Metadata key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_metadata(cs, args): def do_metadata(cs, args):
"""Sets or deletes volume metadata.""" """Sets or deletes volume metadata."""
@@ -590,13 +598,13 @@ def do_snapshot_show(cs, args):
help='Name or ID of volume to snapshot.') help='Name or ID of volume to snapshot.')
@utils.arg('--force', @utils.arg('--force',
metavar='<True|False>', metavar='<True|False>',
default=False,
help='Allows or disallows snapshot of ' help='Allows or disallows snapshot of '
'a volume when the volume is attached to an instance. ' 'a volume when the volume is attached to an instance. '
'If set to True, ignores the current status of the ' 'If set to True, ignores the current status of the '
'volume when attempting to snapshot it rather ' 'volume when attempting to snapshot it rather '
'than forcing it to be available. ' 'than forcing it to be available. '
'Default=False.', 'Default=False.')
default=False)
@utils.arg('--name', @utils.arg('--name',
metavar='<name>', metavar='<name>',
default=None, default=None,
@@ -617,8 +625,8 @@ def do_snapshot_show(cs, args):
type=str, type=str,
nargs='*', nargs='*',
metavar='<key=value>', metavar='<key=value>',
help='Snapshot metadata key and value pairs. Default=None.', default=None,
default=None) help='Snapshot metadata key and value pairs. Default=None.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_snapshot_create(cs, args): def do_snapshot_create(cs, args):
"""Creates a snapshot.""" """Creates a snapshot."""
@@ -664,8 +672,8 @@ def do_snapshot_delete(cs, args):
@utils.arg('name', nargs='?', metavar='<name>', @utils.arg('name', nargs='?', metavar='<name>',
help='New name for snapshot.') help='New name for snapshot.')
@utils.arg('--description', metavar='<description>', @utils.arg('--description', metavar='<description>',
help='Snapshot description. Default=None.', default=None,
default=None) help='Snapshot description. Default=None.')
@utils.arg('--display-description', @utils.arg('--display-description',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@utils.arg('--display_description', @utils.arg('--display_description',
@@ -751,13 +759,13 @@ def do_type_default(cs, args):
@utils.arg('id', @utils.arg('id',
metavar='<id>', metavar='<id>',
help="ID of the volume type.") help='ID of the volume type.')
@utils.arg('--name', @utils.arg('--name',
metavar='<name>', metavar='<name>',
help="Name of the volume type.") help='Name of the volume type.')
@utils.arg('--description', @utils.arg('--description',
metavar='<description>', metavar='<description>',
help="Description of the volume type.") help='Description of the volume type.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_type_update(cs, args): def do_type_update(cs, args):
"""Updates volume type name and/or description.""" """Updates volume type name and/or description."""
@@ -774,14 +782,14 @@ def do_extra_specs_list(cs, args):
@utils.arg('name', @utils.arg('name',
metavar='<name>', metavar='<name>',
help="Name of new volume type.") help='Name of new volume type.')
@utils.arg('--description', @utils.arg('--description',
metavar='<description>', metavar='<description>',
help="Description of new volume type.") help='Description of new volume type.')
@utils.arg('--is-public', @utils.arg('--is-public',
metavar='<is-public>', metavar='<is-public>',
help="Make type accessible to the public (default true).", default=True,
default=True) help='Make type accessible to the public (default true).')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_type_create(cs, args): def do_type_create(cs, args):
"""Creates a volume type.""" """Creates a volume type."""
@@ -792,7 +800,7 @@ def do_type_create(cs, args):
@utils.arg('id', @utils.arg('id',
metavar='<id>', metavar='<id>',
help="ID of volume type to delete.") help='ID of volume type to delete.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_type_delete(cs, args): def do_type_delete(cs, args):
"""Deletes a volume type.""" """Deletes a volume type."""
@@ -801,17 +809,17 @@ def do_type_delete(cs, args):
@utils.arg('vtype', @utils.arg('vtype',
metavar='<vtype>', metavar='<vtype>',
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help='The extra specs key and value pair to set or unset. ' help='The extra specs key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_type_key(cs, args): def do_type_key(cs, args):
"""Sets or unsets extra_spec for a volume type.""" """Sets or unsets extra_spec for a volume type."""
@@ -825,7 +833,7 @@ def do_type_key(cs, args):
@utils.arg('--volume-type', metavar='<volume_type>', required=True, @utils.arg('--volume-type', metavar='<volume_type>', required=True,
help="Filter results by volume type name or ID.") help='Filter results by volume type name or ID.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_type_access_list(cs, args): def do_type_access_list(cs, args):
"""Print access information about the given volume type.""" """Print access information about the given volume type."""
@@ -840,7 +848,7 @@ def do_type_access_list(cs, args):
@utils.arg('--volume-type', metavar='<volume_type>', required=True, @utils.arg('--volume-type', metavar='<volume_type>', required=True,
help="Volume type name or ID to add access for the given project.") help='Volume type name or ID to add access for the given project.')
@utils.arg('--project-id', metavar='<project_id>', required=True, @utils.arg('--project-id', metavar='<project_id>', required=True,
help='Project ID to add volume type access for.') help='Project ID to add volume type access for.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
@@ -1065,22 +1073,22 @@ def _find_volume_type(cs, vtype):
help='Name or ID of volume to snapshot.') help='Name or ID of volume to snapshot.')
@utils.arg('--force', @utils.arg('--force',
metavar='<True|False>', metavar='<True|False>',
default=False,
help='Enables or disables upload of ' help='Enables or disables upload of '
'a volume that is attached to an instance. ' 'a volume that is attached to an instance. '
'Default=False.', 'Default=False.')
default=False)
@utils.arg('--container-format', @utils.arg('--container-format',
metavar='<container-format>', metavar='<container-format>',
default='bare',
help='Container format type. ' help='Container format type. '
'Default is bare.', 'Default is bare.')
default='bare')
@utils.arg('--container_format', @utils.arg('--container_format',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@utils.arg('--disk-format', @utils.arg('--disk-format',
metavar='<disk-format>', metavar='<disk-format>',
default='raw',
help='Disk format type. ' help='Disk format type. '
'Default is raw.', 'Default is raw.')
default='raw')
@utils.arg('--disk_format', @utils.arg('--disk_format',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@utils.arg('image_name', @utils.arg('image_name',
@@ -1102,10 +1110,10 @@ def do_upload_to_image(cs, args):
@utils.arg('host', metavar='<host>', help='Destination host.') @utils.arg('host', metavar='<host>', help='Destination host.')
@utils.arg('--force-host-copy', metavar='<True|False>', @utils.arg('--force-host-copy', metavar='<True|False>',
choices=['True', 'False'], required=False, choices=['True', 'False'], required=False,
default=False,
help='Enables or disables generic host-based ' help='Enables or disables generic host-based '
'force-migration, which bypasses driver ' 'force-migration, which bypasses driver '
'optimizations. Default=False.', 'optimizations. Default=False.')
default=False)
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_migrate(cs, args): def do_migrate(cs, args):
"""Migrates volume to a new host.""" """Migrates volume to a new host."""
@@ -1129,13 +1137,13 @@ def do_retype(cs, args):
@utils.arg('volume', metavar='<volume>', @utils.arg('volume', metavar='<volume>',
help='Name or ID of volume to backup.') help='Name or ID of volume to backup.')
@utils.arg('--container', metavar='<container>', @utils.arg('--container', metavar='<container>',
help='Backup container name. Default=None.', default=None,
default=None) help='Backup container name. Default=None.')
@utils.arg('--display-name', @utils.arg('--display-name',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@utils.arg('--name', metavar='<name>', @utils.arg('--name', metavar='<name>',
help='Backup name. Default=None.', default=None,
default=None) help='Backup name. Default=None.')
@utils.arg('--display-description', @utils.arg('--display-description',
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
@utils.arg('--description', @utils.arg('--description',
@@ -1199,12 +1207,12 @@ def do_backup_delete(cs, args):
@utils.arg('backup', metavar='<backup>', @utils.arg('backup', metavar='<backup>',
help='ID of backup to restore.') help='ID of backup to restore.')
@utils.arg('--volume-id', metavar='<volume>', @utils.arg('--volume-id', metavar='<volume>',
help=argparse.SUPPRESS, default=None,
default=None) help=argparse.SUPPRESS)
@utils.arg('--volume', metavar='<volume>', @utils.arg('--volume', metavar='<volume>',
default=None,
help='Name or ID of volume to which to restore. ' help='Name or ID of volume to which to restore. '
'Default=None.', 'Default=None.')
default=None)
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_backup_restore(cs, args): def do_backup_restore(cs, args):
"""Restores a backup.""" """Restores a backup."""
@@ -1462,7 +1470,7 @@ def do_encryption_type_list(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_encryption_type_show(cs, args): def do_encryption_type_show(cs, args):
"""Shows encryption type details for a volume type. Admin only.""" """Shows encryption type details for a volume type. Admin only."""
@@ -1480,26 +1488,26 @@ def do_encryption_type_show(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.arg('provider', @utils.arg('provider',
metavar='<provider>', metavar='<provider>',
type=str, type=str,
help='The class that provides encryption support. ' help='The class that provides encryption support. '
'For example, LuksEncryptor.') 'For example, LuksEncryptor.')
@utils.arg('--cipher', @utils.arg('--cipher',
metavar='<cipher>', metavar='<cipher>',
type=str, type=str,
required=False, required=False,
default=None, default=None,
help='The encryption algorithm or mode. ' help='The encryption algorithm or mode. '
'For example, aes-xts-plain64. Default=None.') 'For example, aes-xts-plain64. Default=None.')
@utils.arg('--key_size', @utils.arg('--key_size',
metavar='<key_size>', metavar='<key_size>',
type=int, type=int,
required=False, required=False,
default=None, default=None,
help='Size of encryption key, in bits. ' help='Size of encryption key, in bits. '
'For example, 128 or 256. Default=None.') 'For example, 128 or 256. Default=None.')
@utils.arg('--control_location', @utils.arg('--control_location',
metavar='<control_location>', metavar='<control_location>',
choices=['front-end', 'back-end'], choices=['front-end', 'back-end'],
@@ -1507,8 +1515,8 @@ def do_encryption_type_show(cs, args):
required=False, required=False,
default='front-end', default='front-end',
help='Notional service where encryption is performed. ' help='Notional service where encryption is performed. '
'Valid values are "front-end" or "back-end." ' 'Valid values are "front-end" or "back-end." '
'For example, front-end=Nova. Default is "front-end."') 'For example, front-end=Nova. Default is "front-end."')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_encryption_type_create(cs, args): def do_encryption_type_create(cs, args):
"""Creates encryption type for a volume type. Admin only.""" """Creates encryption type for a volume type. Admin only."""
@@ -1527,7 +1535,7 @@ def do_encryption_type_create(cs, args):
@utils.arg('volume_type', @utils.arg('volume_type',
metavar='<volume_type>', metavar='<volume_type>',
type=str, type=str,
help="Name or ID of volume type.") help='Name or ID of volume type.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_encryption_type_delete(cs, args): def do_encryption_type_delete(cs, args):
"""Deletes encryption type for a volume type. Admin only.""" """Deletes encryption type for a volume type. Admin only."""
@@ -1553,12 +1561,12 @@ def _print_associations_list(associations):
@utils.arg('name', @utils.arg('name',
metavar='<name>', metavar='<name>',
help="Name of new QoS specifications.") help='Name of new QoS specifications.')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help="QoS specifications.") help='QoS specifications.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_qos_create(cs, args): def do_qos_create(cs, args):
"""Creates a qos specs.""" """Creates a qos specs."""
@@ -1577,7 +1585,7 @@ def do_qos_list(cs, args):
@utils.arg('qos_specs', metavar='<qos_specs>', @utils.arg('qos_specs', metavar='<qos_specs>',
help="ID of QoS specifications to show.") help='ID of QoS specifications to show.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_qos_show(cs, args): def do_qos_show(cs, args):
"""Shows qos specs details.""" """Shows qos specs details."""
@@ -1586,7 +1594,7 @@ def do_qos_show(cs, args):
@utils.arg('qos_specs', metavar='<qos_specs>', @utils.arg('qos_specs', metavar='<qos_specs>',
help="ID of QoS specifications to delete.") help='ID of QoS specifications to delete.')
@utils.arg('--force', @utils.arg('--force',
metavar='<True|False>', metavar='<True|False>',
default=False, default=False,
@@ -1604,7 +1612,7 @@ def do_qos_delete(cs, args):
help='ID of QoS specifications.') help='ID of QoS specifications.')
@utils.arg('vol_type_id', metavar='<volume_type_id>', @utils.arg('vol_type_id', metavar='<volume_type_id>',
help='ID of volume type with which to associate ' help='ID of volume type with which to associate '
'QoS specifications.') 'QoS specifications.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_qos_associate(cs, args): def do_qos_associate(cs, args):
"""Associates qos specs with specified volume type.""" """Associates qos specs with specified volume type."""
@@ -1615,7 +1623,7 @@ def do_qos_associate(cs, args):
help='ID of QoS specifications.') help='ID of QoS specifications.')
@utils.arg('vol_type_id', metavar='<volume_type_id>', @utils.arg('vol_type_id', metavar='<volume_type_id>',
help='ID of volume type with which to associate ' help='ID of volume type with which to associate '
'QoS specifications.') 'QoS specifications.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_qos_disassociate(cs, args): def do_qos_disassociate(cs, args):
"""Disassociates qos specs from specified volume type.""" """Disassociates qos specs from specified volume type."""
@@ -1635,12 +1643,12 @@ def do_qos_disassociate_all(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', metavar='key=value', @utils.arg('metadata', metavar='key=value',
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair to set or unset. ' help='Metadata key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
def do_qos_key(cs, args): def do_qos_key(cs, args):
"""Sets or unsets specifications for a qos spec.""" """Sets or unsets specifications for a qos spec."""
keypair = _extract_metadata(args) keypair = _extract_metadata(args)
@@ -1666,13 +1674,13 @@ def do_qos_get_association(cs, args):
@utils.arg('action', @utils.arg('action',
metavar='<action>', metavar='<action>',
choices=['set', 'unset'], choices=['set', 'unset'],
help="The action. Valid values are 'set' or 'unset.'") help='The action. Valid values are "set" or "unset."')
@utils.arg('metadata', @utils.arg('metadata',
metavar='<key=value>', metavar='<key=value>',
nargs='+', nargs='+',
default=[], default=[],
help='Metadata key and value pair to set or unset. ' help='Metadata key and value pair to set or unset. '
'For unset, specify only the key.') 'For unset, specify only the key.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_snapshot_metadata(cs, args): def do_snapshot_metadata(cs, args):
"""Sets or deletes snapshot metadata.""" """Sets or deletes snapshot metadata."""
@@ -1743,7 +1751,7 @@ def do_snapshot_metadata_update_all(cs, args):
metavar='<True|true|False|false>', metavar='<True|true|False|false>',
choices=['True', 'true', 'False', 'false'], choices=['True', 'true', 'False', 'false'],
help='Enables or disables update of volume to ' help='Enables or disables update of volume to '
'read-only access mode.') 'read-only access mode.')
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_readonly_mode_update(cs, args): def do_readonly_mode_update(cs, args):
"""Updates volume read-only access-mode flag.""" """Updates volume read-only access-mode flag."""
@@ -1938,12 +1946,12 @@ def do_consisgroup_create(cs, args):
'to be deleted.') 'to be deleted.')
@utils.arg('--force', @utils.arg('--force',
action='store_true', action='store_true',
default=False,
help='Allows or disallows consistency groups ' help='Allows or disallows consistency groups '
'to be deleted. If the consistency group is empty, ' 'to be deleted. If the consistency group is empty, '
'it can be deleted without the force flag. ' 'it can be deleted without the force flag. '
'If the consistency group is not empty, the force ' 'If the consistency group is not empty, the force '
'flag is required for it to be deleted.', 'flag is required for it to be deleted.')
default=False)
@utils.service_type('volumev2') @utils.service_type('volumev2')
def do_consisgroup_delete(cs, args): def do_consisgroup_delete(cs, args):
"""Removes one or more consistency groups.""" """Removes one or more consistency groups."""