Merge "Add support for deleting volumes with associated snapshots"
This commit is contained in:
commit
5f6257206e
@ -88,13 +88,19 @@ Delete volume(s)
|
|||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
os volume delete
|
os volume delete
|
||||||
[--force]
|
[--force | --purge]
|
||||||
<volume> [<volume> ...]
|
<volume> [<volume> ...]
|
||||||
|
|
||||||
.. option:: --force
|
.. option:: --force
|
||||||
|
|
||||||
Attempt forced removal of volume(s), regardless of state (defaults to False)
|
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:
|
.. _volume_delete-volume:
|
||||||
.. describe:: <volume>
|
.. describe:: <volume>
|
||||||
|
|
||||||
|
@ -420,13 +420,16 @@ class TestVolumeDelete(TestVolume):
|
|||||||
volumes[0].id
|
volumes[0].id
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
("volumes", [volumes[0].id])
|
("force", False),
|
||||||
|
("purge", False),
|
||||||
|
("volumes", [volumes[0].id]),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
result = self.cmd.take_action(parsed_args)
|
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)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
def test_volume_delete_multi_volumes(self):
|
def test_volume_delete_multi_volumes(self):
|
||||||
@ -434,13 +437,15 @@ class TestVolumeDelete(TestVolume):
|
|||||||
|
|
||||||
arglist = [v.id for v in volumes]
|
arglist = [v.id for v in volumes]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
|
('force', False),
|
||||||
|
('purge', False),
|
||||||
('volumes', arglist),
|
('volumes', arglist),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
result = self.cmd.take_action(parsed_args)
|
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.volumes_mock.delete.assert_has_calls(calls)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@ -452,6 +457,8 @@ class TestVolumeDelete(TestVolume):
|
|||||||
'unexist_volume',
|
'unexist_volume',
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
|
('force', False),
|
||||||
|
('purge', False),
|
||||||
('volumes', arglist),
|
('volumes', arglist),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
@ -471,8 +478,46 @@ class TestVolumeDelete(TestVolume):
|
|||||||
|
|
||||||
self.assertEqual(2, find_mock.call_count)
|
self.assertEqual(2, find_mock.call_count)
|
||||||
self.volumes_mock.delete.assert_called_once_with(
|
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):
|
class TestVolumeList(TestVolume):
|
||||||
|
@ -166,13 +166,19 @@ class DeleteVolume(command.Command):
|
|||||||
nargs="+",
|
nargs="+",
|
||||||
help=_("Volume(s) to delete (name or ID)")
|
help=_("Volume(s) to delete (name or ID)")
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
"--force",
|
"--force",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=False,
|
|
||||||
help=_("Attempt forced removal of volume(s), regardless of state "
|
help=_("Attempt forced removal of volume(s), regardless of state "
|
||||||
"(defaults to False)")
|
"(defaults to False)")
|
||||||
)
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--purge",
|
||||||
|
action="store_true",
|
||||||
|
help=_("Remove any snapshots along with volume(s) "
|
||||||
|
"(defaults to False)")
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -186,12 +192,13 @@ class DeleteVolume(command.Command):
|
|||||||
if parsed_args.force:
|
if parsed_args.force:
|
||||||
volume_client.volumes.force_delete(volume_obj.id)
|
volume_client.volumes.force_delete(volume_obj.id)
|
||||||
else:
|
else:
|
||||||
volume_client.volumes.delete(volume_obj.id)
|
volume_client.volumes.delete(volume_obj.id,
|
||||||
|
cascade=parsed_args.purge)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result += 1
|
result += 1
|
||||||
LOG.error(_("Failed to delete volume with "
|
LOG.error(_("Failed to delete volume with "
|
||||||
"name or ID '%(volume)s': %(e)s")
|
"name or ID '%(volume)s': %(e)s"),
|
||||||
% {'volume': i, 'e': e})
|
{'volume': i, 'e': e})
|
||||||
|
|
||||||
if result > 0:
|
if result > 0:
|
||||||
total = len(parsed_args.volumes)
|
total = len(parsed_args.volumes)
|
||||||
|
7
releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml
Normal file
7
releasenotes/notes/bug-1589332-2941f5286df7e5d4.yaml
Normal file
@ -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>`_]
|
Loading…
x
Reference in New Issue
Block a user