From 20b97388efcc3540066ca7743c761c1ec899dd2c Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Thu, 19 Sep 2013 15:07:23 +0400 Subject: [PATCH] Send proper exception info as expected by the neutron client The python neutron client for the V2 API expects the neutron API to send information back such as the type and detail of the exception in the body of the message Change-Id: I9486d757258c4be72799c41102babe1f7923121c Closes-bug: #1226400 --- neutron/api/v2/resource.py | 5 ++++- neutron/tests/unit/test_api_v2.py | 4 ++-- neutron/tests/unit/test_api_v2_resource.py | 24 ++++++++++++++++++---- neutron/tests/unit/test_db_plugin.py | 4 ++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/neutron/api/v2/resource.py b/neutron/api/v2/resource.py index 0066846aa..8a69b5557 100644 --- a/neutron/api/v2/resource.py +++ b/neutron/api/v2/resource.py @@ -86,7 +86,10 @@ def Resource(controller, faults=None, deserializers=None, serializers=None): netaddr.AddrFormatError) as e: LOG.exception(_('%s failed'), action) e = translate(e, language) - body = serializer.serialize({'NeutronError': e}) + # following structure is expected by python-neutronclient + err_data = {'type': e.__class__.__name__, + 'message': e, 'detail': ''} + body = serializer.serialize({'NeutronError': err_data}) kwargs = {'body': body, 'content_type': content_type} for fault in faults: if isinstance(e, fault): diff --git a/neutron/tests/unit/test_api_v2.py b/neutron/tests/unit/test_api_v2.py index 012822e0d..3268bbac1 100644 --- a/neutron/tests/unit/test_api_v2.py +++ b/neutron/tests/unit/test_api_v2.py @@ -1315,7 +1315,7 @@ class QuotaTest(APIv2TestBase): instance.get_networks_count.assert_called_with(mock.ANY, filters=mock.ANY) self.assertIn("Quota exceeded for resources", - res.json['NeutronError']) + res.json['NeutronError']['message']) def test_create_network_quota_no_counts(self): cfg.CONF.set_override('quota_network', 1, group='QUOTAS') @@ -1332,7 +1332,7 @@ class QuotaTest(APIv2TestBase): instance.get_networks_count.assert_called_with(mock.ANY, filters=mock.ANY) self.assertIn("Quota exceeded for resources", - res.json['NeutronError']) + res.json['NeutronError']['message']) def test_create_network_quota_without_limit(self): cfg.CONF.set_override('quota_network', -1, group='QUOTAS') diff --git a/neutron/tests/unit/test_api_v2_resource.py b/neutron/tests/unit/test_api_v2_resource.py index 3ada9cf64..564a01c4c 100644 --- a/neutron/tests/unit/test_api_v2_resource.py +++ b/neutron/tests/unit/test_api_v2_resource.py @@ -129,7 +129,11 @@ class ResourceTestCase(base.BaseTestCase): class TestException(q_exc.NeutronException): message = msg - expected_res = {'body': {'NeutronError': msg}} + expected_res = {'body': { + 'NeutronError': { + 'type': 'TestException', + 'message': msg, + 'detail': ''}}} controller = mock.MagicMock() controller.test.side_effect = TestException() @@ -147,7 +151,11 @@ class ResourceTestCase(base.BaseTestCase): class TestException(q_exc.NeutronException): message = msg - expected_res = {'body': {'NeutronError': msg}} + expected_res = {'body': { + 'NeutronError': { + 'type': 'TestException', + 'message': msg, + 'detail': ''}}} controller = mock.MagicMock() controller.test.side_effect = TestException() @@ -187,7 +195,11 @@ class ResourceTestCase(base.BaseTestCase): class TestException(q_exc.NeutronException): message = msg - expected_res = {'body': {'NeutronError': msg}} + expected_res = {'body': { + 'NeutronError': { + 'type': 'TestException', + 'message': msg, + 'detail': ''}}} controller = mock.MagicMock() controller.test.side_effect = TestException() @@ -207,7 +219,11 @@ class ResourceTestCase(base.BaseTestCase): class TestException(q_exc.NeutronException): message = msg - expected_res = {'body': {'NeutronError': msg}} + expected_res = {'body': { + 'NeutronError': { + 'type': 'TestException', + 'message': msg, + 'detail': ''}}} controller = mock.MagicMock() controller.test.side_effect = TestException() diff --git a/neutron/tests/unit/test_db_plugin.py b/neutron/tests/unit/test_db_plugin.py index 9d7da0621..002f28388 100644 --- a/neutron/tests/unit/test_db_plugin.py +++ b/neutron/tests/unit/test_db_plugin.py @@ -1162,7 +1162,7 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s res = self._create_port(self.fmt, id) data = self.deserialize(self.fmt, res) msg = str(q_exc.IpAddressGenerationFailure(net_id=id)) - self.assertEqual(data['NeutronError'], msg) + self.assertEqual(data['NeutronError']['message'], msg) self.assertEqual(res.status_int, webob.exc.HTTPConflict.code) def test_update_port_update_ip(self): @@ -2477,7 +2477,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): data = self.deserialize(self.fmt, res) self.assertEqual(res.status_int, webob.exc.HTTPConflict.code) msg = str(q_exc.SubnetInUse(subnet_id=id)) - self.assertEqual(data['NeutronError'], msg) + self.assertEqual(data['NeutronError']['message'], msg) def test_delete_network(self): gateway_ip = '10.0.0.1'