diff --git a/releasenotes/notes/catch-general-requests-exceptions-b5fd706597708fb6.yaml b/releasenotes/notes/catch-general-requests-exceptions-b5fd706597708fb6.yaml new file mode 100644 index 00000000..ae7ff8d7 --- /dev/null +++ b/releasenotes/notes/catch-general-requests-exceptions-b5fd706597708fb6.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixes potential cases where exceptions from the underlying ``requests`` + library may be raised up through ``sushy``, resulting in client + applications possibly not understanding that an error has occurred. + The sushy ``ConnectionError`` exception is now returned upon any exception + falling under ``RequestException`` from the ``requests`` library. diff --git a/sushy/connector.py b/sushy/connector.py index c56fcd6e..7cb32a71 100644 --- a/sushy/connector.py +++ b/sushy/connector.py @@ -125,7 +125,14 @@ class Connector(object): response = self._session.request(method, url, json=data, headers=headers, **extra_session_req_kwargs) - except requests.ConnectionError as e: + except requests.exceptions.RequestException as e: + # Capture any general exception by looking for the parent + # class of exceptions in the requests library. + # Specifically this will cover cases such as transport + # failures, connection timeouts, and encoding errors. + # Raising this as sushy ConnectionError allows users to + # understand something bad has happened, and to + # allow them to respond accordingly. raise exceptions.ConnectionError(url=url, error=e) if self._response_callback: diff --git a/sushy/tests/unit/test_connector.py b/sushy/tests/unit/test_connector.py index 5398619d..958e4d25 100644 --- a/sushy/tests/unit/test_connector.py +++ b/sushy/tests/unit/test_connector.py @@ -558,3 +558,22 @@ class ConnectorOpTestCase(base.TestCase): 'returned code HTTPStatus.FORBIDDEN. unknown error ' 'Extended information: none'} ) + + def test__op_raises_connection_error(self): + + exception_list = [ + requests.exceptions.ChunkedEncodingError, + requests.exceptions.ContentDecodingError, + requests.exceptions.ReadTimeout, + requests.exceptions.ConnectTimeout, + requests.exceptions.SSLError, + requests.exceptions.ConnectionError, + requests.exceptions.RequestException, + ] + for exc in exception_list: + self.request.side_effect = exc + self.assertRaises(exceptions.ConnectionError, + self.conn._op, + 'POST', + 'http://foo.bar', + blocking=True)