From: Mike Perez <thingee@gmail.com>
Date: Sun, 4 Nov 2012 09:20:47 +0000 (-0800)
Subject: moving all middleware code in cinder.api.middleware
X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=c15d5eae48c42d5b885b8a6557d091a75713015f;p=openstack-build%2Fcinder-build.git

moving all middleware code in cinder.api.middleware

This includes auth, sizelimit, and faultwrapper middleware. Test
directory struture has been adjusted to match.

progress on blueprint apiv2

Change-Id: I62eecb208553abfee8dc8d2679264884b4cec153
---

diff --git a/cinder/api/middleware/__init__.py b/cinder/api/middleware/__init__.py
new file mode 100644
index 000000000..d65c689a8
--- /dev/null
+++ b/cinder/api/middleware/__init__.py
@@ -0,0 +1,16 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
diff --git a/cinder/api/auth.py b/cinder/api/middleware/auth.py
similarity index 65%
rename from cinder/api/auth.py
rename to cinder/api/middleware/auth.py
index cea6c60c5..e806576d8 100644
--- a/cinder/api/auth.py
+++ b/cinder/api/middleware/auth.py
@@ -1,6 +1,7 @@
 # vim: tabstop=4 shiftwidth=4 softtabstop=4
 
-# Copyright (c) 2011 OpenStack, LLC
+# Copyright 2010 OpenStack LLC.
+# All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
@@ -17,15 +18,17 @@
 Common Auth Middleware.
 
 """
+import os
 
 import webob.dec
 import webob.exc
 
+from cinder.api.openstack import wsgi
 from cinder import context
 from cinder import flags
 from cinder.openstack.common import cfg
 from cinder.openstack.common import log as logging
-from cinder import wsgi
+from cinder import wsgi as base_wsgi
 
 
 use_forwarded_for_opt = cfg.BoolOpt('use_forwarded_for',
@@ -53,23 +56,23 @@ def pipeline_factory(loader, global_conf, **local_conf):
     return app
 
 
-class InjectContext(wsgi.Middleware):
+class InjectContext(base_wsgi.Middleware):
     """Add a 'cinder.context' to WSGI environ."""
 
     def __init__(self, context, *args, **kwargs):
         self.context = context
         super(InjectContext, self).__init__(*args, **kwargs)
 
-    @webob.dec.wsgify(RequestClass=wsgi.Request)
+    @webob.dec.wsgify(RequestClass=base_wsgi.Request)
     def __call__(self, req):
         req.environ['cinder.context'] = self.context
         return self.application
 
 
-class CinderKeystoneContext(wsgi.Middleware):
+class CinderKeystoneContext(base_wsgi.Middleware):
     """Make a request context from keystone headers"""
 
-    @webob.dec.wsgify(RequestClass=wsgi.Request)
+    @webob.dec.wsgify(RequestClass=base_wsgi.Request)
     def __call__(self, req):
         user_id = req.headers.get('X_USER')
         user_id = req.headers.get('X_USER_ID', user_id)
@@ -101,3 +104,37 @@ class CinderKeystoneContext(wsgi.Middleware):
 
         req.environ['cinder.context'] = ctx
         return self.application
+
+
+class NoAuthMiddleware(base_wsgi.Middleware):
+    """Return a fake token if one isn't specified."""
+
+    @webob.dec.wsgify(RequestClass=wsgi.Request)
+    def __call__(self, req):
+        if 'X-Auth-Token' not in req.headers:
+            user_id = req.headers.get('X-Auth-User', 'admin')
+            project_id = req.headers.get('X-Auth-Project-Id', 'admin')
+            os_url = os.path.join(req.url, project_id)
+            res = webob.Response()
+            # NOTE(vish): This is expecting and returning Auth(1.1), whereas
+            #             keystone uses 2.0 auth.  We should probably allow
+            #             2.0 auth here as well.
+            res.headers['X-Auth-Token'] = '%s:%s' % (user_id, project_id)
+            res.headers['X-Server-Management-Url'] = os_url
+            res.content_type = 'text/plain'
+            res.status = '204'
+            return res
+
+        token = req.headers['X-Auth-Token']
+        user_id, _sep, project_id = token.partition(':')
+        project_id = project_id or user_id
+        remote_address = getattr(req, 'remote_address', '127.0.0.1')
+        if FLAGS.use_forwarded_for:
+            remote_address = req.headers.get('X-Forwarded-For', remote_address)
+        ctx = context.RequestContext(user_id,
+                                     project_id,
+                                     is_admin=True,
+                                     remote_address=remote_address)
+
+        req.environ['cinder.context'] = ctx
+        return self.application
diff --git a/cinder/api/middleware/fault.py b/cinder/api/middleware/fault.py
new file mode 100644
index 000000000..15892b4e3
--- /dev/null
+++ b/cinder/api/middleware/fault.py
@@ -0,0 +1,75 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import webob.dec
+import webob.exc
+
+from cinder.api.openstack import wsgi
+from cinder.openstack.common import log as logging
+from cinder import utils
+from cinder import wsgi as base_wsgi
+
+
+LOG = logging.getLogger(__name__)
+
+
+class FaultWrapper(base_wsgi.Middleware):
+    """Calls down the middleware stack, making exceptions into faults."""
+
+    _status_to_type = {}
+
+    @staticmethod
+    def status_to_type(status):
+        if not FaultWrapper._status_to_type:
+            for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
+                FaultWrapper._status_to_type[clazz.code] = clazz
+        return FaultWrapper._status_to_type.get(
+                                  status, webob.exc.HTTPInternalServerError)()
+
+    def _error(self, inner, req):
+        LOG.exception(_("Caught error: %s"), unicode(inner))
+
+        safe = getattr(inner, 'safe', False)
+        headers = getattr(inner, 'headers', None)
+        status = getattr(inner, 'code', 500)
+        if status is None:
+            status = 500
+
+        msg_dict = dict(url=req.url, status=status)
+        LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
+        outer = self.status_to_type(status)
+        if headers:
+            outer.headers = headers
+        # NOTE(johannes): We leave the explanation empty here on
+        # purpose. It could possibly have sensitive information
+        # that should not be returned back to the user. See
+        # bugs 868360 and 874472
+        # NOTE(eglynn): However, it would be over-conservative and
+        # inconsistent with the EC2 API to hide every exception,
+        # including those that are safe to expose, see bug 1021373
+        if safe:
+            outer.explanation = '%s: %s' % (inner.__class__.__name__,
+                                            unicode(inner))
+        return wsgi.Fault(outer)
+
+    @webob.dec.wsgify(RequestClass=wsgi.Request)
+    def __call__(self, req):
+        try:
+            return req.get_response(self.application)
+        except Exception as ex:
+            return self._error(ex, req)
diff --git a/cinder/api/sizelimit.py b/cinder/api/middleware/sizelimit.py
similarity index 100%
rename from cinder/api/sizelimit.py
rename to cinder/api/middleware/sizelimit.py
diff --git a/cinder/api/openstack/__init__.py b/cinder/api/openstack/__init__.py
index 9f6079dd3..d68639860 100644
--- a/cinder/api/openstack/__init__.py
+++ b/cinder/api/openstack/__init__.py
@@ -21,8 +21,6 @@ WSGI middleware for OpenStack API controllers.
 """
 
 import routes
-import webob.dec
-import webob.exc
 
 from cinder.api.openstack import wsgi
 from cinder.openstack.common import log as logging
@@ -33,53 +31,6 @@ from cinder import wsgi as base_wsgi
 LOG = logging.getLogger(__name__)
 
 
-class FaultWrapper(base_wsgi.Middleware):
-    """Calls down the middleware stack, making exceptions into faults."""
-
-    _status_to_type = {}
-
-    @staticmethod
-    def status_to_type(status):
-        if not FaultWrapper._status_to_type:
-            for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
-                FaultWrapper._status_to_type[clazz.code] = clazz
-        return FaultWrapper._status_to_type.get(
-                                  status, webob.exc.HTTPInternalServerError)()
-
-    def _error(self, inner, req):
-        LOG.exception(_("Caught error: %s"), unicode(inner))
-
-        safe = getattr(inner, 'safe', False)
-        headers = getattr(inner, 'headers', None)
-        status = getattr(inner, 'code', 500)
-        if status is None:
-            status = 500
-
-        msg_dict = dict(url=req.url, status=status)
-        LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
-        outer = self.status_to_type(status)
-        if headers:
-            outer.headers = headers
-        # NOTE(johannes): We leave the explanation empty here on
-        # purpose. It could possibly have sensitive information
-        # that should not be returned back to the user. See
-        # bugs 868360 and 874472
-        # NOTE(eglynn): However, it would be over-conservative and
-        # inconsistent with the EC2 API to hide every exception,
-        # including those that are safe to expose, see bug 1021373
-        if safe:
-            outer.explanation = '%s: %s' % (inner.__class__.__name__,
-                                            unicode(inner))
-        return wsgi.Fault(outer)
-
-    @webob.dec.wsgify(RequestClass=wsgi.Request)
-    def __call__(self, req):
-        try:
-            return req.get_response(self.application)
-        except Exception as ex:
-            return self._error(ex, req)
-
-
 class APIMapper(routes.Mapper):
     def routematch(self, url=None, environ=None):
         if url is "":
diff --git a/cinder/api/openstack/auth.py b/cinder/api/openstack/auth.py
deleted file mode 100644
index 68c98dad5..000000000
--- a/cinder/api/openstack/auth.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2010 OpenStack LLC.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import os
-
-import webob.dec
-import webob.exc
-
-from cinder.api.openstack import wsgi
-from cinder import context
-from cinder import flags
-from cinder.openstack.common import log as logging
-from cinder import wsgi as base_wsgi
-
-LOG = logging.getLogger(__name__)
-FLAGS = flags.FLAGS
-flags.DECLARE('use_forwarded_for', 'cinder.api.auth')
-
-
-class NoAuthMiddleware(base_wsgi.Middleware):
-    """Return a fake token if one isn't specified."""
-
-    @webob.dec.wsgify(RequestClass=wsgi.Request)
-    def __call__(self, req):
-        if 'X-Auth-Token' not in req.headers:
-            user_id = req.headers.get('X-Auth-User', 'admin')
-            project_id = req.headers.get('X-Auth-Project-Id', 'admin')
-            os_url = os.path.join(req.url, project_id)
-            res = webob.Response()
-            # NOTE(vish): This is expecting and returning Auth(1.1), whereas
-            #             keystone uses 2.0 auth.  We should probably allow
-            #             2.0 auth here as well.
-            res.headers['X-Auth-Token'] = '%s:%s' % (user_id, project_id)
-            res.headers['X-Server-Management-Url'] = os_url
-            res.content_type = 'text/plain'
-            res.status = '204'
-            return res
-
-        token = req.headers['X-Auth-Token']
-        user_id, _sep, project_id = token.partition(':')
-        project_id = project_id or user_id
-        remote_address = getattr(req, 'remote_address', '127.0.0.1')
-        if FLAGS.use_forwarded_for:
-            remote_address = req.headers.get('X-Forwarded-For', remote_address)
-        ctx = context.RequestContext(user_id,
-                                     project_id,
-                                     is_admin=True,
-                                     remote_address=remote_address)
-
-        req.environ['cinder.context'] = ctx
-        return self.application
diff --git a/cinder/tests/api/middleware/__init__.py b/cinder/tests/api/middleware/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/cinder/tests/api/test_auth.py b/cinder/tests/api/middleware/test_auth.py
similarity index 93%
rename from cinder/tests/api/test_auth.py
rename to cinder/tests/api/middleware/test_auth.py
index cfb8b7775..4fca13fe6 100644
--- a/cinder/tests/api/test_auth.py
+++ b/cinder/tests/api/middleware/test_auth.py
@@ -14,7 +14,7 @@
 
 import webob
 
