summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Gundlach <michael.gundlach@rackspace.com>2010-08-10 18:17:44 -0400
committerMichael Gundlach <michael.gundlach@rackspace.com>2010-08-10 18:17:44 -0400
commit049b89babe10068d3976f3f3a99b7dce120e2962 (patch)
tree22c0f28b94387c8b893d98234e164233bd7b607c
parentc00ae202b93da7c6f9b407adfb099586863d9a6f (diff)
work on a router that works with wsgi and non-wsgi routing
-rw-r--r--nova/endpoint/rackspace.py27
-rw-r--r--nova/wsgi.py76
-rw-r--r--tools/pip-requires3
3 files changed, 94 insertions, 12 deletions
diff --git a/nova/endpoint/rackspace.py b/nova/endpoint/rackspace.py
index 75b828e91..b4e6cd823 100644
--- a/nova/endpoint/rackspace.py
+++ b/nova/endpoint/rackspace.py
@@ -45,18 +45,20 @@ class API(wsgi.Middleware):
def __init__(self):
super(API, self).__init__(Router(webob.exc.HTTPNotFound()))
- def __call__(self, environ, start_response):
+ @webob.dec.wsgify
+ def __call__(self, req):
+ return self.application
context = {}
- if "HTTP_X_AUTH_TOKEN" in environ:
+ if "HTTP_X_AUTH_TOKEN" in req.environ:
context['user'] = manager.AuthManager().get_user_from_access_key(
- environ['HTTP_X_AUTH_TOKEN'])
+ req.environ['HTTP_X_AUTH_TOKEN'])
if context['user']:
context['project'] = manager.AuthManager().get_project(
context['user'].name)
if "user" not in context:
- return webob.exc.HTTPForbidden()(environ, start_response)
+ return webob.exc.HTTPForbidden()
environ['nova.context'] = context
- return self.application(environ, start_response)
+ return self.application
class Router(wsgi.Router):
@@ -64,13 +66,14 @@ class Router(wsgi.Router):
def _build_map(self):
"""Build routing map for authentication and cloud."""
- self._connect("/v1.0", controller=AuthenticationAPI())
- cloud = CloudServerAPI()
- self._connect("/servers", controller=cloud.launch_server,
- conditions={"method": ["POST"]})
- self._connect("/servers/{server_id}", controller=cloud.delete_server,
- conditions={'method': ["DELETE"]})
- self._connect("/servers", controller=cloud)
+ self.map.resource("server", "servers", controller=CloudServerAPI())
+ #self._connect("/v1.0", controller=AuthenticationAPI())
+ #cloud = CloudServerAPI()
+ #self._connect("/servers", controller=cloud.launch_server,
+ # conditions={"method": ["POST"]})
+ #self._connect("/servers/{server_id}", controller=cloud.delete_server,
+ # conditions={'method': ["DELETE"]})
+ #self._connect("/servers", controller=cloud)
class AuthenticationAPI(wsgi.Application):
diff --git a/nova/wsgi.py b/nova/wsgi.py
index 4fd6e59e3..271648105 100644
--- a/nova/wsgi.py
+++ b/nova/wsgi.py
@@ -40,6 +40,7 @@ def run_server(application, port):
eventlet.wsgi.server(sock, application)
+# TODO(gundlach): I think we should toss this class, now that it has no purpose.
class Application(object):
"""Base WSGI application wrapper. Subclasses need to implement __call__."""
@@ -140,6 +141,81 @@ class ParsedRoutes(Middleware):
app = environ['wsgiorg.routing_args'][1]['controller']
return app(environ, start_response)
+class MichaelRouter(object):
+ """
+ My attempt at a routing class. Just override __init__ to call
+ super, then set up routes in self.map.
+ """
+
+ def __init__(self):
+ self.map = routes.Mapper()
+ self._router = routes.middleware.RoutesMiddleware(self._proceed, self.map)
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ """
+ Route the incoming request to a controller based on self.map.
+ If no match, return a 404.
+ """
+ return self._router
+
+ @webob.dec.wsgify
+ def _proceed(self, req):
+ """
+ Called by self._router after matching the incoming request to a route
+ and putting the information into req.environ.
+ """
+ if req.environ['routes.route'] is None:
+ return webob.exc.HTTPNotFound()
+ match = environ['wsgiorg.routing_args'][1]
+ if match.get('_is_wsgi', False):
+ wsgiapp = match['controller']
+ return req.get_response(wsgiapp)
+ else:
+ # TODO(gundlach): doubt this is the right way -- and it really
+ # feels like this code should exist somewhere already on the
+ # internet
+ controller, action = match['controller'], match['action']
+ delete match['controller']
+ delete match['action']
+ return _as_response(getattr(controller, action)(**match))
+
+ controller = environ['wsgiorg.routing_args'][1]['controller']
+ self._dispatch(controller)
+
+ def _as_response(self, result):
+ """
+ When routing to a non-wsgi controller+action, its result will
+ be passed here before returning up the WSGI chain to be converted
+ into a webob.Response
+
+
+
+
+
+class ApiVersionRouter(MichaelRouter):
+
+ def __init__(self):
+ super(ApiVersionRouter, self).__init__(self)
+
+ self.map.connect(None, "/v1.0/{path_info:.*}", controller=RsApiRouter())
+ self.map.connect(None, "/ec2/{path_info:.*}", controller=Ec2ApiRouter())
+
+class RsApiRouter(MichaelRouter):
+ def __init__(self):
+ super(RsApiRouter, self).__init__(self)
+
+ self.map.resource("server", "servers", controller=CloudServersServerApi())
+ self.map.resource("image", "images", controller=CloudServersImageApi())
+ self.map.resource("flavor", "flavors", controller=CloudServersFlavorApi())
+ self.map.resource("sharedipgroup", "sharedipgroups",
+ controller=CloudServersSharedIpGroupApi())
+
+class Ec2ApiRouter(object):
+ def __getattr__(self, key):
+ return lambda *x: {'dummy response': 'i am a dummy response'}
+CloudServersServerApi = CloudServersImageApi = CloudServersFlavorApi = \
+ CloudServersSharedIpGroupApi = Ec2ApiRouter
class Router(Middleware): # pylint: disable-msg=R0921
"""Wrapper to help setup routes.middleware.RoutesMiddleware."""
diff --git a/tools/pip-requires b/tools/pip-requires
index 4eb47ca2b..2317907d1 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -4,11 +4,14 @@ amqplib==0.6.1
anyjson==0.2.4
boto==2.0b1
carrot==0.10.5
+eventlet==0.9.10
lockfile==0.8
python-daemon==1.5.5
python-gflags==1.3
redis==2.0.0
+routes==1.12.3
tornado==1.0
+webob==0.9.8
wsgiref==0.1.2
zope.interface==3.6.1
mox==0.5.0