diff options
author | Julia Kreger <juliaashleykreger@gmail.com> | 2020-04-22 08:42:29 -0700 |
---|---|---|
committer | Julia Kreger <juliaashleykreger@gmail.com> | 2020-04-24 09:55:09 -0700 |
commit | bfeef067aac7572bb914396db4553da5c013403f (patch) | |
tree | 7a48829f2bff7760260d77c58e042bf0dc5066e4 /ironic | |
parent | b49319137181cee00342175395bc93eac87e0033 (diff) | |
download | ironic-bfeef067aac7572bb914396db4553da5c013403f.tar.gz |
Fix agent_client handling of embedded errors
The agent_client may get a general "command_error" field
returned to it upon commands and the agent may not properly
sinal that the command failed because we are reliant upon
the same data elsewhere in the ironic/agent interaction.
This resulted in the case where the embedded error signaled that
the error was method compatability as opposed to the actual method
command error.
This could cause higher level failures and prevent fallback logic
from detecting that we could try a different command.
We now consider the error type, and raise the appropriate exception
to signal that the issue may be an API compatability issue.
Change-Id: Ia2f63bd853632e1d7138901cf23fde1e261fc4d6
Diffstat (limited to 'ironic')
-rw-r--r-- | ironic/drivers/modules/agent_client.py | 17 | ||||
-rw-r--r-- | ironic/tests/unit/drivers/modules/test_agent_client.py | 21 |
2 files changed, 37 insertions, 1 deletions
diff --git a/ironic/drivers/modules/agent_client.py b/ironic/drivers/modules/agent_client.py index 4c17403b9..feb4ebc88 100644 --- a/ironic/drivers/modules/agent_client.py +++ b/ironic/drivers/modules/agent_client.py @@ -127,11 +127,18 @@ class AgentClient(object): LOG.error(msg) raise exception.IronicException(msg) + error = result.get('command_error') + exc_type = None + if error: + # if an error, we should see if a type field exists. This type + # field may signal an exception that is compatability based. + exc_type = error.get('type') + LOG.debug('Agent command %(method)s for node %(node)s returned ' 'result %(res)s, error %(error)s, HTTP status code %(code)d', {'node': node.uuid, 'method': method, 'res': result.get('command_result'), - 'error': result.get('command_error'), + 'error': error, 'code': response.status_code}) if response.status_code >= http_client.BAD_REQUEST: @@ -142,6 +149,14 @@ class AgentClient(object): raise exception.AgentAPIError(node=node.uuid, status=response.status_code, error=result.get('faultstring')) + if exc_type == 'TypeError': + LOG.error('Agent command %(method)s for node %(node)s failed. ' + 'Internal %(exc_type)s error detected: Error %(error)s', + {'method': method, 'node': node.uuid, + 'exc_type': exc_type, 'error': error}) + raise exception.AgentAPIError(node=node.uuid, + status=error.get('code'), + error=result.get('faultstring')) return result diff --git a/ironic/tests/unit/drivers/modules/test_agent_client.py b/ironic/tests/unit/drivers/modules/test_agent_client.py index 65bb58172..1bea74188 100644 --- a/ironic/tests/unit/drivers/modules/test_agent_client.py +++ b/ironic/tests/unit/drivers/modules/test_agent_client.py @@ -178,6 +178,27 @@ class TestAgentClient(base.TestCase): params={'wait': 'false'}, timeout=60) + def test__command_error_code_okay_error_typeerror_embedded(self): + response_text = ('{"faultstring": "you dun goofd", ' + '"command_error": {"type": "TypeError"}}') + self.client.session.post.return_value = MockResponse( + response_text) + method = 'standby.run_image' + image_info = {'image_id': 'test_image'} + params = {'image_info': image_info} + + url = self.client._get_command_url(self.node) + body = self.client._get_command_body(method, params) + + self.assertRaises(exception.AgentAPIError, + self.client._command, + self.node, method, params) + self.client.session.post.assert_called_once_with( + url, + data=body, + params={'wait': 'false'}, + timeout=60) + def test_get_commands_status(self): with mock.patch.object(self.client.session, 'get', autospec=True) as mock_get: |