-import cinder.api.auth
+import cinder.api.middleware.auth
 from cinder import test
 
 
@@ -29,7 +29,8 @@ class TestCinderKeystoneContextMiddleware(test.TestCase):
             return webob.Response()
 
         self.context = None
-        self.middleware = cinder.api.auth.CinderKeystoneContext(fake_app)
+        self.middleware = (cinder.api.middleware.auth
+                           .CinderKeystoneContext(fake_app))
         self.request = webob.Request.blank('/')
         self.request.headers['X_TENANT_ID'] = 'testtenantid'
         self.request.headers['X_AUTH_TOKEN'] = 'testauthtoken'
diff --git a/cinder/tests/api/openstack/test_faults.py b/cinder/tests/api/middleware/test_faults.py
similarity index 100%
rename from cinder/tests/api/openstack/test_faults.py
rename to cinder/tests/api/middleware/test_faults.py
diff --git a/cinder/tests/api/test_sizelimit.py b/cinder/tests/api/middleware/test_sizelimit.py
similarity index 91%
rename from cinder/tests/api/test_sizelimit.py
rename to cinder/tests/api/middleware/test_sizelimit.py
index 280ee9c29..0a151dabf 100644
--- a/cinder/tests/api/test_sizelimit.py
+++ b/cinder/tests/api/middleware/test_sizelimit.py
@@ -14,7 +14,7 @@
 
 import webob
 
