PowerMax Driver - Prevent unmanage with snapvx

Current unmanage operations attempt to clean up
any temporary snapshot links that exist on the volume.
However these links are not cleaned unless they have
reached their expiration timeout. Adding additional check
to prevent unmanage from completing unless all temporary
links have been cleared.

Change-Id: I3409308eb0b37352b069ec250db6adb9e082a27d
This commit is contained in:
odonos12 2020-08-17 16:06:39 +01:00
parent ef28bff90d
commit c5f694e008
2 changed files with 26 additions and 2 deletions

View File

@ -1903,10 +1903,12 @@ class PowerMaxCommonTest(test.TestCase):
self.common.manage_existing_get_size, self.common.manage_existing_get_size,
self.data.test_volume, external_ref) self.data.test_volume, external_ref)
@mock.patch.object(rest.PowerMaxRest, 'is_vol_in_rep_session',
return_value=(False, False, False))
@mock.patch.object(common.PowerMaxCommon, @mock.patch.object(common.PowerMaxCommon,
'_remove_vol_and_cleanup_replication') '_remove_vol_and_cleanup_replication')
@mock.patch.object(common.PowerMaxCommon, '_clone_check') @mock.patch.object(common.PowerMaxCommon, '_clone_check')
def test_unmanage_success(self, mck_clone, mock_rm): def test_unmanage_success(self, mck_clone, mock_rm, mck_sess):
volume = self.data.test_volume volume = self.data.test_volume
with mock.patch.object(self.rest, 'rename_volume') as mock_rename: with mock.patch.object(self.rest, 'rename_volume') as mock_rename:
self.common.unmanage(volume) self.common.unmanage(volume)
@ -1931,6 +1933,14 @@ class PowerMaxCommonTest(test.TestCase):
self.common.unmanage(volume) self.common.unmanage(volume)
mock_rename.assert_not_called() mock_rename.assert_not_called()
@mock.patch.object(rest.PowerMaxRest, 'is_vol_in_rep_session',
return_value=(True, True, False))
@mock.patch.object(common.PowerMaxCommon, '_clone_check')
def test_unmanage_temp_snapshot_links(self, mck_clone, mck_sess):
volume = self.data.test_volume
self.assertRaises(exception.VolumeIsBusy, self.common.unmanage,
volume)
@mock.patch.object(common.PowerMaxCommon, '_slo_workload_migration') @mock.patch.object(common.PowerMaxCommon, '_slo_workload_migration')
def test_retype(self, mock_migrate): def test_retype(self, mock_migrate):
device_id = self.data.device_id device_id = self.data.device_id

View File

@ -3330,13 +3330,27 @@ class PowerMaxCommon(object):
{'name': volume_name, 'id': volume_id}) {'name': volume_name, 'id': volume_id})
extra_specs = self._initial_setup(volume) extra_specs = self._initial_setup(volume)
device_id = self._find_device_on_array(volume, extra_specs) device_id = self._find_device_on_array(volume, extra_specs)
array = extra_specs['array']
if device_id is None: if device_id is None:
LOG.error("Cannot find Volume: %(id)s for " LOG.error("Cannot find Volume: %(id)s for "
"unmanage operation. Exiting...", "unmanage operation. Exiting...",
{'id': volume_id}) {'id': volume_id})
else: else:
# Check if volume is snap source # Check if volume is snap source
self._clone_check(extra_specs['array'], device_id, extra_specs) self._clone_check(array, device_id, extra_specs)
snapvx_tgt, snapvx_src, __ = self.rest.is_vol_in_rep_session(
array, device_id)
if snapvx_src or snapvx_tgt:
msg = _(
'Cannot unmanage volume %s with device id %s as it is '
'busy. Please either wait until all temporary snapshot '
'have expired or manually unlink and terminate any '
'remaining temporary sessions when they have been '
'fully copied to their targets. Volume is a snapvx '
'source: %s. Volume is a snapvx target: %s' %
(volume_id, device_id, snapvx_src, snapvx_tgt))
LOG.error(msg)
raise exception.VolumeIsBusy(volume.id)
# Remove volume from any openstack storage groups # Remove volume from any openstack storage groups
# and remove any replication # and remove any replication
self._remove_vol_and_cleanup_replication( self._remove_vol_and_cleanup_replication(