From afcdbdd1923d148f947c53984c42102fd9188207 Mon Sep 17 00:00:00 2001
From: Laine Stump <laine@laine.org>
Date: Fri, 17 Jan 2014 11:58:46 +0200
Subject: [PATCH] support systemd-based netcf-transaction
https://bugzilla.redhat.com/show_bug.cgi?id=1044681
The netcf-transaction script is used in two ways:
1) It is called by libnetcf.so to begin, commit, and manually rollback
a set of network interface config changes.
2) It is called as part of normal system startup to automatically
rollback any config changes that are part of a netcf transaction that
hasn't yet been committed. (in other words, if you reboot after
calling ncf_change_begin() but before calling ncf_change_commit(), all
the changes you made subsequent to ncf_change_begin() will be erased).
This functionality is only supported for the "redhat" driver (used by
Fedora, CentOS, and RHEL), and up until now, it was all self-contained
in an initscripts-style shell script installed to
/etc/init.d/netcf-transaction - libnetcf.so would exec this script,
and it was also conveniently placed for initscripts to run it at
startup.
Some time ago, Fedora started supporting systemd for system
init/daemon management, but is still maintaining legacy support for
initscripts for packages that haven't yet moved over to systemd. RHEL7
also will support systemd.
This patch updates netcf to allow building packages either with an
initscripts-style script for /etc/init.d or a systemd-style init file
for /lib/systemd/system. The selection of which to include in the
build can either be made manually at configure-time (using the
--with-sysinit=(initscripts|systemd) option) or, if not explicitly
given on the configure commandline, configure.ac attempts to
automatically determine which style to use based on the existence of
the directory "/etc/systemd". Additionally, netcf.spec decides which
type of sysinit to build for based on the Fedora/RHEL version, so that
anyone building a netcf rpm on Fedora < 20 will continue to get
initscripts files rather than switching midstream to systemd.
The core functionality that was previously in
/etc/init.d/netcf-transaction has been moved to the file
/usr/libexec/netcf-transaction.sh, which is referenced both by the
initscripts init file (/etc/init.d/netcf-transaction) and by the
systemd service file (/lib/systemd/system/netcf-transaction.service):
src/netcf-transaction.init.in (new initscripts file)
src/netcf-transaction.service.in (systemd service file)
src/netcf-transaction.sh.in (this was previously the initscripts file)
netcf.spec.in:
* add check to decide systemd vs. initscripts based on
RHEL/Fedora version and set configure commandline accordingly;
* update %post and %postun to do the right thing for systems, and add
a new %preun section for the same reason. Unlike libvirt, we know
that any version of netcf chosen to use systemd by this specfile
will already have the systemd rpm macros available, so we don't
need the extra check for that which is present in the libvirt
specfile. (this patch was written by heavily referencing the
libvirt bits responsible for setting up the "libvirt-guests"
service in libvirt).
src/Makefile.am:
* generate the three new files when appropriate
* change install-data-local and uninstall-local targets as appropriate
for systemd vs initscripts vs none.
configure.ac:
* support new --with-sysinit arg to manually specify
systemd/initscripts/none.
* autodetect which to use based on setting of $with_driver and
presence of /etd/systemd directory.
NB: the location of the netcf-transaction script, which src/drv_*.c
find via the NETCF_TRANSACTION #define is currently hardcoded to look
in /usr/libexec. Ideally, this should use $libexecdir, but that
resolves to "${exec_prefix}/libexec" at configure time. To get the
desired results, we need to update gnulib and use gnulib's configmake
package, this way we'll end up with a NETCF_TRANSACTION that will be
set at the time make is run rather than configure. This is left as a
separate patch though, so that the initial support for systemd can be
backported to older releases of netcf (a gnulib update shouldn't be
backported to the maintenance branch of an already-cut release).
(cherry picked from commit 2ca7857cc5ececf12288f4bcda586befdb16378c)
Conflicts: had to remove changes to .gitignore, since it isn't present
in the release tarball.
---
configure.ac | 57 ++++++++++++--
netcf.spec.in | 60 ++++++++++++++-
src/Makefile.am | 86 ++++++++++++++++------
src/netcf-transaction.init.in | 31 ++++++++
src/netcf-transaction.service.in | 15 ++++
...transaction.init.sh => netcf-transaction.sh.in} | 34 +++++----
6 files changed, 236 insertions(+), 47 deletions(-)
create mode 100644 src/netcf-transaction.init.in
create mode 100644 src/netcf-transaction.service.in
rename src/{netcf-transaction.init.sh => netcf-transaction.sh.in} (88%)
mode change 100755 => 100644
diff --git a/configure.ac b/configure.ac
index 3f30865..4dc415f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,14 +50,14 @@ if test "$prefix" = "/usr" && test "$sysconfdir" = '${prefix}/etc' ; then
fi
dnl
-dnl init script flavor
+dnl network driver flavor
dnl
AC_ARG_WITH([driver],
[AS_HELP_STRING([--with-driver],
- [Network driver name])],
+ [network driver name])],
[],[with_driver=check])
-AC_MSG_CHECKING([Network driver name])
+AC_MSG_CHECKING([network driver name])
if test "x$with_driver" = "xcheck" ; then
case "$host" in
*-*-mingw*)
@@ -93,12 +93,57 @@ AM_CONDITIONAL([NETCF_DRIVER_SUSE], test "x$with_driver" = "xsuse")
AM_CONDITIONAL([NETCF_DRIVER_MSWINDOWS], test "x$with_driver" = "xmswindows")
if test "x$with_driver" = "xredhat"; then
+ # FIXME: This should be defined relative to $libexecdir,
+ # but that requires gnulib configmake to do correctly.
AC_DEFINE_UNQUOTED([NETCF_TRANSACTION],
- ["$sysconfdir/rc.d/init.d/netcf-transaction"],
+ ["/usr/libexec/netcf-transaction.sh"],
[Location of the netcf-transaction shell script])
fi
-AM_CONDITIONAL([NETCF_INIT_SCRIPT_RED_HAT],
- [test x$with_driver = xredhat])
+
+dnl
+dnl system init flavor
+dnl
+AC_MSG_CHECKING([for system init flavor])
+AC_ARG_WITH([sysinit],
+ [AS_HELP_STRING([--with-sysinit@<:@=STYLE@:>@],
+ [Style of init script to install: initscripts, systemd,
+ check, none @<:@default=check@:>@])],
+ [],[with_sysinit=check])
+
+case "$with_sysinit" in
+ systemd)
+ ;;
+ initscripts)
+ ;;
+ none)
+ ;;
+ check)
+ if test "$cross_compiling" != "yes" && \
+ test "$with_driver" = "redhat"; then
+ if test -d /etc/systemd; then
+ with_sysinit=systemd
+ else
+ with_sysinit=initscripts
+ fi
+ else
+ with_sysinit=none
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown system initscript flavor $with_sysinit])
+ ;;
+esac
+if test "x$with_sysinit" = "xcheck" ; then
+ with_sysinit=none
+fi
+
+AM_CONDITIONAL([NETCF_USE_INITSCRIPTS], test "$with_sysinit" = "initscripts")
+AM_CONDITIONAL([NETCF_USE_SYSTEMD], test "$with_sysinit" = "systemd")
+AM_CONDITIONAL([NETCF_TRANSACTION_SUPPORT], "$with_sysinit" != "none")
+AC_MSG_RESULT($with_sysinit)
+if test "$with_sysinit" != "none" && test "$with_driver" != "redhat"; then
+ AC_MSG_ERROR([netcf does not have support for $with_sysinit combined with the $with_driver driver])
+fi
AC_ARG_WITH([libnl1],
AS_HELP_STRING([--with-libnl1], [Force usage of libnl1 @<:@default=no@:>@]),
diff --git a/netcf.spec.in b/netcf.spec.in
index d243f1c..6ab3ee5 100644
--- a/netcf.spec.in
+++ b/netcf.spec.in
@@ -9,6 +9,22 @@ URL: https://fedorahosted.org/netcf/
Source0: https://fedorahosted.org/released/%{name}/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+# Fedora 20 / RHEL-7 are where netcf first uses systemd. Although earlier
+# Fedora has systemd, netcf still used sysvinit there.
+%if 0%{?fedora} >= 20 || 0%{?rhel} >= 7
+ %define with_systemd 1
+%else
+ %define with_systemd 0
+%endif
+
+%if %{with_systemd}
+BuildRequires: systemd-units
+Requires(post): systemd-units
+Requires(post): systemd-sysv
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+%endif
+
BuildRequires: readline-devel augeas-devel >= 0.5.2
BuildRequires: libxml2-devel libxslt-devel
@@ -60,22 +76,53 @@ The libraries for %{name}.
%if %{with_libnl1}
%define _with_libnl1 --with-libnl1
%endif
+%if %{with_systemd}
+ %define sysinit --with-sysinit=systemd
+%else
+ %define sysinit --with-sysinit=initscripts
+%endif
+
%configure --disable-static \
- %{?_with_libnl1}
+ %{?_with_libnl1} \
+ %{sysinit}
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
-make install DESTDIR=$RPM_BUILD_ROOT INSTALL="%{__install} -p"
+make install DESTDIR=$RPM_BUILD_ROOT SYSTEMD_UNIT_DIR=%{_unitdir} \
+ INSTALL="%{__install} -p"
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
%clean
rm -rf $RPM_BUILD_ROOT
-%post libs -p /sbin/ldconfig
+%preun libs
-%postun libs -p /sbin/ldconfig
+%if %{with_systemd}
+ %systemd_preun netcf-transaction.service
+%else
+if [ $1 = 0 ]; then
+ /sbin/chkconfig --del netcf-transaction
+fi
+%endif
+
+%post libs
+
+/sbin/ldconfig
+%if %{with_systemd}
+ %systemd_post netcf-transaction.service
+ /bin/systemctl --no-reload enable netcf-transaction.service >/dev/null 2>&1 || :
+%else
+/sbin/chkconfig --add netcf-transaction
+%endif
+
+%postun libs
+
+/sbin/ldconfig
+%if %{with_systemd}
+ %systemd_postun netcf-transaction.service
+%endif
%files
%defattr(-,root,root,-)
@@ -86,7 +133,12 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-)
%{_datadir}/netcf
%{_libdir}/*.so.*
+%if %{with_systemd}
+%{_unitdir}/netcf-transaction.service
+%else
%{_sysconfdir}/rc.d/init.d/netcf-transaction
+%endif
+%attr(0755, root, root) %{_libexecdir}/netcf-transaction.sh
%doc AUTHORS COPYING NEWS
%files devel
diff --git a/src/Makefile.am b/src/Makefile.am
index 9963402..2f76614 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,7 +16,9 @@ include_HEADERS = netcf.h
lib_LTLIBRARIES = libnetcf.la
bin_PROGRAMS = ncftool
-
+if NETCF_TRANSACTION_SUPPORT
+libexec_SCRIPTS = netcf-transaction.sh
+endif
if ! NETCF_DRIVER_MSWINDOWS
noinst_PROGRAMS = ncftransform
endif
@@ -31,7 +33,6 @@ DRIVER_SOURCES_SUSE = drv_suse.c
EXTRA_DIST = netcf_public.syms \
netcf_private.syms \
- netcf-transaction.init.sh \
$(DRIVER_SOURCES_COMMON) \
$(DRIVER_SOURCES_POSIX) \
$(DRIVER_SOURCES_LINUX) \
@@ -112,35 +113,78 @@ internal.h: datadir.h
datadir.h: $(top_builddir)/config.status
echo '#define NETCF_DATADIR "$(datadir)"' > datadir.h
-install-data-local: install-init
+EXTRA_DIST += netcf-transaction.sh.in \
+ netcf-transaction.init.in \
+ netcf-transaction.service.in
+
+if NETCF_DRIVER_REDHAT
+
+install-data-local: install-sysinit
+
+uninstall-local: uninstall-sysinit
+
+# This is for the shell script that handles network config change
+# transactions. It is used by both the initscripts and systemd
+# flavors, as well as by libnetcf.so itself
+netcf-transaction.sh: netcf-transaction.sh.in $(top_builddir)/config.status
+ $(AM_V_GEN)sed \
+ -e 's![@]localstatedir[@]!$(localstatedir)!g' \
+ -e 's![@]sysconfdir[@]!$(sysconfdir)!g' \
+ < $< > $@-t && \
+ chmod a+x $@-t && \
+ mv $@-t $@
-uninstall-local: uninstall-init
+BUILT_SOURCES += netcf-transaction.sh
-if NETCF_INIT_SCRIPT_RED_HAT
-# This is for the initscript that handles network config change
-# transactions.
-install-init: netcf-transaction.init
- mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d
+if NETCF_USE_INITSCRIPTS
+install-sysinit: netcf-transaction.init
+ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/rc.d/init.d
$(INSTALL_SCRIPT) netcf-transaction.init \
$(DESTDIR)$(sysconfdir)/rc.d/init.d/netcf-transaction
-uninstall-init:
+uninstall-sysinit:
rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/netcf-transaction \
$(DESTDIR)$(sysconfdir)/sysconfig/netcf-transaction
+netcf-transaction.init: netcf-transaction.init.in \
+ $(top_builddir)/config.status
+ $(AM_V_GEN)sed \
+ -e 's![@]localstatedir[@]!$(localstatedir)!g' \
+ -e 's|[@]libexecdir[@]|$(libexecdir)|g' \
+ < $< > $@-t && \
+ chmod a+x $@-t && \
+ mv $@-t $@
+
BUILT_SOURCES += netcf-transaction.init
-netcf-transaction.init: netcf-transaction.init.sh $(top_builddir)/config.status
- $(AM_V_GEN)sed \
- -e 's!\@localstatedir\@!$(localstatedir)!g' \
- -e 's!\@sysconfdir\@!$(sysconfdir)!g' \
- < $< > $@-t && \
- chmod a+x $@-t && \
+else ! NETCF_USE_INITSCRIPTS
+
+if NETCF_USE_SYSTEMD
+SYSTEMD_UNIT_DIR = $(prefix)/lib/systemd/system
+
+install-sysinit: netcf-transaction.service
+ $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
+ $(INSTALL_DATA) netcf-transaction.service \
+ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/netcf-transaction.service
+
+uninstall-sysinit:
+ rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/netcf-transaction.service
+ rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) ||:
+
+netcf-transaction.service: netcf-transaction.service.in \
+ $(top_builddir)/config.status
+ $(AM_V_GEN)sed \
+ -e 's|[@]libexecdir[@]|$(libexecdir)|g' \
+ < $< > $@-t && \
mv $@-t $@
-else
-install-init:
-uninstall-init:
-netcf-transaction.init:
-endif # NETCF_INIT_SCRIPT_RED_HAT
+
+BUILT_SOURCES += netcf-transaction.service
+
+else ! NETCF_USE_SYSTEMD
+install-sysinit:
+uninstall-sysinit:
+endif ! NETCF_USE_SYSTEMD
+endif ! NETCF_USE_INITSCRIPTS
+endif NETCF_DRIVER_REDHAT
DISTCLEANFILES += $(BUILT_SOURCES)
diff --git a/src/netcf-transaction.init.in b/src/netcf-transaction.init.in
new file mode 100644
index 0000000..36beb53
--- /dev/null
+++ b/src/netcf-transaction.init.in
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# the following is the LSB init header
+#
+### BEGIN INIT INFO
+# Provides: netcf-transaction
+# Required-Start: $local_fs
+# Default-Start: 2 3 4 5
+# Short-Description: save/restore network configuration files
+# Description: This script can save the current state of network config,
+# and later revert to that config, or commit the new config
+# (by deleting the snapshot). At boot time, if there are
+# uncommitted changes to the network config, they are
+# reverted (and the discarded changes are archived in
+# @localstatedir@/lib/netcf/network-rollback-*).
+#
+### END INIT INFO
+
+# the following is chkconfig init header
+#
+# netcf-transaction: save/restore current network interface configuration
+#
+# chkconfig: - 09 91
+# description: This script can save the current state of network config, \
+# and later revert to that config, or commit the new config \
+# (by deleting the snapshot). At boot time, if there are \
+# uncommitted changes to the network config, they are \
+# reverted (and the discarded changes are archived in \
+# @localstatedir@/lib/netcf/network-rollback-*).
+
+exec @libexecdir@/netcf-transaction.sh "$@"
diff --git a/src/netcf-transaction.service.in b/src/netcf-transaction.service.in
new file mode 100644
index 0000000..6e17627
--- /dev/null
+++ b/src/netcf-transaction.service.in
@@ -0,0 +1,15 @@
+[Unit]
+Description=Rollback uncommitted netcf network config change transactions
+Before=network.target
+Before=NetworkManager.service
+
+[Service]
+# call common script that is also used by initscript-based service
+# and libnetcf.so
+ExecStart=@libexecdir@/netcf-transaction.sh start
+Type=oneshot
+RemainAfterExit=yes
+StandardOutput=journal+console
+
+[Install]
+WantedBy=multi-user.target
diff --git a/src/netcf-transaction.init.sh b/src/netcf-transaction.sh.in
old mode 100755
new mode 100644
similarity index 88%
rename from src/netcf-transaction.init.sh
rename to src/netcf-transaction.sh.in
index 1465b8a..c9aafdf
--- a/src/netcf-transaction.init.sh
+++ b/src/netcf-transaction.sh.in
@@ -1,27 +1,29 @@
#!/bin/sh
#
-# netcf-transaction: save/restore current network interface configuration
+# netcf-transaction.sh: save/restore current network interface configuration
+#
+# Copyright (C) 2011, 2014 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
#
-# chkconfig: - 09 91
-# description: This script can save the current state of network config, \
-# and later revert to that config, or commit the new config \
-# (by deleting the snapshot). At boot time, if there are \
-# uncommitted changes to the network config, they are \
-# reverted (and the discarded changes are archived in \
-# /var/lib/netcf/network-rollback-*).
-
-### BEGIN INIT INFO
-# Provides: netcf-transaction
-# Required-Start: $local_fs
-# Short-Description: save/restore network configuration files
# Description: This script can save the current state of network config,
# and later revert to that config, or commit the new config
# (by deleting the snapshot). At boot time, if there are
# uncommitted changes to the network config, they are
# reverted (and the discarded changes are archived in
-# /var/lib/netcf/network-rollback-*).
-#
-### END INIT INFO
+# @localstatedir@/lib/netcf/network-rollback-*).
# special exit code that means a command was issued that is invalid for the
# current state (e.g. change-begin when there is already an open transaction)
--
1.8.3.1