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.