~ubuntu-branches/ubuntu/trusty/cinder/trusty

« back to all changes in this revision

Viewing changes to cinder/wsgi.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Yolanda Robla Mota, James Page, Chuck Short
  • Date: 2013-02-22 10:45:17 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20130222104517-ng3r6ace9vi4m869
Tags: 2013.1.g3-0ubuntu1
[ Yolanda Robla Mota ]
* d/control: Add BD on python-hp3parclient.
* d/patches: Drop patches related to disabling hp3parclient.

[ James Page ]
* d/control: Add Suggests: python-hp3parclient for python-cinder.
* d/control: Add BD on python-oslo-config.
* d/*: Wrapped and sorted.

[ Chuck Short ]
* New upstream release.
* debian/rules, debian/cinder-volumes.install: 
  - Fail if binaries are missing and install missing binaries.
* debian/patches/fix-ubuntu-tests.patch: Fix failing tests.
* debian/control: Add python-rtslib and python-mock.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
"""Utility methods for working with WSGI servers."""
21
21
 
 
22
import errno
 
23
import os
 
24
import socket
 
25
import ssl
22
26
import sys
 
27
import time
23
28
 
24
29
import eventlet
25
30
import eventlet.wsgi
26
31
import greenlet
 
32
from oslo.config import cfg
27
33
from paste import deploy
28
34
import routes.middleware
29
35
import webob.dec
34
40
from cinder.openstack.common import log as logging
35
41
from cinder import utils
36
42
 
 
43
socket_opts = [
 
44
    cfg.IntOpt('backlog',
 
45
               default=4096,
 
46
               help="Number of backlog requests to configure the socket with"),
 
47
    cfg.IntOpt('tcp_keepidle',
 
48
               default=600,
 
49
               help="Sets the value of TCP_KEEPIDLE in seconds for each "
 
50
                    "server socket. Not supported on OS X."),
 
51
    cfg.StrOpt('ssl_ca_file',
 
52
               default=None,
 
53
               help="CA certificate file to use to verify "
 
54
                    "connecting clients"),
 
55
    cfg.StrOpt('ssl_cert_file',
 
56
               default=None,
 
57
               help="Certificate file to use when starting "
 
58
                    "the server securely"),
 
59
    cfg.StrOpt('ssl_key_file',
 
60
               default=None,
 
61
               help="Private key file to use when starting "
 
62
                    "the server securely"),
 
63
]
 
64
 
 
65
CONF = cfg.CONF
 
66
CONF.register_opts(socket_opts)
37
67
 
38
68
FLAGS = flags.FLAGS
39
69
LOG = logging.getLogger(__name__)
58
88
        """
59
89
        self.name = name
60
90
        self.app = app
61
 
        self.host = host or "0.0.0.0"
62
 
        self.port = port or 0
 
91
        self._host = host or "0.0.0.0"
 
92
        self._port = port or 0
63
93
        self._server = None
64
94
        self._socket = None
65
95
        self._protocol = protocol
67
97
        self._logger = logging.getLogger("eventlet.wsgi.server")
68
98
        self._wsgi_logger = logging.WritableLogger(self._logger)
69
99
 
 
100
    def _get_socket(self, host, port, backlog):
 
101
        bind_addr = (host, port)
 
102
        # TODO(dims): eventlet's green dns/socket module does not actually
 
103
        # support IPv6 in getaddrinfo(). We need to get around this in the
 
104
        # future or monitor upstream for a fix
 
105
        try:
 
106
            info = socket.getaddrinfo(bind_addr[0],
 
107
                                      bind_addr[1],
 
108
                                      socket.AF_UNSPEC,
 
109
                                      socket.SOCK_STREAM)[0]
 
110
            family = info[0]
 
111
            bind_addr = info[-1]
 
112
        except Exception:
 
113
            family = socket.AF_INET
 
114
 
 
115
        cert_file = CONF.ssl_cert_file
 
116
        key_file = CONF.ssl_key_file
 
117
        ca_file = CONF.ssl_ca_file
 
118
        use_ssl = cert_file or key_file
 
119
 
 
120
        if cert_file and not os.path.exists(cert_file):
 
121
            raise RuntimeError(_("Unable to find cert_file : %s") % cert_file)
 
122
 
 
123
        if ca_file and not os.path.exists(ca_file):
 
124
            raise RuntimeError(_("Unable to find ca_file : %s") % ca_file)
 
125
 
 
126
        if key_file and not os.path.exists(key_file):
 
127
            raise RuntimeError(_("Unable to find key_file : %s") % key_file)
 
128
 
 
129
        if use_ssl and (not cert_file or not key_file):
 
130
            raise RuntimeError(_("When running server in SSL mode, you must "
 
131
                                 "specify both a cert_file and key_file "
 
132
                                 "option value in your configuration file"))
 
133
 
 
134
        def wrap_ssl(sock):
 
135
            ssl_kwargs = {
 
136
                'server_side': True,
 
137
                'certfile': cert_file,
 
138
                'keyfile': key_file,
 
139
                'cert_reqs': ssl.CERT_NONE,
 
140
            }
 
141
 
 
142
            if CONF.ssl_ca_file:
 
143
                ssl_kwargs['ca_certs'] = ca_file
 
144
                ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED
 
145
 
 
146
            return ssl.wrap_socket(sock, **ssl_kwargs)
 
147
 
 
148
        sock = None
 
149
        retry_until = time.time() + 30
 
150
        while not sock and time.time() < retry_until:
 
151
            try:
 
152
                sock = eventlet.listen(bind_addr,
 
153
                                       backlog=backlog,
 
154
                                       family=family)
 
155
                if use_ssl:
 
156
                    sock = wrap_ssl(sock)
 
157
 
 
158
            except socket.error, err:
 
159
                if err.args[0] != errno.EADDRINUSE:
 
160
                    raise
 
161
                eventlet.sleep(0.1)
 
162
        if not sock:
 
163
            raise RuntimeError(_("Could not bind to %(host)s:%(port)s "
 
164
                               "after trying for 30 seconds") %
 
165
                               {'host': host, 'port': port})
 
166
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
167
        # sockets can hang around forever without keepalive
 
168
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
 
169
 
 
170
        # This option isn't available in the OS X version of eventlet
 
171
        if hasattr(socket, 'TCP_KEEPIDLE'):
 
172
            sock.setsockopt(socket.IPPROTO_TCP,
 
173
                            socket.TCP_KEEPIDLE,
 
174
                            CONF.tcp_keepidle)
 
175
 
 
176
        return sock
 
177
 
70
178
    def _start(self):
71
179
        """Run the blocking eventlet WSGI server.
72
180
 
90
198
        if backlog < 1:
91
199
            raise exception.InvalidInput(
92
200
                reason='The backlog must be more than 1')
93
 
        self._socket = eventlet.listen((self.host, self.port), backlog=backlog)
 
201
 
 
202
        self._socket = self._get_socket(self._host,
 
203
                                        self._port,
 
204
                                        backlog=backlog)
94
205
        self._server = eventlet.spawn(self._start)
95
 
        (self.host, self.port) = self._socket.getsockname()
96
 
        LOG.info(_("Started %(name)s on %(host)s:%(port)s") % self.__dict__)
 
206
        (self._host, self._port) = self._socket.getsockname()[0:2]
 
207
        LOG.info(_("Started %(name)s on %(_host)s:%(_port)s") % self.__dict__)
 
208
 
 
209
    @property
 
210
    def host(self):
 
211
        return self._host
 
212
 
 
213
    @property
 
214
    def port(self):
 
215
        return self._port
97
216
 
98
217
    def stop(self):
99
218
        """Stop this server.