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:
Alex O'Rourke 2016-06-09 09:13:13 -07:00
parent 37e32bcae7
commit 5248fca729
3 changed files with 48 additions and 15 deletions

View File

@ -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"

View File

@ -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

View File

@ -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