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 c56aaac5570..4e09e2ba702 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -6731,14 +6731,14 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.driver.create_group_from_src, self.ctxt, group, [vol1]) - hyper_specs = {'hyperswap_group_enabled': ' True'} + hyper_specs = {'hyperswap_group_enabled': ' False'} hyper_type_ref = group_types.create(self.ctxt, 'hypergroup', hyper_specs) group = self._create_group_in_db(volume_type_ids=[type_ref.id], group_type_id=hyper_type_ref.id) vol1 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, group_id=group.id) - self.assertRaises(exception.VolumeBackendAPIException, + self.assertRaises(NotImplementedError, self.driver.create_group_from_src, self.ctxt, group, [vol1]) @@ -8024,11 +8024,77 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self._assert_vol_exists(vol.name, True) snap = testutils.create_snapshot(self.ctxt, vol.id) - self.assertRaises(exception.VolumeDriverException, - self.driver.create_snapshot, snap) + + if self.USESIM: + self.sim.error_injection('lsfcmap', 'speed_up') + self.sim.error_injection('startfcmap', 'bad_id') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.create_snapshot, snap) + self._assert_vol_exists(snap['name'], False) + self.sim.error_injection('prestartfcmap', 'bad_id') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.create_snapshot, snap) + self._assert_vol_exists(snap['name'], False) + + self.driver.create_snapshot(snap) + self._assert_vol_exists(snap['name'], True) self.driver.delete_volume(vol) self._assert_vol_exists(vol.name, False) + self.driver.delete_snapshot(snap) + self._assert_vol_exists(snap['name'], False) + + def test_create_hyperswap_volume_from_snapshot(self): + with mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'get_system_info') as get_system_info: + fake_system_info = {'code_level': (7, 7, 0, 0), + 'topology': 'hyperswap', + 'system_name': 'storwize-svc-sim', + 'system_id': '0123456789ABCDEF'} + get_system_info.return_value = fake_system_info + self.driver.do_setup(None) + + hyper_type = self._create_hyperswap_type('test_hyperswap_type') + vol = self._create_hyperswap_volume(hyper_type) + self._assert_vol_exists(vol.name, True) + + snap = testutils.create_snapshot(self.ctxt, vol.id) + self.driver.create_snapshot(snap) + self._assert_vol_exists(snap['name'], True) + + vol1 = testutils.create_volume(self.ctxt, + host='openstack@svc#hyperswap1', + volume_type_id=hyper_type.id) + + self.driver.create_volume_from_snapshot(vol1, snap) + self._assert_vol_exists(vol1.name, True) + self._assert_vol_exists('site2' + vol1.name, True) + self._assert_vol_exists('fcsite1' + vol1.name, True) + self._assert_vol_exists('fcsite2' + vol1.name, True) + + vol2 = testutils.create_volume(self.ctxt, + host='openstack@svc#hyperswap1', + volume_type_id=hyper_type.id) + with (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'convert_volume_to_hyperswap')) as convert_volume_to_hyperswap,\ + (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'ensure_vdisk_no_fc_mappings')) as ensure_vdisk_no_fc_mappings: + self.driver.create_volume_from_snapshot(vol2, snap) + ensure_vdisk_no_fc_mappings.assert_called() + convert_volume_to_hyperswap.assert_called() + self.assertEqual(1, convert_volume_to_hyperswap.call_count) + self.assertEqual(1, ensure_vdisk_no_fc_mappings.call_count) + self._assert_vol_exists(vol2.name, True) + + self.driver.delete_volume(vol) + self._assert_vol_exists(vol.name, False) + self._assert_vol_exists('site2' + vol.name, False) + self._assert_vol_exists('fcsite1' + vol.name, False) + self._assert_vol_exists('fcsite2' + vol.name, False) + self.driver.delete_snapshot(snap) + self._assert_vol_exists(snap['name'], False) + self.driver.delete_volume(vol1) + self._assert_vol_exists(vol1.name, False) def test_create_cloned_hyperswap_volume(self): with mock.patch.object(storwize_svc_common.StorwizeHelpers, @@ -8073,10 +8139,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): 'system_id': '0123456789ABCDEF'} get_system_info.return_value = fake_system_info self.driver.do_setup(None) - spec = {'drivers:volume_topology': 'hyperswap', - 'peer_pool': 'hyperswap2'} - vol_type_ref = volume_types.create(self.ctxt, 'test_hyperswap_type', - spec) + vol_type_ref = self._create_hyperswap_type('test_hyperswap_type') vol = self._create_hyperswap_volume(vol_type_ref) self._assert_vol_exists(vol.name, True) @@ -8086,6 +8149,38 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertAlmostEqual(vol_size, 13) self.driver.delete_volume(vol) + # Extend hyperswap volume that added to group. + group_specs = {'hyperswap_group_enabled': ' True'} + group_type_ref = group_types.create(self.ctxt, 'testgroup', + group_specs) + hyper_group = testutils.create_group( + self.ctxt, name='hypergroup', + group_type_id=group_type_ref['id'], + volume_type_ids=[vol_type_ref['id']]) + model_update = self.driver.create_group(self.ctxt, hyper_group) + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + + vol = self._create_hyperswap_volume(vol_type_ref) + self.db.volume_update(context.get_admin_context(), vol['id'], + {'group_id': hyper_group.id}) + add_volumes = [vol] + del_volumes = [] + (model_update, add_volumes_update, + remove_volumes_update) = self.driver.update_group(self.ctxt, + hyper_group, + add_volumes, + del_volumes) + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + self.assertEqual([{'id': vol.id, 'group_id': hyper_group.id}], + add_volumes_update) + self.assertEqual([], remove_volumes_update) + + self.driver.extend_volume(vol, '15') + attrs = self.driver._helpers.get_vdisk_attributes(vol['name']) + vol_size = int(attrs['capacity']) / units.Gi + self.assertAlmostEqual(vol_size, 15) + self.driver.delete_volume(vol) + # Extend hyperswap volume with thick_provisioning_support. spec = {'drivers:volume_topology': 'hyperswap', 'peer_pool': 'hyperswap2', @@ -8094,7 +8189,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.ctxt, 'test_hyperswap_thick_type', spec) hs_vol = self._create_hyperswap_volume(hs_thick_type) self._assert_vol_exists(hs_vol.name, True) - if self.USESIM: # tell expandvdisksize to fail while called extend_volume # because volume is fast formatting @@ -8106,46 +8200,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertAlmostEqual(vol_size, 1) self.driver.delete_volume(hs_vol) - # Extend hyperswap volume that added to group. - with mock.patch.object(storwize_svc_common.StorwizeHelpers, - 'extend_vdisk') as extend_vdisk: - group_specs = {'hyperswap_group_enabled': ' True'} - group_type_ref = group_types.create(self.ctxt, 'testgroup', - group_specs) - hyper_group = testutils.create_group( - self.ctxt, name='hypergroup', - group_type_id=group_type_ref['id'], - volume_type_ids=[vol_type_ref['id']]) - model_update = self.driver.create_group(self.ctxt, hyper_group) - self.assertEqual(fields.GroupStatus.AVAILABLE, - model_update['status']) - - vol = self._create_hyperswap_volume(vol_type_ref) - self.db.volume_update(context.get_admin_context(), vol['id'], - {'group_id': hyper_group.id}) - add_volumes = [vol] - del_volumes = [] - - (model_update, add_volumes_update, - remove_volumes_update) = self.driver.update_group(self.ctxt, - hyper_group, - add_volumes, - del_volumes) - self.assertEqual(fields.GroupStatus.AVAILABLE, - model_update['status']) - self.assertEqual([{'id': vol.id, 'group_id': hyper_group.id}], - add_volumes_update) - self.assertEqual([], remove_volumes_update) - - self.assertRaises(exception.VolumeDriverException, - self.driver.extend_volume, vol, 15) - - self.assertFalse(extend_vdisk.called) - attrs = self.driver._helpers.get_vdisk_attributes(vol['name']) - vol_size = int(attrs['capacity']) / units.Gi - self.assertAlmostEqual(vol_size, 1) - self.driver.delete_volume(vol) - def test_migrate_hyperswap_volume(self): with mock.patch.object(storwize_svc_common.StorwizeHelpers, 'get_system_info') as get_system_info: @@ -8595,8 +8649,12 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.ctxt, mirror_volume, hyperswap_vol_type, diff, host3) + @mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver, + '_get_rccg_name') + @mock.patch.object(storwize_svc_common.StorwizeHelpers, 'create_rccg') @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type') - def test_storwize_hyperswap_group_create(self, is_grp_a_cg_snapshot_type): + def test_storwize_hyperswap_group_create(self, is_grp_a_cg_snapshot_type, + create_rccg, get_rccg_name): """Test group create.""" is_grp_a_cg_snapshot_type.side_effect = [False, False, False, False] with mock.patch.object(storwize_svc_common.StorwizeHelpers, @@ -8620,6 +8678,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): model_update = self.driver.create_group(self.ctxt, group) self.assertEqual(fields.GroupStatus.ERROR, model_update['status']) + create_rccg.assert_not_called() + get_rccg_name.assert_not_called() # create hyperswap group with hyper volume type. spec = {'drivers:volume_topology': 'hyperswap', @@ -8633,9 +8693,15 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): model_update = self.driver.create_group(self.ctxt, hyper_group) self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + create_rccg.assert_not_called() + get_rccg_name.assert_not_called() + @mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver, + '_get_rccg_name') + @mock.patch.object(storwize_svc_common.StorwizeHelpers, 'delete_rccg') @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type') - def test_storwize_hyperswap_group_delete(self, is_grp_a_cg_snapshot_type): + def test_storwize_hyperswap_group_delete(self, is_grp_a_cg_snapshot_type, + delete_rccg, get_rccg_name): """Test group create.""" is_grp_a_cg_snapshot_type.side_effect = [False, False, False] @@ -8679,8 +8745,20 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): for volume in model_update[1]: self.assertEqual('deleted', volume['status']) + delete_rccg.assert_not_called() + get_rccg_name.assert_not_called() + + @mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver, + '_get_rccg_name') + @mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'get_relationship_info') + @mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'chrcrelationship') @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type') - def test_storwize_hyperswap_group_update(self, is_grp_a_cg_snapshot_type): + def test_storwize_hyperswap_group_update(self, is_grp_a_cg_snapshot_type, + chrcrelationship, + get_relationship_info, + get_rccg_name): """Test group create.""" is_grp_a_cg_snapshot_type.side_effect = [False, False, False, False, False] @@ -8717,6 +8795,9 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): add_volumes = [vol1, vol2] del_volumes = [] + get_relationship_info.assert_called() + self.assertEqual(2, get_relationship_info.call_count) + # add hyperswap volume (model_update, add_volumes_update, remove_volumes_update) = self.driver.update_group(self.ctxt, @@ -8729,6 +8810,10 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): {'id': vol2.id, 'group_id': hyper_group.id}], add_volumes_update, ) self.assertEqual([], remove_volumes_update) + chrcrelationship.assert_not_called() + get_relationship_info.assert_called() + self.assertEqual(2, get_relationship_info.call_count) + get_rccg_name.assert_not_called() # del hyperswap volume from volume group add_volumes = [] @@ -8744,6 +8829,10 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertEqual([{'id': vol1.id, 'group_id': None}, {'id': vol2.id, 'group_id': None}], remove_volumes_update) + chrcrelationship.assert_not_called() + get_relationship_info.assert_called() + self.assertEqual(2, get_relationship_info.call_count) + get_rccg_name.assert_not_called() # add non-hyper volume non_type_ref = volume_types.create(self.ctxt, 'nonhypertype', None) @@ -8757,6 +8846,266 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): add_volumes_update) self.assertEqual([], remove_volumes_update) + # del non-hyper volume + vol4 = self._create_volume(volume_type_id=non_type_ref['id']) + (model_update, add_volumes_update, + remove_volumes_update) = self.driver.update_group( + self.ctxt, hyper_group, [], [vol4, vol1]) + self.assertEqual(fields.GroupStatus.ERROR, + model_update['status']) + self.assertEqual([{'id': vol1.id, 'group_id': None}], + remove_volumes_update) + self.assertEqual([], add_volumes_update) + + @mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', + new=testutils.ZeroIntervalLoopingCall) + @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type') + def test_hyperswap_create_group_from_grp(self, is_group_a_cg_snap_type): + # Valid case for create hyperswap group from src + is_group_a_cg_snap_type.return_value = False + with mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'get_system_info') as get_system_info: + fake_system_info = {'code_level': (7, 7, 0, 0), + 'topology': 'hyperswap', + 'system_name': 'storwize-svc-sim', + 'system_id': '0123456789ABCDEF'} + get_system_info.return_value = fake_system_info + self.driver.do_setup(None) + + group_specs = {'hyperswap_group_enabled': ' True'} + group_type_ref = group_types.create(self.ctxt, 'testgroup', + group_specs) + + # create hyperswap group with hyper volume type. + volume_type_ref = self._create_hyperswap_type( + 'hyper_type') + source_hyper_group = testutils.create_group( + self.ctxt, name='src_hypergroup', + group_type_id=group_type_ref['id'], + volume_type_ids=[volume_type_ref['id']]) + + model_update = self.driver.create_group(self.ctxt, source_hyper_group) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + + src_vol1 = self._create_hyperswap_volume(volume_type_ref) + src_vol2 = self._create_hyperswap_volume(volume_type_ref) + ctxt = context.get_admin_context() + self.db.volume_update(ctxt, src_vol1['id'], + {'group_id': source_hyper_group.id}) + self.db.volume_update(ctxt, src_vol2['id'], + {'group_id': source_hyper_group.id}) + add_volumes = [src_vol1, src_vol2] + del_volumes = [] + + # add hyperswap volume + (model_update, add_volumes_update, + remove_volumes_update) = self.driver.update_group(self.ctxt, + source_hyper_group, + add_volumes, + del_volumes) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + self.assertEqual([{'id': src_vol1.id, + 'group_id': source_hyper_group.id}, + {'id': src_vol2.id, + 'group_id': source_hyper_group.id}], + add_volumes_update, ) + source_vols = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), source_hyper_group['id']) + + # clone hyper group + Clone_hyper_group = testutils.create_group( + self.ctxt, name='clon_hypergroup', + group_type_id=group_type_ref['id'], + volume_type_ids=[volume_type_ref['id']]) + + clone_vol1 = testutils.create_volume( + self.ctxt, host='openstack@svc#hyperswap1', + volume_type_id=volume_type_ref.id, group_id=Clone_hyper_group.id) + clone_vol2 = testutils.create_volume( + self.ctxt, host='openstack@svc#hyperswap1', + volume_type_id=volume_type_ref.id, group_id=Clone_hyper_group.id) + + clone_volumes = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), Clone_hyper_group['id']) + + # Create hyperswap group from source hyperswap group + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, Clone_hyper_group, + clone_volumes, None, None, + source_hyper_group, + source_vols)) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status'], + "CG create from src created failed") + for each_vol in volumes_model_update: + self.assertEqual('available', each_vol['status']) + + for vol in clone_volumes: + self._assert_vol_exists(vol.name, True) + self._assert_vol_exists('site2' + vol.name, True) + self._assert_vol_exists('fcsite1' + vol.name, True) + self._assert_vol_exists('fcsite2' + vol.name, True) + + self.driver.delete_group(self.ctxt, Clone_hyper_group, + [clone_vol1, clone_vol2]) + + with (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'convert_volume_to_hyperswap')) as convert_volume_to_hyperswap,\ + (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'ensure_vdisk_no_fc_mappings')) as ensure_vdisk_no_fc_mappings: + + # Create cg from source cg + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, + Clone_hyper_group, + clone_volumes, None, + None, source_hyper_group, + source_vols)) + ensure_vdisk_no_fc_mappings.assert_called() + self.assertEqual(2, ensure_vdisk_no_fc_mappings.call_count) + convert_volume_to_hyperswap.assert_called() + self.assertEqual(2, convert_volume_to_hyperswap.call_count) + + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status'], + "CG create from src created failed") + for each_vol in volumes_model_update: + self.assertEqual('available', each_vol['status']) + + for vol in clone_volumes: + self._assert_vol_exists(vol.name, True) + self._assert_vol_exists('site2' + vol.name, False) + self._assert_vol_exists('fcsite1' + vol.name, False) + self._assert_vol_exists('fcsite2' + vol.name, False) + + @mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', + new=testutils.ZeroIntervalLoopingCall) + @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type') + def test_hyperswap_create_group_from_snapshot(self, + is_group_a_cg_snap_type): + # Valid case for create hyperswap group from src + is_group_a_cg_snap_type.return_value = False + with mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'get_system_info') as get_system_info: + fake_system_info = {'code_level': (7, 7, 0, 0), + 'topology': 'hyperswap', + 'system_name': 'storwize-svc-sim', + 'system_id': '0123456789ABCDEF'} + get_system_info.return_value = fake_system_info + self.driver.do_setup(None) + + group_specs = {'hyperswap_group_enabled': ' True'} + group_type_ref = group_types.create(self.ctxt, 'testgroup', + group_specs) + + # create hyperswap group with hyper volume type. + volume_type_ref = self._create_hyperswap_type( + 'hyper_type') + source_hyper_group = testutils.create_group( + self.ctxt, name='src_hypergroup', + group_type_id=group_type_ref['id'], + volume_type_ids=[volume_type_ref['id']]) + + model_update = self.driver.create_group(self.ctxt, + source_hyper_group) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + + src_vol1 = self._create_hyperswap_volume(volume_type_ref) + src_vol2 = self._create_hyperswap_volume(volume_type_ref) + ctxt = context.get_admin_context() + self.db.volume_update(ctxt, src_vol1['id'], + {'group_id': source_hyper_group.id}) + self.db.volume_update(ctxt, src_vol2['id'], + {'group_id': source_hyper_group.id}) + add_volumes = [src_vol1, src_vol2] + del_volumes = [] + + # add hyperswap volume + (model_update, add_volumes_update, + remove_volumes_update) = self.driver.update_group(self.ctxt, + source_hyper_group, + add_volumes, + del_volumes) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + self.assertEqual([{'id': src_vol1.id, + 'group_id': source_hyper_group.id}, + {'id': src_vol2.id, + 'group_id': source_hyper_group.id}], + add_volumes_update, ) + + # clone hyper group + Clone_hyper_group = testutils.create_group( + self.ctxt, name='clon_hypergroup', + group_type_id=group_type_ref['id'], + volume_type_ids=[volume_type_ref['id']]) + + clone_vol1 = testutils.create_volume( + self.ctxt, host='openstack@svc#hyperswap1', + volume_type_id=volume_type_ref.id, group_id=Clone_hyper_group.id) + clone_vol2 = testutils.create_volume( + self.ctxt, host='openstack@svc#hyperswap1', + volume_type_id=volume_type_ref.id, group_id=Clone_hyper_group.id) + + clone_volumes = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), Clone_hyper_group['id']) + + # Create hyperswap group snapshot + group_snapshot, snapshots = self._create_group_snapshot( + source_hyper_group['id'], group_type_id=group_type_ref.id) + + # Create hyperswap group from hyperswap group snapshot + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, Clone_hyper_group, + clone_volumes, group_snapshot, + snapshots, None, None)) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status'], + "CG create from src created failed") + for each_vol in volumes_model_update: + self.assertEqual('available', each_vol['status']) + + for vol in clone_volumes: + self._assert_vol_exists(vol.name, True) + self._assert_vol_exists('site2' + vol.name, True) + self._assert_vol_exists('fcsite1' + vol.name, True) + self._assert_vol_exists('fcsite2' + vol.name, True) + + self.driver.delete_group(self.ctxt, Clone_hyper_group, + [clone_vol1, clone_vol2]) + + with (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'convert_volume_to_hyperswap')) as convert_volume_to_hyperswap,\ + (mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'ensure_vdisk_no_fc_mappings')) as ensure_vdisk_no_fc_mappings: + + # Create cg from source cg + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, + Clone_hyper_group, + clone_volumes, + group_snapshot, + snapshots, None, None)) + ensure_vdisk_no_fc_mappings.assert_called() + self.assertEqual(2, ensure_vdisk_no_fc_mappings.call_count) + convert_volume_to_hyperswap.assert_called() + self.assertEqual(2, convert_volume_to_hyperswap.call_count) + + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status'], + "CG create from src created failed") + for each_vol in volumes_model_update: + self.assertEqual('available', each_vol['status']) + + for vol in clone_volumes: + self._assert_vol_exists(vol.name, True) + self._assert_vol_exists('site2' + vol.name, False) + self._assert_vol_exists('fcsite1' + vol.name, False) + self._assert_vol_exists('fcsite2' + vol.name, False) + @ddt.data({'spec': {'rsize': -1}}, {'spec': {'mirror_pool': 'dr_pool2'}}, {'spec': {'drivers:volume_topology': 'hyperswap', 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 7d9ba4317f4..c79a02ee6d3 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -3658,12 +3658,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, pool = volume_utils.extract_host(source_vol['host'], 'pool') opts = self._get_vdisk_params(source_vol['volume_type_id']) - if opts['volume_topology'] == 'hyperswap': - msg = _('create_snapshot: Create snapshot to a ' - 'hyperswap volume is not allowed.') - LOG.error(msg) - raise exception.VolumeDriverException(message=msg) - self._helpers.create_copy(snapshot['volume_name'], snapshot['name'], snapshot['volume_id'], self.configuration, opts, False, self._state, pool=pool) @@ -3719,6 +3713,20 @@ class StorwizeSVCCommonDriver(san.SanDriver, # enabled. model_update = self._update_replication_properties(ctxt, volume, model_update) + + if opts['volume_topology'] == 'hyperswap': + LOG.debug('The volume %s to be created is a hyperswap ' + 'volume.', volume.name) + # Ensures the vdisk is not part of FC mapping. + # Otherwize convert it to hyperswap volume will be failed. + self._helpers.ensure_vdisk_no_fc_mappings(volume['name'], + allow_snaps=True, + allow_fctgt=False) + + self._helpers.convert_volume_to_hyperswap(volume['name'], + opts, + self._state) + return model_update def create_cloned_volume(self, tgt_volume, src_volume): @@ -5780,15 +5788,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, model_update = {'status': fields.GroupStatus.ERROR} return model_update - rccg_name = self._get_rccg_name(group, hyper_grp=True) - try: - self._helpers.create_rccg( - rccg_name, self._state['system_name']) - except exception.VolumeBackendAPIException as err: - LOG.error("Failed to create rccg %(rccg)s. " - "Exception: %(exception)s.", - {'rccg': group.name, 'exception': err}) - model_update = {'status': fields.GroupStatus.ERROR} return model_update def delete_group(self, context, group, volumes): @@ -5898,16 +5897,15 @@ class StorwizeSVCCommonDriver(san.SanDriver, """ LOG.debug('Enter: create_group_from_src.') + is_hyper_group = False if volume_utils.is_group_a_type(group, "hyperswap_group_enabled"): - # An unsupported configuration - msg = _('Unable to create hyperswap group: create hyperswap ' - 'group from a hyperswap group is not supported.') - LOG.exception(msg) - raise exception.VolumeBackendAPIException(data=msg) + is_hyper_group = True if (not volume_utils.is_group_a_cg_snapshot_type(group) and not volume_utils.is_group_a_type - (group, "consistent_group_replication_enabled")): + (group, "consistent_group_replication_enabled") + and not volume_utils.is_group_a_type( + group, "hyperswap_group_enabled")): # we'll rely on the generic volume groups implementation if it is # not a consistency group request. raise NotImplementedError() @@ -5976,10 +5974,23 @@ class StorwizeSVCCommonDriver(san.SanDriver, volumes_model[volumes.index(vol)] = ( self._qos_model_update( volumes_model[volumes.index(vol)], vol)) + + if is_hyper_group: + self._helpers.ensure_vdisk_no_fc_mappings(vol['name'], + allow_snaps=True, + allow_fctgt=False) + opts = self._get_vdisk_params(vol['volume_type_id'], + volume_metadata= + vol.get('volume_metadata')) + self._helpers.convert_volume_to_hyperswap(vol['name'], + opts, + self._state) + if volume_utils.is_group_a_type( group, "consistent_group_replication_enabled"): self.update_group(context, group, add_volumes=volumes, remove_volumes=[]) + LOG.debug("Leave: create_group_from_src.") return model_update, volumes_model @@ -5993,7 +6004,9 @@ class StorwizeSVCCommonDriver(san.SanDriver, """ if (not volume_utils.is_group_a_cg_snapshot_type(group_snapshot) and not volume_utils.is_group_a_type - (group_snapshot, "consistent_group_replication_enabled")): + (group_snapshot, "consistent_group_replication_enabled") + and not volume_utils.is_group_a_type( + group_snapshot, "hyperswap_group_enabled")): # we'll rely on the generic group implementation if it is not a # consistency group request. raise NotImplementedError() @@ -6022,7 +6035,9 @@ class StorwizeSVCCommonDriver(san.SanDriver, :returns: model_update, snapshots_model_update """ - if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + if (not volume_utils.is_group_a_cg_snapshot_type(group_snapshot) and + not volume_utils.is_group_a_type( + group_snapshot, "hyperswap_group_enabled")): # we'll rely on the generic group implementation if it is not a # consistency group request. raise NotImplementedError() @@ -6435,14 +6450,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, def _delete_hyperswap_grp(self, group, volumes): model_update = {'status': fields.GroupStatus.DELETED} volumes_model_update = [] - try: - rccg_name = self._get_rccg_name(group, hyper_grp=True) - self._helpers.delete_rccg(rccg_name) - except exception.VolumeBackendAPIException as err: - LOG.error("Failed to delete rccg %(rccg)s. " - "Exception: %(exception)s.", - {'rccg': group.name, 'exception': err}) - model_update = {'status': fields.GroupStatus.ERROR_DELETING} for volume in volumes: try: @@ -6464,14 +6471,7 @@ class StorwizeSVCCommonDriver(san.SanDriver, add_volumes=None, remove_volumes=None): LOG.info("Update hyperswap group: %(group)s. ", {'group': group.id}) model_update = {'status': fields.GroupStatus.AVAILABLE} - rccg_name = self._get_rccg_name(group, hyper_grp=True) - if not self._helpers.get_rccg(rccg_name): - LOG.error("Failed to update rccg: %(grp)s does not exist in " - "backend.", {'grp': group.id}) - model_update['status'] = fields.GroupStatus.ERROR - return model_update, None, None - # Add remote copy relationship to rccg added_vols = [] for volume in add_volumes: hyper_volume = self.is_volume_hyperswap(volume) @@ -6481,42 +6481,19 @@ class StorwizeSVCCommonDriver(san.SanDriver, {'vol': volume.id}) model_update['status'] = fields.GroupStatus.ERROR continue - try: - rcrel = self._helpers.get_relationship_info(volume.name) - if not rcrel: - LOG.error("Failed to update rccg: remote copy relationship" - " of %(vol)s does not exist in backend.", - {'vol': volume.id}) - model_update['status'] = fields.GroupStatus.ERROR - else: - self._helpers.chrcrelationship(rcrel['name'], rccg_name) - added_vols.append({'id': volume.id, - 'group_id': group.id}) - except exception.VolumeBackendAPIException as err: - model_update['status'] = fields.GroupStatus.ERROR - LOG.error("Failed to add the remote copy of volume %(vol)s to " - "rccg. Exception: %(exception)s.", - {'vol': volume.name, 'exception': err}) + added_vols.append({'id': volume.id, 'group_id': group.id}) - # Remove remote copy relationship from rccg removed_vols = [] for volume in remove_volumes: - try: - rcrel = self._helpers.get_relationship_info(volume.name) - if not rcrel: - LOG.error("Failed to update rccg: remote copy relationship" - " of %(vol)s does not exit in backend.", - {'vol': volume.id}) - model_update['status'] = fields.GroupStatus.ERROR - else: - self._helpers.chrcrelationship(rcrel['name']) - removed_vols.append({'id': volume.id, - 'group_id': None}) - except exception.VolumeBackendAPIException as err: + hyper_volume = self.is_volume_hyperswap(volume) + if not hyper_volume: + LOG.error("Failed to update rccg: the non hyperswap volume" + " of %(vol)s can't be added to hyperswap group.", + {'vol': volume.id}) model_update['status'] = fields.GroupStatus.ERROR - LOG.error("Failed to remove the remote copy of volume %(vol)s " - "from rccg. Exception: %(exception)s.", - {'vol': volume.name, 'exception': err}) + continue + removed_vols.append({'id': volume.id, 'group_id': None}) + return model_update, added_vols, removed_vols def _get_volume_host_site_from_conf(self, volume, connector, iscsi=False): diff --git a/releasenotes/notes/bug-1924602-ibm-svf_Storwize_HyperSwap_snapshot_clone_is_failing-c144e6b99d56de64.yaml b/releasenotes/notes/bug-1924602-ibm-svf_Storwize_HyperSwap_snapshot_clone_is_failing-c144e6b99d56de64.yaml new file mode 100644 index 00000000000..be42fe3bb55 --- /dev/null +++ b/releasenotes/notes/bug-1924602-ibm-svf_Storwize_HyperSwap_snapshot_clone_is_failing-c144e6b99d56de64.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + IBM Spectrum Virtualize Family driver `Bug #1924602 + `_: Fixed issue to + create snapshots, clones, group snapshots, and group clones for + HyperSwap volumes.