Add option to force delete cinder volume

Cinder's API gives possibility to force delete volume
which is in state 'deleting' or 'error deleting'.
This patch adds support for such force delete of volume
to shade.

Change-Id: Iffede494e5af250a6bfea98e1fbfd8014eff0b02
This commit is contained in:
Sławek Kapłoński 2017-08-17 21:07:54 +00:00 committed by Slawek Kaplonski
parent b92697b1a3
commit 3cfaa4c63b
2 changed files with 32 additions and 3 deletions

View File

@ -4762,12 +4762,15 @@ class OpenStackCloud(
return self._normalize_volume(volume)
def delete_volume(self, name_or_id=None, wait=True, timeout=None):
def delete_volume(self, name_or_id=None, wait=True, timeout=None,
force=False):
"""Delete a volume.
:param name_or_id: Name or unique ID of the volume.
:param wait: If true, waits for volume to be deleted.
:param timeout: Seconds to wait for volume deletion. None is forever.
:param force: Force delete volume even if the volume is in deleting
or error_deleting state.
:raises: OpenStackCloudTimeout if wait time exceeded.
:raises: OpenStackCloudException on operation error.
@ -4785,8 +4788,13 @@ class OpenStackCloud(
with _utils.shade_exceptions("Error in deleting volume"):
try:
self._volume_client.delete(
'volumes/{id}'.format(id=volume['id']))
if force:
self._volume_client.post(
'volumes/{id}/action'.format(id=volume['id']),
json={'os-force_delete': None})
else:
self._volume_client.delete(
'volumes/{id}'.format(id=volume['id']))
except OpenStackCloudURINotFound:
self.log.debug(
"Volume {id} not found when deleting. Ignoring.".format(

View File

@ -279,6 +279,27 @@ class TestVolume(base.RequestsMockTestCase):
self.assertFalse(self.cloud.delete_volume(volume['id']))
self.assert_calls()
def test_delete_volume_force(self):
vol = {'id': 'volume001', 'status': 'attached',
'name': '', 'attachments': []}
volume = meta.obj_to_munch(fakes.FakeVolume(**vol))
self.register_uris([
dict(method='GET',
uri=self.get_mock_url(
'volumev2', 'public', append=['volumes', 'detail']),
json={'volumes': [volume]}),
dict(method='POST',
uri=self.get_mock_url(
'volumev2', 'public',
append=['volumes', volume.id, 'action']),
json={'os-force_delete': None}),
dict(method='GET',
uri=self.get_mock_url(
'volumev2', 'public', append=['volumes', 'detail']),
json={'volumes': []})])
self.assertTrue(self.cloud.delete_volume(volume['id'], force=True))
self.assert_calls()
def test_list_volumes_with_pagination(self):
vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1'))
vol2 = meta.obj_to_munch(fakes.FakeVolume('02', 'available', 'vol2'))