Capture requests errors

Situations can occur where rare exceptions can originate
from within python requests, which are not captured or handled
in Sushy.

Example: Encoding errors should trigger some sort of recovery,
but cached session clients cannot recover, and power synchronization
for users, such as Ironic, break on the cached session when they
attempt to access them for the same task, again.

Change-Id: I0f79083d41b0b7ccf7e4dbfc81fd1d42c2e5eb15
This commit is contained in:
Julia Kreger 2022-08-15 17:10:21 -07:00 committed by Aija Jauntēva
parent 19831b61f9
commit b855365ef0
3 changed files with 35 additions and 1 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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)