From 5646b96119947ba1b3086ac598d9c97bee3fca58 Mon Sep 17 00:00:00 2001 From: Brian Elliott Date: Thu, 9 Aug 2012 22:51:11 +0000 Subject: [PATCH] Fix TypeError conversion in API layer Fix conversion of TypeError to Fault in ResourceExceptionHandler. TypeError can result when the list of extensions is inovked if the parameters don't match the extension method's signature. Specifically, if an empty body was sent with an HTTP POST to create a server, a 500 error was returned. This change is a fix to properly return a 400 instead. (In Python2.6, the ex_value argument of __exit__ is type string when ex_type is a TypeError, which caused the conversion logic to get skipped.) bug 1035120 Change-Id: I96ad335a6338523345d28b7e744dbc7449b4753d --- nova/api/openstack/wsgi.py | 6 +++++- nova/tests/api/openstack/test_wsgi.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 3ea7c1c7c6d4..9f8bf63674a2 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -628,7 +628,11 @@ class ResourceExceptionHandler(object): elif isinstance(ex_value, exception.Invalid): raise Fault(exception.ConvertedException( code=ex_value.code, explanation=unicode(ex_value))) - elif isinstance(ex_value, TypeError): + + # Under python 2.6, TypeError's exception value is actually a string, + # so test # here via ex_type instead: + # http://bugs.python.org/issue7853 + elif issubclass(ex_type, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_('Exception handling resource: %s') % ex_value, exc_info=exc_info) diff --git a/nova/tests/api/openstack/test_wsgi.py b/nova/tests/api/openstack/test_wsgi.py index f4545049576e..7427eb2afb31 100644 --- a/nova/tests/api/openstack/test_wsgi.py +++ b/nova/tests/api/openstack/test_wsgi.py @@ -752,6 +752,18 @@ class ResourceTest(test.TestCase): self.assertEqual(called, [2]) self.assertEqual(response, 'foo') + def test_resource_exception_handler_type_error(self): + """A TypeError should be translated to a Fault/HTTP 400""" + def foo(a,): + return a + + try: + with wsgi.ResourceExceptionHandler(): + foo() # generate a TypeError + self.fail("Should have raised a Fault (HTTP 400)") + except wsgi.Fault as fault: + self.assertEqual(400, fault.status_int) + class ResponseObjectTest(test.TestCase): def test_default_code(self):