summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Gundlach <michael.gundlach@rackspace.com>2010-09-02 13:04:05 -0400
committerMichael Gundlach <michael.gundlach@rackspace.com>2010-09-02 13:04:05 -0400
commit8169a2a26c5b646a4d6c63c77f15f6aaa6898cb4 (patch)
tree8c161f17495a837a027e65b2b327ee1a8307f6a7
parentb965dde9e95e16a9a207697d5729bd146c2dfd23 (diff)
Small typos, plus rework api_unittest to use WSGI instead of Tornado
-rw-r--r--nova/api/__init__.py2
-rw-r--r--nova/api/ec2/__init__.py10
-rw-r--r--nova/tests/api_unittest.py120
3 files changed, 29 insertions, 103 deletions
diff --git a/nova/api/__init__.py b/nova/api/__init__.py
index 0166b7fc1..786b246ec 100644
--- a/nova/api/__init__.py
+++ b/nova/api/__init__.py
@@ -37,5 +37,5 @@ class API(wsgi.Router):
# be dropped; and I'm leaving off CloudPipeRequestHandler until
# I hear that we need it.
mapper.connect("/v1.0/{path_info:.*}", controller=rackspace.API())
- mapper.connect("/ec2/{path_info:.*}", controller=ec2.API())
+ mapper.connect("/services/{path_info:.*}", controller=ec2.API())
super(API, self).__init__(mapper)
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index 3335338e0..a94bcb863 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -44,6 +44,7 @@ class API(wsgi.Middleware):
def __init__(self):
self.application = Authenticate(Router(Authorizer(Executor())))
+
class Authenticate(wsgi.Middleware):
"""Authenticate an EC2 request and add 'ec2.context' to WSGI environ."""
@@ -81,11 +82,12 @@ class Authenticate(wsgi.Middleware):
return self.application
-class Router(wsgi.Application):
+class Router(wsgi.Middleware):
"""
Add 'ec2.controller', 'ec2.action', and 'ec2.action_args' to WSGI environ.
"""
- def __init__(self):
+ def __init__(self, application):
+ super(Router, self).__init__(application)
self.map = routes.Mapper()
self.map.connect("/{controller_name}/")
self.controllers = dict(Cloud=cloud.CloudController(),
@@ -122,14 +124,14 @@ class Router(wsgi.Application):
return self.application
-class Authorization(wsgi.Middleware):
+class Authorizer(wsgi.Middleware):
"""
Return a 401 if ec2.controller and ec2.action in WSGI environ may not be
executed in ec2.context.
"""
def __init__(self, application):
- super(Authorization, self).__init__(application)
+ super(Authorizer, self).__init__(application)
self.action_roles = {
'CloudController': {
'DescribeAvailabilityzones': ['all'],
diff --git a/nova/tests/api_unittest.py b/nova/tests/api_unittest.py
index d21ded75b..a13bbdeed 100644
--- a/nova/tests/api_unittest.py
+++ b/nova/tests/api_unittest.py
@@ -21,53 +21,14 @@ from boto.ec2 import regioninfo
import httplib
import random
import StringIO
-from tornado import httpserver
-from twisted.internet import defer
+import webob
-from nova import flags
from nova import test
from nova.auth import manager
+from nova.api import ec2
from nova.api.ec2 import cloud
-FLAGS = flags.FLAGS
-
-
-# NOTE(termie): These are a bunch of helper methods and classes to short
-# circuit boto calls and feed them into our tornado handlers,
-# it's pretty damn circuitous so apologies if you have to fix
-# a bug in it
-def boto_to_tornado(method, path, headers, data, host, connection=None):
- """ translate boto requests into tornado requests
-
- connection should be a FakeTornadoHttpConnection instance
- """
- try:
- headers = httpserver.HTTPHeaders()
- except AttributeError:
- from tornado import httputil
- headers = httputil.HTTPHeaders()
- for k, v in headers.iteritems():
- headers[k] = v
-
- req = httpserver.HTTPRequest(method=method,
- uri=path,
- headers=headers,
- body=data,
- host=host,
- remote_ip='127.0.0.1',
- connection=connection)
- return req
-
-
-def raw_to_httpresponse(s):
- """ translate a raw tornado http response into an httplib.HTTPResponse """
- sock = FakeHttplibSocket(s)
- resp = httplib.HTTPResponse(sock)
- resp.begin()
- return resp
-
-
class FakeHttplibSocket(object):
""" a fake socket implementation for httplib.HTTPResponse, trivial """
def __init__(self, s):
@@ -77,73 +38,36 @@ class FakeHttplibSocket(object):
return self.fp
-class FakeTornadoStream(object):
- """ a fake stream to satisfy tornado's assumptions, trivial """
- def set_close_callback(self, f):
- pass
-
-
-class FakeTornadoConnection(object):
- """ a fake connection object for tornado to pass to its handlers
-
- web requests are expected to write to this as they get data and call
- finish when they are done with the request, we buffer the writes and
- kick off a callback when it is done so that we can feed the result back
- into boto.
- """
- def __init__(self, d):
- self.d = d
- self._buffer = StringIO.StringIO()
-
- def write(self, chunk):
- self._buffer.write(chunk)
-
- def finish(self):
- s = self._buffer.getvalue()
- self.d.callback(s)
-
- xheaders = None
-
- @property
- def stream(self):
- return FakeTornadoStream()
-
-
class FakeHttplibConnection(object):
""" a fake httplib.HTTPConnection for boto to use
requests made via this connection actually get translated and routed into
- our tornado app, we then wait for the response and turn it back into
+ our WSGI app, we then wait for the response and turn it back into
the httplib.HTTPResponse that boto expects.
"""
def __init__(self, app, host, is_secure=False):
self.app = app
self.host = host
- self.deferred = defer.Deferred()
def request(self, method, path, data, headers):
- req = boto_to_tornado
- conn = FakeTornadoConnection(self.deferred)
- request = boto_to_tornado(connection=conn,
- method=method,
- path=path,
- headers=headers,
- data=data,
- host=self.host)
- handler = self.app(request)
- self.deferred.addCallback(raw_to_httpresponse)
+ req = webob.Request.blank(path)
+ req.method = method
+ req.body = data
+ req.headers = headers
+ req.headers['Accept'] = 'text/html'
+ req.host = self.host
+ # Call the WSGI app, get the HTTP response
+ resp = str(req.get_response(self.app))
+ # For some reason, the response doesn't have "HTTP/1.0 " prepended; I
+ # guess that's a function the web server usually provides.
+ resp = "HTTP/1.0 %s" % resp
+
+ sock = FakeHttplibSocket(resp)
+ self.http_response = httplib.HTTPResponse(sock)
+ self.http_response.begin()
def getresponse(self):
- @defer.inlineCallbacks
- def _waiter():
- result = yield self.deferred
- defer.returnValue(result)
- d = _waiter()
- # NOTE(termie): defer.returnValue above should ensure that
- # this deferred has already been called by the time
- # we get here, we are going to cheat and return
- # the result of the callback
- return d.result
+ return self.http_response
def close(self):
pass
@@ -158,20 +82,20 @@ class ApiEc2TestCase(test.BaseTestCase):
self.host = '127.0.0.1'
- self.app = api.APIServerApplication({'Cloud': self.cloud})
+ self.app = ec2.API()
self.ec2 = boto.connect_ec2(
aws_access_key_id='fake',
aws_secret_access_key='fake',
is_secure=False,
region=regioninfo.RegionInfo(None, 'test', self.host),
- port=FLAGS.cc_port,
+ port=0,
path='/services/Cloud')
self.mox.StubOutWithMock(self.ec2, 'new_http_connection')
def expect_http(self, host=None, is_secure=False):
http = FakeHttplibConnection(
- self.app, '%s:%d' % (self.host, FLAGS.cc_port), False)
+ self.app, '%s:0' % (self.host), False)
self.ec2.new_http_connection(host, is_secure).AndReturn(http)
return http