[plague] Some fixes for systemd compatibility, e.g. patch daemonize.py double-fork to let parent die only aft

Michael Schwendt mschwendt at fedoraproject.org
Tue Nov 8 23:57:52 UTC 2011


commit b2cf34e0eca1faae1579f65543019efd91d5b0b7
Author: Michael Schwendt <mschwendt at fedoraproject.org>
Date:   Wed Nov 9 00:57:44 2011 +0100

    Some fixes for systemd compatibility, e.g. patch daemonize.py double-fork
    to let parent die only after second child has written PID file.
    Add systemd unit files and related package scriptlets.

 plague-0.4.5.8-systemd-compat.patch |  126 +++++++++++++++++++++++++++++++++++
 plague-builder.service              |   11 +++
 plague-server.service               |   11 +++
 plague.spec                         |   88 +++++++++++++++++++++---
 4 files changed, 225 insertions(+), 11 deletions(-)
---
diff --git a/plague-0.4.5.8-systemd-compat.patch b/plague-0.4.5.8-systemd-compat.patch
new file mode 100644
index 0000000..08555bf
--- /dev/null
+++ b/plague-0.4.5.8-systemd-compat.patch
@@ -0,0 +1,126 @@
+diff -Nur plague-0.4.5.8-orig/builder/builder.py plague-0.4.5.8/builder/builder.py
+--- plague-0.4.5.8-orig/builder/builder.py	2010-05-05 12:45:20.000000000 +0200
++++ plague-0.4.5.8/builder/builder.py	2011-11-09 00:45:33.011902281 +0100
+@@ -838,18 +838,15 @@
+         log("No useable mock buildroots configured.  Exiting...\n")
+         sys.exit(1)
+ 
++    if opts.pidfile and os.path.exists(opts.pidfile):
++        os.unlink(opts.pidfile)
++
+     if opts.daemon:
+-        ret=daemonize.createDaemon()
++        ret=daemonize.createDaemon(opts.pidfile)
+         if ret:
+             log("Daemonizing failed!\n")
+             sys.exit(2)
+ 
+-    if opts.pidfile:
+-        f = open(opts.pidfile, 'w', 1)
+-        f.write('%d\n' % os.getpid())
+-        f.flush()
+-        f.close()
+-
+     if opts.logfile:
+         logf=open(opts.logfile, 'a')
+         sys.stdout=logf
+@@ -921,7 +918,7 @@
+             break
+     log(" done.\n");
+     sys.stdout.flush()
+-    time.sleep(2)
++
+     os._exit(0)
+ 
+ 
+diff -Nur plague-0.4.5.8-orig/common/daemonize.py plague-0.4.5.8/common/daemonize.py
+--- plague-0.4.5.8-orig/common/daemonize.py	2008-01-31 14:48:41.000000000 +0100
++++ plague-0.4.5.8/common/daemonize.py	2011-11-09 00:46:31.708713648 +0100
+@@ -22,12 +22,22 @@
+ import os               # Miscellaneous OS interfaces.
+ import sys              # System-specific parameters and functions.
+ import signal           # Set handlers for asynchronous events.
++import time
+ 
+-def createDaemon():
++parentcanexit = False
++
++def grandparenthandler(signum, frame):
++   if signum == signal.SIGUSR1:
++      global parentcanexit
++      parentcanexit = True
++   
++def createDaemon(pidfile):
+    """Detach a process from the controlling terminal and run it in the
+    background as a daemon.
+    """
+ 
++   signal.signal(signal.SIGUSR1, grandparenthandler)
++
+    try:
+       # Fork a child process so the parent can exit.  This will return control
+       # to the command line or shell.  This is required so that the new process
+@@ -41,6 +51,8 @@
+ 
+    if (pid == 0):       # The first child.
+ 
++      ppid = os.getppid()
++
+       # Next we call os.setsid() to become the session leader of this new
+       # session.  The process also becomes the process group leader of the
+       # new process group.  Since a controlling terminal is associated with a
+@@ -70,9 +82,20 @@
+          os.chdir("/")
+          # Give the child complete control over permissions.
+          os.umask(0002)
++
++         if pidfile:
++            f = open(pidfile, 'w', 1)
++            f.write('%d\n' % os.getpid())
++            f.flush()
++            f.close()
++
++         os.kill(ppid,signal.SIGUSR1)
+       else:
+          os._exit(0)      # Exit parent (the first child) of the second child.
+    else:
++      global parentcanexit
++      while not parentcanexit:
++         time.sleep(0.01)
+       os._exit(0)         # Exit parent of the first child.
+ 
+    # Close all open files.  Try the system configuration variable, SC_OPEN_MAX,
+diff -Nur plague-0.4.5.8-orig/server/main.py plague-0.4.5.8/server/main.py
+--- plague-0.4.5.8-orig/server/main.py	2008-01-31 14:28:05.000000000 +0100
++++ plague-0.4.5.8/server/main.py	2011-11-09 00:46:24.729092809 +0100
+@@ -87,15 +87,15 @@
+         print "Must specify a config file."
+         sys.exit(1)
+ 
++    if opts.pidfile and os.path.exists(opts.pidfile):
++        os.unlink(opts.pidfile)
++
+     if opts.daemon:
+-        ret=daemonize.createDaemon()
++        ret=daemonize.createDaemon(opts.pidfile)
+         if ret:
+             print "Daemonizing failed!"
+             sys.exit(2)
+ 
+-    if opts.pidfile:
+-        open(opts.pidfile, 'w').write('%d\n' % os.getpid())
+-
+     if opts.logfile:
+         # 1 == line buffer the log file
+         log=open(opts.logfile, 'a', 1)
+@@ -186,10 +186,6 @@
+     if use_tbs:
+         tbs.stop()
+ 
+-    if opts.pidfile:
+-        os.unlink(opts.pidfile)
+-
+-    time.sleep(2)
+     print "Done."
+     os._exit(0)
+ 
diff --git a/plague-builder.service b/plague-builder.service
new file mode 100644
index 0000000..6a766bb
--- /dev/null
+++ b/plague-builder.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Plague builder daemon for build-system slave machines
+After=syslog.target network.target
+
+[Service]
+Type=forking
+EnvironmentFile=/etc/sysconfig/plague-builder
+ExecStart=/usr/bin/plague-builder -d -c ${CONFIG} -p ${PIDFILE} $OPTIONS
+
+[Install]
+WantedBy=multiuser.target
diff --git a/plague-server.service b/plague-server.service
new file mode 100644
index 0000000..9aafd07
--- /dev/null
+++ b/plague-server.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Plague server daemon for build-system master machines
+After=syslog.target network.target
+
+[Service]
+Type=forking
+EnvironmentFile=/etc/sysconfig/plague-server
+ExecStart=/usr/bin/plague-server -d -c ${CONFIG} -p ${PIDFILE} $OPTIONS
+
+[Install]
+WantedBy=multiuser.target
diff --git a/plague.spec b/plague.spec
index 0184090..bd40319 100644
--- a/plague.spec
+++ b/plague.spec
@@ -3,14 +3,22 @@ BuildArch: noarch
 Summary: Distributed build system for RPMs
 Name: plague
 Version: 0.4.5.8
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: GPLv2+
 Group: Development/Tools
 #Source: http://fedoraproject.org/projects/plague/releases/%{name}-%{version}.tar.bz2
 Source: http://mschwendt.fedorapeople.org/plague/%{name}-%{version}.tar.bz2
