From bccec6c8bac90517a972a5eb8bb91a82b3a13065 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 6 Jan 2011 02:08:01 -0500 Subject: Fix openstack api tests and add a FaultWrapper to turn exceptions to faults. --- etc/nova-api.conf | 10 ++++++-- nova/api/openstack/__init__.py | 24 +++++++++++++++---- nova/tests/api/openstack/fakes.py | 13 ++++++++++ nova/tests/api/openstack/test_adminapi.py | 10 +++++--- nova/tests/api/openstack/test_api.py | 26 +++++++++++++------- nova/tests/api/openstack/test_auth.py | 18 +++++++------- nova/tests/api/openstack/test_flavors.py | 2 +- nova/tests/api/openstack/test_images.py | 4 ++-- nova/tests/api/openstack/test_servers.py | 40 +++++++++++++++---------------- 9 files changed, 96 insertions(+), 51 deletions(-) diff --git a/etc/nova-api.conf b/etc/nova-api.conf index dcb4e7894..59b21f387 100644 --- a/etc/nova-api.conf +++ b/etc/nova-api.conf @@ -61,7 +61,10 @@ use = egg:Paste#urlmap /v1.0: openstackapi [pipeline:openstackapi] -pipeline = auth ratelimit osapi +pipeline = faultwrap auth ratelimit osapi + +[filter:faultwrap] +paste.filter_factory = nova.api.openstack:fault_wrapper_factory [filter:auth] paste.filter_factory = nova.api.openstack.auth:auth_factory @@ -72,5 +75,8 @@ paste.filter_factory = nova.api.openstack.ratelimiting:ratelimit_factory [app:osapi] paste.app_factory = nova.api.openstack:router_factory -[app:osversions] +[pipeline:osversions] +pipeline = faultwrap osversionapp + +[app:osversionapp] paste.app_factory = nova.api.openstack:versions_factory diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c5de03a09..21b9b1d7d 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -20,8 +20,6 @@ WSGI middleware for OpenStack API controllers. """ -import time - import logging import routes import traceback @@ -29,15 +27,12 @@ import webob.dec import webob.exc import webob -from nova import context from nova import flags -from nova import utils from nova import wsgi from nova.api.openstack import faults from nova.api.openstack import backup_schedules from nova.api.openstack import flavors from nova.api.openstack import images -from nova.api.openstack import ratelimiting from nova.api.openstack import servers from nova.api.openstack import sharedipgroups @@ -48,6 +43,19 @@ flags.DEFINE_bool('allow_admin_api', 'When True, this API service will accept admin operations.') +class FaultWrapper(wsgi.Middleware): + """Calls down the middleware stack, making exceptions into faults.""" + + @webob.dec.wsgify + def __call__(self, req): + try: + return req.get_response(self.application) + except Exception as ex: + logging.warn(_("Caught error: %s") % str(ex)) + logging.error(traceback.format_exc()) + exc = webob.exc.HTTPInternalServerError(explanation=str(ex)) + return faults.Fault(exc) + class APIRouter(wsgi.Router): """ Routes requests on the OpenStack API to the appropriate controller @@ -105,3 +113,9 @@ def router_factory(global_cof, **local_conf): def versions_factory(global_conf, **local_conf): return Versions() + + +def fault_wrapper_factory(global_conf, **local_conf): + def fwrap(app): + return FaultWrapper(app) + return fwrap diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 961431154..2028024bb 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -22,6 +22,7 @@ import string import webob import webob.dec +from paste import urlmap from nova import auth from nova import context @@ -29,6 +30,7 @@ from nova import exception as exc from nova import flags from nova import utils import nova.api.openstack.auth +from nova.api import openstack from nova.api.openstack import auth from nova.api.openstack import ratelimiting from nova.image import glance @@ -69,6 +71,17 @@ def fake_wsgi(self, req): return self.application +def wsgi_app(inner_application=None): + if not inner_application: + inner_application = openstack.APIRouter() + mapper = urlmap.URLMap() + api = openstack.FaultWrapper(auth.AuthMiddleware( + ratelimiting.RateLimitingMiddleware(inner_application))) + mapper['/v1.0'] = api + mapper['/'] = openstack.FaultWrapper(openstack.Versions()) + return mapper + + def stub_out_key_pair_funcs(stubs): def key_pair(context, user_id): return [dict(name='key', public_key='public_key')] diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 1b2e1654d..73120c31d 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -19,15 +19,19 @@ import unittest import stubout import webob +from paste import urlmap -import nova.api from nova import flags +from nova.api import openstack +from nova.api.openstack import ratelimiting +from nova.api.openstack import auth from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS class AdminAPITest(unittest.TestCase): + def setUp(self): self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} @@ -45,7 +49,7 @@ class AdminAPITest(unittest.TestCase): FLAGS.allow_admin_api = True # We should still be able to access public operations. req = webob.Request.blank('/v1.0/flavors') - res = req.get_response(nova.api.API('os')) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are available. @@ -53,7 +57,7 @@ class AdminAPITest(unittest.TestCase): FLAGS.allow_admin_api = False # We should still be able to access public operations. req = webob.Request.blank('/v1.0/flavors') - res = req.get_response(nova.api.API('os')) + res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are unavailable. diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py index d8b202e21..1474148f5 100644 --- a/nova/tests/api/openstack/test_api.py +++ b/nova/tests/api/openstack/test_api.py @@ -19,14 +19,18 @@ import unittest import webob.exc import webob.dec -import nova.api.openstack -from nova.api.openstack import API -from nova.api.openstack import faults from webob import Request +from nova.api import openstack +from nova.api.openstack import faults + class APITest(unittest.TestCase): + def _wsgi_app(self, inner_app): + # simpler version of the app than fakes.wsgi_app + return openstack.FaultWrapper(inner_app) + def test_exceptions_are_converted_to_faults(self): @webob.dec.wsgify @@ -46,29 +50,33 @@ class APITest(unittest.TestCase): exc = webob.exc.HTTPNotFound(explanation='Raised a webob.exc') return faults.Fault(exc) - api = API() - api.application = succeed + #api.application = succeed + api = self._wsgi_app(succeed) resp = Request.blank('/').get_response(api) self.assertFalse('computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 200, resp.body) - api.application = raise_webob_exc + #api.application = raise_webob_exc + api = self._wsgi_app(raise_webob_exc) resp = Request.blank('/').get_response(api) self.assertFalse('computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 404, resp.body) - api.application = raise_api_fault + #api.application = raise_api_fault + api = self._wsgi_app(raise_api_fault) resp = Request.blank('/').get_response(api) self.assertTrue('itemNotFound' in resp.body, resp.body) self.assertEqual(resp.status_int, 404, resp.body) - api.application = fail + #api.application = fail + api = self._wsgi_app(fail) resp = Request.blank('/').get_response(api) self.assertTrue('{"computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 500, resp.body) - api.application = fail + #api.application = fail + api = self._wsgi_app(fail) resp = Request.blank('/.xml').get_response(api) self.assertTrue('