Set socket options in correct way

Currently socket options, socket.SO_REUSEADDR, socket.TCP_KEEPIDLE and
socket.SO_KEEPALIVE are set only if SSL is enabled.

socket.SO_REUSEADDR:
This socket option tells the kernel that even if this port is busy
(in the TIME_WAIT state), go ahead and reuse it anyway. It is useful if your
server has been shut down, and then restarted right away while sockets are
still active on its port.

socket.SO_KEEPALIVE:
To confirm that an idle connection is still active, these implementations
send a probe segment designed to elicit a response from the peer TCP. The the
probe causes the receiver to return an acknowledgement segment, confirming
that the connection is still live. If the peer has dropped the connection due
to a network partition or a crash, it will respond with a RST instead of an
acknowledgement segment.

socket.TCP_KEEPIDLE:
It is useful to set this socket option, because if the other peers lose their
connection (for example by rebooting) you will notice that the connection is
broken, even if you don't have traffic on it. If the probes are not replied
to by your peer, you can assert that the connection cannot be considered valid
and then take the correct action.

IMO, these options are useful in both the cases, whether SSL is enabled or not.

Made provision to set socket.SO_REUSEADDR, socket.TCP_KEEPIDLE and
socket.SO_KEEPALIVE socket options if SSL is enabled or not.

Closes-Bug: #1369414

Change-Id: I25b353dcf1ca6eba1c54d297994d56c0064daca5
This commit is contained in:
abhishekkekane
2014-09-12 02:59:08 -07:00
parent 779b760421
commit 0e3f85352c
2 changed files with 50 additions and 13 deletions

View File

@@ -17,6 +17,7 @@
"""Unit tests for `nova.wsgi`."""
import os.path
import socket
import tempfile
import urllib2
@@ -127,6 +128,24 @@ class TestWSGIServer(test.NoDBTestCase):
server.stop()
server.wait()
def test_socket_options_for_simple_server(self):
# test normal socket options has set properly
self.flags(tcp_keepidle=500)
server = nova.wsgi.Server("test_socket_options", None,
host="127.0.0.1", port=0)
server.start()
sock = server._socket
self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR))
self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
socket.SO_KEEPALIVE))
if hasattr(socket, 'TCP_KEEPIDLE'):
self.assertEqual(CONF.tcp_keepidle,
sock.getsockopt(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE))
server.stop()
server.wait()
def test_server_pool_waitall(self):
# test pools waitall method gets called while stopping server
server = nova.wsgi.Server("test_server", None,
@@ -270,6 +289,25 @@ class TestWSGIServerWithSSL(test.NoDBTestCase):
fake_ssl_server.stop()
fake_ssl_server.wait()
def test_socket_options_for_ssl_server(self):
# test normal socket options has set properly
self.flags(tcp_keepidle=500)
server = nova.wsgi.Server("test_socket_options", None,
host="127.0.0.1", port=0,
use_ssl=True)
server.start()
sock = server._socket
self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR))
self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
socket.SO_KEEPALIVE))
if hasattr(socket, 'TCP_KEEPIDLE'):
self.assertEqual(CONF.tcp_keepidle,
sock.getsockopt(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE))
server.stop()
server.wait()
@testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
def test_app_using_ipv6_and_ssl(self):
greetings = 'Hello, World!!!'

View File

@@ -159,6 +159,18 @@ class Server(object):
# to keep file descriptor usable.
dup_socket = self._socket.dup()
dup_socket.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
# sockets can hang around forever without keepalive
dup_socket.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'):
dup_socket.setsockopt(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE,
CONF.tcp_keepidle)
if self._use_ssl:
try:
ca_file = CONF.ssl_ca_file
@@ -195,19 +207,6 @@ class Server(object):
dup_socket = eventlet.wrap_ssl(dup_socket,
**ssl_kwargs)
dup_socket.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
# sockets can hang around forever without keepalive
dup_socket.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'):
dup_socket.setsockopt(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE,
CONF.tcp_keepidle)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Failed to start %(name)s on %(host)s"