This defaults to 20 -- the same as the current hardcoded option.
Signed-off-by: Brian Foley <[email protected]>
---
lib/http/server.py | 11 ++++++++---
lib/server/noded.py | 22 ++++++++++++++++------
lib/server/rapi.py | 16 ++++++++++++----
man/ganeti-noded.rst | 10 ++++++++--
man/ganeti-rapi.rst | 7 ++++++-
5 files changed, 50 insertions(+), 16 deletions(-)
diff --git a/lib/http/server.py b/lib/http/server.py
index 9a4563e..b4a41c8 100644
--- a/lib/http/server.py
+++ b/lib/http/server.py
@@ -479,9 +479,8 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
"""Generic HTTP server class
"""
- MAX_CHILDREN = 20
- def __init__(self, mainloop, local_address, port, handler,
+ def __init__(self, mainloop, local_address, port, max_clients, handler,
ssl_params=None, ssl_verify_peer=False,
request_executor_class=None, ssl_verify_callback=None):
"""Initializes the HTTP server
@@ -492,6 +491,11 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
@param local_address: Local IP address to bind to
@type port: int
@param port: TCP port to listen on
+ @type max_clients: int
+ @param max_clients: maximum number of client connections
+ open simultaneously.
+ @type handler: HttpServerHandler
+ @param handler: Request handler object
@type ssl_params: HttpSslParams
@param ssl_params: SSL key and certificate
@type ssl_verify_peer: bool
@@ -524,6 +528,7 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
self._children = []
self.set_socket(self.socket)
self.accepting = True
+ self.max_clients = max_clients
mainloop.RegisterSignal(self)
def Start(self):
@@ -549,7 +554,7 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
"""
if not quick:
# Don't wait for other processes if it should be a quick check
- while len(self._children) > self.MAX_CHILDREN:
+ while len(self._children) > self.max_clients:
try:
# Waiting without a timeout brings us into a potential DoS situation.
# As soon as too many children run, we'll not respond to new
diff --git a/lib/server/noded.py b/lib/server/noded.py
index a5e05dd..9375fa0 100644
--- a/lib/server/noded.py
+++ b/lib/server/noded.py
@@ -1283,7 +1283,7 @@ class NodeRequestHandler(http.server.HttpServerHandler):
return backend.CleanupImportExport(params[0])
-def CheckNoded(_, args):
+def CheckNoded(options, args):
"""Initial checks whether to run or exit with a failure.
"""
@@ -1291,6 +1291,12 @@ def CheckNoded(_, args):
print >> sys.stderr, ("Usage: %s [-f] [-d] [-p port] [-b ADDRESS]" %
sys.argv[0])
sys.exit(constants.EXIT_FAILURE)
+
+ if options.max_clients < 1:
+ print >> sys.stderr, ("%s --max-clients argument must be >= 1" %
+ sys.argv[0])
+ sys.exit(constants.EXIT_FAILURE)
+
try:
codecs.lookup("string-escape")
except LookupError:
@@ -1404,11 +1410,11 @@ def PrepNoded(options, _):
handler = NodeRequestHandler()
mainloop = daemon.Mainloop()
- server = \
- http.server.HttpServer(mainloop, options.bind_address, options.port,
- handler, ssl_params=ssl_params,
ssl_verify_peer=True,
- request_executor_class=request_executor_class,
- ssl_verify_callback=SSLVerifyPeer)
+ server = http.server.HttpServer(
+ mainloop, options.bind_address, options.port, options.max_clients,
+ handler, ssl_params=ssl_params, ssl_verify_peer=True,
+ request_executor_class=request_executor_class,
+ ssl_verify_callback=SSLVerifyPeer)
server.Start()
return (mainloop, server)
@@ -1437,6 +1443,10 @@ def Main():
parser.add_option("--no-mlock", dest="mlock",
help="Do not mlock the node memory in ram",
default=True, action="store_false")
+ parser.add_option("--max-clients", dest="max_clients",
+ default=20, type="int",
+ help="Number of simultaneous connections accepted"
+ " by noded")
daemon.GenericMain(constants.NODED, parser, CheckNoded, PrepNoded, ExecNoded,
default_ssl_cert=pathutils.NODED_CERT_FILE,
diff --git a/lib/server/rapi.py b/lib/server/rapi.py
index 9782ada..fc1d27c 100644
--- a/lib/server/rapi.py
+++ b/lib/server/rapi.py
@@ -318,6 +318,11 @@ def CheckRapi(options, args):
sys.argv[0])
sys.exit(constants.EXIT_FAILURE)
+ if options.max_clients < 1:
+ print >> sys.stderr, ("%s --max-clients argument must be >= 1" %
+ sys.argv[0])
+ sys.exit(constants.EXIT_FAILURE)
+
ssconf.CheckMaster(options.debug)
# Read SSL certificate (this is a little hackish to read the cert as root)
@@ -344,10 +349,9 @@ def PrepRapi(options, _):
users.Load(pathutils.RAPI_USERS_FILE)
- server = \
- http.server.HttpServer(mainloop, options.bind_address, options.port,
- handler,
- ssl_params=options.ssl_params,
ssl_verify_peer=False)
+ server = http.server.HttpServer(
+ mainloop, options.bind_address, options.port, options.max_clients,
+ handler, ssl_params=options.ssl_params, ssl_verify_peer=False)
server.Start()
return (mainloop, server)
@@ -377,6 +381,10 @@ def Main():
default=False, action="store_true",
help=("Disable anonymous HTTP requests and require"
" authentication"))
+ parser.add_option("--max-clients", dest="max_clients",
+ default=20, type="int",
+ help="Number of simultaneous connections accepted"
+ " by ganeti-rapi")
daemon.GenericMain(constants.RAPI, parser, CheckRapi, PrepRapi, ExecRapi,
default_ssl_cert=pathutils.RAPI_CERT_FILE,
diff --git a/man/ganeti-noded.rst b/man/ganeti-noded.rst
index 3321cb8..df725e4 100644
--- a/man/ganeti-noded.rst
+++ b/man/ganeti-noded.rst
@@ -9,8 +9,9 @@ ganeti-noded - Ganeti node daemon
Synopsis
--------
-**ganeti-noded** [-f] [-d] [-p *PORT*] [-b *ADDRESS*] [-i *INTERFACE*]
-[--no-mlock] [--syslog] [--no-ssl] [-K *SSL_KEY_FILE*] [-C *SSL_CERT_FILE*]
+| **ganeti-noded** [-f] [-d] [-p *PORT*] [-b *ADDRESS*] [-i *INTERFACE*]
+| [\--max-clients *CLIENTS*] [\--no-mlock] [\--syslog] [\--no-ssl]
+| [-K *SSL_KEY_FILE*] [-C *SSL_CERT_FILE*]
DESCRIPTION
-----------
@@ -38,6 +39,11 @@ option. The ``-b`` option can be used to specify the
address to bind
to (defaults to ``0.0.0.0``); alternatively, the ``-i`` option can be
used to specify the interface to bind do.
+The maximum number of simultaneous client connections may be configured
+with the ``--max-clients`` option. This defaults to 20. Connections
+above this count are accepted, but no responses are sent until enough
+connections are closed.
+
Ganeti noded communication is protected via SSL, with a key
generated at cluster init time. This can be disabled with the
``--no-ssl`` option, or a different SSL key and certificate can be
diff --git a/man/ganeti-rapi.rst b/man/ganeti-rapi.rst
index 3cded7b..2111f82 100644
--- a/man/ganeti-rapi.rst
+++ b/man/ganeti-rapi.rst
@@ -10,7 +10,7 @@ Synopsis
--------
| **ganeti-rapi** [-d] [-f] [-p *PORT*] [-b *ADDRESS*] [-i *INTERFACE*]
-| [\--no-ssl] [-K *SSL_KEY_FILE*] [-C *SSL_CERT_FILE*]
+| [\--max-clients] [\--no-ssl] [-K *SSL_KEY_FILE*] [-C *SSL_CERT_FILE*]
| [\--require-authentication]
DESCRIPTION
@@ -34,6 +34,11 @@ it will not be able to reach the RAPI interface and will
attempt to
restart it all the time. Alternatively to setting the IP with ``--b``,
the ``-i`` option can be used to specify the interface to bind do.
+The maximum number of simultaneous client connections may be configured
+with the ``--max-clients`` option. This defaults to 20. Connections
+above this count are accepted, but no responses are sent until enough
+connections are closed.
+
See the *Ganeti remote API* documentation for further information.
Requests are logged to ``@LOCALSTATEDIR@/log/ganeti/rapi-daemon.log``,
--
2.8.0.rc3.226.g39d4020