+Source1: plague-builder.service
+Source2: plague-server.service
 URL: http://www.fedoraproject.org/wiki/Projects/Plague
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+# some fixes for systemd compatibility - it doesn't like double-fork daemons,
+# where the parent process exits before the main PID is known
+Patch0: plague-0.4.5.8-systemd-compat.patch
+
 BuildRequires: python
+BuildRequires: systemd-units
 Requires: createrepo >= 0.4.7
 # get the version of the sqlite api thats available to us
 %if 0%{?rhel}
@@ -20,10 +28,13 @@ Requires: python-sqlite2
 %endif
 
 Requires: %{name}-common = %{version}-%{release}
-Requires(post): /sbin/chkconfig
-Requires(post): /sbin/service
-Requires(preun): /sbin/chkconfig
-Requires(preun): /sbin/service
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+# This is actually needed for the %triggerun script but Requires(triggerun)
+# is not valid.  We can use %post because this particular %triggerun script
+# should fire just after this package is installed.
+Requires(post): systemd-sysv
 
 
 %description
@@ -79,6 +90,7 @@ the interface to the build server.
 
 %prep
 %setup -q
+%patch0 -p1 -b .systemd-compat
 
 
 %build
@@ -88,6 +100,9 @@ make
 %install
 rm -rf $RPM_BUILD_ROOT
 make DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" install
