From da6301bc468028bf8915e26c9ebef3ac10d18f11 Mon Sep 17 00:00:00 2001 From: Olivier Bourdon Date: Tue, 6 Mar 2018 15:45:43 +0100 Subject: [PATCH] Add extra failure codes to bad request exception For instance on call to cloud.node_set_provision_state(uuid, 'dummy') the API currently only returns: (400) Client Error for url: http://127.0.0.1:6385/v1/nodes/\ /states/provision Bad Request whereas the HTTP request also contains some more valuable information in the body: The requested action "dummy" can not be performed on node "" \ while it is in state "enroll". Change-Id: I8412a2fd4ba78ad4f43ac2f13b1404dd3c151ce5 --- shade/exc.py | 8 +++++ shade/tests/unit/test_baremetal_node.py | 40 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/shade/exc.py b/shade/exc.py index 1ccc437de..0091f838c 100644 --- a/shade/exc.py +++ b/shade/exc.py @@ -13,6 +13,7 @@ # limitations under the License. import sys +import json import munch from requests import exceptions as _rex @@ -140,6 +141,13 @@ def raise_from_response(response, error_message=None): except AttributeError: if response.reason: remote_error += " {reason}".format(reason=response.reason) + try: + json_resp = json.loads(details[detail_key]) + fault_string = json_resp.get('faultstring') + if fault_string: + remote_error += " {fault}".format(fault=fault_string) + except Exception: + pass _log_response_extras(response) diff --git a/shade/tests/unit/test_baremetal_node.py b/shade/tests/unit/test_baremetal_node.py index 9a8795745..df75f5c39 100644 --- a/shade/tests/unit/test_baremetal_node.py +++ b/shade/tests/unit/test_baremetal_node.py @@ -858,6 +858,46 @@ class TestBaremetalNode(base.IronicTestCase): self.assertEqual(available_node, return_value) self.assert_calls() + def test_node_set_provision_state_bad_request(self): + self.fake_baremetal_node['provision_state'] = 'enroll' + self.register_uris([ + dict( + method='PUT', + status_code=400, + json={'error': "{\"faultstring\": \"invalid state\"}"}, + uri=self.get_mock_url( + resource='nodes', + append=[self.fake_baremetal_node['uuid'], + 'states', 'provision'])), + ]) + self.assertRaisesRegexp( + exc.OpenStackCloudException, + '^Baremetal .* to dummy.*/states/provision invalid state$', + self.op_cloud.node_set_provision_state, + self.fake_baremetal_node['uuid'], + 'dummy') + self.assert_calls() + + def test_node_set_provision_state_bad_request_bad_json(self): + self.fake_baremetal_node['provision_state'] = 'enroll' + self.register_uris([ + dict( + method='PUT', + status_code=400, + json={'error': 'invalid json'}, + uri=self.get_mock_url( + resource='nodes', + append=[self.fake_baremetal_node['uuid'], + 'states', 'provision'])), + ]) + self.assertRaisesRegexp( + exc.OpenStackCloudException, + '^Baremetal .* to dummy.*/states/provision$', + self.op_cloud.node_set_provision_state, + self.fake_baremetal_node['uuid'], + 'dummy') + self.assert_calls() + def test_wait_for_baremetal_node_lock_locked(self): self.fake_baremetal_node['reservation'] = 'conductor0' unlocked_node = self.fake_baremetal_node.copy()