-import cinder.api.sizelimit
+import cinder.api.middleware.sizelimit
 from cinder import flags
 from cinder import test
 
@@ -31,7 +31,8 @@ class TestRequestBodySizeLimiter(test.TestCase):
         def fake_app(req):
             return webob.Response()
 
-        self.middleware = cinder.api.sizelimit.RequestBodySizeLimiter(fake_app)
+        self.middleware = (cinder.api.middleware.sizelimit
+                           .RequestBodySizeLimiter(fake_app))
         self.request = webob.Request.blank('/', method='POST')
 
     def test_content_length_acceptable(self):
diff --git a/cinder/tests/api/openstack/fakes.py b/cinder/tests/api/openstack/fakes.py
index cbc8613b3..87c2a61d3 100644
--- a/cinder/tests/api/openstack/fakes.py
+++ b/cinder/tests/api/openstack/fakes.py
@@ -23,9 +23,8 @@ import webob
 import webob.dec
 import webob.request
 
-from cinder.api import auth as api_auth
-from cinder.api import openstack as openstack_api
-from cinder.api.openstack import auth
+from cinder.api.middleware import auth
+from cinder.api.middleware import fault
 from cinder.api.openstack import volume
 from cinder.api.openstack.volume import limits
 from cinder.api.openstack import wsgi as os_wsgi
