[SVF]:Storwize HyperSwap snapshot clone is failing
[Spectrum Virtualize Family] During create HyperSwap snapshot, create HyperSwap clone volume, create HyperSwap group snapshot, delete HyperSwap group snapshot, create HyperSwap group clone operations are failing with VolumeDriverException. This patch fixes the issue by skipping the hyperswap checks for snapshot, clone, group snapshot and group clone operations. Closes-Bug: #1924602 Change-Id: I8b7b372e1c8d95b0c199e1f9bca97c065f265fa7
This commit is contained in:
parent
bfb89b652c
commit
91482ac12d
@ -6731,14 +6731,14 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, [vol1])
|
||||
|
||||
hyper_specs = {'hyperswap_group_enabled': '<is> True'}
|
||||
hyper_specs = {'hyperswap_group_enabled': '<is> 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': '<is> 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': '<is> 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': '<is> 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': '<is> 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',
|
||||
|
@ -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):
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
IBM Spectrum Virtualize Family driver `Bug #1924602
|
||||
<https://bugs.launchpad.net/cinder/+bug/1924602>`_: Fixed issue to
|
||||
create snapshots, clones, group snapshots, and group clones for
|
||||
HyperSwap volumes.
|
Loading…
Reference in New Issue
Block a user