diff options
Diffstat (limited to 'keystone/common/environment/eventlet_server.py')
-rw-r--r-- | keystone/common/environment/eventlet_server.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/keystone/common/environment/eventlet_server.py b/keystone/common/environment/eventlet_server.py new file mode 100644 index 00000000..18987d26 --- /dev/null +++ b/keystone/common/environment/eventlet_server.py @@ -0,0 +1,114 @@ +# 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 socket +import ssl +import sys + +import eventlet +import eventlet.wsgi +import greenlet + +from keystone.common import logging +from keystone.common import wsgi + + +LOG = logging.getLogger(__name__) + + +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 + except greenlet.GreenletExit: + 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 |