Merge "NetApp SolidFire: Fix clone and request timeout issues"
This commit is contained in:
commit
0f2eff2ec3
@ -221,7 +221,7 @@ class SolidFireVolumeTestCase(test.TestCase):
|
|||||||
'volumeID': 6}]
|
'volumeID': 6}]
|
||||||
|
|
||||||
def fake_issue_api_request(self, method, params, version='1.0',
|
def fake_issue_api_request(self, method, params, version='1.0',
|
||||||
endpoint=None):
|
endpoint=None, timeout=None):
|
||||||
if method == 'GetClusterCapacity':
|
if method == 'GetClusterCapacity':
|
||||||
data = {}
|
data = {}
|
||||||
if version == '1.0':
|
if version == '1.0':
|
||||||
@ -638,6 +638,12 @@ class SolidFireVolumeTestCase(test.TestCase):
|
|||||||
'volume_type_id': None,
|
'volume_type_id': None,
|
||||||
'created_at': timeutils.utcnow()}
|
'created_at': timeutils.utcnow()}
|
||||||
|
|
||||||
|
fake_model_info = {
|
||||||
|
'provider_id': '%s %s cluster-id-01' % (
|
||||||
|
self.fake_sfvol['volumeID'],
|
||||||
|
self.fake_sfaccount['accountID'])
|
||||||
|
}
|
||||||
|
|
||||||
ctx = context.get_admin_context()
|
ctx = context.get_admin_context()
|
||||||
testvol = fake_volume.fake_volume_obj(ctx, **updates_vol_a)
|
testvol = fake_volume.fake_volume_obj(ctx, **updates_vol_a)
|
||||||
testvol_b = fake_volume.fake_volume_obj(ctx, **updates_vol_b)
|
testvol_b = fake_volume.fake_volume_obj(ctx, **updates_vol_b)
|
||||||
@ -657,7 +663,7 @@ class SolidFireVolumeTestCase(test.TestCase):
|
|||||||
return_value=[]), \
|
return_value=[]), \
|
||||||
mock.patch.object(sfv,
|
mock.patch.object(sfv,
|
||||||
'_get_model_info',
|
'_get_model_info',
|
||||||
return_value={}):
|
return_value=fake_model_info):
|
||||||
sfv.create_cloned_volume(testvol_b, testvol)
|
sfv.create_cloned_volume(testvol_b, testvol)
|
||||||
|
|
||||||
def test_initialize_connector_with_blocksizes(self):
|
def test_initialize_connector_with_blocksizes(self):
|
||||||
@ -3041,6 +3047,7 @@ class SolidFireVolumeTestCase(test.TestCase):
|
|||||||
'mvip': self.mvip,
|
'mvip': self.mvip,
|
||||||
'svip': self.svip}
|
'svip': self.svip}
|
||||||
|
|
||||||
|
self.configuration.sf_volume_clone_timeout = 1
|
||||||
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
|
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
|
||||||
sfv.replication_enabled = False
|
sfv.replication_enabled = False
|
||||||
|
|
||||||
@ -3085,7 +3092,7 @@ class SolidFireVolumeTestCase(test.TestCase):
|
|||||||
mock_issue_api_request.assert_has_calls(calls)
|
mock_issue_api_request.assert_has_calls(calls)
|
||||||
mock_test_set_cluster_pairs.assert_not_called()
|
mock_test_set_cluster_pairs.assert_not_called()
|
||||||
mock_update_attributes.assert_not_called()
|
mock_update_attributes.assert_not_called()
|
||||||
mock_get_model_info.assert_called_once()
|
mock_get_model_info.assert_called()
|
||||||
mock_snapshot_discovery.assert_not_called()
|
mock_snapshot_discovery.assert_not_called()
|
||||||
|
|
||||||
reset_mocks()
|
reset_mocks()
|
||||||
|
@ -100,7 +100,18 @@ sf_opts = [
|
|||||||
default=3600,
|
default=3600,
|
||||||
min=30,
|
min=30,
|
||||||
help='Sets time in seconds to wait for a migrating volume to '
|
help='Sets time in seconds to wait for a migrating volume to '
|
||||||
'complete pairing and sync.')]
|
'complete pairing and sync.'),
|
||||||
|
cfg.IntOpt('sf_api_request_timeout',
|
||||||
|
default=30,
|
||||||
|
min=30,
|
||||||
|
help='Sets time in seconds to wait for an api request to '
|
||||||
|
'complete.'),
|
||||||
|
cfg.IntOpt('sf_volume_clone_timeout',
|
||||||
|
default=600,
|
||||||
|
min=60,
|
||||||
|
help='Sets time in seconds to wait for a clone of a volume or '
|
||||||
|
'snapshot to complete.'
|
||||||
|
)]
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.register_opts(sf_opts, group=configuration.SHARED_CONF_GROUP)
|
CONF.register_opts(sf_opts, group=configuration.SHARED_CONF_GROUP)
|
||||||
@ -656,11 +667,14 @@ class SolidFireDriver(san.SanISCSIDriver):
|
|||||||
return endpoint
|
return endpoint
|
||||||
|
|
||||||
@retry(retry_exc_tuple, tries=6)
|
@retry(retry_exc_tuple, tries=6)
|
||||||
def _issue_api_request(self, method, params, version='1.0', endpoint=None):
|
def _issue_api_request(self, method, params, version='1.0',
|
||||||
|
endpoint=None, timeout=None):
|
||||||
if params is None:
|
if params is None:
|
||||||
params = {}
|
params = {}
|
||||||
if endpoint is None:
|
if endpoint is None:
|
||||||
endpoint = self.active_cluster['endpoint']
|
endpoint = self.active_cluster['endpoint']
|
||||||
|
if not timeout:
|
||||||
|
timeout = self.configuration.sf_api_request_timeout
|
||||||
|
|
||||||
payload = {'method': method, 'params': params}
|
payload = {'method': method, 'params': params}
|
||||||
url = '%s/json-rpc/%s/' % (endpoint['url'], version)
|
url = '%s/json-rpc/%s/' % (endpoint['url'], version)
|
||||||
@ -672,7 +686,7 @@ class SolidFireDriver(san.SanISCSIDriver):
|
|||||||
data=json.dumps(payload),
|
data=json.dumps(payload),
|
||||||
auth=(endpoint['login'], endpoint['passwd']),
|
auth=(endpoint['login'], endpoint['passwd']),
|
||||||
verify=self.verify_ssl,
|
verify=self.verify_ssl,
|
||||||
timeout=30)
|
timeout=timeout)
|
||||||
response = req.json()
|
response = req.json()
|
||||||
req.close()
|
req.close()
|
||||||
if (('error' in response) and
|
if (('error' in response) and
|
||||||
@ -859,15 +873,13 @@ class SolidFireDriver(san.SanISCSIDriver):
|
|||||||
|
|
||||||
def _get_model_info(self, sfaccount, sf_volume_id, endpoint=None):
|
def _get_model_info(self, sfaccount, sf_volume_id, endpoint=None):
|
||||||
volume = None
|
volume = None
|
||||||
iteration_count = 0
|
volume_list = self._get_volumes_by_sfaccount(
|
||||||
while not volume and iteration_count < 600:
|
sfaccount['accountID'], endpoint=endpoint)
|
||||||
volume_list = self._get_volumes_by_sfaccount(
|
|
||||||
sfaccount['accountID'], endpoint=endpoint)
|
for v in volume_list:
|
||||||
for v in volume_list:
|
if v['volumeID'] == sf_volume_id:
|
||||||
if v['volumeID'] == sf_volume_id:
|
volume = v
|
||||||
volume = v
|
break
|
||||||
break
|
|
||||||
iteration_count += 1
|
|
||||||
|
|
||||||
if not volume:
|
if not volume:
|
||||||
LOG.error('Failed to retrieve volume SolidFire-'
|
LOG.error('Failed to retrieve volume SolidFire-'
|
||||||
@ -937,10 +949,27 @@ class SolidFireDriver(san.SanISCSIDriver):
|
|||||||
params['volumeID'] = sf_cloned_id
|
params['volumeID'] = sf_cloned_id
|
||||||
data = self._issue_api_request('ModifyVolume', params)
|
data = self._issue_api_request('ModifyVolume', params)
|
||||||
|
|
||||||
model_update = self._get_model_info(sf_account, sf_cloned_id)
|
def _wait_volume_is_active():
|
||||||
if model_update is None:
|
try:
|
||||||
mesg = _('Failed to get model update from clone')
|
model_info = self._get_model_info(sf_account, sf_cloned_id)
|
||||||
raise SolidFireAPIException(mesg)
|
if model_info:
|
||||||
|
raise loopingcall.LoopingCallDone(model_info)
|
||||||
|
except exception.VolumeNotFound:
|
||||||
|
LOG.debug('Waiting for cloned volume [%s] - [%s] to become '
|
||||||
|
'active', sf_cloned_id, vref.id)
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
timer = loopingcall.FixedIntervalWithTimeoutLoopingCall(
|
||||||
|
_wait_volume_is_active)
|
||||||
|
model_update = timer.start(
|
||||||
|
interval=1,
|
||||||
|
timeout=self.configuration.sf_volume_clone_timeout).wait()
|
||||||
|
except loopingcall.LoopingCallTimeOut:
|
||||||
|
msg = _('Failed to get model update from clone [%s] - [%s]' %
|
||||||
|
(sf_cloned_id, vref.id))
|
||||||
|
LOG.error(msg)
|
||||||
|
raise SolidFireAPIException(msg)
|
||||||
|
|
||||||
rep_settings = self._retrieve_replication_settings(vref)
|
rep_settings = self._retrieve_replication_settings(vref)
|
||||||
if self.replication_enabled and rep_settings:
|
if self.replication_enabled and rep_settings:
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
`Bug #1898587 <https://bugs.launchpad.net/cinder/+bug/1898587>`_:
|
||||||
|
Address cloning and api request timeout issues users may hit in
|
||||||
|
certain environments, by allowing configuring timeout values for
|
||||||
|
these operations through cinder configuration file.
|
Loading…
x
Reference in New Issue
Block a user