summaryrefslogtreecommitdiffstats
path: root/openstack/common/wsgi.py
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-02-02 16:52:24 +0000
committerGerrit Code Review <review@openstack.org>2013-02-02 16:52:24 +0000
commit6ce830b0e4e8a9c00d3cfb51f643dec3e1286cee (patch)
treed2263f2476ec6b1f465fc2187333cb1a2d8eb78f /openstack/common/wsgi.py
parent864e934cfa7003767dabb4f9a51ebe1e493f6027 (diff)
parente50b68c0d28cb00fa627525f23bb0c0f614b9312 (diff)
downloadoslo-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.py65
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))