+mkdir -p $RPM_BUILD_ROOT%{_unitdir}
+install -p -m 0644 %{SOURCE1} $RPM_BUILD_ROOT%{_unitdir}
+install -p -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_unitdir}
 chmod +x $RPM_BUILD_ROOT%{_bindir}/*
 install -p -D -m 0644 etc/plague-builder.config $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/%{name}-builder
 install -p -D -m 0755 etc/plague-builder.init $RPM_BUILD_ROOT%{_initrddir}/%{name}-builder
@@ -105,11 +120,33 @@ rm -rf $RPM_BUILD_ROOT
 /sbin/service plague-server condrestart >> /dev/null || :
 
 %preun
-if [ $1 = 0 ]; then
-  /sbin/service plague-server stop &> /dev/null
-  /sbin/chkconfig --del plague-server
+if [ $1 -eq 0 ] ; then
+    # Package removal, not upgrade
+    /bin/systemctl --no-reload disable plague-server.service > /dev/null 2>&1 || :
+    /bin/systemctl stop plague-server.service > /dev/null 2>&1 || :
+fi
+
+%postun
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ] ; then
+    # Package upgrade, not uninstall
+    /bin/systemctl try-restart plague-server.service >/dev/null 2>&1 || :
 fi
 
+%triggerun -- plague < 0.4.5.8-3
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply plague-server
+# to migrate them to systemd targets
+/usr/bin/systemd-sysv-convert --save plague-server >/dev/null 2>&1 ||:
+
+# If the package is allowed to autostart:
+/bin/systemctl --no-reload enable plague-server.service >/dev/null 2>&1 ||:
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del plague-server >/dev/null 2>&1 || :
+/bin/systemctl try-restart plague-server.service >/dev/null 2>&1 || :
+
+
 %pre builder
 /usr/sbin/useradd -G mock -s /sbin/nologin -M -r -d /var/lib/plague/builder plague-builder 2>/dev/null || :
 
@@ -118,11 +155,33 @@ fi
 /sbin/service plague-builder condrestart >> /dev/null || :
 
 %preun builder
-if [ $1 = 0 ]; then
-  /sbin/service plague-builder stop &> /dev/null
-  /sbin/chkconfig --del plague-builder
+if [ $1 -eq 0 ] ; then
+    # Package removal, not upgrade
+    /bin/systemctl --no-reload disable plague-builder.service > /dev/null 2>&1 || :
+    /bin/systemctl stop plague-builder.service > /dev/null 2>&1 || :
 fi
 
+%postun builder
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ] ; then
+    # Package upgrade, not uninstall
+    /bin/systemctl try-restart plague-builder.service >/dev/null 2>&1 || :
+fi
+
+%triggerun builder -- plague-builder < 0.4.5.8-3
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply plague-builder
+# to migrate them to systemd targets
+/usr/bin/systemd-sysv-convert --save plague-builder >/dev/null 2>&1 ||:
+
+# If the package is allowed to autostart:
+/bin/systemctl --no-reload enable plague-builder.service >/dev/null 2>&1 ||:
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del plague-builder >/dev/null 2>&1 || :
+/bin/systemctl try-restart plague-builder.service >/dev/null 2>&1 || :
+
+
 %files
 %defattr(-, root, root)
 %{_bindir}/%{name}-server
@@ -132,6 +191,7 @@ fi
 %dir %{_sysconfdir}/%{name}/server/certs
 %config(noreplace) %{_sysconfdir}/sysconfig/%{name}-server
 %{_initrddir}/%{name}-server
+%{_unitdir}/%{name}-server.service
 %doc www
 
 %files common
@@ -151,6 +211,7 @@ fi
 %dir %{_sysconfdir}/%{name}/builder/certs
 %config(noreplace) %{_sysconfdir}/sysconfig/%{name}-builder
 %{_initrddir}/%{name}-builder
+%{_unitdir}/%{name}-builder.service
 %dir /var/lib/plague
 %attr(0755, plague-builder, plague-builder) /var/lib/plague/builder
 
@@ -165,6 +226,11 @@ fi
 
 
 %changelog
+* Tue Nov  8 2011 Michael Schwendt <mschwendt at fedoraproject.org> - 0.4.5.8-3
+- Some fixes for systemd compatibility, e.g. patch daemonize.py double-fork
+  to let parent die only after second child has written PID file.
+- Add systemd unit files and related package scriptlets.
+
 * Wed Feb 09 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.4.5.8-2
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
 


More information about the scm-commits mailing list