diff options
-rwxr-xr-x | bin/keystone-all | 7 | ||||
-rw-r--r-- | keystone/common/wsgi.py | 83 | ||||
-rw-r--r-- | keystone/common/wsgi_server.py | 120 | ||||
-rw-r--r-- | keystone/test.py | 9 |
4 files changed, 127 insertions, 92 deletions
diff --git a/bin/keystone-all b/bin/keystone-all index 2fdc8c7a..ff3143bd 100755 --- a/bin/keystone-all +++ b/bin/keystone-all @@ -2,7 +2,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 import greenlet -import eventlet import logging import os import signal @@ -23,6 +22,7 @@ from paste import deploy from keystone import config from keystone.common import wsgi +from keystone.common import wsgi_server from keystone.common import utils from keystone.openstack.common import importutils from keystone.openstack.common import version @@ -33,7 +33,7 @@ CONF = config.CONF def create_server(conf, name, host, port): app = deploy.loadapp('config:%s' % conf, name=name) - server = wsgi.Server(app, host=host, port=port) + server = wsgi_server.Server(app, host=host, port=port) if CONF.ssl.enable: server.set_ssl(CONF.ssl.certfile, CONF.ssl.keyfile, CONF.ssl.ca_certs, CONF.ssl.cert_required) @@ -106,8 +106,7 @@ if __name__ == '__main__': # http://lists.openstack.org/pipermail/openstack-dev/2012-August/ # 000794.html monkeypatch_thread = False - eventlet.patcher.monkey_patch(all=False, socket=True, time=True, - thread=monkeypatch_thread) + wsgi_server.monkey_patch_eventlet(monkeypatch_thread=monkeypatch_thread) options = deploy.appconfig('config:%s' % paste_config) diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py index 80516ea1..4ea05628 100644 --- a/keystone/common/wsgi.py +++ b/keystone/common/wsgi.py @@ -21,12 +21,8 @@ """Utility methods for working with WSGI servers.""" import re -import socket -import sys -import eventlet.wsgi import routes.middleware -import ssl import webob.dec import webob.exc @@ -88,85 +84,6 @@ class WritableLogger(object): self.logger.log(self.level, msg) -class Server(object): - """Server class to manage multiple WSGI sockets and applications.""" - - def __init__(self, application, host=None, port=None, threads=1000): - self.application = application - self.host = host or '0.0.0.0' - self.port = port or 0 - self.pool = eventlet.GreenPool(threads) - self.socket_info = {} - self.greenthread = None - self.do_ssl = False - self.cert_required = False - - def start(self, key=None, backlog=128): - """Run a WSGI server with the given application.""" - LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') % - {'arg0': sys.argv[0], - 'host': self.host, - 'port': self.port}) - - # TODO(dims): eventlet's green dns/socket module does not actually - # support IPv6 in getaddrinfo(). We need to get around this in the - # future or monitor upstream for a fix - info = socket.getaddrinfo(self.host, - self.port, - socket.AF_UNSPEC, - socket.SOCK_STREAM)[0] - _socket = eventlet.listen(info[-1], - family=info[0], - backlog=backlog) - if key: - self.socket_info[key] = _socket.getsockname() - # SSL is enabled - if self.do_ssl: - if self.cert_required: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - sslsocket = eventlet.wrap_ssl(_socket, certfile=self.certfile, - keyfile=self.keyfile, - server_side=True, - cert_reqs=cert_reqs, - ca_certs=self.ca_certs) - _socket = sslsocket - - self.greenthread = self.pool.spawn(self._run, - self.application, - _socket) - - def set_ssl(self, certfile, keyfile=None, ca_certs=None, - cert_required=True): - self.certfile = certfile - self.keyfile = keyfile - self.ca_certs = ca_certs - self.cert_required = cert_required - self.do_ssl = True - - def kill(self): - if self.greenthread: - self.greenthread.kill() - - def wait(self): - """Wait until all servers have completed running.""" - try: - self.pool.waitall() - except KeyboardInterrupt: - pass - - def _run(self, application, socket): - """Start a WSGI server in a new green thread.""" - log = logging.getLogger('eventlet.wsgi.server') - try: - eventlet.wsgi.server(socket, application, custom_pool=self.pool, - log=WritableLogger(log)) - except Exception: - LOG.exception(_('Server error')) - raise - - class Request(webob.Request): pass diff --git a/keystone/common/wsgi_server.py b/keystone/common/wsgi_server.py new file mode 100644 index 00000000..f3c22907 --- /dev/null +++ b/keystone/common/wsgi_server.py @@ -0,0 +1,120 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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 socket +import ssl +import sys + +import eventlet +import eventlet.wsgi + +from keystone.common import logging +from keystone.common import wsgi + + +LOG = logging.getLogger(__name__) + + +def monkey_patch_eventlet(monkeypatch_thread=None): + if monkeypatch_thread is None: + monkeypatch_thread = not os.getenv('STANDARD_THREADS') + + eventlet.patcher.monkey_patch(all=False, socket=True, time=True, + thread=monkeypatch_thread) + + +class Server(object): + """Server class to manage multiple WSGI sockets and applications.""" + + def __init__(self, application, host=None, port=None, threads=1000): + self.application = application + self.host = host or '0.0.0.0' + self.port = port or 0 + self.pool = eventlet.GreenPool(threads) + self.socket_info = {} + self.greenthread = None + self.do_ssl = False + self.cert_required = False + + def start(self, key=None, backlog=128): + """Run a WSGI server with the given application.""" + LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') % + {'arg0': sys.argv[0], + 'host': self.host, + 'port': self.port}) + + # TODO(dims): eventlet's green dns/socket module does not actually + # support IPv6 in getaddrinfo(). We need to get around this in the + # future or monitor upstream for a fix + info = socket.getaddrinfo(self.host, + self.port, + socket.AF_UNSPEC, + socket.SOCK_STREAM)[0] + _socket = eventlet.listen(info[-1], + family=info[0], + backlog=backlog) + if key: + self.socket_info[key] = _socket.getsockname() + # SSL is enabled + if self.do_ssl: + if self.cert_required: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + sslsocket = eventlet.wrap_ssl(_socket, certfile=self.certfile, + keyfile=self.keyfile, + server_side=True, + cert_reqs=cert_reqs, + ca_certs=self.ca_certs) + _socket = sslsocket + + self.greenthread = self.pool.spawn(self._run, + self.application, + _socket) + + def set_ssl(self, certfile, keyfile=None, ca_certs=None, + cert_required=True): + self.certfile = certfile + self.keyfile = keyfile + self.ca_certs = ca_certs + self.cert_required = cert_required + self.do_ssl = True + + def kill(self): + if self.greenthread: + self.greenthread.kill() + + def wait(self): + """Wait until all servers have completed running.""" + try: + self.pool.waitall() + except KeyboardInterrupt: + pass + + def _run(self, application, socket): + """Start a WSGI server in a new green thread.""" + log = logging.getLogger('eventlet.wsgi.server') + try: + eventlet.wsgi.server(socket, application, custom_pool=self.pool, + log=wsgi.WritableLogger(log)) + except Exception: + LOG.exception(_('Server error')) + raise diff --git a/keystone/test.py b/keystone/test.py index f47c253c..b5f421da 100644 --- a/keystone/test.py +++ b/keystone/test.py @@ -22,7 +22,6 @@ import subprocess import sys import time -import eventlet import mox import nose.exc from paste import deploy @@ -34,6 +33,7 @@ from keystone.common import kvs from keystone.common import logging from keystone.common import utils from keystone.common import wsgi +from keystone.common import wsgi_server from keystone import config from keystone import credential from keystone import exception @@ -44,9 +44,8 @@ from keystone import token from keystone import trust -do_monkeypatch = not os.getenv('STANDARD_THREADS') -eventlet.patcher.monkey_patch(all=False, socket=True, time=True, - thread=do_monkeypatch) +wsgi_server.monkey_patch_eventlet() + LOG = logging.getLogger(__name__) ROOTDIR = os.path.dirname(os.path.abspath(os.curdir)) @@ -316,7 +315,7 @@ class TestCase(NoModule, unittest.TestCase): def serveapp(self, config, name=None, cert=None, key=None, ca=None, cert_required=None, host="127.0.0.1", port=0): app = self.loadapp(config, name=name) - server = wsgi.Server(app, host, port) + server = wsgi_server.Server(app, host, port) if cert is not None and ca is not None and key is not None: server.set_ssl(certfile=cert, keyfile=key, ca_certs=ca, cert_required=cert_required) |