Return 503 rather than 500 error when _ds_manager unreachable
It can happen that the _ds_manager is temporarily unreachable due service not ready or network issues. In these cases, the patch makes sure the API returns 503 http status code instead of 500, so that the client knows the issue is temporary. Change-Id: I8a03a2e0ac84c2395b5ea2015647c5c7d2fed03e Closes-bug: 1811754
This commit is contained in:
parent
e84057a6f5
commit
18e3060af5
|
@ -93,6 +93,11 @@ class DatasourceModel(base.APIModel):
|
|||
LOG.debug(_("Datasource creation failed."))
|
||||
raise webservice.DataModelException(
|
||||
e.code, webservice.original_msg(e), http_status_code=e.code)
|
||||
except exception.RpcTargetNotFound as e:
|
||||
LOG.debug("Datasource creation failed.")
|
||||
LOG.warning(webservice.original_msg(e))
|
||||
raise webservice.DataModelException(
|
||||
e.code, webservice.original_msg(e), http_status_code=503)
|
||||
|
||||
return (obj['id'], obj)
|
||||
|
||||
|
@ -116,7 +121,13 @@ class DatasourceModel(base.APIModel):
|
|||
# Let PE synchronizer takes care of deleting policy
|
||||
except (exception.DatasourceNotFound,
|
||||
exception.DanglingReference) as e:
|
||||
LOG.debug("Datasource deletion failed.")
|
||||
raise webservice.DataModelException(e.code, str(e))
|
||||
except exception.RpcTargetNotFound as e:
|
||||
LOG.debug("Datasource deletion failed.")
|
||||
LOG.warning(webservice.original_msg(e))
|
||||
raise webservice.DataModelException(
|
||||
e.code, webservice.original_msg(e), http_status_code=503)
|
||||
|
||||
# Note(thread-safety): blocking function
|
||||
def request_refresh_action(self, params, context=None, request=None):
|
||||
|
|
|
@ -320,7 +320,7 @@ class DseNode(object):
|
|||
except (messaging_exceptions.MessagingTimeout,
|
||||
messaging_exceptions.MessageDeliveryFailure):
|
||||
msg = "service '%s' could not be found"
|
||||
raise exception.NotFound(msg % service_id)
|
||||
raise exception.RpcTargetNotFound(msg % service_id)
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
try:
|
||||
|
@ -356,7 +356,7 @@ class DseNode(object):
|
|||
kwargs = {}
|
||||
if not self.is_valid_service(service_id):
|
||||
msg = "service '%s' is not a registered service"
|
||||
raise exception.NotFound(msg % service_id)
|
||||
raise exception.RpcTargetNotFound(msg % service_id)
|
||||
|
||||
target = self.service_rpc_target(service_id, fanout=True)
|
||||
LOG.trace("<%s> Casting RPC '%s' on %s", self.node_id, method, target)
|
||||
|
|
|
@ -235,6 +235,10 @@ class InvalidDatasourceName(BadConfig):
|
|||
"start with underscore. Must be valid in policy language")
|
||||
|
||||
|
||||
class RpcTargetNotFound(NotFound):
|
||||
pass
|
||||
|
||||
|
||||
class DatasourceNotFound(NotFound):
|
||||
msg_fmt = _("Datasource not found %(id)s")
|
||||
|
||||
|
|
|
@ -81,6 +81,16 @@ class TestDatasourceModel(base.SqlTestCase):
|
|||
self.assertEqual('datasource_test_3', obj.name)
|
||||
self.assertIsNotNone(ds_obj)
|
||||
|
||||
def test_add_item_manager_unreachable(self):
|
||||
datasource3 = self._get_datasource_request()
|
||||
datasource3['name'] = 'datasource_test_3'
|
||||
self.datasource_model.invoke_rpc = mock.Mock(
|
||||
side_effect=exception.RpcTargetNotFound())
|
||||
try:
|
||||
self.datasource_model.add_item(datasource3, {})
|
||||
except webservice.DataModelException as e:
|
||||
self.assertEqual(e.http_status_code, 503)
|
||||
|
||||
def test_add_datasource_with_custom_driver(self):
|
||||
datasource4 = self._get_datasource_request()
|
||||
datasource4['name'] = 'datasource_test_4'
|
||||
|
@ -124,6 +134,15 @@ class TestDatasourceModel(base.SqlTestCase):
|
|||
self.datasource_model.delete_item,
|
||||
None, {}, context=context)
|
||||
|
||||
def test_delete_item_manager_unreachable(self):
|
||||
context = {'ds_id': 'fake'}
|
||||
self.datasource_model.invoke_rpc = mock.Mock(
|
||||
side_effect=exception.RpcTargetNotFound())
|
||||
try:
|
||||
self.datasource_model.add_item(None, {}, context=context)
|
||||
except webservice.DataModelException as e:
|
||||
self.assertEqual(e.http_status_code, 503)
|
||||
|
||||
def test_datasource_api_model_execute(self):
|
||||
def _execute_api(client, action, action_args):
|
||||
positional_args = action_args.get('positional', [])
|
||||
|
|
Loading…
Reference in New Issue