[SVF] Fix issue to get volume relationship details
[Spectrum Virtualize Family] Fix the issue while fetching relationship details of a volume with replication enabled. During some bulk cinder operations such as volume create, retype and clone for a volume with replication enabled, replication properties to metadata are not being updated properly due to an error response from the storage backend while trying to fetch volume-relationship details. Users will feel that the operation is successful but have no idea that volume metadata is partially updated or not updated correctly. So, given a fix by applying a retry mechanism to get volume-relationship details and raising an exception if that backend call still gives an error response. Closes-Bug: #1926286 Change-Id: Iaa03e417727e97011e421e1f45ac2ac5b8e6af6a
This commit is contained in:
parent
81f2aaeea9
commit
eaafd81e9a
@ -4843,6 +4843,14 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self.driver.create_volume(vol)
|
||||
return vol
|
||||
|
||||
def _generate_hyperswap_vol_info(self, hyper_type, size=10):
|
||||
pool = 'hyperswap1'
|
||||
prop = {'host': 'openstack@svc#%s' % pool,
|
||||
'size': size,
|
||||
'volume_type_id': hyper_type.id}
|
||||
vol = testutils.create_volume(self.ctxt, **prop)
|
||||
return vol
|
||||
|
||||
def _generate_vol_info(self, vol_type=None, size=10):
|
||||
pool = _get_test_pool()
|
||||
prop = {'size': size,
|
||||
@ -7745,6 +7753,31 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self._assert_vol_exists('fcsite1' + vol.name, False)
|
||||
self._assert_vol_exists('fcsite2' + vol.name, False)
|
||||
|
||||
# Validate that _update_replication_properties is being called on
|
||||
# Hyperswap volume creation
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeSVCCommonDriver,
|
||||
'_update_replication_properties') as update_rep_properties:
|
||||
vol = self._create_hyperswap_volume(hyper_type)
|
||||
self.assertEqual(fields.VolumeStatus.AVAILABLE, vol['status'])
|
||||
self.assertTrue(update_rep_properties.called)
|
||||
self.driver.delete_volume(vol)
|
||||
|
||||
# Validate that _update_replication_properties is handling
|
||||
# the exception from get_relationship_info call on Hyperswap volume
|
||||
# creation by raising an exception
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeHelpers,
|
||||
'get_relationship_info') as get_relationship_info:
|
||||
get_relationship_info.side_effect = [
|
||||
exception.VolumeBackendAPIException]
|
||||
volume = self._generate_hyperswap_vol_info(hyper_type)
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_volume, volume)
|
||||
self.assertTrue(get_relationship_info.called)
|
||||
self.assertEqual(3, get_relationship_info.call_count)
|
||||
self.driver.delete_volume(volume)
|
||||
|
||||
def test_create_snapshot_to_hyperswap_volume(self):
|
||||
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_system_info') as get_system_info:
|
||||
@ -7994,6 +8027,102 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self.ctxt, hyperswap_vol_type['id'], warning_type['id'])
|
||||
self.driver.retype(self.ctxt, volume, warning_type, diff, host)
|
||||
|
||||
def test_storwize_update_replication_properties_on_retype_hyperswap_volume(
|
||||
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)
|
||||
|
||||
hyperswap_vol_type = self._create_hyperswap_type('test_hyperswap_type')
|
||||
|
||||
spec1 = {'drivers:iogrp': '0,1'}
|
||||
non_hyper_type = self._create_volume_type(spec1, 'non_hyper_type')
|
||||
|
||||
volume1 = testutils.create_volume(self.ctxt,
|
||||
volume_type_id=non_hyper_type.id,
|
||||
host='openstack@svc#hyperswap1')
|
||||
self.driver.create_volume(volume1)
|
||||
volume2 = testutils.create_volume(self.ctxt,
|
||||
volume_type_id=non_hyper_type.id,
|
||||
host='openstack@svc#hyperswap1')
|
||||
self.driver.create_volume(volume2)
|
||||
volume3 = self._create_hyperswap_volume(hyperswap_vol_type)
|
||||
host = {'host': 'openstack@svc#hyperswap1'}
|
||||
|
||||
# Validate that _update_replication_properties is handling
|
||||
# the exception from get_relationship_info call while retyping a
|
||||
# normal volume to Hyperswap volume by raising an exception
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeHelpers,
|
||||
'get_relationship_info') as get_relationship_info:
|
||||
get_relationship_info.side_effect = [
|
||||
exception.VolumeBackendAPIException]
|
||||
diff, _equal = volume_types.volume_types_diff(
|
||||
self.ctxt, non_hyper_type['id'], hyperswap_vol_type['id'])
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.retype, self.ctxt, volume1,
|
||||
hyperswap_vol_type, diff, host)
|
||||
self.assertTrue(get_relationship_info.called)
|
||||
self.assertEqual(3, get_relationship_info.call_count)
|
||||
volume1['volume_type_id'] = hyperswap_vol_type['id']
|
||||
volume1['volume_type'] = hyperswap_vol_type
|
||||
self.driver.delete_volume(volume1)
|
||||
|
||||
# Validate that _update_replication_properties is being called while
|
||||
# retyping a normal volume to Hyperswap volume
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeSVCCommonDriver,
|
||||
'_update_replication_properties') as update_rep_properties:
|
||||
diff, _equal = volume_types.volume_types_diff(
|
||||
self.ctxt, non_hyper_type['id'], hyperswap_vol_type['id'])
|
||||
self.driver.retype(
|
||||
self.ctxt, volume2, hyperswap_vol_type, diff, host)
|
||||
volume2['volume_type_id'] = hyperswap_vol_type['id']
|
||||
volume2['volume_type'] = hyperswap_vol_type
|
||||
self._assert_vol_exists(volume2.name, True)
|
||||
self._assert_vol_exists('site2' + volume2.name, True)
|
||||
self._assert_vol_exists('fcsite1' + volume2.name, True)
|
||||
self._assert_vol_exists('fcsite2' + volume2.name, True)
|
||||
self.assertTrue(update_rep_properties.called)
|
||||
|
||||
# Validate that _update_replication_properties is being called while
|
||||
# retyping a Hyperswap volume to normal volume
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeSVCCommonDriver,
|
||||
'_update_replication_properties') as update_rep_properties:
|
||||
diff, _equal = volume_types.volume_types_diff(
|
||||
self.ctxt, hyperswap_vol_type['id'], non_hyper_type['id'])
|
||||
self.driver.retype(
|
||||
self.ctxt, volume2, non_hyper_type, diff, host)
|
||||
volume2['volume_type_id'] = non_hyper_type['id']
|
||||
volume2['volume_type'] = non_hyper_type
|
||||
self.assertTrue(update_rep_properties.called)
|
||||
self.driver.delete_volume(volume2)
|
||||
|
||||
# Validate that _update_replication_properties is handling
|
||||
# the exception from get_relationship_info call while retyping a
|
||||
# Hyperswap volume to normal volume by raising an exception
|
||||
with mock.patch.object(
|
||||
storwize_svc_common.StorwizeHelpers,
|
||||
'get_relationship_info') as get_relationship_info:
|
||||
get_relationship_info.side_effect = [
|
||||
exception.VolumeBackendAPIException]
|
||||
diff, _equal = volume_types.volume_types_diff(
|
||||
self.ctxt, hyperswap_vol_type['id'], non_hyper_type['id'])
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.retype,
|
||||
self.ctxt, volume3, non_hyper_type, diff, host)
|
||||
self.assertTrue(get_relationship_info.called)
|
||||
self.assertEqual(3, get_relationship_info.call_count)
|
||||
volume3['volume_type_id'] = non_hyper_type['id']
|
||||
volume3['volume_type'] = non_hyper_type
|
||||
self.driver.delete_volume(volume3)
|
||||
|
||||
def test_retype_hyperswap_volume_failure_case(self):
|
||||
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_system_info') as get_system_info:
|
||||
|
@ -3337,6 +3337,20 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
raise exception.VolumeDriverException(reason=msg)
|
||||
|
||||
def _update_replication_properties(self, ctxt, volume, model_update):
|
||||
|
||||
@cinder_utils.retry(exception.VolumeBackendAPIException,
|
||||
interval=2,
|
||||
retries=3)
|
||||
def _try_get_relationship_info(volume_name):
|
||||
try:
|
||||
rel_info = self._helpers.get_relationship_info(volume_name)
|
||||
return rel_info
|
||||
except Exception:
|
||||
msg = (_('_update_replication_properties: Failed to fetch '
|
||||
'relationship details for the volume.'))
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(message=msg)
|
||||
|
||||
model_update = model_update or dict()
|
||||
vol_metadata = model_update.get('metadata', {})
|
||||
|
||||
@ -3348,7 +3362,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
del model_update['metadata']['IOThrottle_rate']
|
||||
model_update['metadata'].update(vol_metadata)
|
||||
|
||||
rel_info = self._helpers.get_relationship_info(volume.name)
|
||||
rel_info = _try_get_relationship_info(volume.name)
|
||||
|
||||
rep_properties = {
|
||||
'Id': 'id',
|
||||
'Relationship Name': 'name',
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
IBM Spectrum Virtualize Family driver
|
||||
`Bug #1926286 <https://bugs.launchpad.net/cinder/+bug/1926286>`_:
|
||||
Fixed an issue while fetching relationship details of a volume with
|
||||
replication enabled.
|
Loading…
Reference in New Issue
Block a user