Small typos, plus rework api_unittest to use WSGI instead of Tornado
This commit is contained in:
		| @@ -21,53 +21,14 @@ from boto.ec2 import regioninfo | |||||||
| import httplib | import httplib | ||||||
| import random | import random | ||||||
| import StringIO | import StringIO | ||||||
| from tornado import httpserver | import webob | ||||||
| from twisted.internet import defer |  | ||||||
|  |  | ||||||
| from nova import flags |  | ||||||
| from nova import test | from nova import test | ||||||
| from nova.auth import manager | from nova.auth import manager | ||||||
|  | from nova.api import ec2 | ||||||
| from nova.api.ec2 import cloud | 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): | class FakeHttplibSocket(object): | ||||||
|     """ a fake socket implementation for httplib.HTTPResponse, trivial """ |     """ a fake socket implementation for httplib.HTTPResponse, trivial """ | ||||||
|     def __init__(self, s): |     def __init__(self, s): | ||||||
| @@ -77,73 +38,36 @@ class FakeHttplibSocket(object): | |||||||
|         return self.fp |         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): | class FakeHttplibConnection(object): | ||||||
|     """ a fake httplib.HTTPConnection for boto to use |     """ a fake httplib.HTTPConnection for boto to use | ||||||
|  |  | ||||||
|     requests made via this connection actually get translated and routed into |     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. |     the httplib.HTTPResponse that boto expects. | ||||||
|     """ |     """ | ||||||
|     def __init__(self, app, host, is_secure=False): |     def __init__(self, app, host, is_secure=False): | ||||||
|         self.app = app |         self.app = app | ||||||
|         self.host = host |         self.host = host | ||||||
|         self.deferred = defer.Deferred() |  | ||||||
|  |  | ||||||
|     def request(self, method, path, data, headers): |     def request(self, method, path, data, headers): | ||||||
|         req = boto_to_tornado |         req = webob.Request.blank(path) | ||||||
|         conn = FakeTornadoConnection(self.deferred) |         req.method = method | ||||||
|         request = boto_to_tornado(connection=conn, |         req.body = data | ||||||
|                                   method=method, |         req.headers = headers | ||||||
|                                   path=path, |         req.headers['Accept'] = 'text/html' | ||||||
|                                   headers=headers, |         req.host = self.host | ||||||
|                                   data=data, |         # Call the WSGI app, get the HTTP response | ||||||
|                                   host=self.host) |         resp = str(req.get_response(self.app)) | ||||||
|         handler = self.app(request) |         # For some reason, the response doesn't have "HTTP/1.0 " prepended; I | ||||||
|         self.deferred.addCallback(raw_to_httpresponse) |         # 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): |     def getresponse(self): | ||||||
|         @defer.inlineCallbacks |         return self.http_response | ||||||
|         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 |  | ||||||
|  |  | ||||||
|     def close(self): |     def close(self): | ||||||
|         pass |         pass | ||||||
| @@ -158,20 +82,20 @@ class ApiEc2TestCase(test.BaseTestCase): | |||||||
|  |  | ||||||
|         self.host = '127.0.0.1' |         self.host = '127.0.0.1' | ||||||
|  |  | ||||||
|         self.app = api.APIServerApplication({'Cloud': self.cloud}) |         self.app = ec2.API() | ||||||
|         self.ec2 = boto.connect_ec2( |         self.ec2 = boto.connect_ec2( | ||||||
|                 aws_access_key_id='fake', |                 aws_access_key_id='fake', | ||||||
|                 aws_secret_access_key='fake', |                 aws_secret_access_key='fake', | ||||||
|                 is_secure=False, |                 is_secure=False, | ||||||
|                 region=regioninfo.RegionInfo(None, 'test', self.host), |                 region=regioninfo.RegionInfo(None, 'test', self.host), | ||||||
|                 port=FLAGS.cc_port, |                 port=0, | ||||||
|                 path='/services/Cloud') |                 path='/services/Cloud') | ||||||
|  |  | ||||||
|         self.mox.StubOutWithMock(self.ec2, 'new_http_connection') |         self.mox.StubOutWithMock(self.ec2, 'new_http_connection') | ||||||
|  |  | ||||||
|     def expect_http(self, host=None, is_secure=False): |     def expect_http(self, host=None, is_secure=False): | ||||||
|         http = FakeHttplibConnection( |         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) |         self.ec2.new_http_connection(host, is_secure).AndReturn(http) | ||||||
|         return http |         return http | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Michael Gundlach
					Michael Gundlach