@@ -72,18 +71,18 @@ def wsgi_app(inner_app_v1=None, fake_auth=True, fake_auth_context=None,
             ctxt = fake_auth_context
         else:
             ctxt = context.RequestContext('fake', 'fake', auth_token=True)
-        api_v1 = openstack_api.FaultWrapper(api_auth.InjectContext(ctxt,
+        api_v1 = fault.FaultWrapper(auth.InjectContext(ctxt,
               inner_app_v1))
     elif use_no_auth:
-        api_v1 = openstack_api.FaultWrapper(auth.NoAuthMiddleware(
+        api_v1 = fault.FaultWrapper(auth.NoAuthMiddleware(
               limits.RateLimitingMiddleware(inner_app_v1)))
     else:
-        api_v1 = openstack_api.FaultWrapper(auth.AuthMiddleware(
+        api_v1 = fault.FaultWrapper(auth.AuthMiddleware(
               limits.RateLimitingMiddleware(inner_app_v1)))
 
     mapper = urlmap.URLMap()
     mapper['/v1'] = api_v1
-    mapper['/'] = openstack_api.FaultWrapper(versions.Versions())
+    mapper['/'] = fault.FaultWrapper(versions.Versions())
     return mapper
 
 
diff --git a/cinder/tests/test_wsgi.py b/cinder/tests/test_wsgi.py
index f9189afa7..08b933809 100644
--- a/cinder/tests/test_wsgi.py
+++ b/cinder/tests/test_wsgi.py
@@ -24,7 +24,7 @@ import tempfile
 import unittest
 import webob.dec
 
-from cinder.api import openstack as openstack_api
+from cinder.api.middleware import fault
 from cinder import exception
 from cinder import test
 import cinder.wsgi
@@ -97,7 +97,7 @@ class TestWSGIServer(unittest.TestCase):
 class ExceptionTest(test.TestCase):
 
     def _wsgi_app(self, inner_app):
-        return openstack_api.FaultWrapper(inner_app)
+        return fault.FaultWrapper(inner_app)
 
     def _do_test_exception_safety_reflected_in_faults(self, expose):
         class ExceptionWithSafety(exception.CinderException):
diff --git a/etc/cinder/api-paste.ini b/etc/cinder/api-paste.ini
index 575f4bd6a..c7c5baf7e 100644
--- a/etc/cinder/api-paste.ini
+++ b/etc/cinder/api-paste.ini
@@ -8,19 +8,19 @@ use = call:cinder.api.urlmap:urlmap_factory
 /v1: openstack_volume_api_v1
 
 [composite:openstack_volume_api_v1]
-use = call:cinder.api.auth:pipeline_factory
+use = call:cinder.api.middleware.auth:pipeline_factory
 noauth = faultwrap sizelimit noauth osapi_volume_app_v1
 keystone = faultwrap sizelimit authtoken keystonecontext osapi_volume_app_v1
 keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_volume_app_v1
 
 [filter:faultwrap]
-paste.filter_factory = cinder.api.openstack:FaultWrapper.factory
+paste.filter_factory = cinder.api.middleware.fault:FaultWrapper.factory
 
 [filter:noauth]
-paste.filter_factory = cinder.api.openstack.auth:NoAuthMiddleware.factory
+paste.filter_factory = cinder.api.middleware.auth:NoAuthMiddleware.factory
 
 [filter:sizelimit]
-paste.filter_factory = cinder.api.sizelimit:RequestBodySizeLimiter.factory
+paste.filter_factory = cinder.api.middleware.sizelimit:RequestBodySizeLimiter.factory
 
 [app:osapi_volume_app_v1]
 paste.app_factory = cinder.api.openstack.volume:APIRouter.factory
@@ -36,7 +36,7 @@ paste.app_factory = cinder.api.versions:Versions.factory
 ##########
 
 [filter:keystonecontext]
-paste.filter_factory = cinder.api.auth:CinderKeystoneContext.factory
+paste.filter_factory = cinder.api.middleware.auth:CinderKeystoneContext.factory
 
 [filter:authtoken]
 paste.filter_factory = keystone.middleware.auth_token:filter_factory