diff options
author | Jenkins <jenkins@review.openstack.org> | 2013-02-02 16:52:24 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2013-02-02 16:52:24 +0000 |
commit | 6ce830b0e4e8a9c00d3cfb51f643dec3e1286cee (patch) | |
tree | d2263f2476ec6b1f465fc2187333cb1a2d8eb78f /openstack/common/wsgi.py | |
parent | 864e934cfa7003767dabb4f9a51ebe1e493f6027 (diff) | |
parent | e50b68c0d28cb00fa627525f23bb0c0f614b9312 (diff) | |
download | oslo-6ce830b0e4e8a9c00d3cfb51f643dec3e1286cee.tar.gz oslo-6ce830b0e4e8a9c00d3cfb51f643dec3e1286cee.tar.xz oslo-6ce830b0e4e8a9c00d3cfb51f643dec3e1286cee.zip |
Merge "Support for SSL in wsgi.Service"
Diffstat (limited to 'openstack/common/wsgi.py')
-rw-r--r-- | openstack/common/wsgi.py | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/openstack/common/wsgi.py b/openstack/common/wsgi.py index f0096d3..550ea4d 100644 --- a/openstack/common/wsgi.py +++ b/openstack/common/wsgi.py @@ -18,6 +18,7 @@ """Utility methods for working with WSGI servers.""" import datetime +import errno import eventlet import eventlet.wsgi @@ -25,18 +26,34 @@ eventlet.patcher.monkey_patch(all=False, socket=True) import routes import routes.middleware +import socket import sys +import time import webob.dec import webob.exc from xml.dom import minidom from xml.parsers import expat +from openstack.common import cfg from openstack.common import exception from openstack.common.gettextutils import _ from openstack.common import jsonutils from openstack.common import log as logging from openstack.common import service +from openstack.common import sslutils +socket_opts = [ + cfg.IntOpt('backlog', + default=4096, + help="Number of backlog requests to configure the socket with"), + cfg.IntOpt('tcp_keepidle', + default=600, + help="Sets the value of TCP_KEEPIDLE in seconds for each " + "server socket. Not supported on OS X."), +] + +CONF = cfg.CONF +CONF.register_opts(socket_opts) LOG = logging.getLogger(__name__) @@ -56,13 +73,46 @@ class Service(service.Service): """ def __init__(self, application, port, - host='0.0.0.0', backlog=128, threads=1000): + host='0.0.0.0', backlog=4096, threads=1000): self.application = application self._port = port self._host = host - self.backlog = backlog + self._backlog = backlog if backlog else CONF.backlog super(Service, self).__init__(threads) + def _get_socket(self, host, port, backlog): + + bind_addr = (host, port) + + sock = None + retry_until = time.time() + 30 + while not sock and time.time() < retry_until: + try: + sock = eventlet.listen(bind_addr, + backlog=backlog) + if sslutils.is_enabled(): + sock = sslutils.wrap(sock) + + except socket.error, err: + if err.args[0] != errno.EADDRINUSE: + raise + eventlet.sleep(0.1) + if not sock: + raise RuntimeError(_("Could not bind to %(host)s:%(port)s " + "after trying for 30 seconds") % + {'host': host, 'port': port}) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + # sockets can hang around forever without keepalive + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + + # This option isn't available in the OS X version of eventlet + if hasattr(socket, 'TCP_KEEPIDLE'): + sock.setsockopt(socket.IPPROTO_TCP, + socket.TCP_KEEPIDLE, + CONF.tcp_keepidle) + + return sock + def start(self): """Start serving this service using the provided server instance. @@ -70,11 +120,14 @@ class Service(service.Service): """ super(Service, self).start() - self._socket = eventlet.listen((self._host, self._port), - backlog=self.backlog) + self._socket = self._get_socket(self._host, self._port, self._backlog) self.tg.add_thread(self._run, self.application, self._socket) @property + def backlog(self): + return self._backlog + + @property def host(self): return self._socket.getsockname()[0] if self._socket else self._host @@ -93,7 +146,9 @@ class Service(service.Service): def _run(self, application, socket): """Start a WSGI server in a new green thread.""" logger = logging.getLogger('eventlet.wsgi') - eventlet.wsgi.server(socket, application, custom_pool=self.tg.pool, + eventlet.wsgi.server(socket, + application, + custom_pool=self.tg.pool, log=logging.WritableLogger(logger)) |