Skip to content

Commit

Permalink
Add client_socket_timeout option
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Stuart McLaren committed Oct 16, 2014
1 parent 272b863 commit 08bfa77
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
37 changes: 37 additions & 0 deletions cinder/tests/test_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
"""Unit tests for `cinder.wsgi`."""

import os.path
import re
import socket
import tempfile
import time
import urllib2

import mock
Expand Down Expand Up @@ -141,7 +144,41 @@ def hello_world(env, start_response):

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):
Expand Down
9 changes: 8 additions & 1 deletion cinder/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@
"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
Expand Down Expand Up @@ -107,6 +112,7 @@ def __init__(self, name, app, host=None, port=None, pool_size=None,
"""
# 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"
Expand Down Expand Up @@ -229,7 +235,8 @@ def start(self):
'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)
Expand Down
6 changes: 6 additions & 0 deletions etc/cinder/cinder.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 08bfa77

Please sign in to comment.