From: Stuart McLaren Date: Fri, 5 Sep 2014 12:48:04 +0000 (+0000) Subject: Add client_socket_timeout option X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=08bfa77aeccb8ca589e3fb5cf9771879818f59de;p=openstack-build%2Fcinder-build.git Add client_socket_timeout option Add a parameter to take advantage of the new(ish) eventlet socket timeout behaviour. Allows closing idle client connections after a period of time, eg: $ time nc localhost 8776 real 1m0.063s Setting 'client_socket_timeout = 0' means do not timeout. DocImpact Change-Id: If492810a2f10fa5954f8c8bb708b14be0b77fb90 Closes-bug: #1371022 --- diff --git a/cinder/tests/test_wsgi.py b/cinder/tests/test_wsgi.py index a267bb879..36c1e73b5 100644 --- a/cinder/tests/test_wsgi.py +++ b/cinder/tests/test_wsgi.py @@ -17,7 +17,10 @@ """Unit tests for `cinder.wsgi`.""" import os.path +import re +import socket import tempfile +import time import urllib2 import mock @@ -141,7 +144,41 @@ class TestWSGIServer(test.TestCase): response = open_no_proxy('http://127.0.0.1:%d/' % server.port) self.assertEqual(greetings, response.read()) + server.stop() + + def test_client_socket_timeout(self): + CONF.set_default("client_socket_timeout", 0.1) + greetings = 'Hello, World!!!' + + def hello_world(env, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return [greetings] + + server = cinder.wsgi.Server("test_app", hello_world, + host="127.0.0.1", port=0) + server.start() + + s = socket.socket() + s.connect(("127.0.0.1", server.port)) + + fd = s.makefile('rw') + fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') + fd.flush() + + buf = fd.read() + self.assertTrue(re.search(greetings, buf)) + + s2 = socket.socket() + s2.connect(("127.0.0.1", server.port)) + time.sleep(0.2) + + fd = s2.makefile('rw') + fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') + fd.flush() + buf = fd.read() + # connection is closed so we get nothing from the server + self.assertFalse(buf) server.stop() def test_app_using_ssl(self): diff --git a/cinder/wsgi.py b/cinder/wsgi.py index cbd62e665..5e433e723 100644 --- a/cinder/wsgi.py +++ b/cinder/wsgi.py @@ -79,6 +79,11 @@ eventlet_opts = [ "max_header_line may need to be increased when using " "large tokens (typically those generated by the " "Keystone v3 API with big service catalogs)."), + cfg.IntOpt('client_socket_timeout', default=900, + help="Timeout for client connections\' socket operations. " + "If an incoming connection is idle for this number of " + "seconds it will be closed. A value of \'0\' means " + "wait forever."), ] CONF = cfg.CONF @@ -107,6 +112,7 @@ class Server(object): """ # Allow operators to customize http requests max header line size. eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line + self.client_socket_timeout = CONF.client_socket_timeout or None self.name = name self.app = app self._host = host or "0.0.0.0" @@ -229,7 +235,8 @@ class Server(object): 'site': self.app, 'protocol': self._protocol, 'custom_pool': self._pool, - 'log': self._wsgi_logger + 'log': self._wsgi_logger, + 'socket_timeout': self.client_socket_timeout } self._server = eventlet.spawn(**wsgi_kwargs) diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index 65976fb00..f54956fd0 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -305,6 +305,12 @@ # with big service catalogs). (integer value) #max_header_line=16384 +# Timeout for client connections' socket operations. If an +# incoming connection is idle for this number of seconds it +# will be closed. A value of '0' means wait forever. (integer +# value) +#client_socket_timeout=900 + # Sets the value of TCP_KEEPALIVE (True/False) for each server # socket. (boolean value) #tcp_keepalive=true