HPE 3PAR: fix delete operation of replicated volume

When QoS is set to the replicated volume, at Storage
level the same volume becomes part of vvset

This patch delete vvset if one volume per vvset
else it remove volume from vvset.
Then delete the volume

Change-Id: Iebac77f569adbf763f0a5668cfdc5ea546846d67
Closes-Bug: #1717875
This commit is contained in:
kushal 2017-09-21 03:29:12 -07:00 committed by Kushal Wathore
parent 2b58f2bb04
commit 48771cc744
2 changed files with 36 additions and 15 deletions

View File

@ -2146,7 +2146,10 @@ class HPE3PARBaseDriver(object):
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
mock_client.getStorageSystemInfo.return_value = {'id': self.CLIENT_ID}
ex = hpeexceptions.HTTPConflict("In use")
ex._error_code = 34
mock_client.deleteVolume = mock.Mock(side_effect=[ex, 200])
mock_client.findVolumeSet.return_value = self.VVS_NAME
_mock_volume_types.return_value = {
'name': 'replicated',
'extra_specs': {
@ -2170,6 +2173,10 @@ class HPE3PARBaseDriver(object):
self.VOLUME_3PAR_NAME,
removeFromTarget=True),
mock.call.removeRemoteCopyGroup(self.RCG_3PAR_NAME),
mock.call.deleteVolume(self.VOLUME_3PAR_NAME),
mock.call.findVolumeSet(self.VOLUME_3PAR_NAME),
mock.call.removeVolumeFromVolumeSet(self.VVS_NAME,
self.VOLUME_3PAR_NAME),
mock.call.deleteVolume(self.VOLUME_3PAR_NAME)]
mock_client.assert_has_calls(

View File

@ -262,11 +262,13 @@ class HPE3PARCommon(object):
3.0.35 - Add volume to consistency group if flag enabled. bug #1702317
3.0.36 - Swap volume name in migration. bug #1699733
3.0.37 - Fixed image cache enabled capability. bug #1686985
3.0.38 - Fixed delete operation of replicated volume which is part
of QOS. bug #1717875
"""
VERSION = "3.0.37"
VERSION = "3.0.38"
stats = {}
@ -2266,19 +2268,7 @@ class HPE3PARCommon(object):
if ex.get_code() == 34:
# This is a special case which means the
# volume is part of a volume set.
vvset_name = self.client.findVolumeSet(volume_name)
LOG.debug("Returned vvset_name = %s", vvset_name)
if vvset_name is not None and \
vvset_name.startswith('vvs-'):
# We have a single volume per volume set, so
# remove the volume set.
self.client.deleteVolumeSet(
self._get_3par_vvs_name(volume['id']))
elif vvset_name is not None:
# We have a pre-defined volume set just remove the
# volume and leave the volume set.
self.client.removeVolumeFromVolumeSet(vvset_name,
volume_name)
self._delete_vvset(volume)
self.client.deleteVolume(volume_name)
elif ex.get_code() == 151:
if self.client.isOnlinePhysicalCopy(volume_name):
@ -3680,6 +3670,12 @@ class HPE3PARCommon(object):
try:
if not retype:
self.client.deleteVolume(vol_name)
except hpeexceptions.HTTPConflict as ex:
if ex.get_code() == 34:
# This is a special case which means the
# volume is part of a volume set.
self._delete_vvset(volume)
self.client.deleteVolume(vol_name)
except Exception:
pass
@ -3709,6 +3705,24 @@ class HPE3PARCommon(object):
self.client.toggleRemoteCopyConfigMirror(target_name,
mirror_config=True)
def _delete_vvset(self, volume):
# volume is part of a volume set.
volume_name = self._get_3par_vol_name(volume['id'])
vvset_name = self.client.findVolumeSet(volume_name)
LOG.debug("Returned vvset_name = %s", vvset_name)
if vvset_name is not None:
if vvset_name.startswith('vvs-'):
# We have a single volume per volume set, so
# remove the volume set.
self.client.deleteVolumeSet(
self._get_3par_vvs_name(volume['id']))
else:
# We have a pre-defined volume set just remove the
# volume and leave the volume set.
self.client.removeVolumeFromVolumeSet(vvset_name,
volume_name)
class TaskWaiter(object):
"""TaskWaiter waits for task to be not active and returns status."""