summaryrefslogtreecommitdiff
path: root/openstackclient/volume
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/volume')
-rw-r--r--openstackclient/volume/v2/consistency_group.py3
-rw-r--r--openstackclient/volume/v2/qos_specs.py13
-rw-r--r--openstackclient/volume/v2/volume.py62
-rw-r--r--openstackclient/volume/v2/volume_backup.py45
-rw-r--r--openstackclient/volume/v2/volume_snapshot.py54
-rw-r--r--openstackclient/volume/v2/volume_type.py61
6 files changed, 169 insertions, 69 deletions
diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py
index 0a932f84..26dd8ffc 100644
--- a/openstackclient/volume/v2/consistency_group.py
+++ b/openstackclient/volume/v2/consistency_group.py
@@ -16,6 +16,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -238,7 +239,7 @@ class ListConsistencyGroup(command.Lister):
return (columns, (
utils.get_item_properties(
s, columns,
- formatters={'Volume Types': utils.format_list})
+ formatters={'Volume Types': format_columns.ListColumn})
for s in consistency_groups))
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index c7160581..3037d34a 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -17,6 +17,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -96,7 +97,8 @@ class CreateQos(command.ShowOne):
qos_spec = volume_client.qos_specs.create(parsed_args.name, specs)
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))}
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))}
)
return zip(*sorted(six.iteritems(qos_spec._info)))
@@ -210,8 +212,8 @@ class ListQos(command.Lister):
(utils.get_dict_properties(
s._info, columns,
formatters={
- 'Specs': utils.format_dict,
- 'Associations': utils.format_list
+ 'Specs': format_columns.DictColumn,
+ 'Associations': format_columns.ListColumn
},
) for s in qos_specs_list))
@@ -267,10 +269,11 @@ class ShowQos(command.ShowOne):
associations = [association.name
for association in qos_associations]
qos_spec._info.update({
- 'associations': utils.format_list(associations)
+ 'associations': format_columns.ListColumn(associations)
})
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))})
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))})
return zip(*sorted(six.iteritems(qos_spec._info)))
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index ef65d097..17ccd3d3 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -16,8 +16,11 @@
import argparse
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -31,6 +34,37 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class AttachmentsColumn(cliff_columns.FormattableColumn):
+ """Formattable column for attachments column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes server_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(AttachmentsColumn, server_cache)``.
+ """
+
+ def __init__(self, value, server_cache=None):
+ super(AttachmentsColumn, self).__init__(value)
+ self._server_cache = server_cache or {}
+
+ def human_readable(self):
+ """Return a formatted string of a volume's attached instances
+
+ :rtype: a string of formatted instances
+ """
+
+ msg = ''
+ for attachment in self._value:
+ server = attachment['server_id']
+ if server in self._server_cache.keys():
+ server = self._server_cache[server].name
+ device = attachment['device']
+ msg += 'Attached to %s on %s ' % (server, device)
+ return msg
+
+
def _check_size_arg(args):
"""Check whether --size option is required or not.
@@ -212,7 +246,8 @@ class CreateVolume(command.ShowOne):
# Remove key links from being displayed
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type')
}
)
@@ -331,22 +366,6 @@ class ListVolume(command.Lister):
compute_client = self.app.client_manager.compute
identity_client = self.app.client_manager.identity
- def _format_attach(attachments):
- """Return a formatted string of a volume's attached instances
-
- :param attachments: a volume.attachments field
- :rtype: a string of formatted instances
- """
-
- msg = ''
- for attachment in attachments:
- server = attachment['server_id']
- if server in server_cache:
- server = server_cache[server].name
- device = attachment['device']
- msg += 'Attached to %s on %s ' % (server, device)
- return msg
-
if parsed_args.long:
columns = [
'ID',
@@ -381,6 +400,8 @@ class ListVolume(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ AttachmentsColumnWithCache = functools.partial(
+ AttachmentsColumn, server_cache=server_cache)
project_id = None
if parsed_args.project:
@@ -417,8 +438,8 @@ class ListVolume(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Attachments': _format_attach},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Attachments': AttachmentsColumnWithCache},
) for s in data))
@@ -722,7 +743,8 @@ class ShowVolume(command.ShowOne):
# 'volume_type' --> 'type'
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type'),
},
)
diff --git a/openstackclient/volume/v2/volume_backup.py b/openstackclient/volume/v2/volume_backup.py
index 1d2b0cde..4d0d54c1 100644
--- a/openstackclient/volume/v2/volume_backup.py
+++ b/openstackclient/volume/v2/volume_backup.py
@@ -15,8 +15,10 @@
"""Volume v2 Backup action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -29,6 +31,33 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].name
+ return volume
+
+
class CreateVolumeBackup(command.ShowOne):
_description = _("Create new volume backup")
@@ -189,18 +218,6 @@ class ListVolumeBackup(command.Lister):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Name', 'Description', 'Status', 'Size',
'Availability Zone', 'Volume ID', 'Container']
@@ -218,6 +235,8 @@ class ListVolumeBackup(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ _VolumeIdColumn = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
filter_volume_id = None
if parsed_args.volume:
@@ -242,7 +261,7 @@ class ListVolumeBackup(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Volume ID': _format_volume_id},
+ formatters={'Volume ID': _VolumeIdColumn},
) for s in data))
diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py
index fe969410..2b26ae32 100644
--- a/openstackclient/volume/v2/volume_snapshot.py
+++ b/openstackclient/volume/v2/volume_snapshot.py
@@ -15,8 +15,11 @@
"""Volume v2 snapshot action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -30,6 +33,33 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].name
+ return volume
+
+
class CreateVolumeSnapshot(command.ShowOne):
_description = _("Create new volume snapshot")
@@ -107,7 +137,8 @@ class CreateVolumeSnapshot(command.ShowOne):
metadata=parsed_args.property,
)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
@@ -216,18 +247,6 @@ class ListVolumeSnapshot(command.Lister):
volume_client = self.app.client_manager.volume
identity_client = self.app.client_manager.identity
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Name', 'Description', 'Status',
'Size', 'Created At', 'Volume ID', 'Metadata']
@@ -246,6 +265,8 @@ class ListVolumeSnapshot(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ _VolumeIdColumn = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
volume_id = None
if parsed_args.volume:
@@ -279,8 +300,8 @@ class ListVolumeSnapshot(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Volume ID': _format_volume_id},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Volume ID': _VolumeIdColumn},
) for s in data))
@@ -402,7 +423,8 @@ class ShowVolumeSnapshot(command.ShowOne):
snapshot = utils.find_resource(
volume_client.volume_snapshots, parsed_args.snapshot)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 749d1dd6..54b1f497 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -14,8 +14,11 @@
"""Volume v2 Type action implementations"""
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -29,6 +32,36 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class EncryptionInfoColumn(cliff_columns.FormattableColumn):
+ """Formattable column for encryption info column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes encryption_data as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(EncryptionInfoColumn encryption_data)``.
+ """
+
+ def __init__(self, value, encryption_data=None):
+ super(EncryptionInfoColumn, self).__init__(value)
+ self._encryption_data = encryption_data or {}
+
+ def _get_encryption_info(self):
+ type_id = self._value
+ return self._encryption_data.get(type_id)
+
+ def human_readable(self):
+ encryption_info = self._get_encryption_info()
+ if encryption_info:
+ return utils.format_dict(encryption_info)
+ else:
+ return '-'
+
+ def machine_readable(self):
+ return self._get_encryption_info()
+
+
def _create_encryption_type(volume_client, volume_type, parsed_args):
if not parsed_args.encryption_provider:
msg = _("'--encryption-provider' should be specified while "
@@ -183,7 +216,8 @@ class CreateVolumeType(command.ShowOne):
LOG.error(msg % {'project': parsed_args.project, 'e': e})
if parsed_args.property:
result = volume_type.set_keys(parsed_args.property)
- volume_type._info.update({'properties': utils.format_dict(result)})
+ volume_type._info.update(
+ {'properties': format_columns.DictColumn(result)})
if (parsed_args.encryption_provider or
parsed_args.encryption_cipher or
parsed_args.encryption_key_size or
@@ -198,7 +232,7 @@ class CreateVolumeType(command.ShowOne):
# add encryption info in result
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption': format_columns.DictColumn(encryption._info)})
volume_type._info.pop("os-volume-type-access:is_public", None)
return zip(*sorted(six.iteritems(volume_type._info)))
@@ -296,12 +330,7 @@ class ListVolumeType(command.Lister):
data = volume_client.volume_types.list(
is_public=is_public)
- def _format_encryption_info(type_id, encryption_data=None):
- encryption_data = encryption
- encryption_info = '-'
- if type_id in encryption_data.keys():
- encryption_info = encryption_data[type_id]
- return encryption_info
+ formatters = {'Extra Specs': format_columns.DictColumn}
if parsed_args.encryption_type:
encryption = {}
@@ -318,18 +347,21 @@ class ListVolumeType(command.Lister):
for key in del_key:
d._info.pop(key, None)
# save the encryption information with their volume type ID
- encryption[volume_type_id] = utils.format_dict(d._info)
+ encryption[volume_type_id] = d._info
# We need to get volume type ID, then show encryption
# information according to the ID, so use "id" to keep
# difference to the real "ID" column.
columns += ['id']
column_headers += ['Encryption']
+ _EncryptionInfoColumn = functools.partial(
+ EncryptionInfoColumn, encryption_data=encryption)
+ formatters['id'] = _EncryptionInfoColumn
+
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Extra Specs': utils.format_dict,
- 'id': _format_encryption_info},
+ formatters=formatters,
) for s in data))
@@ -490,7 +522,7 @@ class ShowVolumeType(command.ShowOne):
volume_client = self.app.client_manager.volume
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
- properties = utils.format_dict(
+ properties = format_columns.DictColumn(
volume_type._info.pop('extra_specs', {}))
volume_type._info.update({'properties': properties})
access_project_ids = None
@@ -502,7 +534,7 @@ class ShowVolumeType(command.ShowOne):
for item in volume_type_access]
# TODO(Rui Chen): This format list case can be removed after
# patch https://review.opendev.org/#/c/330223/ merged.
- access_project_ids = utils.format_list(project_ids)
+ access_project_ids = format_columns.ListColumn(project_ids)
except Exception as e:
msg = _('Failed to get access project list for volume type '
'%(type)s: %(e)s')
@@ -515,7 +547,8 @@ class ShowVolumeType(command.ShowOne):
volume_type.id)
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption':
+ format_columns.DictColumn(encryption._info)})
except Exception as e:
LOG.error(_("Failed to display the encryption information "
"of this volume type: %s"), e)