add systemd integration
authorAlexander Bokovoy <ab@samba.org>
Tue, 25 Mar 2014 10:53:04 +0000 (12:53 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 23 Apr 2014 00:29:08 +0000 (02:29 +0200)
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.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10517

Signed-off-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
12 files changed:
lib/util/become_daemon.c
lib/util/samba_util.h
lib/util/wscript_build
packaging/systemd/nmb.service
packaging/systemd/samba.service
packaging/systemd/smb.service
packaging/systemd/winbind.service
source3/nmbd/nmbd.c
source3/smbd/server.c
source3/winbindd/winbindd.c
source4/smbd/server.c
wscript

index 2ca047861f18321c4e173d901ace0e56dcb943fb..35c8b3252bee7ced966663444675504dcf365b60 100644 (file)
@@ -24,6 +24,9 @@
 #include "includes.h"
 #include "system/filesys.h"
 #include "system/locale.h"
+#if HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
 
 /*******************************************************************
  Close the low 3 fd's and open dev/null in their place.
@@ -75,8 +78,13 @@ _PUBLIC_ void close_low_fds(bool stdin_too, bool stdout_too, bool stderr_too)
 
 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout)
 {
+       pid_t newpid;
        if (do_fork) {
-               if (fork()) {
+               newpid = fork();
+               if (newpid) {
+#if HAVE_SYSTEMD
+                       sd_notifyf(0, "READY=0\nSTATUS=Starting process...\nMAINPID=%lu", (unsigned long) newpid);
+#endif /* HAVE_SYSTEMD */
                        _exit(0);
                }
        }
@@ -100,3 +108,30 @@ _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout
         * never close stderr (but debug might dup it onto a log file) */
        close_low_fds(do_fork, !log_stdout, false);
 }
+
+_PUBLIC_ void exit_daemon(const char *msg, int error)
+{
+#ifdef HAVE_SYSTEMD
+       if (msg == NULL) {
+               msg = strerror(error);
+       }
+
+       sd_notifyf(0, "STATUS=daemon failed to start: %s\n"
+                                 "ERRNO=%i",
+                                 msg,
+                                 error);
+#endif
+       DEBUG(0, ("STATUS=daemon failed to start: %s, error code %d\n", msg, error));
+       exit(1);
+}
+
+_PUBLIC_ void daemon_ready(const char *daemon)
+{
+       if (daemon == NULL) {
+               daemon = "Samba";
+       }
+#ifdef HAVE_SYSTEMD
+       sd_notifyf(0, "READY=1\nSTATUS=%s: ready to serve connections...", daemon);
+#endif
+       DEBUG(0, ("STATUS=daemon '%s' finished starting up and ready to serve connections", daemon));
+}
index dcb92eed461ff9e20b21d0ce7fc81d056fcb35b8..e3fe6a6079229053fed063d7c84c88be430b551b 100644 (file)
@@ -841,6 +841,18 @@ _PUBLIC_ void close_low_fds(bool stdin_too, bool stdout_too, bool stderr_too);
 **/
 _PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout);
 
