From 23ee2fd8f060ed312a84eb03c99494e8af2ffb6f Mon Sep 17 00:00:00 2001 From: Huanxuan Ao Date: Wed, 14 Sep 2016 14:54:29 +0800 Subject: [PATCH] Refactor "snapshot" commands 1.change the command name ``snapshot create/delete/list/ show/set/unset`` to ``volume snapshot create/delete/list/ show/set/unset``. 2.change the optional parameter "--name " to a positional parameter ""; Change the positional parameter "" to a optional parameter "--volume " Change-Id: If03276ecdf6f0d96893d5ecf91c2aaa64929cff3 Implements: bp backup-snapshot-renamed-for-volume-resource Co-Authored-By: Sheel Rana --- doc/source/command-objects/snapshot.rst | 6 + .../command-objects/volume-snapshot.rst | 171 +++++++++ doc/source/commands.rst | 3 +- .../functional/volume/v1/test_snapshot.py | 32 +- .../functional/volume/v2/test_snapshot.py | 32 +- .../tests/functional/volume/v2/test_volume.py | 10 +- .../tests/unit/volume/v1/test_snapshot.py | 50 ++- .../tests/unit/volume/v2/test_snapshot.py | 51 ++- openstackclient/volume/v1/snapshot.py | 18 + openstackclient/volume/v1/volume_snapshot.py | 305 ++++++++++++++++ openstackclient/volume/v2/snapshot.py | 18 + openstackclient/volume/v2/volume_snapshot.py | 338 ++++++++++++++++++ ...me-snapshot-commands-e0937f7143a4ef55.yaml | 8 + setup.cfg | 14 + 14 files changed, 996 insertions(+), 60 deletions(-) create mode 100644 doc/source/command-objects/volume-snapshot.rst create mode 100644 openstackclient/volume/v1/volume_snapshot.py create mode 100644 openstackclient/volume/v2/volume_snapshot.py create mode 100644 releasenotes/notes/rename-snapshot-commands-e0937f7143a4ef55.yaml diff --git a/doc/source/command-objects/snapshot.rst b/doc/source/command-objects/snapshot.rst index a2709adbe5..e75693ca18 100644 --- a/doc/source/command-objects/snapshot.rst +++ b/doc/source/command-objects/snapshot.rst @@ -8,6 +8,7 @@ snapshot create --------------- Create new snapshot +(Deprecated, please use ``volume snapshot create`` instead) .. program:: snapshot create .. code:: bash @@ -46,6 +47,7 @@ snapshot delete --------------- Delete snapshot(s) +(Deprecated, please use ``volume snapshot delete`` instead) .. program:: snapshot delete .. code:: bash @@ -62,6 +64,7 @@ snapshot list ------------- List snapshots +(Deprecated, please use ``volume snapshot list`` instead) .. program:: snapshot list .. code:: bash @@ -96,6 +99,7 @@ snapshot set ------------ Set snapshot properties +(Deprecated, please use ``volume snapshot set`` instead) .. program:: snapshot set .. code:: bash @@ -137,6 +141,7 @@ snapshot show ------------- Display snapshot details +(Deprecated, please use ``volume snapshot show`` instead) .. program:: snapshot show .. code:: bash @@ -153,6 +158,7 @@ snapshot unset -------------- Unset snapshot properties +(Deprecated, please use ``volume snapshot unset`` instead) .. program:: snapshot unset .. code:: bash diff --git a/doc/source/command-objects/volume-snapshot.rst b/doc/source/command-objects/volume-snapshot.rst new file mode 100644 index 0000000000..b84601f464 --- /dev/null +++ b/doc/source/command-objects/volume-snapshot.rst @@ -0,0 +1,171 @@ +=============== +volume snapshot +=============== + +Block Storage v1, v2 + +volume snapshot create +---------------------- + +Create new volume snapshot + +.. program:: volume snapshot create +.. code:: bash + + os volume snapshot create + [--volume ] + [--description ] + [--force] + [--property [...] ] + + +.. option:: --volume + + Volume to snapshot (name or ID) (default is ) + +.. option:: --description + + Description of the snapshot + +.. option:: --force + + Create a snapshot attached to an instance. Default is False + +.. option:: --property + + Set a property to this snapshot (repeat option to set multiple properties) + + *Volume version 2 only* + +.. _volume_snapshot_create-snapshot-name: +.. describe:: + + Name of the new snapshot (default to None) + +volume snapshot delete +---------------------- + +Delete volume snapshot(s) + +.. program:: volume snapshot delete +.. code:: bash + + os volume snapshot delete + [ ...] + +.. _volume_snapshot_delete-snapshot: +.. describe:: + + Snapshot(s) to delete (name or ID) + +volume snapshot list +-------------------- + +List volume snapshots + +.. program:: volume snapshot list +.. code:: bash + + os volume snapshot list + [--all-projects] + [--long] + [--limit ] + [--marker ] + +.. option:: --all-projects + + Include all projects (admin only) + +.. option:: --long + + List additional fields in output + +.. option:: --limit + + Maximum number of snapshots to display + + *Volume version 2 only* + +.. option:: --marker + + The last snapshot ID of the previous page + + *Volume version 2 only* + +volume snapshot set +------------------- + +Set volume snapshot properties + +.. program:: volume snapshot set +.. code:: bash + + os volume snapshot set + [--name ] + [--description ] + [--property [...] ] + [--state ] + + +.. option:: --name + + New snapshot name + +.. option:: --description + + New snapshot description + +.. option:: --property + + Property to add or modify for this snapshot (repeat option to set multiple properties) + +.. option:: --state + + 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) + + *Volume version 2 only* + +.. _volume_snapshot_set-snapshot: +.. describe:: + + Snapshot to modify (name or ID) + +volume snapshot show +-------------------- + +Display volume snapshot details + +.. program:: volume snapshot show +.. code:: bash + + os volume snapshot show + + +.. _volume_snapshot_show-snapshot: +.. describe:: + + Snapshot to display (name or ID) + +volume snapshot unset +--------------------- + +Unset volume snapshot properties + +.. program:: volume snapshot unset +.. code:: bash + + os volume snapshot unset + [--property ] + + +.. option:: --property + + Property to remove from snapshot (repeat option to remove multiple properties) + +.. _volume_snapshot_unset-snapshot: +.. describe:: + + Snapshot to modify (name or ID) diff --git a/doc/source/commands.rst b/doc/source/commands.rst index 3e0f932eeb..36c48b0e2b 100644 --- a/doc/source/commands.rst +++ b/doc/source/commands.rst @@ -74,7 +74,6 @@ referring to both Compute and Volume quotas. * ``address scope``: (**Network**) a scope of IPv4 or IPv6 addresses * ``aggregate``: (**Compute**) a grouping of compute hosts * ``availability zone``: (**Compute**, **Network**, **Volume**) a logical partition of hosts or block storage or network services -* ``backup``: (**Volume**) a volume copy * ``catalog``: (**Identity**) service catalog * ``command``: (**Internal**) installed commands in the OSC process * ``compute agent``: (**Compute**) a cloud Compute agent available to a hypervisor @@ -134,7 +133,6 @@ referring to both Compute and Volume quotas. * ``server image``: (**Compute**) saved server disk image * ``service``: (**Identity**) a cloud service * ``service provider``: (**Identity**) a resource that consumes assertions from an ``identity provider`` -* ``snapshot``: (**Volume**) a point-in-time copy of a volume * ``subnet``: (**Network**) - a contiguous range of IP addresses assigned to a network * ``subnet pool``: (**Network**) - a pool of subnets * ``token``: (**Identity**) a bearer token managed by Identity service @@ -145,6 +143,7 @@ referring to both Compute and Volume quotas. * ``volume``: (**Volume**) block volumes * ``volume backup``: (**Volume**) backup for volumes * ``volume qos``: (**Volume**) quality-of-service (QoS) specification for volumes +* ``volume snapshot``: (**Volume**) a point-in-time copy of a volume * ``volume type``: (**Volume**) deployment-specific types of volumes available * ``volume service``: (**Volume**) services to manage block storage operations * ``volume transfer request``: (**Volume**) volume owner transfer request diff --git a/openstackclient/tests/functional/volume/v1/test_snapshot.py b/openstackclient/tests/functional/volume/v1/test_snapshot.py index c6d65ccc60..1e1c6b2144 100644 --- a/openstackclient/tests/functional/volume/v1/test_snapshot.py +++ b/openstackclient/tests/functional/volume/v1/test_snapshot.py @@ -16,8 +16,8 @@ import uuid from openstackclient.tests.functional.volume.v1 import common -class SnapshotTests(common.BaseVolumeTests): - """Functional tests for snapshot. """ +class VolumeSnapshotTests(common.BaseVolumeTests): + """Functional tests for volume snapshot. """ VOLLY = uuid.uuid4().hex NAME = uuid.uuid4().hex @@ -36,24 +36,25 @@ class SnapshotTests(common.BaseVolumeTests): @classmethod def setUpClass(cls): - super(SnapshotTests, cls).setUpClass() + super(VolumeSnapshotTests, cls).setUpClass() cls.openstack('volume create --size 1 ' + cls.VOLLY) cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3) opts = cls.get_opts(['status']) - raw_output = cls.openstack('snapshot create --name ' + cls.NAME + - ' ' + cls.VOLLY + opts) + raw_output = cls.openstack('volume snapshot create --volume ' + + cls.VOLLY + ' ' + cls.NAME + opts) cls.assertOutput('creating\n', raw_output) - cls.wait_for_status('snapshot show ' + cls.NAME, 'available\n', 3) + cls.wait_for_status( + 'volume snapshot show ' + cls.NAME, 'available\n', 3) @classmethod def tearDownClass(cls): # Rename test raw_output = cls.openstack( - 'snapshot set --name ' + cls.OTHER_NAME + ' ' + cls.NAME) + 'volume snapshot set --name ' + cls.OTHER_NAME + ' ' + cls.NAME) cls.assertOutput('', raw_output) # Delete test raw_output_snapshot = cls.openstack( - 'snapshot delete ' + cls.OTHER_NAME) + 'volume snapshot delete ' + cls.OTHER_NAME) cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6) raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY) cls.assertOutput('', raw_output_snapshot) @@ -61,26 +62,27 @@ class SnapshotTests(common.BaseVolumeTests): def test_snapshot_list(self): opts = self.get_opts(self.HEADERS) - raw_output = self.openstack('snapshot list' + opts) + raw_output = self.openstack('volume snapshot list' + opts) self.assertIn(self.NAME, raw_output) def test_snapshot_set_unset_properties(self): raw_output = self.openstack( - 'snapshot set --property a=b --property c=d ' + self.NAME) + 'volume snapshot set --property a=b --property c=d ' + self.NAME) self.assertEqual("", raw_output) opts = self.get_opts(["properties"]) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("a='b', c='d'\n", raw_output) - raw_output = self.openstack('snapshot unset --property a ' + self.NAME) + raw_output = self.openstack( + 'volume snapshot unset --property a ' + self.NAME) self.assertEqual("", raw_output) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("c='d'\n", raw_output) def test_snapshot_set_description(self): raw_output = self.openstack( - 'snapshot set --description backup ' + self.NAME) + 'volume snapshot set --description backup ' + self.NAME) self.assertEqual("", raw_output) opts = self.get_opts(["display_description", "display_name"]) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("backup\n" + self.NAME + "\n", raw_output) diff --git a/openstackclient/tests/functional/volume/v2/test_snapshot.py b/openstackclient/tests/functional/volume/v2/test_snapshot.py index fcbc31cbec..4eb69e9d7f 100644 --- a/openstackclient/tests/functional/volume/v2/test_snapshot.py +++ b/openstackclient/tests/functional/volume/v2/test_snapshot.py @@ -16,8 +16,8 @@ import uuid from openstackclient.tests.functional.volume.v2 import common -class SnapshotTests(common.BaseVolumeTests): - """Functional tests for snapshot. """ +class VolumeSnapshotTests(common.BaseVolumeTests): + """Functional tests for volume snapshot. """ VOLLY = uuid.uuid4().hex NAME = uuid.uuid4().hex @@ -36,24 +36,25 @@ class SnapshotTests(common.BaseVolumeTests): @classmethod def setUpClass(cls): - super(SnapshotTests, cls).setUpClass() + super(VolumeSnapshotTests, cls).setUpClass() cls.openstack('volume create --size 1 ' + cls.VOLLY) cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3) opts = cls.get_opts(['status']) - raw_output = cls.openstack('snapshot create --name ' + cls.NAME + - ' ' + cls.VOLLY + opts) + raw_output = cls.openstack('volume snapshot create --volume ' + + cls.VOLLY + ' ' + cls.NAME + opts) cls.assertOutput('creating\n', raw_output) - cls.wait_for_status('snapshot show ' + cls.NAME, 'available\n', 3) + cls.wait_for_status( + 'volume snapshot show ' + cls.NAME, 'available\n', 3) @classmethod def tearDownClass(cls): # Rename test raw_output = cls.openstack( - 'snapshot set --name ' + cls.OTHER_NAME + ' ' + cls.NAME) + 'volume snapshot set --name ' + cls.OTHER_NAME + ' ' + cls.NAME) cls.assertOutput('', raw_output) # Delete test raw_output_snapshot = cls.openstack( - 'snapshot delete ' + cls.OTHER_NAME) + 'volume snapshot delete ' + cls.OTHER_NAME) cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6) raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY) cls.assertOutput('', raw_output_snapshot) @@ -61,26 +62,27 @@ class SnapshotTests(common.BaseVolumeTests): def test_snapshot_list(self): opts = self.get_opts(self.HEADERS) - raw_output = self.openstack('snapshot list' + opts) + raw_output = self.openstack('volume snapshot list' + opts) self.assertIn(self.NAME, raw_output) def test_snapshot_properties(self): raw_output = self.openstack( - 'snapshot set --property a=b --property c=d ' + self.NAME) + 'volume snapshot set --property a=b --property c=d ' + self.NAME) self.assertEqual("", raw_output) opts = self.get_opts(["properties"]) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("a='b', c='d'\n", raw_output) - raw_output = self.openstack('snapshot unset --property a ' + self.NAME) + raw_output = self.openstack( + 'volume snapshot unset --property a ' + self.NAME) self.assertEqual("", raw_output) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("c='d'\n", raw_output) def test_snapshot_set(self): raw_output = self.openstack( - 'snapshot set --description backup ' + self.NAME) + 'volume snapshot set --description backup ' + self.NAME) self.assertEqual("", raw_output) opts = self.get_opts(["description", "name"]) - raw_output = self.openstack('snapshot show ' + self.NAME + opts) + raw_output = self.openstack('volume snapshot show ' + self.NAME + opts) self.assertEqual("backup\n" + self.NAME + "\n", raw_output) diff --git a/openstackclient/tests/functional/volume/v2/test_volume.py b/openstackclient/tests/functional/volume/v2/test_volume.py index fb880578c9..ea891cba55 100644 --- a/openstackclient/tests/functional/volume/v2/test_volume.py +++ b/openstackclient/tests/functional/volume/v2/test_volume.py @@ -106,11 +106,12 @@ class VolumeTests(common.BaseVolumeTests): opts = self.get_opts(self.FIELDS) # Create snapshot from test volume - raw_output = self.openstack('snapshot create ' + self.NAME + - ' --name ' + self.SNAPSHOT_NAME + opts) + raw_output = self.openstack('volume snapshot create ' + + self.SNAPSHOT_NAME + + ' --volume ' + self.NAME + opts) expected = self.SNAPSHOT_NAME + '\n' self.assertOutput(expected, raw_output) - self.wait_for("snapshot", self.SNAPSHOT_NAME, "available") + self.wait_for("volume snapshot", self.SNAPSHOT_NAME, "available") # Create volume from snapshot raw_output = self.openstack('volume create --size 2 --snapshot ' + @@ -126,7 +127,8 @@ class VolumeTests(common.BaseVolumeTests): self.assertOutput('', raw_output) # Delete test snapshot - raw_output = self.openstack('snapshot delete ' + self.SNAPSHOT_NAME) + raw_output = self.openstack( + 'volume snapshot delete ' + self.SNAPSHOT_NAME) self.assertOutput('', raw_output) self.wait_for("volume", self.NAME, "available") diff --git a/openstackclient/tests/unit/volume/v1/test_snapshot.py b/openstackclient/tests/unit/volume/v1/test_snapshot.py index edfbdc190c..8e30d6a9d5 100644 --- a/openstackclient/tests/unit/volume/v1/test_snapshot.py +++ b/openstackclient/tests/unit/volume/v1/test_snapshot.py @@ -19,7 +19,7 @@ from osc_lib import exceptions from osc_lib import utils from openstackclient.tests.unit.volume.v1 import fakes as volume_fakes -from openstackclient.volume.v1 import snapshot +from openstackclient.volume.v1 import volume_snapshot class TestSnapshot(volume_fakes.TestVolumev1): @@ -67,20 +67,20 @@ class TestSnapshotCreate(TestSnapshot): self.volumes_mock.get.return_value = self.volume self.snapshots_mock.create.return_value = self.new_snapshot # Get the command object to test - self.cmd = snapshot.CreateSnapshot(self.app, None) + self.cmd = volume_snapshot.CreateVolumeSnapshot(self.app, None) def test_snapshot_create(self): arglist = [ - "--name", self.new_snapshot.display_name, + "--volume", self.new_snapshot.volume_id, "--description", self.new_snapshot.display_description, "--force", - self.new_snapshot.volume_id, + self.new_snapshot.display_name, ] verifylist = [ - ("name", self.new_snapshot.display_name), + ("volume", self.new_snapshot.volume_id), ("description", self.new_snapshot.display_description), ("force", True), - ("volume", self.new_snapshot.volume_id), + ("snapshot_name", self.new_snapshot.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -97,7 +97,7 @@ class TestSnapshotCreate(TestSnapshot): def test_snapshot_create_without_name(self): arglist = [ - self.new_snapshot.volume_id, + "--volume", self.new_snapshot.volume_id, "--description", self.new_snapshot.display_description, "--force" ] @@ -119,6 +119,32 @@ class TestSnapshotCreate(TestSnapshot): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_snapshot_create_without_volume(self): + arglist = [ + "--description", self.new_snapshot.display_description, + "--force", + self.new_snapshot.display_name + ] + verifylist = [ + ("description", self.new_snapshot.display_description), + ("force", True), + ("snapshot_name", self.new_snapshot.display_name) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.volumes_mock.get.assert_called_once_with( + self.new_snapshot.display_name) + self.snapshots_mock.create.assert_called_once_with( + self.new_snapshot.volume_id, + True, + self.new_snapshot.display_name, + self.new_snapshot.display_description, + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + class TestSnapshotDelete(TestSnapshot): @@ -132,7 +158,7 @@ class TestSnapshotDelete(TestSnapshot): self.snapshots_mock.delete.return_value = None # Get the command object to mock - self.cmd = snapshot.DeleteSnapshot(self.app, None) + self.cmd = volume_snapshot.DeleteVolumeSnapshot(self.app, None) def test_snapshot_delete(self): arglist = [ @@ -244,7 +270,7 @@ class TestSnapshotList(TestSnapshot): self.volumes_mock.list.return_value = [self.volume] self.snapshots_mock.list.return_value = self.snapshots # Get the command to test - self.cmd = snapshot.ListSnapshot(self.app, None) + self.cmd = volume_snapshot.ListVolumeSnapshot(self.app, None) def test_snapshot_list_without_options(self): arglist = [] @@ -307,7 +333,7 @@ class TestSnapshotSet(TestSnapshot): self.snapshots_mock.get.return_value = self.snapshot self.snapshots_mock.set_metadata.return_value = None # Get the command object to mock - self.cmd = snapshot.SetSnapshot(self.app, None) + self.cmd = volume_snapshot.SetVolumeSnapshot(self.app, None) def test_snapshot_set_all(self): arglist = [ @@ -404,7 +430,7 @@ class TestSnapshotShow(TestSnapshot): self.snapshots_mock.get.return_value = self.snapshot # Get the command object to test - self.cmd = snapshot.ShowSnapshot(self.app, None) + self.cmd = volume_snapshot.ShowVolumeSnapshot(self.app, None) def test_snapshot_show(self): arglist = [ @@ -432,7 +458,7 @@ class TestSnapshotUnset(TestSnapshot): self.snapshots_mock.get.return_value = self.snapshot self.snapshots_mock.delete_metadata.return_value = None # Get the command object to mock - self.cmd = snapshot.UnsetSnapshot(self.app, None) + self.cmd = volume_snapshot.UnsetVolumeSnapshot(self.app, None) def test_snapshot_unset(self): arglist = [ diff --git a/openstackclient/tests/unit/volume/v2/test_snapshot.py b/openstackclient/tests/unit/volume/v2/test_snapshot.py index d355662d8b..b67dd6ebf5 100644 --- a/openstackclient/tests/unit/volume/v2/test_snapshot.py +++ b/openstackclient/tests/unit/volume/v2/test_snapshot.py @@ -20,7 +20,7 @@ from osc_lib import exceptions from osc_lib import utils from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes -from openstackclient.volume.v2 import snapshot +from openstackclient.volume.v2 import volume_snapshot class TestSnapshot(volume_fakes.TestVolume): @@ -68,23 +68,23 @@ class TestSnapshotCreate(TestSnapshot): self.volumes_mock.get.return_value = self.volume self.snapshots_mock.create.return_value = self.new_snapshot # Get the command object to test - self.cmd = snapshot.CreateSnapshot(self.app, None) + self.cmd = volume_snapshot.CreateVolumeSnapshot(self.app, None) def test_snapshot_create(self): arglist = [ - "--name", self.new_snapshot.name, + "--volume", self.new_snapshot.volume_id, "--description", self.new_snapshot.description, "--force", '--property', 'Alpha=a', '--property', 'Beta=b', - self.new_snapshot.volume_id, + self.new_snapshot.name, ] verifylist = [ - ("name", self.new_snapshot.name), + ("volume", self.new_snapshot.volume_id), ("description", self.new_snapshot.description), ("force", True), ('property', {'Alpha': 'a', 'Beta': 'b'}), - ("volume", self.new_snapshot.volume_id), + ("snapshot_name", self.new_snapshot.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -102,7 +102,7 @@ class TestSnapshotCreate(TestSnapshot): def test_snapshot_create_without_name(self): arglist = [ - self.new_snapshot.volume_id, + "--volume", self.new_snapshot.volume_id, "--description", self.new_snapshot.description, "--force" ] @@ -125,6 +125,33 @@ class TestSnapshotCreate(TestSnapshot): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_snapshot_create_without_volume(self): + arglist = [ + "--description", self.new_snapshot.description, + "--force", + self.new_snapshot.name + ] + verifylist = [ + ("description", self.new_snapshot.description), + ("force", True), + ("snapshot_name", self.new_snapshot.name) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.volumes_mock.get.assert_called_once_with( + self.new_snapshot.name) + self.snapshots_mock.create.assert_called_once_with( + self.new_snapshot.volume_id, + force=True, + name=self.new_snapshot.name, + description=self.new_snapshot.description, + metadata=None, + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + class TestSnapshotDelete(TestSnapshot): @@ -138,7 +165,7 @@ class TestSnapshotDelete(TestSnapshot): self.snapshots_mock.delete.return_value = None # Get the command object to mock - self.cmd = snapshot.DeleteSnapshot(self.app, None) + self.cmd = volume_snapshot.DeleteVolumeSnapshot(self.app, None) def test_snapshot_delete(self): arglist = [ @@ -250,7 +277,7 @@ class TestSnapshotList(TestSnapshot): self.volumes_mock.list.return_value = [self.volume] self.snapshots_mock.list.return_value = self.snapshots # Get the command to test - self.cmd = snapshot.ListSnapshot(self.app, None) + self.cmd = volume_snapshot.ListVolumeSnapshot(self.app, None) def test_snapshot_list_without_options(self): arglist = [] @@ -330,7 +357,7 @@ class TestSnapshotSet(TestSnapshot): self.snapshots_mock.set_metadata.return_value = None self.snapshots_mock.update.return_value = None # Get the command object to mock - self.cmd = snapshot.SetSnapshot(self.app, None) + self.cmd = volume_snapshot.SetVolumeSnapshot(self.app, None) def test_snapshot_set(self): arglist = [ @@ -457,7 +484,7 @@ class TestSnapshotShow(TestSnapshot): self.snapshots_mock.get.return_value = self.snapshot # Get the command object to test - self.cmd = snapshot.ShowSnapshot(self.app, None) + self.cmd = volume_snapshot.ShowVolumeSnapshot(self.app, None) def test_snapshot_show(self): arglist = [ @@ -485,7 +512,7 @@ class TestSnapshotUnset(TestSnapshot): self.snapshots_mock.get.return_value = self.snapshot self.snapshots_mock.delete_metadata.return_value = None # Get the command object to mock - self.cmd = snapshot.UnsetSnapshot(self.app, None) + self.cmd = volume_snapshot.UnsetVolumeSnapshot(self.app, None) def test_snapshot_unset(self): arglist = [ diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py index bc92c0f56d..1c0c0bc7c5 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 0000000000..c2ecf75b5b --- /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='', + nargs="?", + help=_('Name of the snapshot (default to None)'), + ) + parser.add_argument( + '--volume', + metavar='', + help=_('Volume to snapshot (name or ID) ' + '(default is )'), + ) + parser.add_argument( + '--description', + metavar='', + 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='', + 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='', + help=_('Snapshot to modify (name or ID)') + ) + parser.add_argument( + '--name', + metavar='', + help=_('New snapshot name') + ) + parser.add_argument( + '--description', + metavar='', + help=_('New snapshot description') + ) + parser.add_argument( + '--property', + metavar='', + 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='', + 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='', + help=_('Snapshot to modify (name or ID)'), + ) + parser.add_argument( + '--property', + metavar='', + 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 4994e0da3c..2f3de2119a 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 0000000000..43f30326ed --- /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="", + nargs="?", + help=_("Name of the new snapshot (default to None)") + ) + parser.add_argument( + "--volume", + metavar="", + help=_("Volume to snapshot (name or ID) " + "(default is )") + ) + parser.add_argument( + "--description", + metavar="", + 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="", + 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="", + 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='', + help=_('The last snapshot ID of the previous page'), + ) + parser.add_argument( + '--limit', + type=int, + action=parseractions.NonNegativeAction, + metavar='', + 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='', + help=_('Snapshot to modify (name or ID)') + ) + parser.add_argument( + '--name', + metavar='', + help=_('New snapshot name') + ) + parser.add_argument( + '--description', + metavar='', + help=_('New snapshot description') + ) + parser.add_argument( + '--property', + metavar='', + action=parseractions.KeyValueAction, + help=_('Property to add/change for this snapshot ' + '(repeat option to set multiple properties)'), + ) + parser.add_argument( + '--state', + metavar='', + 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="", + 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='', + help=_('Snapshot to modify (name or ID)'), + ) + parser.add_argument( + '--property', + metavar='', + 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, + ) diff --git a/releasenotes/notes/rename-snapshot-commands-e0937f7143a4ef55.yaml b/releasenotes/notes/rename-snapshot-commands-e0937f7143a4ef55.yaml new file mode 100644 index 0000000000..4228207f43 --- /dev/null +++ b/releasenotes/notes/rename-snapshot-commands-e0937f7143a4ef55.yaml @@ -0,0 +1,8 @@ +--- +features: + - Add new commands ``volume snapshot create/delete/list/show/set/unset``. they are + used to replace the old commands ``snapshot create/delete/list/show/set/unset``. + [Blueprint `backup-snapshot-renamed-for-volume-resource `_] +deprecations: + - Deprecate commands ``snapshot create/delete/list/show/set/unset``. + [Blueprint `backup-snapshot-renamed-for-volume-resource `_] diff --git a/setup.cfg b/setup.cfg index a4abec1bc5..c76e8e3ca9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -473,6 +473,13 @@ openstack.volume.v1 = volume_backup_restore = openstackclient.volume.v1.backup:RestoreVolumeBackup volume_backup_show = openstackclient.volume.v1.backup:ShowVolumeBackup + volume_snapshot_create = openstackclient.volume.v1.volume_snapshot:CreateVolumeSnapshot + volume_snapshot_delete = openstackclient.volume.v1.volume_snapshot:DeleteVolumeSnapshot + volume_snapshot_list = openstackclient.volume.v1.volume_snapshot:ListVolumeSnapshot + volume_snapshot_set = openstackclient.volume.v1.volume_snapshot:SetVolumeSnapshot + volume_snapshot_show = openstackclient.volume.v1.volume_snapshot:ShowVolumeSnapshot + volume_snapshot_unset = openstackclient.volume.v1.volume_snapshot:UnsetVolumeSnapshot + volume_type_create = openstackclient.volume.v1.volume_type:CreateVolumeType volume_type_delete = openstackclient.volume.v1.volume_type:DeleteVolumeType volume_type_list = openstackclient.volume.v1.volume_type:ListVolumeType @@ -528,6 +535,13 @@ openstack.volume.v2 = volume_backup_set = openstackclient.volume.v2.backup:SetVolumeBackup volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup + volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot + volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot + volume_snapshot_list = openstackclient.volume.v2.volume_snapshot:ListVolumeSnapshot + volume_snapshot_set = openstackclient.volume.v2.volume_snapshot:SetVolumeSnapshot + volume_snapshot_show = openstackclient.volume.v2.volume_snapshot:ShowVolumeSnapshot + volume_snapshot_unset = openstackclient.volume.v2.volume_snapshot:UnsetVolumeSnapshot + volume_type_create = openstackclient.volume.v2.volume_type:CreateVolumeType volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType