Currently, GenericMain does a two-staged workflow:
- Check, before forking
- then Exec, after forking
This means we don't have any possibility to treat preparation work
(before the daemon is ready for work) different from the actual work.
The patch adds another PreExec function that is run just before Exec,
and which should ensure that the daemon is ready for serving client
before it returns. Its result is then sent as the third argument to
Exec.
---
daemons/ganeti-confd | 4 ++--
daemons/ganeti-masterd | 6 +++---
daemons/ganeti-noded | 4 ++--
daemons/ganeti-rapi | 6 +++---
lib/daemon.py | 16 +++++++++++++---
5 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/daemons/ganeti-confd b/daemons/ganeti-confd
index 9911543..45d3cdb 100755
--- a/daemons/ganeti-confd
+++ b/daemons/ganeti-confd
@@ -258,7 +258,7 @@ def CheckConfd(_, args):
# conflict with that. If so, we might warn or EXIT_FAILURE.
-def ExecConfd(options, _):
+def ExecConfd(options, _dummy1, _dummy2):
"""Main confd function, executed with PID file held
"""
@@ -293,7 +293,7 @@ def main():
version="%%prog (ganeti) %s" %
constants.RELEASE_VERSION)
- daemon.GenericMain(constants.CONFD, parser, CheckConfd, ExecConfd)
+ daemon.GenericMain(constants.CONFD, parser, CheckConfd, None, ExecConfd)
if __name__ == "__main__":
diff --git a/daemons/ganeti-masterd b/daemons/ganeti-masterd
index 8c32504..2e571b9 100755
--- a/daemons/ganeti-masterd
+++ b/daemons/ganeti-masterd
@@ -530,7 +530,7 @@ def CheckMasterd(options, args):
utils.RunInSeparateProcess(ActivateMasterIP)
-def ExecMasterd(options, args): # pylint: disable-msg=W0613
+def ExecMasterd(options, args, _): # pylint: disable-msg=W0613
"""Main master daemon function, executed with the PID file held.
"""
@@ -568,8 +568,8 @@ def main():
parser.add_option("--yes-do-it", dest="yes_do_it",
help="Override interactive check for --no-voting",
default=False, action="store_true")
- daemon.GenericMain(constants.MASTERD, parser, CheckMasterd, ExecMasterd,
- multithreaded=True)
+ daemon.GenericMain(constants.MASTERD, parser, CheckMasterd, None,
+ ExecMasterd, multithreaded=True)
if __name__ == "__main__":
diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded
index c54b8f6..819bad7 100755
--- a/daemons/ganeti-noded
+++ b/daemons/ganeti-noded
@@ -914,7 +914,7 @@ def CheckNoded(_, args):
sys.exit(constants.EXIT_FAILURE)
-def ExecNoded(options, _):
+def ExecNoded(options, _dummy1, _dummy2):
"""Main node daemon function, executed with the PID file held.
"""
@@ -965,7 +965,7 @@ def main():
help="Do not mlock the node memory in ram",
default=True, action="store_false")
- daemon.GenericMain(constants.NODED, parser, CheckNoded, ExecNoded,
+ daemon.GenericMain(constants.NODED, parser, CheckNoded, None, ExecNoded,
default_ssl_cert=constants.NODED_CERT_FILE,
default_ssl_key=constants.NODED_CERT_FILE,
console_logging=True)
diff --git a/daemons/ganeti-rapi b/daemons/ganeti-rapi
index 09ad68a..f861a0b 100755
--- a/daemons/ganeti-rapi
+++ b/daemons/ganeti-rapi
@@ -1,7 +1,7 @@
#!/usr/bin/python
#
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -280,7 +280,7 @@ def CheckRapi(options, args):
options.ssl_params = None
-def ExecRapi(options, _):
+def ExecRapi(options, _dummy1, _dummy2):
"""Main remote API function, executed with the PID file held.
"""
@@ -315,7 +315,7 @@ def main():
usage="%prog [-f] [-d] [-p port] [-b ADDRESS]",
version="%%prog (ganeti) %s" % constants.RELEASE_VERSION)
- daemon.GenericMain(constants.RAPI, parser, CheckRapi, ExecRapi,
+ daemon.GenericMain(constants.RAPI, parser, CheckRapi, None, ExecRapi,
default_ssl_cert=constants.RAPI_CERT_FILE,
default_ssl_key=constants.RAPI_CERT_FILE)
diff --git a/lib/daemon.py b/lib/daemon.py
index e765614..eceeac4 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -512,7 +512,8 @@ def _VerifyDaemonUser(daemon_name):
daemon_uids[daemon_name])
-def GenericMain(daemon_name, optionparser, check_fn, exec_fn,
+def GenericMain(daemon_name, optionparser,
+ check_fn, prepare_fn, exec_fn,
multithreaded=False, console_logging=False,
default_ssl_cert=None, default_ssl_key=None):
"""Shared main function for daemons.
@@ -525,7 +526,11 @@ def GenericMain(daemon_name, optionparser, check_fn,
exec_fn,
@type check_fn: function which accepts (options, args)
@param check_fn: function that checks start conditions and exits if they're
not met
- @type exec_fn: function which accepts (options, args)
+ @type prepare_fn: function which accepts (options, args)
+ @param prepare_fn: function that is run before forking, or None;
+ it's result will be passed as the third parameter to exec_fn, or
+ if None was passed in, we will just pass None to exec_fn
+ @type exec_fn: function which accepts (options, args, prepare_results)
@param exec_fn: function that's executed with the daemon's pid file held, and
runs the daemon itself.
@type multithreaded: bool
@@ -631,6 +636,11 @@ def GenericMain(daemon_name, optionparser, check_fn,
exec_fn,
syslog=options.syslog,
console_logging=console_logging)
logging.info("%s daemon startup", daemon_name)
- exec_fn(options, args)
+ if callable(prepare_fn):
+ prep_results = prepare_fn(options, args)
+ else:
+ prep_results = None
+
+ exec_fn(options, args, prep_results)
finally:
utils.RemovePidFile(daemon_name)
--
1.7.1