diff --git a/libvirt.spec.in b/libvirt.spec.in index d5fd75a4c6..36881c4096 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1497,6 +1497,7 @@ done %else if [ $1 -eq 1 ] ; then # Initial installation + /bin/systemctl enable virtlockd.socket >/dev/null 2>&1 || : /bin/systemctl enable libvirtd.service >/dev/null 2>&1 || : fi %endif @@ -1524,8 +1525,10 @@ fi %else if [ $1 -eq 0 ] ; then # Package removal, not upgrade + /bin/systemctl --no-reload disable virtlockd.socket > /dev/null 2>&1 || : /bin/systemctl --no-reload disable libvirtd.service > /dev/null 2>&1 || : /bin/systemctl stop libvirtd.service > /dev/null 2>&1 || : + /bin/systemctl stop virtlockd.service > /dev/null 2>&1 || : fi %endif %else @@ -1543,6 +1546,7 @@ fi /bin/systemctl daemon-reload >/dev/null 2>&1 || : if [ $1 -ge 1 ] ; then # Package upgrade, not uninstall + /bin/systemctl try-restart virtlockd.service >/dev/null 2>&1 || : /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || : fi %endif @@ -1659,6 +1663,8 @@ fi %if %{with_systemd} %{_unitdir}/libvirtd.service %{_unitdir}/libvirt-guests.service +%{_unitdir}/virtlockd.service +%{_unitdir}/virtlockd.socket %else %{_sysconfdir}/rc.d/init.d/libvirtd %{_sysconfdir}/rc.d/init.d/libvirt-guests diff --git a/src/Makefile.am b/src/Makefile.am index 27f9b41eeb..9b1cad01dc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1613,6 +1613,53 @@ virtlockd.init: locking/virtlockd.init.in $(top_builddir)/config.status +EXTRA_DIST += locking/virtlockd.service.in locking/virtlockd.socket.in + +if WITH_LIBVIRTD +if LIBVIRT_INIT_SCRIPT_SYSTEMD + +SYSTEMD_UNIT_DIR = /lib/systemd/system + +BUILT_SOURCES += virtlockd.service virtlockd.socket + +install-systemd: virtlockd.init install-sysconfig + mkdir -p $(DESTDIR)$(SYSTEMD_UNIT_DIR) + $(INSTALL_SCRIPT) virtlockd.service \ + $(DESTDIR)$(SYSTEMD_UNIT_DIR)/ + $(INSTALL_SCRIPT) virtlockd.socket \ + $(DESTDIR)$(SYSTEMD_UNIT_DIR)/ + +uninstall-systemd: uninstall-sysconfig + rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/virtlockd.service + rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/virtlockd.socket +else +install-systemd: +uninstall-systemd: +endif +else +install-systemd: +uninstall-systemd: +endif + +virtlockd.service: locking/virtlockd.service.in $(top_builddir)/config.status + $(AM_V_GEN)sed \ + -e "s!::localstatedir::!$(localstatedir)!g" \ + -e "s!::sbindir::!$(sbindir)!g" \ + -e "s!::sysconfdir::!$(sysconfdir)!g" \ + < $< > $@-t && \ + chmod a+x $@-t && \ + mv $@-t $@ + +virtlockd.socket: locking/virtlockd.socket.in $(top_builddir)/config.status + $(AM_V_GEN)sed \ + -e "s!::localstatedir::!$(localstatedir)!g" \ + -e "s!::sbindir::!$(sbindir)!g" \ + -e "s!::sysconfdir::!$(sysconfdir)!g" \ + < $< > $@-t && \ + chmod a+x $@-t && \ + mv $@-t $@ + + if HAVE_SANLOCK lockdriverdir = $(libdir)/libvirt/lock-driver lockdriver_LTLIBRARIES = sanlock.la @@ -1850,7 +1897,7 @@ endif endif EXTRA_DIST += $(SECURITY_DRIVER_APPARMOR_HELPER_SOURCES) -install-data-local: install-init +install-data-local: install-init install-systemd if WITH_LIBVIRTD $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd" $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/lockd" @@ -1903,7 +1950,7 @@ if WITH_NETWORK $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml endif -uninstall-local:: uninstall-init +uninstall-local:: uninstall-init uninstall-systemd if WITH_LIBVIRTD rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd" ||: rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/lockd" ||: diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index 9dbcc75f74..74eb5f272d 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -496,8 +496,69 @@ virLockDaemonSetupSignals(virNetServerPtr srv) return 0; } + static int -virLockDaemonSetupNetworking(virNetServerPtr srv, const char *sock_path) +virLockDaemonSetupNetworkingSystemD(virNetServerPtr srv) +{ + virNetServerServicePtr svc; + const char *pidstr; + const char *fdstr; + unsigned long long procid; + unsigned int nfds; + + if (!(pidstr = getenv("LISTEN_PID"))) { + VIR_DEBUG("No LISTEN_FDS from systemd"); + return 0; + } + + if (virStrToLong_ull(pidstr, NULL, 10, &procid) < 0) { + VIR_DEBUG("Malformed LISTEN_PID from systemd %s", pidstr); + return 0; + } + + if ((pid_t)procid != getpid()) { + VIR_DEBUG("LISTEN_PID %s is not for us %llu", + pidstr, (unsigned long long)getpid()); + return 0; + } + + if (!(fdstr = getenv("LISTEN_FDS"))) { + VIR_DEBUG("No LISTEN_FDS from systemd"); + return 0; + } + + if (virStrToLong_ui(fdstr, NULL, 10, &nfds) < 0) { + VIR_DEBUG("Malformed LISTEN_FDS from systemd %s", fdstr); + return 0; + } + + if (nfds > 1) { + VIR_DEBUG("Too many (%d) file descriptors from systemd", + nfds); + nfds = 1; + } + + unsetenv("LISTEN_PID"); + unsetenv("LISTEN_FDS"); + + if (nfds == 0) + return 0; + + /* Systemd passes FDs, starting immediately after stderr, + * so the first FD we'll get is '3'. */ + if (!(svc = virNetServerServiceNewFD(3, 0, false, 1, NULL))) + return -1; + + if (virNetServerAddService(srv, svc, NULL) < 0) { + virObjectUnref(svc); + return -1; + } + return 1; +} + + +static int +virLockDaemonSetupNetworkingNative(virNetServerPtr srv, const char *sock_path) { virNetServerServicePtr svc; @@ -726,6 +787,7 @@ int main(int argc, char **argv) { mode_t old_umask; bool privileged = false; virLockDaemonConfigPtr config = NULL; + int rv; struct option opts[] = { { "verbose", no_argument, &verbose, 1}, @@ -901,7 +963,14 @@ int main(int argc, char **argv) { goto cleanup; } - if (virLockDaemonSetupNetworking(lockDaemon->srv, sock_file) < 0) { + if ((rv = virLockDaemonSetupNetworkingSystemD(lockDaemon->srv)) < 0) { + ret = VIR_LOCK_DAEMON_ERR_NETWORK; + goto cleanup; + } + + /* Only do this, if systemd did not pass a FD */ + if (rv == 0 && + virLockDaemonSetupNetworkingNative(lockDaemon->srv, sock_file) < 0) { ret = VIR_LOCK_DAEMON_ERR_NETWORK; goto cleanup; } diff --git a/src/locking/virtlockd.service.in b/src/locking/virtlockd.service.in new file mode 100644 index 0000000000..a9f9f932cc --- /dev/null +++ b/src/locking/virtlockd.service.in @@ -0,0 +1,13 @@ +[Unit] +Description=Virtual machine lock manager +Requires=virtlockd.socket +After=syslog.target + +[Service] +EnvironmentFile=-/etc/sysconfig/virtlockd +ExecStart=@sbindir@/virtlockd +ExecReload=/bin/kill -HUP $MAINPID +# Loosing the locks is a really bad thing that will +# cause the machine to be fenced (rebooted), so make +# sure we discourage OOM killer +OOMScoreAdjust=-900 diff --git a/src/locking/virtlockd.socket.in b/src/locking/virtlockd.socket.in new file mode 100644 index 0000000000..0589a29018 --- /dev/null +++ b/src/locking/virtlockd.socket.in @@ -0,0 +1,8 @@ +[Unit] +Description=Virtual machine lock manager socket + +[Socket] +ListenStream=/var/run/libvirt/virtlockd/virtlockd.sock + +[Install] +WantedBy=multi-user.target