summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwuyuting <wytdahu@gmail.com>2016-06-05 22:55:43 -0400
committerRui Chen <chenrui.momo@gmail.com>2016-07-27 11:30:52 +0800
commit954c28dfa21be76b0522af051d71fb9470877a1a (patch)
treee39e3e3eeb5722a85259a72566987a8b876a10ed
parent7a667d700f97dda386c3db3bffc8138182fbeccb (diff)
downloadpython-openstackclient-954c28dfa21be76b0522af051d71fb9470877a1a.tar.gz
Add support for deleting volumes with associated snapshots
OSC doesn't support deleting volumes with associated snapshots. This patch provides support for deleting volumes with associated snapshots by adding an optional argument. Change-Id: I7e74f251574993ff13a38e508fd2f9debeda8d0a Closes-Bug: #1589332 Co-Authored-By: Rui Chen <chenrui.momo@gmail.com>
-rw-r--r--doc/source/command-objects/volume.rst8
-rw-r--r--openstackclient/tests/volume/v2/test_volume.py55
-rw-r--r--openstackclient/volume/v2/volume.py17
-rw-r--r--releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml7
4 files changed, 76 insertions, 11 deletions
diff --git a/doc/source/command-objects/volume.rst b/doc/source/command-objects/volume.rst
index a51d1117..021518be 100644
--- a/doc/source/command-objects/volume.rst
+++ b/doc/source/command-objects/volume.rst
@@ -88,13 +88,19 @@ Delete volume(s)
.. code:: bash
os volume delete
- [--force]
+ [--force | --purge]
<volume> [<volume> ...]
.. option:: --force
Attempt forced removal of volume(s), regardless of state (defaults to False)
+.. option:: --purge
+
+ Remove any snapshots along with volume(s) (defaults to False)
+
+ *Volume version 2 only*
+
.. _volume_delete-volume:
.. describe:: <volume>
diff --git a/openstackclient/tests/volume/v2/test_volume.py b/openstackclient/tests/volume/v2/test_volume.py
index 25d0e92f..6f552ad6 100644
--- a/openstackclient/tests/volume/v2/test_volume.py
+++ b/openstackclient/tests/volume/v2/test_volume.py
@@ -420,13 +420,16 @@ class TestVolumeDelete(TestVolume):
volumes[0].id
]
verifylist = [
- ("volumes", [volumes[0].id])
+ ("force", False),
+ ("purge", False),
+ ("volumes", [volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.volumes_mock.delete.assert_called_with(volumes[0].id)
+ self.volumes_mock.delete.assert_called_once_with(
+ volumes[0].id, cascade=False)
self.assertIsNone(result)
def test_volume_delete_multi_volumes(self):
@@ -434,13 +437,15 @@ class TestVolumeDelete(TestVolume):
arglist = [v.id for v in volumes]
verifylist = [
+ ('force', False),
+ ('purge', False),
('volumes', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- calls = [call(v.id) for v in volumes]
+ calls = [call(v.id, cascade=False) for v in volumes]
self.volumes_mock.delete.assert_has_calls(calls)
self.assertIsNone(result)
@@ -452,6 +457,8 @@ class TestVolumeDelete(TestVolume):
'unexist_volume',
]
verifylist = [
+ ('force', False),
+ ('purge', False),
('volumes', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -471,8 +478,46 @@ class TestVolumeDelete(TestVolume):
self.assertEqual(2, find_mock.call_count)
self.volumes_mock.delete.assert_called_once_with(
- volumes[0].id
- )
+ volumes[0].id, cascade=False)
+
+ def test_volume_delete_with_purge(self):
+ volumes = self.setup_volumes_mock(count=1)
+
+ arglist = [
+ '--purge',
+ volumes[0].id,
+ ]
+ verifylist = [
+ ('force', False),
+ ('purge', True),
+ ('volumes', [volumes[0].id]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.delete.assert_called_once_with(
+ volumes[0].id, cascade=True)
+ self.assertIsNone(result)
+
+ def test_volume_delete_with_force(self):
+ volumes = self.setup_volumes_mock(count=1)
+
+ arglist = [
+ '--force',
+ volumes[0].id,
+ ]
+ verifylist = [
+ ('force', True),
+ ('purge', False),
+ ('volumes', [volumes[0].id]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.force_delete.assert_called_once_with(volumes[0].id)
+ self.assertIsNone(result)
class TestVolumeList(TestVolume):
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index 85f267ef..6f055922 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -166,13 +166,19 @@ class DeleteVolume(command.Command):
nargs="+",
help=_("Volume(s) to delete (name or ID)")
)
- parser.add_argument(
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument(
"--force",
action="store_true",
- default=False,
help=_("Attempt forced removal of volume(s), regardless of state "
"(defaults to False)")
)
+ group.add_argument(
+ "--purge",
+ action="store_true",
+ help=_("Remove any snapshots along with volume(s) "
+ "(defaults to False)")
+ )
return parser
def take_action(self, parsed_args):
@@ -186,12 +192,13 @@ class DeleteVolume(command.Command):
if parsed_args.force:
volume_client.volumes.force_delete(volume_obj.id)
else:
- volume_client.volumes.delete(volume_obj.id)
+ volume_client.volumes.delete(volume_obj.id,
+ cascade=parsed_args.purge)
except Exception as e:
result += 1
LOG.error(_("Failed to delete volume with "
- "name or ID '%(volume)s': %(e)s")
- % {'volume': i, 'e': e})
+ "name or ID '%(volume)s': %(e)s"),
+ {'volume': i, 'e': e})
if result > 0:
total = len(parsed_args.volumes)
diff --git a/releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml b/releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml
new file mode 100644
index 00000000..0ac17c39
--- /dev/null
+++ b/releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Add ``--purge`` option to ``volume delete`` command (Volume v2 only) in
+ order to removing any snapshots along with volume automatically when user
+ delete the volume.
+ [Bug `1589332 <https://bugs.launchpad.net/python-openstackclient/+bug/1589332>`_]