From 82379423b587757cba69c8bd3f3b33b1828993ab Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 25 Mar 2014 12:53:04 +0200 Subject: [PATCH] add systemd integration Add --with-systemd / --without-systemd options to check whether libsystemd-daemon library is available and use it to report service startup status to systemd for smbd/winbindd/nmbd and AD DC. The problem it solves is correct reporting of the Samba services at the point when they are ready to serve clients, important for high availability software integration. Signed-off-by: Alexander Bokovoy --- lib/util/become_daemon.c | 11 +++++++++-- lib/util/samba_util.h | 6 +++++- lib/util/wscript_build | 2 +- packaging/systemd/nmb.service | 3 ++- packaging/systemd/smb.service | 3 ++- packaging/systemd/winbind.service | 3 ++- source3/nmbd/nmbd.c | 8 +++++++- source3/smbd/server.c | 9 ++++++++- source3/winbindd/winbindd.c | 9 ++++++++- source4/smbd/server.c | 8 +++++++- wscript | 18 +++++++++++++++--- 11 files changed, 66 insertions(+), 14 deletions(-) diff --git a/lib/util/become_daemon.c b/lib/util/become_daemon.c index 2ca0478..97b9c66 100644 --- a/lib/util/become_daemon.c +++ b/lib/util/become_daemon.c @@ -73,10 +73,17 @@ _PUBLIC_ void close_low_fds(bool stdin_too, bool stdout_too, bool stderr_too) Become a daemon, discarding the controlling terminal. ****************************************************************************/ -_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout) +_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout, bool wait_for_child_init) { + pid_t newpid; if (do_fork) { - if (fork()) { + newpid = fork(); + if (newpid) { +#if HAVE_SYSTEMD + if (wait_for_child_init) { + sd_notifyf(0, "READY=0\nSTATUS=Starting process...\nMAINPID=%lu", (unsigned long) newpid); + } +#endif /* HAVE_SYSTEMD */ _exit(0); } } diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h index f52347e..456c8fb 100644 --- a/lib/util/samba_util.h +++ b/lib/util/samba_util.h @@ -65,6 +65,10 @@ do { \ #include "lib/util/string_wrappers.h" +#if HAVE_SYSTEMD +#include +#endif + /** * Write backtrace to debug log */ @@ -839,7 +843,7 @@ _PUBLIC_ void close_low_fds(bool stdin_too, bool stdout_too, bool stderr_too); /** Become a daemon, discarding the controlling terminal. **/ -_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout); +_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout, bool wait_for_child_init); /** * @brief Get a password from the console. diff --git a/lib/util/wscript_build b/lib/util/wscript_build index 39a1613..5087116 100755 --- a/lib/util/wscript_build +++ b/lib/util/wscript_build @@ -10,7 +10,7 @@ bld.SAMBA_LIBRARY('samba-util', server_id.c dprintf.c parmlist.c bitmap.c pidfile.c tevent_debug.c util_process.c''', deps='DYNCONFIG', - public_deps='talloc tevent execinfo uid_wrapper pthread LIBCRYPTO charset util_setid', + public_deps='talloc tevent execinfo uid_wrapper pthread LIBCRYPTO charset util_setid systemd-daemon', public_headers='debug.h attr.h byteorder.h data_blob.h memory.h safe_string.h time.h talloc_stack.h xfile.h dlinklist.h samba_util.h string_wrappers.h', header_path= [ ('dlinklist.h samba_util.h', '.'), ('*', 'util') ], local_include=False, diff --git a/packaging/systemd/nmb.service b/packaging/systemd/nmb.service index e5e81a1..3d71a7d 100644 --- a/packaging/systemd/nmb.service +++ b/packaging/systemd/nmb.service @@ -3,7 +3,8 @@ Description=Samba NMB Daemon After=syslog.target network.target [Service] -Type=forking +Type=notify +NotifyAccess=all PIDFile=/run/nmbd.pid EnvironmentFile=-/etc/sysconfig/samba ExecStart=/usr/sbin/nmbd $NMBDOPTIONS diff --git a/packaging/systemd/smb.service b/packaging/systemd/smb.service index d0d945a..9810891 100644 --- a/packaging/systemd/smb.service +++ b/packaging/systemd/smb.service @@ -3,7 +3,8 @@ Description=Samba SMB Daemon After=syslog.target network.target nmb.service winbind.service [Service] -Type=forking +Type=notify +NotifyAccess=all PIDFile=/run/smbd.pid LimitNOFILE=16384 EnvironmentFile=-/etc/sysconfig/samba diff --git a/packaging/systemd/winbind.service b/packaging/systemd/winbind.service index eff266f..f711a17 100644 --- a/packaging/systemd/winbind.service +++ b/packaging/systemd/winbind.service @@ -3,7 +3,8 @@ Description=Samba Winbind Daemon After=syslog.target network.target nmb.service [Service] -Type=forking +Type=notify +NotifyAccess=all PIDFile=/run/winbindd.pid EnvironmentFile=-/etc/sysconfig/samba ExecStart=/usr/sbin/winbindd "$WINBINDOPTIONS" diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index addb416..2684654 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -949,7 +949,7 @@ static bool open_sockets(bool isdaemon, int port) if (is_daemon && !opt_interactive) { DEBUG( 2, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork, no_process_group, log_stdout); + become_daemon(Fork, no_process_group, log_stdout, true); } #if HAVE_SETPGID @@ -1093,6 +1093,12 @@ static bool open_sockets(bool isdaemon, int port) exit(1); } +#if HAVE_SYSTEMD + if (is_daemon && !opt_interactive) { + sd_notify(0, "READY=1\nSTATUS=Serving client connections..."); + } +#endif /* HAVE_SYSTEMD */ + TALLOC_FREE(frame); process(msg); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9d6a250..06e5b01 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1320,7 +1320,8 @@ extern void build_options(bool screen); if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork, no_process_group, log_stdout); + /* Make sure main process waits until we fully initialized */ + become_daemon(Fork, no_process_group, log_stdout, true); } set_my_unique_id(serverid_get_random_unique_id()); @@ -1522,6 +1523,12 @@ extern void build_options(bool screen); exit(1); } +#if HAVE_SYSTEMD + if (is_daemon && !interactive) { + sd_notify(0, "READY=1\nSTATUS=Serving client connections..."); + } +#endif /* HAVE_SYSTEMD */ + /* only start other daemons if we are running as a daemon * -- bad things will happen if smbd is launched via inetd * and we fork a copy of ourselves here */ diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index cfb2f06..550ffeb 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1527,7 +1527,7 @@ int main(int argc, char **argv, char **envp) BlockSignals(False, SIGCHLD); if (!interactive) - become_daemon(Fork, no_process_group, log_stdout); + become_daemon(Fork, no_process_group, log_stdout, True); pidfile_create(lp_pid_directory(), "winbindd"); @@ -1589,6 +1589,13 @@ int main(int argc, char **argv, char **envp) } TALLOC_FREE(frame); + +#ifdef HAVE_SYSTEMD + if (!interactive) { + sd_notify(0, "READY=1\nSTATUS=Serving client connections..."); + } +#endif /* HAVE_SYSTEMD */ + /* Loop waiting for requests */ while (1) { frame = talloc_stackframe(); diff --git a/source4/smbd/server.c b/source4/smbd/server.c index 26fd89a..42aed13 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -379,7 +379,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ if (opt_daemon) { DEBUG(3,("Becoming a daemon.\n")); - become_daemon(true, false, false); + become_daemon(true, false, false, true); } cleanup_tmp_files(cmdline_lp_ctx); @@ -498,6 +498,12 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ return 1; } +#if HAVE_SYSTEMD + if (opt_daemon) { + sd_notify(0, "READY=1\nSTATUS=Serving client connections..."); + } +#endif /* HAVE_SYSTEMD */ + /* wait for events - this is where smbd sits for most of its life */ tevent_loop_wait(event_ctx); diff --git a/wscript b/wscript index 5007834..82c313f 100644 --- a/wscript +++ b/wscript @@ -72,8 +72,15 @@ def set_options(opt): help=("Disable RELRO builds"), action="store_false", dest='enable_relro') - gr = opt.option_group('developer options') + opt.add_option('--with-systemd', + help=("Enable systemd integration"), + action='store_true', dest='enable_systemd') + + opt.add_option('--without-systemd', + help=("Disable systemd integration"), + action='store_false', dest='enable_systemd') + gr = opt.option_group('developer options') opt.tool_options('python') # options for disabling pyc or pyo compilation # enable options related to building python extensions @@ -172,8 +179,6 @@ def configure(conf): addmain=False, msg='Checking configure summary'): raise Utils.WafError('configure summary failed') - - conf.SAMBA_CONFIG_H('include/config.h') if Options.options.enable_pie != False: if Options.options.enable_pie == True: @@ -195,6 +200,13 @@ def configure(conf): msg="Checking compiler for full RELRO support"): conf.env['ENABLE_RELRO'] = True + if Options.options.enable_systemd != False: + conf.PROCESS_SEPARATE_RULE('systemd') + else: + conf.SET_TARGET_TYPE('systemd-daemon', 'EMPTY') + + conf.SAMBA_CONFIG_H('include/config.h') + def etags(ctx): '''build TAGS file using etags''' import Utils -- 1.8.5.3