[SVF]: Fix extend issue for a clone of rep-volume

[Spectrum Virtualize Family] During extend operation the flashcopy
mapping between clone volume and its source volume having snapshots,
was not being deleted after copying, hence extend operation
is failing.

This fix is to properly stop the flashcopy mappings before extending.

Closes-Bug: #1920099

Change-Id: I336a8c92bfdd852cab42c9e5f992a30f3632bfaf
This commit is contained in:
amar7ibm 2021-03-23 16:11:41 +05:30
parent a01b5bb39e
commit 020944bada
3 changed files with 87 additions and 10 deletions

View File

@ -8949,11 +8949,15 @@ class StorwizeHelpersTestCase(test.TestCase):
'_get_flashcopy_mapping_attributes') '_get_flashcopy_mapping_attributes')
@mock.patch.object(storwize_svc_common.StorwizeHelpers, @mock.patch.object(storwize_svc_common.StorwizeHelpers,
'_get_vdisk_fc_mappings') '_get_vdisk_fc_mappings')
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
'get_relationship_info')
def test_check_vdisk_fc_mappings(self, def test_check_vdisk_fc_mappings(self,
fc_data, fc_data,
get_relationship_info,
get_vdisk_fc_mappings, get_vdisk_fc_mappings,
get_fc_mapping_attributes, get_fc_mapping_attributes,
rmfcmap, stopfcmap, chfcmap): rmfcmap, stopfcmap, chfcmap):
vol = 'testvol' vol = 'testvol'
get_vdisk_fc_mappings.return_value = ['4'] get_vdisk_fc_mappings.return_value = ['4']
get_fc_mapping_attributes.return_value = { get_fc_mapping_attributes.return_value = {
@ -8963,13 +8967,72 @@ class StorwizeHelpersTestCase(test.TestCase):
'target_vdisk_name': 'tar-testvol', 'target_vdisk_name': 'tar-testvol',
'rc_controlled': 'no', 'rc_controlled': 'no',
'source_vdisk_name': 'testvol'} 'source_vdisk_name': 'testvol'}
get_relationship_info.return_value = None
if(fc_data['copy_rate'] != '0' and fc_data['progress'] == '100' if(fc_data['copy_rate'] != '0' and fc_data['progress'] == '100'
and fc_data['status'] == 'copying'): and fc_data['status'] == 'copying'):
(self.assertRaises(loopingcall.LoopingCallDone, (self.assertRaises(loopingcall.LoopingCallDone,
self.storwize_svc_common._check_vdisk_fc_mappings, vol, True, self.storwize_svc_common._check_vdisk_fc_mappings, vol, True,
False)) False))
stopfcmap.assert_called_with('4') stopfcmap.assert_called_with('4', False)
self.assertEqual(1, stopfcmap.call_count)
else:
self.storwize_svc_common._check_vdisk_fc_mappings(vol, True,
False)
stopfcmap.assert_not_called()
self.assertEqual(0, stopfcmap.call_count)
get_vdisk_fc_mappings.assert_called()
get_fc_mapping_attributes.assert_called_with('4')
rmfcmap.assert_not_called()
self.assertEqual(1, get_fc_mapping_attributes.call_count)
self.assertEqual(0, rmfcmap.call_count)
if(fc_data['copy_rate'] == '0' and fc_data['progress'] == '0'
and fc_data['status'] in ['copying', 'idle_or_copied']):
chfcmap.assert_called_with('4', copyrate='50', autodel='on')
self.assertEqual(1, chfcmap.call_count)
else:
chfcmap.assert_not_called()
self.assertEqual(0, chfcmap.call_count)
@ddt.data({'copy_rate': '50', 'progress': '3', 'status': 'copying'},
{'copy_rate': '50', 'progress': '100', 'status': 'copying'},
{'copy_rate': '0', 'progress': '0', 'status': 'copying'},
{'copy_rate': '50', 'progress': '0', 'status': 'copying'},
{'copy_rate': '0', 'progress': '0', 'status': 'idle_or_copied'})
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'chfcmap')
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'stopfcmap')
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'rmfcmap')
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
'_get_flashcopy_mapping_attributes')
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
'_get_vdisk_fc_mappings')
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
'get_relationship_info')
def test_check_vdisk_fc_mappings_with_rcrel(self,
fc_data,
get_relationship_info,
get_vdisk_fc_mappings,
get_fc_mapping_attributes,
rmfcmap, stopfcmap, chfcmap):
vol = 'testvol'
get_vdisk_fc_mappings.return_value = ['4']
get_fc_mapping_attributes.return_value = {
'copy_rate': fc_data['copy_rate'],
'progress': fc_data['progress'],
'status': fc_data['status'],
'target_vdisk_name': 'tar-testvol',
'rc_controlled': 'no',
'source_vdisk_name': 'testvol'}
rel_info = {'name': 'rcrel232'}
get_relationship_info.return_value = rel_info
if(fc_data['copy_rate'] != '0' and fc_data['progress'] == '100'
and fc_data['status'] == 'copying'):
(self.assertRaises(loopingcall.LoopingCallDone,
self.storwize_svc_common._check_vdisk_fc_mappings, vol, True,
False, rel_info))
stopfcmap.assert_called_with('4', True)
self.assertEqual(1, stopfcmap.call_count) self.assertEqual(1, stopfcmap.call_count)
else: else:
self.storwize_svc_common._check_vdisk_fc_mappings(vol, True, self.storwize_svc_common._check_vdisk_fc_mappings(vol, True,

View File

@ -2185,7 +2185,7 @@ class StorwizeHelpers(object):
@volume_utils.trace @volume_utils.trace
def _check_delete_vdisk_fc_mappings(self, name, allow_snaps=True, def _check_delete_vdisk_fc_mappings(self, name, allow_snaps=True,
allow_fctgt=False): allow_fctgt=False, rel_info=None):
"""FlashCopy mapping check helper.""" """FlashCopy mapping check helper."""
mapping_ids = self._get_vdisk_fc_mappings(name) mapping_ids = self._get_vdisk_fc_mappings(name)
wait_for_copy = False wait_for_copy = False
@ -2261,7 +2261,10 @@ class StorwizeHelpers(object):
self.ssh.rmfcmap(map_id) self.ssh.rmfcmap(map_id)
elif (status in ['copying', 'prepared'] and elif (status in ['copying', 'prepared'] and
progress == '100'): progress == '100'):
self.ssh.stopfcmap(map_id) force = False
if rel_info:
force = True
self.ssh.stopfcmap(map_id, force)
else: else:
wait_for_copy = True wait_for_copy = True
except exception.VolumeBackendAPIException as ex: except exception.VolumeBackendAPIException as ex:
@ -2273,7 +2276,7 @@ class StorwizeHelpers(object):
@volume_utils.trace @volume_utils.trace
def _check_vdisk_fc_mappings(self, name, allow_snaps=True, def _check_vdisk_fc_mappings(self, name, allow_snaps=True,
allow_fctgt=False): allow_fctgt=False, rel_info=None):
"""FlashCopy mapping check helper.""" """FlashCopy mapping check helper."""
# if this is a remove disk we need to be down to one fc clone # if this is a remove disk we need to be down to one fc clone
mapping_ids = self._get_vdisk_fc_mappings(name) mapping_ids = self._get_vdisk_fc_mappings(name)
@ -2315,14 +2318,15 @@ class StorwizeHelpers(object):
if len(mapping_ids) - len(Rc_mapping_ids) > 1: if len(mapping_ids) - len(Rc_mapping_ids) > 1:
return return
return self._check_delete_vdisk_fc_mappings( return self._check_delete_vdisk_fc_mappings(
name, allow_snaps=allow_snaps, allow_fctgt=allow_fctgt) name, allow_snaps=allow_snaps, allow_fctgt=allow_fctgt,
rel_info=rel_info)
def ensure_vdisk_no_fc_mappings(self, name, allow_snaps=True, def ensure_vdisk_no_fc_mappings(self, name, allow_snaps=True,
allow_fctgt=False): allow_fctgt=False, rel_info=None):
"""Ensure vdisk has no flashcopy mappings.""" """Ensure vdisk has no flashcopy mappings."""
timer = loopingcall.FixedIntervalLoopingCall( timer = loopingcall.FixedIntervalLoopingCall(
self._check_vdisk_fc_mappings, name, self._check_vdisk_fc_mappings, name,
allow_snaps, allow_fctgt) allow_snaps, allow_fctgt, rel_info)
# Create a timer greenthread. The default volume service heart # Create a timer greenthread. The default volume service heart
# beat is every 10 seconds. The flashcopy usually takes hours # beat is every 10 seconds. The flashcopy usually takes hours
# before it finishes. Don't set the sleep interval shorter # before it finishes. Don't set the sleep interval shorter
@ -3681,8 +3685,11 @@ class StorwizeSVCCommonDriver(san.SanDriver,
LOG.error(msg) LOG.error(msg)
raise exception.InvalidInput(message=msg) raise exception.InvalidInput(message=msg)
rel_info = self._helpers.get_relationship_info(volume_name)
ret = self._helpers.ensure_vdisk_no_fc_mappings(volume_name, ret = self._helpers.ensure_vdisk_no_fc_mappings(volume_name,
allow_snaps=False) allow_snaps=False,
rel_info=rel_info)
if not ret: if not ret:
msg = (_('_extend_volume_op: Extending a volume with snapshots is ' msg = (_('_extend_volume_op: Extending a volume with snapshots is '
'not supported.')) 'not supported.'))
@ -3693,7 +3700,6 @@ class StorwizeSVCCommonDriver(san.SanDriver,
old_size = volume.size old_size = volume.size
extend_amt = int(new_size) - old_size extend_amt = int(new_size) - old_size
rel_info = self._helpers.get_relationship_info(volume_name)
if rel_info: if rel_info:
LOG.warning('_extend_volume_op: Extending a volume with ' LOG.warning('_extend_volume_op: Extending a volume with '
'remote copy is not recommended.') 'remote copy is not recommended.')

View File

@ -0,0 +1,8 @@
---
fixes:
- |
IBM Spectrum Virtualize Family driver `Bug #1920099
<https://bugs.launchpad.net/cinder/+bug/1920099>`_:
Fix issue where _check_delete_vdisk_fc_mappings was deleting flashcopy
mappings during extend operation of a clone volume where its
source volume already contained a snapshot.