From 020944bada1f00e0180d8da6fedc7236ba6445b6 Mon Sep 17 00:00:00 2001 From: amar7ibm Date: Tue, 23 Mar 2021 16:11:41 +0530 Subject: [PATCH] [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 --- .../volume/drivers/ibm/test_storwize_svc.py | 67 ++++++++++++++++++- .../ibm/storwize_svc/storwize_svc_common.py | 22 +++--- ...to_clone_rep_volumes-015e030332f2e714.yaml | 8 +++ 3 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 releasenotes/notes/bug-1920099-ibm-svf-fix_extend_to_clone_rep_volumes-015e030332f2e714.yaml diff --git a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py index 51c7d01343a..dcacca8ba7d 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -8949,11 +8949,15 @@ class StorwizeHelpersTestCase(test.TestCase): '_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(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 = { @@ -8963,13 +8967,72 @@ class StorwizeHelpersTestCase(test.TestCase): 'target_vdisk_name': 'tar-testvol', 'rc_controlled': 'no', 'source_vdisk_name': 'testvol'} - + get_relationship_info.return_value = None 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)) - 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) else: self.storwize_svc_common._check_vdisk_fc_mappings(vol, True, diff --git a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py index 246a990cee8..57497ce00f5 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -2185,7 +2185,7 @@ class StorwizeHelpers(object): @volume_utils.trace def _check_delete_vdisk_fc_mappings(self, name, allow_snaps=True, - allow_fctgt=False): + allow_fctgt=False, rel_info=None): """FlashCopy mapping check helper.""" mapping_ids = self._get_vdisk_fc_mappings(name) wait_for_copy = False @@ -2261,7 +2261,10 @@ class StorwizeHelpers(object): self.ssh.rmfcmap(map_id) elif (status in ['copying', 'prepared'] and progress == '100'): - self.ssh.stopfcmap(map_id) + force = False + if rel_info: + force = True + self.ssh.stopfcmap(map_id, force) else: wait_for_copy = True except exception.VolumeBackendAPIException as ex: @@ -2273,7 +2276,7 @@ class StorwizeHelpers(object): @volume_utils.trace def _check_vdisk_fc_mappings(self, name, allow_snaps=True, - allow_fctgt=False): + allow_fctgt=False, rel_info=None): """FlashCopy mapping check helper.""" # if this is a remove disk we need to be down to one fc clone mapping_ids = self._get_vdisk_fc_mappings(name) @@ -2315,14 +2318,15 @@ class StorwizeHelpers(object): if len(mapping_ids) - len(Rc_mapping_ids) > 1: return 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, - allow_fctgt=False): + allow_fctgt=False, rel_info=None): """Ensure vdisk has no flashcopy mappings.""" timer = loopingcall.FixedIntervalLoopingCall( 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 # beat is every 10 seconds. The flashcopy usually takes hours # before it finishes. Don't set the sleep interval shorter @@ -3681,8 +3685,11 @@ class StorwizeSVCCommonDriver(san.SanDriver, LOG.error(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, - allow_snaps=False) + allow_snaps=False, + rel_info=rel_info) if not ret: msg = (_('_extend_volume_op: Extending a volume with snapshots is ' 'not supported.')) @@ -3693,7 +3700,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, old_size = volume.size extend_amt = int(new_size) - old_size - rel_info = self._helpers.get_relationship_info(volume_name) if rel_info: LOG.warning('_extend_volume_op: Extending a volume with ' 'remote copy is not recommended.') diff --git a/releasenotes/notes/bug-1920099-ibm-svf-fix_extend_to_clone_rep_volumes-015e030332f2e714.yaml b/releasenotes/notes/bug-1920099-ibm-svf-fix_extend_to_clone_rep_volumes-015e030332f2e714.yaml new file mode 100644 index 00000000000..ab788dd506f --- /dev/null +++ b/releasenotes/notes/bug-1920099-ibm-svf-fix_extend_to_clone_rep_volumes-015e030332f2e714.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + IBM Spectrum Virtualize Family driver `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.