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 <name>" to a positional parameter "<snapshot-name>"; Change the positional parameter "<volume>" to a optional parameter "--volume <volume>" Change-Id: If03276ecdf6f0d96893d5ecf91c2aaa64929cff3 Implements: bp backup-snapshot-renamed-for-volume-resource Co-Authored-By: Sheel Rana <ranasheel2000@gmail.com>
This commit is contained in:
parent
970b0e0005
commit
23ee2fd8f0
@ -8,6 +8,7 @@ snapshot create
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
Create new snapshot
|
Create new snapshot
|
||||||
|
(Deprecated, please use ``volume snapshot create`` instead)
|
||||||
|
|
||||||
.. program:: snapshot create
|
.. program:: snapshot create
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -46,6 +47,7 @@ snapshot delete
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
Delete snapshot(s)
|
Delete snapshot(s)
|
||||||
|
(Deprecated, please use ``volume snapshot delete`` instead)
|
||||||
|
|
||||||
.. program:: snapshot delete
|
.. program:: snapshot delete
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -62,6 +64,7 @@ snapshot list
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
List snapshots
|
List snapshots
|
||||||
|
(Deprecated, please use ``volume snapshot list`` instead)
|
||||||
|
|
||||||
.. program:: snapshot list
|
.. program:: snapshot list
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -96,6 +99,7 @@ snapshot set
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Set snapshot properties
|
Set snapshot properties
|
||||||
|
(Deprecated, please use ``volume snapshot set`` instead)
|
||||||
|
|
||||||
.. program:: snapshot set
|
.. program:: snapshot set
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -137,6 +141,7 @@ snapshot show
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
Display snapshot details
|
Display snapshot details
|
||||||
|
(Deprecated, please use ``volume snapshot show`` instead)
|
||||||
|
|
||||||
.. program:: snapshot show
|
.. program:: snapshot show
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -153,6 +158,7 @@ snapshot unset
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
Unset snapshot properties
|
Unset snapshot properties
|
||||||
|
(Deprecated, please use ``volume snapshot unset`` instead)
|
||||||
|
|
||||||
.. program:: snapshot unset
|
.. program:: snapshot unset
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
171
doc/source/command-objects/volume-snapshot.rst
Normal file
171
doc/source/command-objects/volume-snapshot.rst
Normal file
@ -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 <volume>]
|
||||||
|
[--description <description>]
|
||||||
|
[--force]
|
||||||
|
[--property <key=value> [...] ]
|
||||||
|
<snapshot-name>
|
||||||
|
|
||||||
|
.. option:: --volume <volume>
|
||||||
|
|
||||||
|
Volume to snapshot (name or ID) (default is <snapshot-name>)
|
||||||
|
|
||||||
|
.. option:: --description <description>
|
||||||
|
|
||||||
|
Description of the snapshot
|
||||||
|
|
||||||
|
.. option:: --force
|
||||||
|
|
||||||
|
Create a snapshot attached to an instance. Default is False
|
||||||
|
|
||||||
|
.. option:: --property <key=value>
|
||||||
|
|
||||||
|
Set a property to this snapshot (repeat option to set multiple properties)
|
||||||
|
|
||||||
|
*Volume version 2 only*
|
||||||
|
|
||||||
|
.. _volume_snapshot_create-snapshot-name:
|
||||||
|
.. describe:: <snapshot-name>
|
||||||
|
|
||||||
|
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
|
||||||
|
<snapshot> [<snapshot> ...]
|
||||||
|
|
||||||
|
.. _volume_snapshot_delete-snapshot:
|
||||||
|
.. describe:: <snapshot>
|
||||||
|
|
||||||
|
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 <limit>]
|
||||||
|
[--marker <marker>]
|
||||||
|
|
||||||
|
.. option:: --all-projects
|
||||||
|
|
||||||
|
Include all projects (admin only)
|
||||||
|
|
||||||
|
.. option:: --long
|
||||||
|
|
||||||
|
List additional fields in output
|
||||||
|
|
||||||
|
.. option:: --limit <limit>
|
||||||
|
|
||||||
|
Maximum number of snapshots to display
|
||||||
|
|
||||||
|
*Volume version 2 only*
|
||||||
|
|
||||||
|
.. option:: --marker <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 <name>]
|
||||||
|
[--description <description>]
|
||||||
|
[--property <key=value> [...] ]
|
||||||
|
[--state <state>]
|
||||||
|
<snapshot>
|
||||||
|
|
||||||
|
.. option:: --name <name>
|
||||||
|
|
||||||
|
New snapshot name
|
||||||
|
|
||||||
|
.. option:: --description <description>
|
||||||
|
|
||||||
|
New snapshot description
|
||||||
|
|
||||||
|
.. option:: --property <key=value>
|
||||||
|
|
||||||
|
Property to add or modify for this snapshot (repeat option to set multiple properties)
|
||||||
|
|
||||||
|
.. option:: --state <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>
|
||||||
|
|
||||||
|
Snapshot to modify (name or ID)
|
||||||
|
|
||||||
|
volume snapshot show
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Display volume snapshot details
|
||||||
|
|
||||||
|
.. program:: volume snapshot show
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
os volume snapshot show
|
||||||
|
<snapshot>
|
||||||
|
|
||||||
|
.. _volume_snapshot_show-snapshot:
|
||||||
|
.. describe:: <snapshot>
|
||||||
|
|
||||||
|
Snapshot to display (name or ID)
|
||||||
|
|
||||||
|
volume snapshot unset
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Unset volume snapshot properties
|
||||||
|
|
||||||
|
.. program:: volume snapshot unset
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
os volume snapshot unset
|
||||||
|
[--property <key>]
|
||||||
|
<snapshot>
|
||||||
|
|
||||||
|
.. option:: --property <key>
|
||||||
|
|
||||||
|
Property to remove from snapshot (repeat option to remove multiple properties)
|
||||||
|
|
||||||
|
.. _volume_snapshot_unset-snapshot:
|
||||||
|
.. describe:: <snapshot>
|
||||||
|
|
||||||
|
Snapshot to modify (name or ID)
|
@ -74,7 +74,6 @@ referring to both Compute and Volume quotas.
|
|||||||
* ``address scope``: (**Network**) a scope of IPv4 or IPv6 addresses
|
* ``address scope``: (**Network**) a scope of IPv4 or IPv6 addresses
|
||||||
* ``aggregate``: (**Compute**) a grouping of compute hosts
|
* ``aggregate``: (**Compute**) a grouping of compute hosts
|
||||||
* ``availability zone``: (**Compute**, **Network**, **Volume**) a logical partition of hosts or block storage or network services
|
* ``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
|
* ``catalog``: (**Identity**) service catalog
|
||||||
* ``command``: (**Internal**) installed commands in the OSC process
|
* ``command``: (**Internal**) installed commands in the OSC process
|
||||||
* ``compute agent``: (**Compute**) a cloud Compute agent available to a hypervisor
|
* ``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
|
* ``server image``: (**Compute**) saved server disk image
|
||||||
* ``service``: (**Identity**) a cloud service
|
* ``service``: (**Identity**) a cloud service
|
||||||
* ``service provider``: (**Identity**) a resource that consumes assertions from an ``identity provider``
|
* ``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``: (**Network**) - a contiguous range of IP addresses assigned to a network
|
||||||
* ``subnet pool``: (**Network**) - a pool of subnets
|
* ``subnet pool``: (**Network**) - a pool of subnets
|
||||||
* ``token``: (**Identity**) a bearer token managed by Identity service
|
* ``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``: (**Volume**) block volumes
|
||||||
* ``volume backup``: (**Volume**) backup for volumes
|
* ``volume backup``: (**Volume**) backup for volumes
|
||||||
* ``volume qos``: (**Volume**) quality-of-service (QoS) specification 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 type``: (**Volume**) deployment-specific types of volumes available
|
||||||
* ``volume service``: (**Volume**) services to manage block storage operations
|
* ``volume service``: (**Volume**) services to manage block storage operations
|
||||||
* ``volume transfer request``: (**Volume**) volume owner transfer request
|
* ``volume transfer request``: (**Volume**) volume owner transfer request
|
||||||
|
@ -16,8 +16,8 @@ import uuid
|
|||||||
from openstackclient.tests.functional.volume.v1 import common
|
from openstackclient.tests.functional.volume.v1 import common
|
||||||
|
|
||||||
|
|
||||||
class SnapshotTests(common.BaseVolumeTests):
|
class VolumeSnapshotTests(common.BaseVolumeTests):
|
||||||
"""Functional tests for snapshot. """
|
"""Functional tests for volume snapshot. """
|
||||||
|
|
||||||
VOLLY = uuid.uuid4().hex
|
VOLLY = uuid.uuid4().hex
|
||||||
NAME = uuid.uuid4().hex
|
NAME = uuid.uuid4().hex
|
||||||
@ -36,24 +36,25 @@ class SnapshotTests(common.BaseVolumeTests):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(SnapshotTests, cls).setUpClass()
|
super(VolumeSnapshotTests, cls).setUpClass()
|
||||||
cls.openstack('volume create --size 1 ' + cls.VOLLY)
|
cls.openstack('volume create --size 1 ' + cls.VOLLY)
|
||||||
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3)
|
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3)
|
||||||
opts = cls.get_opts(['status'])
|
opts = cls.get_opts(['status'])
|
||||||
raw_output = cls.openstack('snapshot create --name ' + cls.NAME +
|
raw_output = cls.openstack('volume snapshot create --volume ' +
|
||||||
' ' + cls.VOLLY + opts)
|
cls.VOLLY + ' ' + cls.NAME + opts)
|
||||||
cls.assertOutput('creating\n', raw_output)
|
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
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# Rename test
|
# Rename test
|
||||||
raw_output = cls.openstack(
|
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)
|
cls.assertOutput('', raw_output)
|
||||||
# Delete test
|
# Delete test
|
||||||
raw_output_snapshot = cls.openstack(
|
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)
|
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6)
|
||||||
raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY)
|
raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY)
|
||||||
cls.assertOutput('', raw_output_snapshot)
|
cls.assertOutput('', raw_output_snapshot)
|
||||||
@ -61,26 +62,27 @@ class SnapshotTests(common.BaseVolumeTests):
|
|||||||
|
|
||||||
def test_snapshot_list(self):
|
def test_snapshot_list(self):
|
||||||
opts = self.get_opts(self.HEADERS)
|
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)
|
self.assertIn(self.NAME, raw_output)
|
||||||
|
|
||||||
def test_snapshot_set_unset_properties(self):
|
def test_snapshot_set_unset_properties(self):
|
||||||
raw_output = self.openstack(
|
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)
|
self.assertEqual("", raw_output)
|
||||||
opts = self.get_opts(["properties"])
|
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)
|
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)
|
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)
|
self.assertEqual("c='d'\n", raw_output)
|
||||||
|
|
||||||
def test_snapshot_set_description(self):
|
def test_snapshot_set_description(self):
|
||||||
raw_output = self.openstack(
|
raw_output = self.openstack(
|
||||||
'snapshot set --description backup ' + self.NAME)
|
'volume snapshot set --description backup ' + self.NAME)
|
||||||
self.assertEqual("", raw_output)
|
self.assertEqual("", raw_output)
|
||||||
opts = self.get_opts(["display_description", "display_name"])
|
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)
|
self.assertEqual("backup\n" + self.NAME + "\n", raw_output)
|
||||||
|
@ -16,8 +16,8 @@ import uuid
|
|||||||
from openstackclient.tests.functional.volume.v2 import common
|
from openstackclient.tests.functional.volume.v2 import common
|
||||||
|
|
||||||
|
|
||||||
class SnapshotTests(common.BaseVolumeTests):
|
class VolumeSnapshotTests(common.BaseVolumeTests):
|
||||||
"""Functional tests for snapshot. """
|
"""Functional tests for volume snapshot. """
|
||||||
|
|
||||||
VOLLY = uuid.uuid4().hex
|
VOLLY = uuid.uuid4().hex
|
||||||
NAME = uuid.uuid4().hex
|
NAME = uuid.uuid4().hex
|
||||||
@ -36,24 +36,25 @@ class SnapshotTests(common.BaseVolumeTests):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(SnapshotTests, cls).setUpClass()
|
super(VolumeSnapshotTests, cls).setUpClass()
|
||||||
cls.openstack('volume create --size 1 ' + cls.VOLLY)
|
cls.openstack('volume create --size 1 ' + cls.VOLLY)
|
||||||
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3)
|
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3)
|
||||||
opts = cls.get_opts(['status'])
|
opts = cls.get_opts(['status'])
|
||||||
raw_output = cls.openstack('snapshot create --name ' + cls.NAME +
|
raw_output = cls.openstack('volume snapshot create --volume ' +
|
||||||
' ' + cls.VOLLY + opts)
|
cls.VOLLY + ' ' + cls.NAME + opts)
|
||||||
cls.assertOutput('creating\n', raw_output)
|
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
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# Rename test
|
# Rename test
|
||||||
raw_output = cls.openstack(
|
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)
|
cls.assertOutput('', raw_output)
|
||||||
# Delete test
|
# Delete test
|
||||||
raw_output_snapshot = cls.openstack(
|
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)
|
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6)
|
||||||
raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY)
|
raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY)
|
||||||
cls.assertOutput('', raw_output_snapshot)
|
cls.assertOutput('', raw_output_snapshot)
|
||||||
@ -61,26 +62,27 @@ class SnapshotTests(common.BaseVolumeTests):
|
|||||||
|
|
||||||
def test_snapshot_list(self):
|
def test_snapshot_list(self):
|
||||||
opts = self.get_opts(self.HEADERS)
|
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)
|
self.assertIn(self.NAME, raw_output)
|
||||||
|
|
||||||
def test_snapshot_properties(self):
|
def test_snapshot_properties(self):
|
||||||
raw_output = self.openstack(
|
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)
|
self.assertEqual("", raw_output)
|
||||||
opts = self.get_opts(["properties"])
|
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)
|
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)
|
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)
|
self.assertEqual("c='d'\n", raw_output)
|
||||||
|
|
||||||
def test_snapshot_set(self):
|
def test_snapshot_set(self):
|
||||||
raw_output = self.openstack(
|
raw_output = self.openstack(
|
||||||
'snapshot set --description backup ' + self.NAME)
|
'volume snapshot set --description backup ' + self.NAME)
|
||||||
self.assertEqual("", raw_output)
|
self.assertEqual("", raw_output)
|
||||||
opts = self.get_opts(["description", "name"])
|
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)
|
self.assertEqual("backup\n" + self.NAME + "\n", raw_output)
|
||||||
|
@ -106,11 +106,12 @@ class VolumeTests(common.BaseVolumeTests):
|
|||||||
opts = self.get_opts(self.FIELDS)
|
opts = self.get_opts(self.FIELDS)
|
||||||
|
|
||||||
# Create snapshot from test volume
|
# Create snapshot from test volume
|
||||||
raw_output = self.openstack('snapshot create ' + self.NAME +
|
raw_output = self.openstack('volume snapshot create ' +
|
||||||
' --name ' + self.SNAPSHOT_NAME + opts)
|
self.SNAPSHOT_NAME +
|
||||||
|
' --volume ' + self.NAME + opts)
|
||||||
expected = self.SNAPSHOT_NAME + '\n'
|
expected = self.SNAPSHOT_NAME + '\n'
|
||||||
self.assertOutput(expected, raw_output)
|
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
|
# Create volume from snapshot
|
||||||
raw_output = self.openstack('volume create --size 2 --snapshot ' +
|
raw_output = self.openstack('volume create --size 2 --snapshot ' +
|
||||||
@ -126,7 +127,8 @@ class VolumeTests(common.BaseVolumeTests):
|
|||||||
self.assertOutput('', raw_output)
|
self.assertOutput('', raw_output)
|
||||||
|
|
||||||
# Delete test snapshot
|
# 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.assertOutput('', raw_output)
|
||||||
self.wait_for("volume", self.NAME, "available")
|
self.wait_for("volume", self.NAME, "available")
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ from osc_lib import exceptions
|
|||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
|
||||||
from openstackclient.tests.unit.volume.v1 import fakes as volume_fakes
|
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):
|
class TestSnapshot(volume_fakes.TestVolumev1):
|
||||||
@ -67,20 +67,20 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
self.volumes_mock.get.return_value = self.volume
|
self.volumes_mock.get.return_value = self.volume
|
||||||
self.snapshots_mock.create.return_value = self.new_snapshot
|
self.snapshots_mock.create.return_value = self.new_snapshot
|
||||||
# Get the command object to test
|
# 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):
|
def test_snapshot_create(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
"--name", self.new_snapshot.display_name,
|
"--volume", self.new_snapshot.volume_id,
|
||||||
"--description", self.new_snapshot.display_description,
|
"--description", self.new_snapshot.display_description,
|
||||||
"--force",
|
"--force",
|
||||||
self.new_snapshot.volume_id,
|
self.new_snapshot.display_name,
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
("name", self.new_snapshot.display_name),
|
("volume", self.new_snapshot.volume_id),
|
||||||
("description", self.new_snapshot.display_description),
|
("description", self.new_snapshot.display_description),
|
||||||
("force", True),
|
("force", True),
|
||||||
("volume", self.new_snapshot.volume_id),
|
("snapshot_name", self.new_snapshot.display_name),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
|
|
||||||
def test_snapshot_create_without_name(self):
|
def test_snapshot_create_without_name(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
self.new_snapshot.volume_id,
|
"--volume", self.new_snapshot.volume_id,
|
||||||
"--description", self.new_snapshot.display_description,
|
"--description", self.new_snapshot.display_description,
|
||||||
"--force"
|
"--force"
|
||||||
]
|
]
|
||||||
@ -119,6 +119,32 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
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):
|
class TestSnapshotDelete(TestSnapshot):
|
||||||
|
|
||||||
@ -132,7 +158,7 @@ class TestSnapshotDelete(TestSnapshot):
|
|||||||
self.snapshots_mock.delete.return_value = None
|
self.snapshots_mock.delete.return_value = None
|
||||||
|
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_delete(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -244,7 +270,7 @@ class TestSnapshotList(TestSnapshot):
|
|||||||
self.volumes_mock.list.return_value = [self.volume]
|
self.volumes_mock.list.return_value = [self.volume]
|
||||||
self.snapshots_mock.list.return_value = self.snapshots
|
self.snapshots_mock.list.return_value = self.snapshots
|
||||||
# Get the command to test
|
# 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):
|
def test_snapshot_list_without_options(self):
|
||||||
arglist = []
|
arglist = []
|
||||||
@ -307,7 +333,7 @@ class TestSnapshotSet(TestSnapshot):
|
|||||||
self.snapshots_mock.get.return_value = self.snapshot
|
self.snapshots_mock.get.return_value = self.snapshot
|
||||||
self.snapshots_mock.set_metadata.return_value = None
|
self.snapshots_mock.set_metadata.return_value = None
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_set_all(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -404,7 +430,7 @@ class TestSnapshotShow(TestSnapshot):
|
|||||||
|
|
||||||
self.snapshots_mock.get.return_value = self.snapshot
|
self.snapshots_mock.get.return_value = self.snapshot
|
||||||
# Get the command object to test
|
# 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):
|
def test_snapshot_show(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -432,7 +458,7 @@ class TestSnapshotUnset(TestSnapshot):
|
|||||||
self.snapshots_mock.get.return_value = self.snapshot
|
self.snapshots_mock.get.return_value = self.snapshot
|
||||||
self.snapshots_mock.delete_metadata.return_value = None
|
self.snapshots_mock.delete_metadata.return_value = None
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_unset(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
|
@ -20,7 +20,7 @@ from osc_lib import exceptions
|
|||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
|
||||||
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
|
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):
|
class TestSnapshot(volume_fakes.TestVolume):
|
||||||
@ -68,23 +68,23 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
self.volumes_mock.get.return_value = self.volume
|
self.volumes_mock.get.return_value = self.volume
|
||||||
self.snapshots_mock.create.return_value = self.new_snapshot
|
self.snapshots_mock.create.return_value = self.new_snapshot
|
||||||
# Get the command object to test
|
# 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):
|
def test_snapshot_create(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
"--name", self.new_snapshot.name,
|
"--volume", self.new_snapshot.volume_id,
|
||||||
"--description", self.new_snapshot.description,
|
"--description", self.new_snapshot.description,
|
||||||
"--force",
|
"--force",
|
||||||
'--property', 'Alpha=a',
|
'--property', 'Alpha=a',
|
||||||
'--property', 'Beta=b',
|
'--property', 'Beta=b',
|
||||||
self.new_snapshot.volume_id,
|
self.new_snapshot.name,
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
("name", self.new_snapshot.name),
|
("volume", self.new_snapshot.volume_id),
|
||||||
("description", self.new_snapshot.description),
|
("description", self.new_snapshot.description),
|
||||||
("force", True),
|
("force", True),
|
||||||
('property', {'Alpha': 'a', 'Beta': 'b'}),
|
('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)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
|
|
||||||
def test_snapshot_create_without_name(self):
|
def test_snapshot_create_without_name(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
self.new_snapshot.volume_id,
|
"--volume", self.new_snapshot.volume_id,
|
||||||
"--description", self.new_snapshot.description,
|
"--description", self.new_snapshot.description,
|
||||||
"--force"
|
"--force"
|
||||||
]
|
]
|
||||||
@ -125,6 +125,33 @@ class TestSnapshotCreate(TestSnapshot):
|
|||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
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):
|
class TestSnapshotDelete(TestSnapshot):
|
||||||
|
|
||||||
@ -138,7 +165,7 @@ class TestSnapshotDelete(TestSnapshot):
|
|||||||
self.snapshots_mock.delete.return_value = None
|
self.snapshots_mock.delete.return_value = None
|
||||||
|
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_delete(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -250,7 +277,7 @@ class TestSnapshotList(TestSnapshot):
|
|||||||
self.volumes_mock.list.return_value = [self.volume]
|
self.volumes_mock.list.return_value = [self.volume]
|
||||||
self.snapshots_mock.list.return_value = self.snapshots
|
self.snapshots_mock.list.return_value = self.snapshots
|
||||||
# Get the command to test
|
# 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):
|
def test_snapshot_list_without_options(self):
|
||||||
arglist = []
|
arglist = []
|
||||||
@ -330,7 +357,7 @@ class TestSnapshotSet(TestSnapshot):
|
|||||||
self.snapshots_mock.set_metadata.return_value = None
|
self.snapshots_mock.set_metadata.return_value = None
|
||||||
self.snapshots_mock.update.return_value = None
|
self.snapshots_mock.update.return_value = None
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_set(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -457,7 +484,7 @@ class TestSnapshotShow(TestSnapshot):
|
|||||||
|
|
||||||
self.snapshots_mock.get.return_value = self.snapshot
|
self.snapshots_mock.get.return_value = self.snapshot
|
||||||
# Get the command object to test
|
# 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):
|
def test_snapshot_show(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -485,7 +512,7 @@ class TestSnapshotUnset(TestSnapshot):
|
|||||||
self.snapshots_mock.get.return_value = self.snapshot
|
self.snapshots_mock.get.return_value = self.snapshot
|
||||||
self.snapshots_mock.delete_metadata.return_value = None
|
self.snapshots_mock.delete_metadata.return_value = None
|
||||||
# Get the command object to mock
|
# 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):
|
def test_snapshot_unset(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
# under the License.
|
# 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"""
|
"""Volume v1 Snapshot action implementations"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
@ -27,6 +31,8 @@ import six
|
|||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
deprecated = True
|
||||||
|
LOG_DEP = logging.getLogger('deprecated')
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +67,8 @@ class CreateSnapshot(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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_client = self.app.client_manager.volume
|
||||||
volume_id = utils.find_resource(volume_client.volumes,
|
volume_id = utils.find_resource(volume_client.volumes,
|
||||||
parsed_args.volume).id
|
parsed_args.volume).id
|
||||||
@ -92,6 +100,8 @@ class DeleteSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
@ -133,6 +143,8 @@ class ListSnapshot(command.Lister):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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):
|
def _format_volume_id(volume_id):
|
||||||
"""Return a volume name if available
|
"""Return a volume name if available
|
||||||
@ -214,6 +226,8 @@ class SetSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
||||||
parsed_args.snapshot)
|
parsed_args.snapshot)
|
||||||
@ -258,6 +272,8 @@ class ShowSnapshot(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
||||||
parsed_args.snapshot)
|
parsed_args.snapshot)
|
||||||
@ -289,6 +305,8 @@ class UnsetSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(
|
snapshot = utils.find_resource(
|
||||||
volume_client.volume_snapshots, parsed_args.snapshot)
|
volume_client.volume_snapshots, parsed_args.snapshot)
|
||||||
|
305
openstackclient/volume/v1/volume_snapshot.py
Normal file
305
openstackclient/volume/v1/volume_snapshot.py
Normal file
@ -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,
|
||||||
|
)
|
@ -12,6 +12,10 @@
|
|||||||
# under the License.
|
# 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"""
|
"""Volume v2 snapshot action implementations"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
@ -26,6 +30,8 @@ import six
|
|||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
deprecated = True
|
||||||
|
LOG_DEP = logging.getLogger('deprecated')
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +72,8 @@ class CreateSnapshot(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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_client = self.app.client_manager.volume
|
||||||
volume_id = utils.find_resource(
|
volume_id = utils.find_resource(
|
||||||
volume_client.volumes, parsed_args.volume).id
|
volume_client.volumes, parsed_args.volume).id
|
||||||
@ -96,6 +104,8 @@ class DeleteSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
@ -149,6 +159,8 @@ class ListSnapshot(command.Lister):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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):
|
def _format_volume_id(volume_id):
|
||||||
"""Return a volume name if available
|
"""Return a volume name if available
|
||||||
@ -239,6 +251,8 @@ class SetSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
snapshot = utils.find_resource(volume_client.volume_snapshots,
|
||||||
parsed_args.snapshot)
|
parsed_args.snapshot)
|
||||||
@ -292,6 +306,8 @@ class ShowSnapshot(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(
|
snapshot = utils.find_resource(
|
||||||
volume_client.volume_snapshots, parsed_args.snapshot)
|
volume_client.volume_snapshots, parsed_args.snapshot)
|
||||||
@ -322,6 +338,8 @@ class UnsetSnapshot(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
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
|
volume_client = self.app.client_manager.volume
|
||||||
snapshot = utils.find_resource(
|
snapshot = utils.find_resource(
|
||||||
volume_client.volume_snapshots, parsed_args.snapshot)
|
volume_client.volume_snapshots, parsed_args.snapshot)
|
||||||
|
338
openstackclient/volume/v2/volume_snapshot.py
Normal file
338
openstackclient/volume/v2/volume_snapshot.py
Normal file
@ -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,
|
||||||
|
)
|
@ -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 <https://blueprints.launchpad.net/python-openstackclient/+spec/backup-snapshot-renamed-for-volume-resource>`_]
|
||||||
|
deprecations:
|
||||||
|
- Deprecate commands ``snapshot create/delete/list/show/set/unset``.
|
||||||
|
[Blueprint `backup-snapshot-renamed-for-volume-resource <https://blueprints.launchpad.net/python-openstackclient/+spec/backup-snapshot-renamed-for-volume-resource>`_]
|
14
setup.cfg
14
setup.cfg
@ -473,6 +473,13 @@ openstack.volume.v1 =
|
|||||||
volume_backup_restore = openstackclient.volume.v1.backup:RestoreVolumeBackup
|
volume_backup_restore = openstackclient.volume.v1.backup:RestoreVolumeBackup
|
||||||
volume_backup_show = openstackclient.volume.v1.backup:ShowVolumeBackup
|
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_create = openstackclient.volume.v1.volume_type:CreateVolumeType
|
||||||
volume_type_delete = openstackclient.volume.v1.volume_type:DeleteVolumeType
|
volume_type_delete = openstackclient.volume.v1.volume_type:DeleteVolumeType
|
||||||
volume_type_list = openstackclient.volume.v1.volume_type:ListVolumeType
|
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_set = openstackclient.volume.v2.backup:SetVolumeBackup
|
||||||
volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup
|
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_create = openstackclient.volume.v2.volume_type:CreateVolumeType
|
||||||
volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType
|
volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType
|
||||||
volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType
|
volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType
|
||||||
|
Loading…
Reference in New Issue
Block a user