3PAR: Fix delete volume when online clone
When an online clone volume is deleted, the clone needs to be stopped
first. On delete, a new exception is raised from the 3PAR. We need to
check for the error code when hpeexceptions.HTTPConflict is raised.
Change-Id: Iceb1b35e0312b109b2b19cd7d5c45b4a6242ccc5
Closes-Bug: #1349639
(cherry picked from commit f0dda71610
)
This commit is contained in:
parent
37e32bcae7
commit
5248fca729
|
@ -73,7 +73,7 @@ class ClientException(Exception):
|
|||
return formatted_string
|
||||
|
||||
|
||||
class HTTPConflict(Exception):
|
||||
class HTTPConflict(ClientException):
|
||||
http_status = 409
|
||||
message = "Conflict"
|
||||
|
||||
|
@ -85,7 +85,7 @@ class HTTPConflict(Exception):
|
|||
return self._error_desc
|
||||
|
||||
|
||||
class HTTPNotFound(Exception):
|
||||
class HTTPNotFound(ClientException):
|
||||
http_status = 404
|
||||
message = "Not found"
|
||||
|
||||
|
@ -95,12 +95,12 @@ class HTTPForbidden(ClientException):
|
|||
message = "Forbidden"
|
||||
|
||||
|
||||
class HTTPBadRequest(Exception):
|
||||
class HTTPBadRequest(ClientException):
|
||||
http_status = 400
|
||||
message = "Bad request"
|
||||
|
||||
|
||||
class HTTPServerError(Exception):
|
||||
class HTTPServerError(ClientException):
|
||||
http_status = 500
|
||||
message = "Error"
|
||||
|
||||
|
|
|
@ -1683,6 +1683,29 @@ class HPE3PARBaseDriver(object):
|
|||
expected +
|
||||
self.standard_logout)
|
||||
|
||||
def test_delete_volume_online_clone_active(self):
|
||||
# setup_mock_client drive with default configuration
|
||||
# and return the mock HTTP 3PAR client
|
||||
mock_client = self.setup_driver()
|
||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
||||
'_create_client') as mock_create_client:
|
||||
mock_create_client.return_value = mock_client
|
||||
ex = hpeexceptions.HTTPConflict("Online clone is active.")
|
||||
ex._error_code = 151
|
||||
mock_client.deleteVolume = mock.Mock(side_effect=ex)
|
||||
mock_client.isOnlinePhysicalCopy.return_value = True
|
||||
self.driver.delete_volume(self.volume)
|
||||
|
||||
expected = [
|
||||
mock.call.deleteVolume(self.VOLUME_3PAR_NAME),
|
||||
mock.call.isOnlinePhysicalCopy(self.VOLUME_3PAR_NAME),
|
||||
mock.call.stopOnlinePhysicalCopy(self.VOLUME_3PAR_NAME)]
|
||||
|
||||
mock_client.assert_has_calls(
|
||||
self.standard_login +
|
||||
expected +
|
||||
self.standard_logout)
|
||||
|
||||
@mock.patch.object(volume_types, 'get_volume_type')
|
||||
def test_delete_volume_replicated(self, _mock_volume_types):
|
||||
# setup_mock_client drive with default configuration
|
||||
|
|
|
@ -234,10 +234,12 @@ class HPE3PARCommon(object):
|
|||
3.0.18.1 - Rework delete_vlun. Bug #1582922 (backported from Newton)
|
||||
3.0.18.2 - Driver no longer fails to initialize if System Reporter
|
||||
license is missing. bug #1568078 (backported from Newton)
|
||||
3.0.18.3 - Fix delete volume when online clone is active. bug #1349639.
|
||||
(backported from Newton)
|
||||
|
||||
"""
|
||||
|
||||
VERSION = "3.0.18.2"
|
||||
VERSION = "3.0.18.3"
|
||||
|
||||
stats = {}
|
||||
|
||||
|
@ -2091,16 +2093,24 @@ class HPE3PARCommon(object):
|
|||
self.client.removeVolumeFromVolumeSet(vvset_name,
|
||||
volume_name)
|
||||
self.client.deleteVolume(volume_name)
|
||||
elif (ex.get_code() == 151):
|
||||
# the volume is being operated on in a background
|
||||
# task on the 3PAR.
|
||||
# TODO(walter-boring) do a retry a few times.
|
||||
# for now lets log a better message
|
||||
msg = _("The volume is currently busy on the 3PAR"
|
||||
" and cannot be deleted at this time. "
|
||||
"You can try again later.")
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeIsBusy(message=msg)
|
||||
elif ex.get_code() == 151:
|
||||
if self.client.isOnlinePhysicalCopy(volume_name):
|
||||
LOG.debug("Found an online copy for %(volume)s",
|
||||
{'volume': volume_name})
|
||||
# the volume is in process of being cloned.
|
||||
# stopOnlinePhysicalCopy will also delete
|
||||
# the volume once it stops the copy.
|
||||
self.client.stopOnlinePhysicalCopy(volume_name)
|
||||
else:
|
||||
# the volume is being operated on in a background
|
||||
# task on the 3PAR.
|
||||
# TODO(walter-boring) do a retry a few times.
|
||||
# for now lets log a better message
|
||||
msg = _("The volume is currently busy on the 3PAR"
|
||||
" and cannot be deleted at this time. "
|
||||
"You can try again later.")
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeIsBusy(message=msg)
|
||||
elif (ex.get_code() == 32):
|
||||
# Error 32 means that the volume has children
|
||||
|
||||
|
|
Loading…
Reference in New Issue