diff --git a/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py b/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py index cd8c2496721..97160420c6d 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py @@ -3732,6 +3732,26 @@ class VMAXProvisionTest(test.TestCase): mock_mod.assert_called_once() mock_del.assert_called_once() + @mock.patch.object( + rest.VMAXRest, 'get_snap_linked_device_list', + side_effect=[[{'targetDevice': VMAXCommonData.device_id2}], + [{'targetDevice': VMAXCommonData.device_id2}, + {'targetDevice': VMAXCommonData.device_id3}]]) + @mock.patch.object(provision.VMAXProvision, '_unlink_volume') + def test_delete_volume_snap_check_for_links(self, mock_unlink, mock_tgts): + self.provision.delete_volume_snap_check_for_links( + self.data.array, self.data.test_snapshot_snap_name, + self.data.device_id, self.data.extra_specs) + mock_unlink.assert_called_once_with( + self.data.array, "", "", self.data.test_snapshot_snap_name, + self.data.extra_specs, list_volume_pairs=[ + (self.data.device_id, VMAXCommonData.device_id2)]) + mock_unlink.reset_mock() + self.provision.delete_volume_snap_check_for_links( + self.data.array, self.data.test_snapshot_snap_name, + self.data.device_id, self.data.extra_specs) + self.assertEqual(2, mock_unlink.call_count) + class VMAXCommonTest(test.TestCase): def setUp(self): diff --git a/cinder/volume/drivers/dell_emc/vmax/provision.py b/cinder/volume/drivers/dell_emc/vmax/provision.py index c4a85061528..1a74517c1ef 100644 --- a/cinder/volume/drivers/dell_emc/vmax/provision.py +++ b/cinder/volume/drivers/dell_emc/vmax/provision.py @@ -343,9 +343,16 @@ class VMAXProvision(object): {'vol': source_device, 'snap_name': snap_name}) linked_list = self.rest.get_snap_linked_device_list( array, source_device, snap_name) - for link in linked_list: - target_device = link['targetDevice'] + if len(linked_list) == 1: + target_device = linked_list[0]['targetDevice'] list_device_pairs.append((source_device, target_device)) + else: + for link in linked_list: + # If a single source volume has multiple targets, + # we must unlink each target individually + target_device = link['targetDevice'] + self._unlink_volume(array, source_device, target_device, + snap_name, extra_specs) if list_device_pairs: self._unlink_volume(array, "", "", snap_name, extra_specs, list_volume_pairs=list_device_pairs)