summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ironic_python_agent/errors.py10
-rw-r--r--ironic_python_agent/ironic_api_client.py2
-rw-r--r--ironic_python_agent/tests/unit/test_ironic_api_client.py10
-rw-r--r--releasenotes/notes/clarify-heartbeat-connection-errors-2af152bf2d7928e2.yaml10
4 files changed, 32 insertions, 0 deletions
diff --git a/ironic_python_agent/errors.py b/ironic_python_agent/errors.py
index 99bbe2b8..bf0253dd 100644
--- a/ironic_python_agent/errors.py
+++ b/ironic_python_agent/errors.py
@@ -348,3 +348,13 @@ class ClockSyncError(RESTError):
"""Error raised when attempting to sync the system clock."""
message = 'Error syncing system clock'
+
+
+class HeartbeatConnectionError(IronicAPIError):
+ """Transitory connection failure occured attempting to contact the API."""
+
+ message = ("Error attempting to heartbeat - Possible transitory network "
+ "failure or blocking port may be present.")
+
+ def __init__(self, details):
+ super(HeartbeatConnectionError, self).__init__(details)
diff --git a/ironic_python_agent/ironic_api_client.py b/ironic_python_agent/ironic_api_client.py
index 747b133d..4738f22d 100644
--- a/ironic_python_agent/ironic_api_client.py
+++ b/ironic_python_agent/ironic_api_client.py
@@ -125,6 +125,8 @@ class APIClient(object):
try:
response = self._request('POST', path, data=data, headers=headers)
+ except requests.exceptions.ConnectionError as e:
+ raise errors.HeartbeatConnectionError(str(e))
except Exception as e:
raise errors.HeartbeatError(str(e))
diff --git a/ironic_python_agent/tests/unit/test_ironic_api_client.py b/ironic_python_agent/tests/unit/test_ironic_api_client.py
index 562f06be..bd710e77 100644
--- a/ironic_python_agent/tests/unit/test_ironic_api_client.py
+++ b/ironic_python_agent/tests/unit/test_ironic_api_client.py
@@ -234,6 +234,16 @@ class TestBaseIronicPythonAgent(base.IronicAgentTest):
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
advertise_address=('192.0.2.1', '9999'))
+ def test_heartbeat_requests_connection_error(self):
+ self.api_client.session.request = mock.Mock()
+ self.api_client.session.request.side_effect = \
+ requests.exceptions.ConnectionError
+ self.assertRaisesRegex(errors.HeartbeatConnectionError,
+ 'transitory network failure or blocking port',
+ self.api_client.heartbeat,
+ uuid='meow',
+ advertise_address=('192.0.2.1', '9999'))
+
@mock.patch('eventlet.greenthread.sleep', autospec=True)
@mock.patch('ironic_python_agent.ironic_api_client.APIClient._do_lookup',
autospec=True)
diff --git a/releasenotes/notes/clarify-heartbeat-connection-errors-2af152bf2d7928e2.yaml b/releasenotes/notes/clarify-heartbeat-connection-errors-2af152bf2d7928e2.yaml
new file mode 100644
index 00000000..dace1cd5
--- /dev/null
+++ b/releasenotes/notes/clarify-heartbeat-connection-errors-2af152bf2d7928e2.yaml
@@ -0,0 +1,10 @@
+---
+other:
+ - |
+ Adds an explicit capture of connectivity failures in the heartbeat
+ process to provide a more verbose error message in line with what is
+ occuring as opposed to just indicating that an error occured. This
+ new exception is called ``HeartbeatConnectionError`` and is likely only
+ going to be visible if there is a local connectivity failure such as a
+ router failure, switchport in a blocking state, or connection centered
+ transient failure.