summaryrefslogtreecommitdiff
path: root/openstackclient/volume
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/volume')
-rw-r--r--openstackclient/volume/v1/backup.py63
-rw-r--r--openstackclient/volume/v1/qos_specs.py16
-rw-r--r--openstackclient/volume/v1/service.py4
-rw-r--r--openstackclient/volume/v1/snapshot.py12
-rw-r--r--openstackclient/volume/v1/volume.py107
-rw-r--r--openstackclient/volume/v1/volume_transfer_request.py10
-rw-r--r--openstackclient/volume/v1/volume_type.py18
-rw-r--r--openstackclient/volume/v2/backup.py84
-rw-r--r--openstackclient/volume/v2/consistency_group.py145
-rw-r--r--openstackclient/volume/v2/consistency_group_snapshot.py190
-rw-r--r--openstackclient/volume/v2/qos_specs.py16
-rw-r--r--openstackclient/volume/v2/service.py4
-rw-r--r--openstackclient/volume/v2/snapshot.py12
-rw-r--r--openstackclient/volume/v2/volume.py114
-rw-r--r--openstackclient/volume/v2/volume_transfer_request.py10
-rw-r--r--openstackclient/volume/v2/volume_type.py21
16 files changed, 715 insertions, 111 deletions
diff --git a/openstackclient/volume/v1/backup.py b/openstackclient/volume/v1/backup.py
index c9d0ca0d..9ac1302a 100644
--- a/openstackclient/volume/v1/backup.py
+++ b/openstackclient/volume/v1/backup.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeBackup(command.ShowOne):
- """Create new volume backup"""
+ _description = _("Create new volume backup")
def get_parser(self, prog_name):
parser = super(CreateVolumeBackup, self).get_parser(prog_name)
@@ -73,7 +73,7 @@ class CreateVolumeBackup(command.ShowOne):
class CreateBackup(CreateVolumeBackup):
- """Create new backup"""
+ _description = _("Create new backup")
# TODO(Huanxuan Ao): Remove this class and ``backup create`` command
# two cycles after Newton.
@@ -90,7 +90,7 @@ class CreateBackup(CreateVolumeBackup):
class DeleteVolumeBackup(command.Command):
- """Delete volume backup(s)"""
+ _description = _("Delete volume backup(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeBackup, self).get_parser(prog_name)
@@ -125,7 +125,7 @@ class DeleteVolumeBackup(command.Command):
class DeleteBackup(DeleteVolumeBackup):
- """Delete backup(s)"""
+ _description = _("Delete backup(s)")
# TODO(Huanxuan Ao): Remove this class and ``backup delete`` command
# two cycles after Newton.
@@ -142,7 +142,7 @@ class DeleteBackup(DeleteVolumeBackup):
class ListVolumeBackup(command.Lister):
- """List volume backups"""
+ _description = _("List volume backups")
def get_parser(self, prog_name):
parser = super(ListVolumeBackup, self).get_parser(prog_name)
@@ -152,9 +152,36 @@ class ListVolumeBackup(command.Lister):
default=False,
help=_('List additional fields in output'),
)
+ parser.add_argument(
+ "--name",
+ metavar="<name>",
+ help=_("Filters results by the backup name")
+ )
+ parser.add_argument(
+ "--status",
+ metavar="<status>",
+ choices=['creating', 'available', 'deleting',
+ 'error', 'restoring', 'error_restoring'],
+ help=_("Filters results by the backup status "
+ "('creating', 'available', 'deleting', "
+ "'error', 'restoring' or 'error_restoring')")
+ )
+ parser.add_argument(
+ "--volume",
+ metavar="<volume>",
+ help=_("Filters results by the volume which they "
+ "backup (name or ID)")
+ )
+ parser.add_argument(
+ '--all-projects',
+ action='store_true',
+ default=False,
+ help=_('Include all projects (admin only)'),
+ )
return parser
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
@@ -180,13 +207,25 @@ class ListVolumeBackup(command.Lister):
# Cache the volume list
volume_cache = {}
try:
- for s in self.app.client_manager.volume.volumes.list():
+ for s in volume_client.volumes.list():
volume_cache[s.id] = s
except Exception:
# Just forget it if there's any trouble
pass
- data = self.app.client_manager.volume.backups.list()
+ filter_volume_id = None
+ if parsed_args.volume:
+ filter_volume_id = utils.find_resource(volume_client.volumes,
+ parsed_args.volume).id
+ search_opts = {
+ 'name': parsed_args.name,
+ 'status': parsed_args.status,
+ 'volume_id': filter_volume_id,
+ 'all_tenants': parsed_args.all_projects,
+ }
+ data = volume_client.backups.list(
+ search_opts=search_opts,
+ )
return (column_headers,
(utils.get_item_properties(
@@ -196,7 +235,7 @@ class ListVolumeBackup(command.Lister):
class ListBackup(ListVolumeBackup):
- """List backups"""
+ _description = _("List backups")
# TODO(Huanxuan Ao): Remove this class and ``backup list`` command
# two cycles after Newton.
@@ -213,7 +252,7 @@ class ListBackup(ListVolumeBackup):
class RestoreVolumeBackup(command.Command):
- """Restore volume backup"""
+ _description = _("Restore volume backup")
def get_parser(self, prog_name):
parser = super(RestoreVolumeBackup, self).get_parser(prog_name)
@@ -240,7 +279,7 @@ class RestoreVolumeBackup(command.Command):
class RestoreBackup(RestoreVolumeBackup):
- """Restore backup"""
+ _description = _("Restore backup")
# TODO(Huanxuan Ao): Remove this class and ``backup restore`` command
# two cycles after Newton.
@@ -257,7 +296,7 @@ class RestoreBackup(RestoreVolumeBackup):
class ShowVolumeBackup(command.ShowOne):
- """Display volume backup details"""
+ _description = _("Display volume backup details")
def get_parser(self, prog_name):
parser = super(ShowVolumeBackup, self).get_parser(prog_name)
@@ -277,7 +316,7 @@ class ShowVolumeBackup(command.ShowOne):
class ShowBackup(ShowVolumeBackup):
- """Display backup details"""
+ _description = _("Display backup details")
# TODO(Huanxuan Ao): Remove this class and ``backup show`` command
# two cycles after Newton.
diff --git a/openstackclient/volume/v1/qos_specs.py b/openstackclient/volume/v1/qos_specs.py
index 93c24a21..b824b351 100644
--- a/openstackclient/volume/v1/qos_specs.py
+++ b/openstackclient/volume/v1/qos_specs.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class AssociateQos(command.Command):
- """Associate a QoS specification to a volume type"""
+ _description = _("Associate a QoS specification to a volume type")
def get_parser(self, prog_name):
parser = super(AssociateQos, self).get_parser(prog_name)
@@ -57,7 +57,7 @@ class AssociateQos(command.Command):
class CreateQos(command.ShowOne):
- """Create new QoS specification"""
+ _description = _("Create new QoS specification")
def get_parser(self, prog_name):
parser = super(CreateQos, self).get_parser(prog_name)
@@ -99,7 +99,7 @@ class CreateQos(command.ShowOne):
class DeleteQos(command.Command):
- """Delete QoS specification"""
+ _description = _("Delete QoS specification")
def get_parser(self, prog_name):
parser = super(DeleteQos, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class DeleteQos(command.Command):
class DisassociateQos(command.Command):
- """Disassociate a QoS specification from a volume type"""
+ _description = _("Disassociate a QoS specification from a volume type")
def get_parser(self, prog_name):
parser = super(DisassociateQos, self).get_parser(prog_name)
@@ -177,7 +177,7 @@ class DisassociateQos(command.Command):
class ListQos(command.Lister):
- """List QoS specifications"""
+ _description = _("List QoS specifications")
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
@@ -202,7 +202,7 @@ class ListQos(command.Lister):
class SetQos(command.Command):
- """Set QoS specification properties"""
+ _description = _("Set QoS specification properties")
def get_parser(self, prog_name):
parser = super(SetQos, self).get_parser(prog_name)
@@ -231,7 +231,7 @@ class SetQos(command.Command):
class ShowQos(command.ShowOne):
- """Display QoS specification details"""
+ _description = _("Display QoS specification details")
def get_parser(self, prog_name):
parser = super(ShowQos, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class ShowQos(command.ShowOne):
class UnsetQos(command.Command):
- """Unset QoS specification properties"""
+ _description = _("Unset QoS specification properties")
def get_parser(self, prog_name):
parser = super(UnsetQos, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/service.py b/openstackclient/volume/v1/service.py
index 867c4b9c..d468c6ff 100644
--- a/openstackclient/volume/v1/service.py
+++ b/openstackclient/volume/v1/service.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class ListService(command.Lister):
- """List service command"""
+ _description = _("List service command")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -76,7 +76,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set volume service properties"""
+ _description = _("Set volume service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py
index 1c0c0bc7..e9e3894b 100644
--- a/openstackclient/volume/v1/snapshot.py
+++ b/openstackclient/volume/v1/snapshot.py
@@ -37,7 +37,7 @@ LOG = logging.getLogger(__name__)
class CreateSnapshot(command.ShowOne):
- """Create new snapshot"""
+ _description = _("Create new snapshot")
def get_parser(self, prog_name):
parser = super(CreateSnapshot, self).get_parser(prog_name)
@@ -87,7 +87,7 @@ class CreateSnapshot(command.ShowOne):
class DeleteSnapshot(command.Command):
- """Delete snapshot(s)"""
+ _description = _("Delete snapshot(s)")
def get_parser(self, prog_name):
parser = super(DeleteSnapshot, self).get_parser(prog_name)
@@ -124,7 +124,7 @@ class DeleteSnapshot(command.Command):
class ListSnapshot(command.Lister):
- """List snapshots"""
+ _description = _("List snapshots")
def get_parser(self, prog_name):
parser = super(ListSnapshot, self).get_parser(prog_name)
@@ -197,7 +197,7 @@ class ListSnapshot(command.Lister):
class SetSnapshot(command.Command):
- """Set snapshot properties"""
+ _description = _("Set snapshot properties")
def get_parser(self, prog_name):
parser = super(SetSnapshot, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class SetSnapshot(command.Command):
class ShowSnapshot(command.ShowOne):
- """Display snapshot details"""
+ _description = _("Display snapshot details")
def get_parser(self, prog_name):
parser = super(ShowSnapshot, self).get_parser(prog_name)
@@ -286,7 +286,7 @@ class ShowSnapshot(command.ShowOne):
class UnsetSnapshot(command.Command):
- """Unset snapshot properties"""
+ _description = _("Unset snapshot properties")
def get_parser(self, prog_name):
parser = super(UnsetSnapshot, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index cafe8ce6..0087bad4 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -45,7 +45,7 @@ def _check_size_arg(args):
class CreateVolume(command.ShowOne):
- """Create new volume"""
+ _description = _("Create new volume")
def get_parser(self, prog_name):
parser = super(CreateVolume, self).get_parser(prog_name)
@@ -178,7 +178,7 @@ class CreateVolume(command.ShowOne):
class DeleteVolume(command.Command):
- """Delete volume(s)"""
+ _description = _("Delete volume(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolume, self).get_parser(prog_name)
@@ -223,7 +223,7 @@ class DeleteVolume(command.Command):
class ListVolume(command.Lister):
- """List volumes"""
+ _description = _("List volumes")
def get_parser(self, prog_name):
parser = super(ListVolume, self).get_parser(prog_name)
@@ -344,8 +344,39 @@ class ListVolume(command.Lister):
) for s in data))
+class MigrateVolume(command.Command):
+ _description = _("Migrate volume to a new host")
+
+ def get_parser(self, prog_name):
+ parser = super(MigrateVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar="<volume>",
+ help=_("Volume to migrate (name or ID)")
+ )
+ parser.add_argument(
+ '--host',
+ metavar="<host>",
+ required=True,
+ help=_("Destination host (takes the form: host@backend-name#pool)")
+ )
+ parser.add_argument(
+ '--force-host-copy',
+ action="store_true",
+ help=_("Enable generic host-based force-migration, "
+ "which bypasses driver optimizations")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ volume_client.volumes.migrate_volume(volume.id, parsed_args.host,
+ parsed_args.force_host_copy,)
+
+
class SetVolume(command.Command):
- """Set volume properties"""
+ _description = _("Set volume properties")
def get_parser(self, prog_name):
parser = super(SetVolume, self).get_parser(prog_name)
@@ -388,42 +419,82 @@ class SetVolume(command.Command):
action="store_true",
help=_("Mark volume as non-bootable")
)
+ readonly_group = parser.add_mutually_exclusive_group()
+ readonly_group.add_argument(
+ "--read-only",
+ action="store_true",
+ help=_("Set volume to read-only access mode")
+ )
+ readonly_group.add_argument(
+ "--read-write",
+ action="store_true",
+ help=_("Set volume to read-write access mode")
+ )
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ result = 0
if parsed_args.size:
- if volume.status != 'available':
- LOG.error(_("Volume is in %s state, it must be available "
- "before size can be extended"), volume.status)
- return
- if parsed_args.size <= volume.size:
- LOG.error(_("New size must be greater than %s GB"),
- volume.size)
- return
- volume_client.volumes.extend(volume.id, parsed_args.size)
-
+ try:
+ if volume.status != 'available':
+ msg = (_("Volume is in %s state, it must be available "
+ "before size can be extended") % volume.status)
+ raise exceptions.CommandError(msg)
+ if parsed_args.size <= volume.size:
+ msg = (_("New size must be greater than %s GB")
+ % volume.size)
+ raise exceptions.CommandError(msg)
+ volume_client.volumes.extend(volume.id, parsed_args.size)
+ except Exception as e:
+ LOG.error(_("Failed to set volume size: %s"), e)
+ result += 1
if parsed_args.property:
- volume_client.volumes.set_metadata(volume.id, parsed_args.property)
+ try:
+ volume_client.volumes.set_metadata(
+ volume.id,
+ parsed_args.property)
+ except Exception as e:
+ LOG.error(_("Failed to set volume property: %s"), e)
+ result += 1
if parsed_args.bootable or parsed_args.non_bootable:
try:
volume_client.volumes.set_bootable(
volume.id, parsed_args.bootable)
except Exception as e:
LOG.error(_("Failed to set volume bootable property: %s"), e)
+ result += 1
+ if parsed_args.read_only or parsed_args.read_write:
+ try:
+ volume_client.volumes.update_readonly_flag(
+ volume.id,
+ parsed_args.read_only)
+ except Exception as e:
+ LOG.error(_("Failed to set volume read-only access "
+ "mode flag: %s"), e)
+ result += 1
kwargs = {}
if parsed_args.name:
kwargs['display_name'] = parsed_args.name
if parsed_args.description:
kwargs['display_description'] = parsed_args.description
if kwargs:
- volume_client.volumes.update(volume.id, **kwargs)
+ try:
+ volume_client.volumes.update(volume.id, **kwargs)
+ except Exception as e:
+ LOG.error(_("Failed to update volume display name "
+ "or display description: %s"), e)
+ result += 1
+
+ if result > 0:
+ raise exceptions.CommandError(_("One or more of the "
+ "set operations failed"))
class ShowVolume(command.ShowOne):
- """Show volume details"""
+ _description = _("Show volume details")
def get_parser(self, prog_name):
parser = super(ShowVolume, self).get_parser(prog_name)
@@ -453,7 +524,7 @@ class ShowVolume(command.ShowOne):
class UnsetVolume(command.Command):
- """Unset volume properties"""
+ _description = _("Unset volume properties")
def get_parser(self, prog_name):
parser = super(UnsetVolume, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume_transfer_request.py b/openstackclient/volume/v1/volume_transfer_request.py
index 4d6f2161..f24d5a56 100644
--- a/openstackclient/volume/v1/volume_transfer_request.py
+++ b/openstackclient/volume/v1/volume_transfer_request.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class AcceptTransferRequest(command.ShowOne):
- """Accept volume transfer request."""
+ _description = _("Accept volume transfer request.")
def get_parser(self, prog_name):
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
@@ -56,7 +56,7 @@ class AcceptTransferRequest(command.ShowOne):
class CreateTransferRequest(command.ShowOne):
- """Create volume transfer request."""
+ _description = _("Create volume transfer request.")
def get_parser(self, prog_name):
parser = super(CreateTransferRequest, self).get_parser(prog_name)
@@ -85,7 +85,7 @@ class CreateTransferRequest(command.ShowOne):
class DeleteTransferRequest(command.Command):
- """Delete volume transfer request(s)."""
+ _description = _("Delete volume transfer request(s).")
def get_parser(self, prog_name):
parser = super(DeleteTransferRequest, self).get_parser(prog_name)
@@ -120,7 +120,7 @@ class DeleteTransferRequest(command.Command):
class ListTransferRequest(command.Lister):
- """Lists all volume transfer requests."""
+ _description = _("Lists all volume transfer requests.")
def get_parser(self, prog_name):
parser = super(ListTransferRequest, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class ListTransferRequest(command.Lister):
class ShowTransferRequest(command.ShowOne):
- """Show volume transfer request details."""
+ _description = _("Show volume transfer request details.")
def get_parser(self, prog_name):
parser = super(ShowTransferRequest, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py
index 61e9f7fc..8adce322 100644
--- a/openstackclient/volume/v1/volume_type.py
+++ b/openstackclient/volume/v1/volume_type.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeType(command.ShowOne):
- """Create new volume type"""
+ _description = _("Create new volume type")
def get_parser(self, prog_name):
parser = super(CreateVolumeType, self).get_parser(prog_name)
@@ -61,7 +61,7 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type(s)"""
+ _description = _("Delete volume type(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
@@ -97,7 +97,7 @@ class DeleteVolumeType(command.Command):
class ListVolumeType(command.Lister):
- """List volume types"""
+ _description = _("List volume types")
def get_parser(self, prog_name):
parser = super(ListVolumeType, self).get_parser(prog_name)
@@ -111,10 +111,10 @@ class ListVolumeType(command.Lister):
def take_action(self, parsed_args):
if parsed_args.long:
- columns = ('ID', 'Name', 'Extra Specs')
- column_headers = ('ID', 'Name', 'Properties')
+ columns = ('ID', 'Name', 'Is Public', 'Extra Specs')
+ column_headers = ('ID', 'Name', 'Is Public', 'Properties')
else:
- columns = ('ID', 'Name')
+ columns = ('ID', 'Name', 'Is Public')
column_headers = columns
data = self.app.client_manager.volume.volume_types.list()
return (column_headers,
@@ -125,7 +125,7 @@ class ListVolumeType(command.Lister):
class SetVolumeType(command.Command):
- """Set volume type properties"""
+ _description = _("Set volume type properties")
def get_parser(self, prog_name):
parser = super(SetVolumeType, self).get_parser(prog_name)
@@ -153,7 +153,7 @@ class SetVolumeType(command.Command):
class ShowVolumeType(command.ShowOne):
- """Display volume type details"""
+ _description = _("Display volume type details")
def get_parser(self, prog_name):
parser = super(ShowVolumeType, self).get_parser(prog_name)
@@ -175,7 +175,7 @@ class ShowVolumeType(command.ShowOne):
class UnsetVolumeType(command.Command):
- """Unset volume type properties"""
+ _description = _("Unset volume type properties")
def get_parser(self, prog_name):
parser = super(UnsetVolumeType, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/backup.py b/openstackclient/volume/v2/backup.py
index 2ca35b24..00389fcb 100644
--- a/openstackclient/volume/v2/backup.py
+++ b/openstackclient/volume/v2/backup.py
@@ -17,6 +17,7 @@
import copy
import logging
+from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -29,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeBackup(command.ShowOne):
- """Create new volume backup"""
+ _description = _("Create new volume backup")
def get_parser(self, prog_name):
parser = super(CreateVolumeBackup, self).get_parser(prog_name)
@@ -94,7 +95,7 @@ class CreateVolumeBackup(command.ShowOne):
class CreateBackup(CreateVolumeBackup):
- """Create new backup"""
+ _description = _("Create new backup")
# TODO(Huanxuan Ao): Remove this class and ``backup create`` command
# two cycles after Newton.
@@ -111,7 +112,7 @@ class CreateBackup(CreateVolumeBackup):
class DeleteVolumeBackup(command.Command):
- """Delete volume backup(s)"""
+ _description = _("Delete volume backup(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeBackup, self).get_parser(prog_name)
@@ -152,7 +153,7 @@ class DeleteVolumeBackup(command.Command):
class DeleteBackup(DeleteVolumeBackup):
- """Delete backup(s)"""
+ _description = _("Delete backup(s)")
# TODO(Huanxuan Ao): Remove this class and ``backup delete`` command
# two cycles after Newton.
@@ -169,7 +170,7 @@ class DeleteBackup(DeleteVolumeBackup):
class ListVolumeBackup(command.Lister):
- """List volume backups"""
+ _description = _("List volume backups")
def get_parser(self, prog_name):
parser = super(ListVolumeBackup, self).get_parser(prog_name)
@@ -179,9 +180,48 @@ class ListVolumeBackup(command.Lister):
default=False,
help=_("List additional fields in output")
)
+ parser.add_argument(
+ "--name",
+ metavar="<name>",
+ help=_("Filters results by the backup name")
+ )
+ parser.add_argument(
+ "--status",
+ metavar="<status>",
+ choices=['creating', 'available', 'deleting',
+ 'error', 'restoring', 'error_restoring'],
+ help=_("Filters results by the backup status "
+ "('creating', 'available', 'deleting', "
+ "'error', 'restoring' or 'error_restoring')")
+ )
+ parser.add_argument(
+ "--volume",
+ metavar="<volume>",
+ help=_("Filters results by the volume which they "
+ "backup (name or ID)")
+ )
+ parser.add_argument(
+ '--marker',
+ metavar='<marker>',
+ help=_('The last backup of the previous page (name or ID)'),
+ )
+ parser.add_argument(
+ '--limit',
+ type=int,
+ action=parseractions.NonNegativeAction,
+ metavar='<limit>',
+ help=_('Maximum number of backups to display'),
+ )
+ parser.add_argument(
+ '--all-projects',
+ action='store_true',
+ default=False,
+ help=_('Include all projects (admin only)'),
+ )
return parser
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
@@ -207,13 +247,31 @@ class ListVolumeBackup(command.Lister):
# Cache the volume list
volume_cache = {}
try:
- for s in self.app.client_manager.volume.volumes.list():
+ for s in volume_client.volumes.list():
volume_cache[s.id] = s
except Exception:
# Just forget it if there's any trouble
pass
- data = self.app.client_manager.volume.backups.list()
+ filter_volume_id = None
+ if parsed_args.volume:
+ filter_volume_id = utils.find_resource(volume_client.volumes,
+ parsed_args.volume).id
+ marker_backup_id = None
+ if parsed_args.marker:
+ marker_backup_id = utils.find_resource(volume_client.backups,
+ parsed_args.marker).id
+ search_opts = {
+ 'name': parsed_args.name,
+ 'status': parsed_args.status,
+ 'volume_id': filter_volume_id,
+ 'all_tenants': parsed_args.all_projects,
+ }
+ data = volume_client.backups.list(
+ search_opts=search_opts,
+ marker=marker_backup_id,
+ limit=parsed_args.limit,
+ )
return (column_headers,
(utils.get_item_properties(
@@ -223,7 +281,7 @@ class ListVolumeBackup(command.Lister):
class ListBackup(ListVolumeBackup):
- """List backups"""
+ _description = _("List backups")
# TODO(Huanxuan Ao): Remove this class and ``backup list`` command
# two cycles after Newton.
@@ -240,7 +298,7 @@ class ListBackup(ListVolumeBackup):
class RestoreVolumeBackup(command.ShowOne):
- """Restore volume backup"""
+ _description = _("Restore volume backup")
def get_parser(self, prog_name):
parser = super(RestoreVolumeBackup, self).get_parser(prog_name)
@@ -265,7 +323,7 @@ class RestoreVolumeBackup(command.ShowOne):
class RestoreBackup(RestoreVolumeBackup):
- """Restore backup"""
+ _description = _("Restore backup")
# TODO(Huanxuan Ao): Remove this class and ``backup restore`` command
# two cycles after Newton.
@@ -282,7 +340,7 @@ class RestoreBackup(RestoreVolumeBackup):
class SetVolumeBackup(command.Command):
- """Set volume backup properties"""
+ _description = _("Set volume backup properties")
def get_parser(self, prog_name):
parser = super(SetVolumeBackup, self).get_parser(prog_name)
@@ -344,7 +402,7 @@ class SetVolumeBackup(command.Command):
class ShowVolumeBackup(command.ShowOne):
- """Display volume backup details"""
+ _description = _("Display volume backup details")
def get_parser(self, prog_name):
parser = super(ShowVolumeBackup, self).get_parser(prog_name)
@@ -364,7 +422,7 @@ class ShowVolumeBackup(command.ShowOne):
class ShowBackup(ShowVolumeBackup):
- """Display backup details"""
+ _description = _("Display backup details")
# TODO(Huanxuan Ao): Remove this class and ``backup show`` command
# two cycles after Newton.
diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py
index 39f2d577..661bcbe5 100644
--- a/openstackclient/volume/v2/consistency_group.py
+++ b/openstackclient/volume/v2/consistency_group.py
@@ -14,14 +14,137 @@
"""Volume v2 consistency group action implementations"""
+import logging
+
from osc_lib.command import command
+from osc_lib import exceptions
from osc_lib import utils
+import six
from openstackclient.i18n import _
+LOG = logging.getLogger(__name__)
+
+
+class DeleteConsistencyGroup(command.Command):
+ _description = _("Delete consistency group(s).")
+
+ def get_parser(self, prog_name):
+ parser = super(DeleteConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ 'consistency_groups',
+ metavar='<consistency-group>',
+ nargs="+",
+ help=_('Consistency group(s) to delete (name or ID)'),
+ )
+ parser.add_argument(
+ '--force',
+ action='store_true',
+ default=False,
+ help=_("Allow delete in state other than error or available"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ result = 0
+
+ for i in parsed_args.consistency_groups:
+ try:
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups, i).id
+ volume_client.consistencygroups.delete(
+ consistency_group_id, parsed_args.force)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete consistency group with "
+ "name or ID '%(consistency_group)s':%(e)s")
+ % {'consistency_group': i, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.consistency_groups)
+ msg = (_("%(result)s of %(total)s consistency groups failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateConsistencyGroup(command.ShowOne):
+ _description = _("Create new consistency group.")
+
+ def get_parser(self, prog_name):
+ parser = super(CreateConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ "name",
+ metavar="<name>",
+ nargs="?",
+ help=_("Name of new consistency group (default to None)")
+ )
+ exclusive_group = parser.add_mutually_exclusive_group(required=True)
+ exclusive_group.add_argument(
+ "--volume-type",
+ metavar="<volume-type>",
+ help=_("Volume type of this consistency group (name or ID)")
+ )
+ exclusive_group.add_argument(
+ "--consistency-group-source",
+ metavar="<consistency-group>",
+ help=_("Existing consistency group (name or ID)")
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help=_("Description of this consistency group")
+ )
+ parser.add_argument(
+ "--availability-zone",
+ metavar="<availability-zone>",
+ help=_("Availability zone for this consistency group "
+ "(not available if creating consistency group "
+ "from source)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ if parsed_args.volume_type:
+ volume_type_id = utils.find_resource(
+ volume_client.volume_types,
+ parsed_args.volume_type).id
+ consistency_group = volume_client.consistencygroups.create(
+ volume_type_id,
+ name=parsed_args.name,
+ description=parsed_args.description,
+ availability_zone=parsed_args.availability_zone
+ )
+ elif parsed_args.consistency_group_source:
+ if parsed_args.availability_zone:
+ msg = _("'--availability-zone' option will not work "
+ "if creating consistency group from source")
+ LOG.warning(msg)
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group_source).id
+ consistency_group_snapshot = None
+ # TODO(Huanxuan Ao): Support for creating from consistency group
+ # snapshot after adding "consistency_group_snapshot" resource
+ consistency_group = (
+ volume_client.consistencygroups.create_from_src(
+ consistency_group_snapshot,
+ consistency_group_id,
+ name=parsed_args.name,
+ description=parsed_args.description
+ )
+ )
+
+ return zip(*sorted(six.iteritems(consistency_group._info)))
+
+
class ListConsistencyGroup(command.Lister):
- """List consistency groups."""
+ _description = _("List consistency groups.")
def get_parser(self, prog_name):
parser = super(ListConsistencyGroup, self).get_parser(prog_name)
@@ -55,3 +178,23 @@ class ListConsistencyGroup(command.Lister):
s, columns,
formatters={'Volume Types': utils.format_list})
for s in consistency_groups))
+
+
+class ShowConsistencyGroup(command.ShowOne):
+ _description = _("Display consistency group details.")
+
+ def get_parser(self, prog_name):
+ parser = super(ShowConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group",
+ metavar="<consistency-group>",
+ help=_("Consistency group to display (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group)
+ return zip(*sorted(six.iteritems(consistency_group._info)))
diff --git a/openstackclient/volume/v2/consistency_group_snapshot.py b/openstackclient/volume/v2/consistency_group_snapshot.py
new file mode 100644
index 00000000..540deb01
--- /dev/null
+++ b/openstackclient/volume/v2/consistency_group_snapshot.py
@@ -0,0 +1,190 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+"""Volume v2 consistency group snapshot action implementations"""
+
+import logging
+
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateConsistencyGroupSnapshot(command.ShowOne):
+ _description = _("Create new consistency group snapshot.")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ CreateConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "snapshot_name",
+ metavar="<snapshot-name>",
+ nargs="?",
+ help=_("Name of new consistency group snapshot (default to None)")
+ )
+ parser.add_argument(
+ "--consistency-group",
+ metavar="<consistency-group>",
+ help=_("Consistency group to snapshot (name or ID) "
+ "(default to be the same as <snapshot-name>)")
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help=_("Description of this consistency group snapshot")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group = parsed_args.consistency_group
+ if not parsed_args.consistency_group:
+ # If "--consistency-group" not specified, then consistency_group
+ # will be the same as the new consistency group snapshot name
+ consistency_group = parsed_args.snapshot_name
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ consistency_group).id
+ consistency_group_snapshot = volume_client.cgsnapshots.create(
+ consistency_group_id,
+ name=parsed_args.snapshot_name,
+ description=parsed_args.description,
+ )
+
+ return zip(*sorted(six.iteritems(consistency_group_snapshot._info)))
+
+
+class DeleteConsistencyGroupSnapshot(command.Command):
+ _description = _("Delete consistency group snapshot(s).")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ DeleteConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group_snapshot",
+ metavar="<consistency-group-snapshot>",
+ nargs="+",
+ help=_("Consistency group snapshot(s) to delete (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ result = 0
+
+ for snapshot in parsed_args.consistency_group_snapshot:
+ try:
+ snapshot_id = utils.find_resource(volume_client.cgsnapshots,
+ snapshot).id
+
+ volume_client.cgsnapshots.delete(snapshot_id)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete consistency group snapshot "
+ "with name or ID '%(snapshot)s': %(e)s")
+ % {'snapshot': snapshot, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.consistency_group_snapshot)
+ msg = (_("%(result)s of %(total)s consistency group snapshots "
+ "failed to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
+
+
+class ListConsistencyGroupSnapshot(command.Lister):
+ _description = _("List consistency group snapshots.")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ ListConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ '--all-projects',
+ action="store_true",
+ help=_('Show detail for all projects (admin only) '
+ '(defaults to False)')
+ )
+ parser.add_argument(
+ '--long',
+ action="store_true",
+ help=_('List additional fields in output')
+ )
+ parser.add_argument(
+ '--status',
+ metavar="<status>",
+ choices=['available', 'error', 'creating', 'deleting',
+ 'error-deleting'],
+ help=_('Filters results by a status ("available", "error", '
+ '"creating", "deleting" or "error_deleting")')
+ )
+ parser.add_argument(
+ '--consistency-group',
+ metavar="<consistency-group>",
+ help=_('Filters results by a consistency group (name or ID)')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ if parsed_args.long:
+ columns = ['ID', 'Status', 'ConsistencyGroup ID',
+ 'Name', 'Description', 'Created At']
+ else:
+ columns = ['ID', 'Status', 'Name']
+ volume_client = self.app.client_manager.volume
+ consistency_group_id = None
+ if parsed_args.consistency_group:
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group,
+ ).id
+ search_opts = {
+ 'all_tenants': parsed_args.all_projects,
+ 'status': parsed_args.status,
+ 'consistencygroup_id': consistency_group_id,
+ }
+ consistency_group_snapshots = volume_client.cgsnapshots.list(
+ detailed=True,
+ search_opts=search_opts,
+ )
+
+ return (columns, (
+ utils.get_item_properties(
+ s, columns)
+ for s in consistency_group_snapshots))
+
+
+class ShowConsistencyGroupSnapshot(command.ShowOne):
+ _description = _("Display consistency group snapshot details")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ ShowConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group_snapshot",
+ metavar="<consistency-group-snapshot>",
+ help=_("Consistency group snapshot to display (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group_snapshot = utils.find_resource(
+ volume_client.cgsnapshots,
+ parsed_args.consistency_group_snapshot)
+ return zip(*sorted(six.iteritems(consistency_group_snapshot._info)))
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index 9797f1a6..b7f49eca 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class AssociateQos(command.Command):
- """Associate a QoS specification to a volume type"""
+ _description = _("Associate a QoS specification to a volume type")
def get_parser(self, prog_name):
parser = super(AssociateQos, self).get_parser(prog_name)
@@ -57,7 +57,7 @@ class AssociateQos(command.Command):
class CreateQos(command.ShowOne):
- """Create new QoS specification"""
+ _description = _("Create new QoS specification")
def get_parser(self, prog_name):
parser = super(CreateQos, self).get_parser(prog_name)
@@ -99,7 +99,7 @@ class CreateQos(command.ShowOne):
class DeleteQos(command.Command):
- """Delete QoS specification"""
+ _description = _("Delete QoS specification")
def get_parser(self, prog_name):
parser = super(DeleteQos, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class DeleteQos(command.Command):
class DisassociateQos(command.Command):
- """Disassociate a QoS specification from a volume type"""
+ _description = _("Disassociate a QoS specification from a volume type")
def get_parser(self, prog_name):
parser = super(DisassociateQos, self).get_parser(prog_name)
@@ -177,7 +177,7 @@ class DisassociateQos(command.Command):
class ListQos(command.Lister):
- """List QoS specifications"""
+ _description = _("List QoS specifications")
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
@@ -202,7 +202,7 @@ class ListQos(command.Lister):
class SetQos(command.Command):
- """Set QoS specification properties"""
+ _description = _("Set QoS specification properties")
def get_parser(self, prog_name):
parser = super(SetQos, self).get_parser(prog_name)
@@ -231,7 +231,7 @@ class SetQos(command.Command):
class ShowQos(command.ShowOne):
- """Display QoS specification details"""
+ _description = _("Display QoS specification details")
def get_parser(self, prog_name):
parser = super(ShowQos, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class ShowQos(command.ShowOne):
class UnsetQos(command.Command):
- """Unset QoS specification properties"""
+ _description = _("Unset QoS specification properties")
def get_parser(self, prog_name):
parser = super(UnsetQos, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/service.py b/openstackclient/volume/v2/service.py
index 867c4b9c..d468c6ff 100644
--- a/openstackclient/volume/v2/service.py
+++ b/openstackclient/volume/v2/service.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class ListService(command.Lister):
- """List service command"""
+ _description = _("List service command")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -76,7 +76,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set volume service properties"""
+ _description = _("Set volume service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/snapshot.py b/openstackclient/volume/v2/snapshot.py
index 2f3de211..a18887e3 100644
--- a/openstackclient/volume/v2/snapshot.py
+++ b/openstackclient/volume/v2/snapshot.py
@@ -36,7 +36,7 @@ LOG = logging.getLogger(__name__)
class CreateSnapshot(command.ShowOne):
- """Create new snapshot"""
+ _description = _("Create new snapshot")
def get_parser(self, prog_name):
parser = super(CreateSnapshot, self).get_parser(prog_name)
@@ -91,7 +91,7 @@ class CreateSnapshot(command.ShowOne):
class DeleteSnapshot(command.Command):
- """Delete volume snapshot(s)"""
+ _description = _("Delete volume snapshot(s)")
def get_parser(self, prog_name):
parser = super(DeleteSnapshot, self).get_parser(prog_name)
@@ -128,7 +128,7 @@ class DeleteSnapshot(command.Command):
class ListSnapshot(command.Lister):
- """List snapshots"""
+ _description = _("List snapshots")
def get_parser(self, prog_name):
parser = super(ListSnapshot, self).get_parser(prog_name)
@@ -211,7 +211,7 @@ class ListSnapshot(command.Lister):
class SetSnapshot(command.Command):
- """Set snapshot properties"""
+ _description = _("Set snapshot properties")
def get_parser(self, prog_name):
parser = super(SetSnapshot, self).get_parser(prog_name)
@@ -294,7 +294,7 @@ class SetSnapshot(command.Command):
class ShowSnapshot(command.ShowOne):
- """Display snapshot details"""
+ _description = _("Display snapshot details")
def get_parser(self, prog_name):
parser = super(ShowSnapshot, self).get_parser(prog_name)
@@ -318,7 +318,7 @@ class ShowSnapshot(command.ShowOne):
class UnsetSnapshot(command.Command):
- """Unset snapshot properties"""
+ _description = _("Unset snapshot properties")
def get_parser(self, prog_name):
parser = super(UnsetSnapshot, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index cb409711..80abfb55 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -45,7 +45,7 @@ def _check_size_arg(args):
class CreateVolume(command.ShowOne):
- """Create new volume"""
+ _description = _("Create new volume")
def get_parser(self, prog_name):
parser = super(CreateVolume, self).get_parser(prog_name)
@@ -211,7 +211,7 @@ class CreateVolume(command.ShowOne):
class DeleteVolume(command.Command):
- """Delete volume(s)"""
+ _description = _("Delete volume(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolume, self).get_parser(prog_name)
@@ -263,7 +263,7 @@ class DeleteVolume(command.Command):
class ListVolume(command.Lister):
- """List volumes"""
+ _description = _("List volumes")
def get_parser(self, prog_name):
parser = super(ListVolume, self).get_parser(prog_name)
@@ -409,8 +409,55 @@ class ListVolume(command.Lister):
) for s in data))
+class MigrateVolume(command.Command):
+ _description = _("Migrate volume to a new host")
+
+ def get_parser(self, prog_name):
+ parser = super(MigrateVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar="<volume>",
+ help=_("Volume to migrate (name or ID)")
+ )
+ parser.add_argument(
+ '--host',
+ metavar="<host>",
+ required=True,
+ help=_("Destination host (takes the form: host@backend-name#pool)")
+ )
+ parser.add_argument(
+ '--force-host-copy',
+ action="store_true",
+ help=_("Enable generic host-based force-migration, "
+ "which bypasses driver optimizations")
+ )
+ lock_group = parser.add_mutually_exclusive_group()
+ lock_group.add_argument(
+ '--lock-volume',
+ action="store_true",
+ help=_("If specified, the volume state will be locked "
+ "and will not allow a migration to be aborted "
+ "(possibly by another operation)")
+ )
+ lock_group.add_argument(
+ '--unlock-volume',
+ action="store_true",
+ help=_("If specified, the volume state will not be "
+ "locked and the a migration can be aborted "
+ "(default) (possibly by another operation)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ volume_client.volumes.migrate_volume(volume.id, parsed_args.host,
+ parsed_args.force_host_copy,
+ parsed_args.lock_volume,)
+
+
class SetVolume(command.Command):
- """Set volume properties"""
+ _description = _("Set volume properties")
def get_parser(self, prog_name):
parser = super(SetVolume, self).get_parser(prog_name)
@@ -462,6 +509,19 @@ class SetVolume(command.Command):
'in the database with no regard to actual status, '
'exercise caution when using)'),
)
+ parser.add_argument(
+ '--type',
+ metavar='<volume-type>',
+ help=_('New volume type (name or ID)'),
+ )
+ parser.add_argument(
+ '--retype-policy',
+ metavar='<retype-policy>',
+ choices=['never', 'on-demand'],
+ help=_('Migration policy while re-typing volume '
+ '("never" or "on-demand", default is "never" ) '
+ '(available only when "--type" option is specified)'),
+ )
bootable_group = parser.add_mutually_exclusive_group()
bootable_group.add_argument(
"--bootable",
@@ -473,6 +533,17 @@ class SetVolume(command.Command):
action="store_true",
help=_("Mark volume as non-bootable")
)
+ readonly_group = parser.add_mutually_exclusive_group()
+ readonly_group.add_argument(
+ "--read-only",
+ action="store_true",
+ help=_("Set volume to read-only access mode")
+ )
+ readonly_group.add_argument(
+ "--read-write",
+ action="store_true",
+ help=_("Set volume to read-write access mode")
+ )
return parser
def take_action(self, parsed_args):
@@ -523,6 +594,37 @@ class SetVolume(command.Command):
except Exception as e:
LOG.error(_("Failed to set volume bootable property: %s"), e)
result += 1
+ if parsed_args.read_only or parsed_args.read_write:
+ try:
+ volume_client.volumes.update_readonly_flag(
+ volume.id,
+ parsed_args.read_only)
+ except Exception as e:
+ LOG.error(_("Failed to set volume read-only access "
+ "mode flag: %s"), e)
+ result += 1
+ if parsed_args.type:
+ # get the migration policy
+ migration_policy = 'never'
+ if parsed_args.retype_policy:
+ migration_policy = parsed_args.retype_policy
+ try:
+ # find the volume type
+ volume_type = utils.find_resource(
+ volume_client.volume_types,
+ parsed_args.type)
+ # reset to the new volume type
+ volume_client.volumes.retype(
+ volume.id,
+ volume_type.id,
+ migration_policy)
+ except Exception as e:
+ LOG.error(_("Failed to set volume type: %s"), e)
+ result += 1
+ elif parsed_args.retype_policy:
+ # If the "--retype-policy" is specified without "--type"
+ LOG.warning(_("'--retype-policy' option will not work "
+ "without '--type' option"))
kwargs = {}
if parsed_args.name:
@@ -543,7 +645,7 @@ class SetVolume(command.Command):
class ShowVolume(command.ShowOne):
- """Display volume details"""
+ _description = _("Display volume details")
def get_parser(self, prog_name):
parser = super(ShowVolume, self).get_parser(prog_name)
@@ -574,7 +676,7 @@ class ShowVolume(command.ShowOne):
class UnsetVolume(command.Command):
- """Unset volume properties"""
+ _description = _("Unset volume properties")
def get_parser(self, prog_name):
parser = super(UnsetVolume, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py
index 9008fe3c..aefe594a 100644
--- a/openstackclient/volume/v2/volume_transfer_request.py
+++ b/openstackclient/volume/v2/volume_transfer_request.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class AcceptTransferRequest(command.ShowOne):
- """Accept volume transfer request."""
+ _description = _("Accept volume transfer request.")
def get_parser(self, prog_name):
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
@@ -56,7 +56,7 @@ class AcceptTransferRequest(command.ShowOne):
class CreateTransferRequest(command.ShowOne):
- """Create volume transfer request."""
+ _description = _("Create volume transfer request.")
def get_parser(self, prog_name):
parser = super(CreateTransferRequest, self).get_parser(prog_name)
@@ -85,7 +85,7 @@ class CreateTransferRequest(command.ShowOne):
class DeleteTransferRequest(command.Command):
- """Delete volume transfer request(s)."""
+ _description = _("Delete volume transfer request(s).")
def get_parser(self, prog_name):
parser = super(DeleteTransferRequest, self).get_parser(prog_name)
@@ -120,7 +120,7 @@ class DeleteTransferRequest(command.Command):
class ListTransferRequest(command.Lister):
- """Lists all volume transfer requests."""
+ _description = _("Lists all volume transfer requests.")
def get_parser(self, prog_name):
parser = super(ListTransferRequest, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class ListTransferRequest(command.Lister):
class ShowTransferRequest(command.ShowOne):
- """Show volume transfer request details."""
+ _description = _("Show volume transfer request details.")
def get_parser(self, prog_name):
parser = super(ShowTransferRequest, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 80a1f21b..42ebb53e 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeType(command.ShowOne):
- """Create new volume type"""
+ _description = _("Create new volume type")
def get_parser(self, prog_name):
parser = super(CreateVolumeType, self).get_parser(prog_name)
@@ -116,7 +116,7 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type(s)"""
+ _description = _("Delete volume type(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
@@ -152,7 +152,7 @@ class DeleteVolumeType(command.Command):
class ListVolumeType(command.Lister):
- """List volume types"""
+ _description = _("List volume types")
def get_parser(self, prog_name):
parser = super(ListVolumeType, self).get_parser(prog_name)
@@ -176,10 +176,11 @@ class ListVolumeType(command.Lister):
def take_action(self, parsed_args):
if parsed_args.long:
- columns = ['ID', 'Name', 'Description', 'Extra Specs']
- column_headers = ['ID', 'Name', 'Description', 'Properties']
+ columns = ['ID', 'Name', 'Is Public', 'Description', 'Extra Specs']
+ column_headers = [
+ 'ID', 'Name', 'Is Public', 'Description', 'Properties']
else:
- columns = ['ID', 'Name']
+ columns = ['ID', 'Name', 'Is Public']
column_headers = columns
is_public = None
@@ -197,7 +198,7 @@ class ListVolumeType(command.Lister):
class SetVolumeType(command.Command):
- """Set volume type properties"""
+ _description = _("Set volume type properties")
def get_parser(self, prog_name):
parser = super(SetVolumeType, self).get_parser(prog_name)
@@ -213,7 +214,7 @@ class SetVolumeType(command.Command):
)
parser.add_argument(
'--description',
- metavar='<name>',
+ metavar='<description>',
help=_('Set volume type description'),
)
parser.add_argument(
@@ -286,7 +287,7 @@ class SetVolumeType(command.Command):
class ShowVolumeType(command.ShowOne):
- """Display volume type details"""
+ _description = _("Display volume type details")
def get_parser(self, prog_name):
parser = super(ShowVolumeType, self).get_parser(prog_name)
@@ -324,7 +325,7 @@ class ShowVolumeType(command.ShowOne):
class UnsetVolumeType(command.Command):
- """Unset volume type properties"""
+ _description = _("Unset volume type properties")
def get_parser(self, prog_name):
parser = super(UnsetVolumeType, self).get_parser(prog_name)