From ddd2851208c49c85bf7c9d0bfd47c100ddcad67c 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 0066846aab..8a69b55577 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 012822e0d6..3268bbac18 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 3ada9cf646..564a01c4ce 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 9d7da0621e..002f283886 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'