diff options
| author | Jenkins <jenkins@review.openstack.org> | 2016-12-03 04:30:51 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2016-12-03 04:30:51 +0000 |
| commit | e05c8d7bb04f477797e46e5728e93a35c104809a (patch) | |
| tree | cc46ac44bae654c3a2a5b71839a87051a6ca7800 /openstackclient/volume | |
| parent | 2fd5ca22f642591e861d3615040feb534479b013 (diff) | |
| parent | 23ee2fd8f060ed312a84eb03c99494e8af2ffb6f (diff) | |
| download | python-openstackclient-e05c8d7bb04f477797e46e5728e93a35c104809a.tar.gz | |
Merge "Refactor "snapshot" commands"
Diffstat (limited to 'openstackclient/volume')
| -rw-r--r-- | openstackclient/volume/v1/snapshot.py | 18 | ||||
| -rw-r--r-- | openstackclient/volume/v1/volume_snapshot.py | 305 | ||||
| -rw-r--r-- | openstackclient/volume/v2/snapshot.py | 18 | ||||
| -rw-r--r-- | openstackclient/volume/v2/volume_snapshot.py | 338 |
4 files changed, 679 insertions, 0 deletions
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py index 0f91ee72..e9e3894b 100644 --- a/openstackclient/volume/v1/snapshot.py +++ b/openstackclient/volume/v1/snapshot.py @@ -13,6 +13,10 @@ # under the License. # +# TODO(Huanxuan Ao): Remove this file and "snapshot create", "snapshot delete", +# "snapshot set", "snapshot show" and "snapshot unset" +# commands two cycles after Ocata. + """Volume v1 Snapshot action implementations""" import copy @@ -27,6 +31,8 @@ import six from openstackclient.i18n import _ +deprecated = True +LOG_DEP = logging.getLogger('deprecated') LOG = logging.getLogger(__name__) @@ -61,6 +67,8 @@ class CreateSnapshot(command.ShowOne): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot create" instead.')) volume_client = self.app.client_manager.volume volume_id = utils.find_resource(volume_client.volumes, parsed_args.volume).id @@ -92,6 +100,8 @@ class DeleteSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot delete" instead.')) volume_client = self.app.client_manager.volume result = 0 @@ -133,6 +143,8 @@ class ListSnapshot(command.Lister): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot list" instead.')) def _format_volume_id(volume_id): """Return a volume name if available @@ -214,6 +226,8 @@ class SetSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot set" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) @@ -258,6 +272,8 @@ class ShowSnapshot(command.ShowOne): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot show" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) @@ -289,6 +305,8 @@ class UnsetSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot unset" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) diff --git a/openstackclient/volume/v1/volume_snapshot.py b/openstackclient/volume/v1/volume_snapshot.py new file mode 100644 index 00000000..c2ecf75b --- /dev/null +++ b/openstackclient/volume/v1/volume_snapshot.py @@ -0,0 +1,305 @@ +# Copyright 2012-2013 OpenStack Foundation +# +# 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 v1 Snapshot action implementations""" + +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 +import six + +from openstackclient.i18n import _ + + +LOG = logging.getLogger(__name__) + + +class CreateVolumeSnapshot(command.ShowOne): + """Create new volume snapshot""" + + def get_parser(self, prog_name): + parser = super(CreateVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot_name', + metavar='<snapshot-name>', + nargs="?", + help=_('Name of the snapshot (default to None)'), + ) + parser.add_argument( + '--volume', + metavar='<volume>', + help=_('Volume to snapshot (name or ID) ' + '(default is <snapshot-name>)'), + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('Description of the snapshot'), + ) + parser.add_argument( + '--force', + dest='force', + action='store_true', + default=False, + help=_('Create a snapshot attached to an instance. ' + 'Default is False'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + volume = parsed_args.volume + if not parsed_args.volume: + volume = parsed_args.snapshot_name + volume_id = utils.find_resource(volume_client.volumes, + volume).id + snapshot = volume_client.volume_snapshots.create( + volume_id, + parsed_args.force, + parsed_args.snapshot_name, + parsed_args.description + ) + + snapshot._info.update( + {'properties': utils.format_dict(snapshot._info.pop('metadata'))} + ) + + return zip(*sorted(six.iteritems(snapshot._info))) + + +class DeleteVolumeSnapshot(command.Command): + """Delete volume snapshot(s)""" + + def get_parser(self, prog_name): + parser = super(DeleteVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshots', + metavar='<snapshot>', + nargs="+", + help=_('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 i in parsed_args.snapshots: + try: + snapshot_id = utils.find_resource( + volume_client.volume_snapshots, i).id + volume_client.volume_snapshots.delete(snapshot_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete snapshot with " + "name or ID '%(snapshot)s': %(e)s"), + {'snapshot': i, 'e': e}) + + if result > 0: + total = len(parsed_args.snapshots) + msg = (_("%(result)s of %(total)s snapshots failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + + +class ListVolumeSnapshot(command.Lister): + """List volume snapshots""" + + def get_parser(self, prog_name): + parser = super(ListVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + '--all-projects', + action='store_true', + default=False, + help=_('Include all projects (admin only)'), + ) + parser.add_argument( + '--long', + action='store_true', + default=False, + help=_('List additional fields in output'), + ) + return parser + + def take_action(self, parsed_args): + + 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].display_name + return volume + + if parsed_args.long: + columns = ['ID', 'Display Name', 'Display Description', 'Status', + 'Size', 'Created At', 'Volume ID', 'Metadata'] + column_headers = copy.deepcopy(columns) + column_headers[6] = 'Volume' + column_headers[7] = 'Properties' + else: + columns = ['ID', 'Display Name', 'Display Description', 'Status', + 'Size'] + column_headers = copy.deepcopy(columns) + + # Always update Name and Description + column_headers[1] = 'Name' + column_headers[2] = 'Description' + + # Cache the volume list + volume_cache = {} + try: + for s in self.app.client_manager.volume.volumes.list(): + volume_cache[s.id] = s + except Exception: + # Just forget it if there's any trouble + pass + + search_opts = { + 'all_tenants': parsed_args.all_projects, + } + + data = self.app.client_manager.volume.volume_snapshots.list( + search_opts=search_opts) + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters={'Metadata': utils.format_dict, + 'Volume ID': _format_volume_id}, + ) for s in data)) + + +class SetVolumeSnapshot(command.Command): + """Set volume snapshot properties""" + + def get_parser(self, prog_name): + parser = super(SetVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot', + metavar='<snapshot>', + help=_('Snapshot to modify (name or ID)') + ) + parser.add_argument( + '--name', + metavar='<name>', + help=_('New snapshot name') + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('New snapshot description') + ) + parser.add_argument( + '--property', + metavar='<key=value>', + action=parseractions.KeyValueAction, + help=_('Property to add/change for this snapshot ' + '(repeat option to set multiple properties)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource(volume_client.volume_snapshots, + parsed_args.snapshot) + + result = 0 + if parsed_args.property: + try: + volume_client.volume_snapshots.set_metadata( + snapshot.id, parsed_args.property) + except Exception as e: + LOG.error(_("Failed to set snapshot property: %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: + try: + snapshot.update(**kwargs) + except Exception as e: + LOG.error(_("Failed to update snapshot display name " + "or display description: %s"), e) + result += 1 + + if result > 0: + raise exceptions.CommandError(_("One or more of the " + "set operations failed")) + + +class ShowVolumeSnapshot(command.ShowOne): + """Display volume snapshot details""" + + def get_parser(self, prog_name): + parser = super(ShowVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot', + metavar='<snapshot>', + help=_('Snapshot to display (name or ID)') + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource(volume_client.volume_snapshots, + parsed_args.snapshot) + + snapshot._info.update( + {'properties': utils.format_dict(snapshot._info.pop('metadata'))} + ) + + return zip(*sorted(six.iteritems(snapshot._info))) + + +class UnsetVolumeSnapshot(command.Command): + """Unset volume snapshot properties""" + + def get_parser(self, prog_name): + parser = super(UnsetVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot', + metavar='<snapshot>', + help=_('Snapshot to modify (name or ID)'), + ) + parser.add_argument( + '--property', + metavar='<key>', + action='append', + help=_('Property to remove from snapshot ' + '(repeat option to remove multiple properties)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource( + volume_client.volume_snapshots, parsed_args.snapshot) + + if parsed_args.property: + volume_client.volume_snapshots.delete_metadata( + snapshot.id, + parsed_args.property, + ) diff --git a/openstackclient/volume/v2/snapshot.py b/openstackclient/volume/v2/snapshot.py index 8cda112a..a18887e3 100644 --- a/openstackclient/volume/v2/snapshot.py +++ b/openstackclient/volume/v2/snapshot.py @@ -12,6 +12,10 @@ # under the License. # +# TODO(Huanxuan Ao): Remove this file and "snapshot create", "snapshot delete", +# "snapshot set", "snapshot show" and "snapshot unset" +# commands two cycles after Ocata. + """Volume v2 snapshot action implementations""" import copy @@ -26,6 +30,8 @@ import six from openstackclient.i18n import _ +deprecated = True +LOG_DEP = logging.getLogger('deprecated') LOG = logging.getLogger(__name__) @@ -66,6 +72,8 @@ class CreateSnapshot(command.ShowOne): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot create" instead.')) volume_client = self.app.client_manager.volume volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id @@ -96,6 +104,8 @@ class DeleteSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot delete" instead.')) volume_client = self.app.client_manager.volume result = 0 @@ -149,6 +159,8 @@ class ListSnapshot(command.Lister): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot list" instead.')) def _format_volume_id(volume_id): """Return a volume name if available @@ -239,6 +251,8 @@ class SetSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot set" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) @@ -292,6 +306,8 @@ class ShowSnapshot(command.ShowOne): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot show" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) @@ -322,6 +338,8 @@ class UnsetSnapshot(command.Command): return parser def take_action(self, parsed_args): + LOG_DEP.warning(_('This command has been deprecated. ' + 'Please use "volume snapshot unset" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py new file mode 100644 index 00000000..43f30326 --- /dev/null +++ b/openstackclient/volume/v2/volume_snapshot.py @@ -0,0 +1,338 @@ +# +# 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 snapshot action implementations""" + +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 +import six + +from openstackclient.i18n import _ + + +LOG = logging.getLogger(__name__) + + +class CreateVolumeSnapshot(command.ShowOne): + """Create new volume snapshot""" + + def get_parser(self, prog_name): + parser = super(CreateVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + "snapshot_name", + metavar="<snapshot-name>", + nargs="?", + help=_("Name of the new snapshot (default to None)") + ) + parser.add_argument( + "--volume", + metavar="<volume>", + help=_("Volume to snapshot (name or ID) " + "(default is <snapshot-name>)") + ) + parser.add_argument( + "--description", + metavar="<description>", + help=_("Description of the snapshot") + ) + parser.add_argument( + "--force", + action="store_true", + default=False, + help=_("Create a snapshot attached to an instance. " + "Default is False") + ) + parser.add_argument( + "--property", + metavar="<key=value>", + action=parseractions.KeyValueAction, + help=_("Set a property to this snapshot " + "(repeat option to set multiple properties)"), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + volume = parsed_args.volume + if not parsed_args.volume: + volume = parsed_args.snapshot_name + volume_id = utils.find_resource( + volume_client.volumes, volume).id + snapshot = volume_client.volume_snapshots.create( + volume_id, + force=parsed_args.force, + name=parsed_args.snapshot_name, + description=parsed_args.description, + metadata=parsed_args.property, + ) + snapshot._info.update( + {'properties': utils.format_dict(snapshot._info.pop('metadata'))} + ) + return zip(*sorted(six.iteritems(snapshot._info))) + + +class DeleteVolumeSnapshot(command.Command): + """Delete volume snapshot(s)""" + + def get_parser(self, prog_name): + parser = super(DeleteVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + "snapshots", + metavar="<snapshot>", + nargs="+", + help=_("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 i in parsed_args.snapshots: + try: + snapshot_id = utils.find_resource( + volume_client.volume_snapshots, i).id + volume_client.volume_snapshots.delete(snapshot_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete snapshot with " + "name or ID '%(snapshot)s': %(e)s") + % {'snapshot': i, 'e': e}) + + if result > 0: + total = len(parsed_args.snapshots) + msg = (_("%(result)s of %(total)s snapshots failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + + +class ListVolumeSnapshot(command.Lister): + """List volume snapshots""" + + def get_parser(self, prog_name): + parser = super(ListVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + '--all-projects', + action='store_true', + default=False, + help=_('Include all projects (admin only)'), + ) + parser.add_argument( + '--long', + action='store_true', + default=False, + help=_('List additional fields in output'), + ) + parser.add_argument( + '--marker', + metavar='<marker>', + help=_('The last snapshot ID of the previous page'), + ) + parser.add_argument( + '--limit', + type=int, + action=parseractions.NonNegativeAction, + metavar='<limit>', + help=_('Maximum number of snapshots to display'), + ) + return parser + + def take_action(self, parsed_args): + + 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'] + column_headers = copy.deepcopy(columns) + column_headers[6] = 'Volume' + column_headers[7] = 'Properties' + else: + columns = ['ID', 'Name', 'Description', 'Status', 'Size'] + column_headers = copy.deepcopy(columns) + + # Cache the volume list + volume_cache = {} + try: + for s in self.app.client_manager.volume.volumes.list(): + volume_cache[s.id] = s + except Exception: + # Just forget it if there's any trouble + pass + + search_opts = { + 'all_tenants': parsed_args.all_projects, + } + + data = self.app.client_manager.volume.volume_snapshots.list( + search_opts=search_opts, + marker=parsed_args.marker, + limit=parsed_args.limit, + ) + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters={'Metadata': utils.format_dict, + 'Volume ID': _format_volume_id}, + ) for s in data)) + + +class SetVolumeSnapshot(command.Command): + """Set volume snapshot properties""" + + def get_parser(self, prog_name): + parser = super(SetVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot', + metavar='<snapshot>', + help=_('Snapshot to modify (name or ID)') + ) + parser.add_argument( + '--name', + metavar='<name>', + help=_('New snapshot name') + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('New snapshot description') + ) + parser.add_argument( + '--property', + metavar='<key=value>', + action=parseractions.KeyValueAction, + help=_('Property to add/change for this snapshot ' + '(repeat option to set multiple properties)'), + ) + parser.add_argument( + '--state', + metavar='<state>', + choices=['available', 'error', 'creating', 'deleting', + 'error-deleting'], + help=_('New snapshot state. ("available", "error", "creating", ' + '"deleting", or "error_deleting") (admin only) ' + '(This option simply changes the state of the snapshot ' + 'in the database with no regard to actual status, ' + 'exercise caution when using)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource(volume_client.volume_snapshots, + parsed_args.snapshot) + + result = 0 + if parsed_args.property: + try: + volume_client.volume_snapshots.set_metadata( + snapshot.id, parsed_args.property) + except Exception as e: + LOG.error(_("Failed to set snapshot property: %s"), e) + result += 1 + + if parsed_args.state: + try: + volume_client.volume_snapshots.reset_state( + snapshot.id, parsed_args.state) + except Exception as e: + LOG.error(_("Failed to set snapshot state: %s"), e) + result += 1 + + kwargs = {} + if parsed_args.name: + kwargs['name'] = parsed_args.name + if parsed_args.description: + kwargs['description'] = parsed_args.description + if kwargs: + try: + volume_client.volume_snapshots.update( + snapshot.id, **kwargs) + except Exception as e: + LOG.error(_("Failed to update snapshot name " + "or description: %s"), e) + result += 1 + + if result > 0: + raise exceptions.CommandError(_("One or more of the " + "set operations failed")) + + +class ShowVolumeSnapshot(command.ShowOne): + """Display volume snapshot details""" + + def get_parser(self, prog_name): + parser = super(ShowVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + "snapshot", + metavar="<snapshot>", + help=_("Snapshot to display (name or ID)") + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource( + volume_client.volume_snapshots, parsed_args.snapshot) + snapshot._info.update( + {'properties': utils.format_dict(snapshot._info.pop('metadata'))} + ) + return zip(*sorted(six.iteritems(snapshot._info))) + + +class UnsetVolumeSnapshot(command.Command): + """Unset volume snapshot properties""" + + def get_parser(self, prog_name): + parser = super(UnsetVolumeSnapshot, self).get_parser(prog_name) + parser.add_argument( + 'snapshot', + metavar='<snapshot>', + help=_('Snapshot to modify (name or ID)'), + ) + parser.add_argument( + '--property', + metavar='<key>', + action='append', + default=[], + help=_('Property to remove from snapshot ' + '(repeat option to remove multiple properties)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + snapshot = utils.find_resource( + volume_client.volume_snapshots, parsed_args.snapshot) + + if parsed_args.property: + volume_client.volume_snapshots.delete_metadata( + snapshot.id, + parsed_args.property, + ) |