+/**
+ Exit daemon and print error message to the log at level 0
+ Optionally report failure to systemd if systemd integration is enabled
+**/
+_PUBLIC_ void exit_daemon(const char *msg, int error);
+
+/**
+ Report that the daemon is ready to serve connections to the log at level 0
+ Optionally report status to systemd if systemd integration is enabled
+**/
+_PUBLIC_ void daemon_ready(const char *daemon);
+
 /**
  * @brief Get a password from the console.
  *
index a45dbde9a2007396fc7b5c10de5a78c1989b87fb..fe2c18339238d24a6e1f81123df527718b29f701 100755 (executable)
@@ -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 pthread LIBCRYPTO charset util_setid',
+                  public_deps='talloc tevent execinfo 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,
index e5e81a1fc743076d6ff874be9aef3bf7a929fd82..3d71a7dacd2d5a3bc302230a33bef8d3725fbc08 100644 (file)
@@ -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
index e2878d1a5e13fc10adc975cad761ed1c7a08c82a..824f89c203036a743ef1a4c59174187d934c450d 100644 (file)
@@ -3,7 +3,8 @@ Description=Samba AD Daemon
 After=syslog.target network.target
 
 [Service]
-Type=forking
+Type=notify
+NotifyAccess=all
 PIDFile=/run/samba.pid
 LimitNOFILE=16384
 EnvironmentFile=-/etc/sysconfig/samba
index d0d945aae791f6bd94b88c5563b5404eb4cc48fc..9810891e8c2ff240c73de245ba819e44741dd563 100644 (file)
@@ -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
index eff266f0d837ac8afb15b00eafbfe91fd9622460..f711a17f040e86ace395402e12860f7ccb395aaf 100644 (file)
@@ -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"
index 80c2329b2de0d641b2c4859f303a65c10548ba57..c75f3b1063b198efdeed6787f54881c96756106f 100644 (file)
@@ -1097,6 +1097,10 @@ static bool open_sockets(bool isdaemon, int port)
                 exit(1);
         }
 
+       if (is_daemon && !opt_interactive) {
+               daemon_ready("nmbd");
+       }
+
        TALLOC_FREE(frame);
        process(msg);
 
index bc9d293b494aa28dbfa6ee4c99d9dad3fdfbc221..5955c2956d548677e189ac9e4bd1df35bbb0bc0a 100644 (file)
@@ -1531,6 +1531,10 @@ extern void build_options(bool screen);
                exit(1);
        }
 
+       if (is_daemon && !interactive) {
+               daemon_ready("smbd");
+       }
+
        /* 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 */
index 8bc13431e8f507359852f5c69d0033edb8436805..9694c6374f109031c5d9580f754c9f4a2f538ea8 100644 (file)
@@ -1589,6 +1589,11 @@ int main(int argc, const char **argv)
        }
 
        TALLOC_FREE(frame);
+
+       if (!interactive) {
+               daemon_ready("winbindd");
+       }
+
        /* Loop waiting for requests */
        while (1) {
                frame = talloc_stackframe();
index 26fd89a10d75ccf914ab3cc5d196c9677e19c3b7..9051b485317cd0ec3dbad1ba3eb6788026006b66 100644 (file)
@@ -498,6 +498,10 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
                return 1;
        }
 
+       if (opt_daemon) {
+               daemon_ready("samba");
+       }
+
        /* 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 ae4ff50b6d194f74adf50b83f1a3090a59fedd17..87541da62ceea8ab2177995aac6f8eaea992f2f2 100644 (file)
--- a/wscript
+++ b/wscript
@@ -69,8 +69,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
@@ -169,8 +176,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:
@@ -192,6 +197,21 @@ def configure(conf):
                          msg="Checking compiler for full RELRO support"):
             conf.env['ENABLE_RELRO'] = True
 
+    if Options.options.enable_systemd != False:
+        conf.check_cfg(package='libsystemd-daemon', args='--cflags --libs',
+                       msg='Checking for libsystemd-daemon', uselib_store="SYSTEMD-DAEMON")
+        conf.CHECK_HEADERS('systemd/sd-daemon.h', lib='systemd-daemon')
+        conf.CHECK_LIB('systemd-daemon', shlib=True)
+
+    if conf.CONFIG_SET('HAVE_SYSTEMD_SD_DAEMON_H'):
+        conf.DEFINE('HAVE_SYSTEMD', '1')
+        conf.env['ENABLE_SYSTEMD'] = True
+    else:
+        conf.SET_TARGET_TYPE('systemd-daemon', 'EMPTY')
+        conf.undefine('HAVE_SYSTEMD')
+
+    conf.SAMBA_CONFIG_H('include/config.h')
+
 def etags(ctx):
     '''build TAGS file using etags'''
     import Utils