[libvirt] [PATCH 05/14] Introduce basic infrastructure for virtlockd daemon

Michal Privoznik mprivozn at redhat.com
Wed Dec 12 18:14:20 UTC 2012


On 11.12.2012 21:41, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> The virtlockd daemon will maintain locks on behalf of libvirtd.
> There are two reasons for it to be separate
> 
>  - Avoid risk of other libvirtd threads accidentally
>    releasing fcntl() locks by opening + closing a file
>    that is locked
>  - Ensure locks can be preserved across libvirtd restarts.
>    virtlockd will need to be able to re-exec itself while
>    maintaining locks. This is simpler to achieve if its
>    sole job is maintaining locks
> 
> Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
> ---
>  .gitignore                       |   2 +
>  cfg.mk                           |   6 +-
>  libvirt.spec.in                  |   7 +
>  po/POTFILES.in                   |   2 +
>  src/Makefile.am                  |  89 +++-
>  src/locking/lock_daemon.c        | 850 +++++++++++++++++++++++++++++++++++++++
>  src/locking/lock_daemon.h        |  43 ++
>  src/locking/lock_daemon_config.c | 193 +++++++++
>  src/locking/lock_daemon_config.h |  50 +++
>  src/locking/virtlockd.init.in    |  93 +++++
>  src/locking/virtlockd.sysconf    |   3 +
>  11 files changed, 1334 insertions(+), 4 deletions(-)
>  create mode 100644 src/locking/lock_daemon.c
>  create mode 100644 src/locking/lock_daemon.h
>  create mode 100644 src/locking/lock_daemon_config.c
>  create mode 100644 src/locking/lock_daemon_config.h
>  create mode 100644 src/locking/virtlockd.init.in
>  create mode 100644 src/locking/virtlockd.sysconf
> 
> diff --git a/.gitignore b/.gitignore
> index 0dadd21..1e3a624 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -123,6 +123,8 @@
>  /src/test_libvirt*.aug
>  /src/util/virkeymaps.h
>  /src/virt-aa-helper
> +/src/virtlockd
> +/src/virtlockd.init
>  /tests/*.log
>  /tests/*.pid
>  /tests/*xml2*test
> diff --git a/cfg.mk b/cfg.mk
> index f218eb6..95a1d3a 100644
> --- a/cfg.mk
> +++ b/cfg.mk
> @@ -655,6 +655,8 @@ sc_prohibit_cross_inclusion:
>  	@for dir in $(cross_dirs); do					\
>  	  case $$dir in							\
>  	    util/) safe="util";;					\
> +	    locking/)							\
> +	      safe="($$dir|util|conf|rpc)";;				\
>  	    cpu/ | locking/ | network/ | rpc/ | security/)		\
>  	      safe="($$dir|util|conf)";;				\
>  	    xenapi/ | xenxs/ ) safe="($$dir|util|conf|xen)";;		\
> @@ -743,7 +745,7 @@ $(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protoco
>  # List all syntax-check exemptions:
>  exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$
>  
> -_src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller
> +_src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon
>  exclude_file_name_regexp--sc_avoid_write = \
>    ^(src/($(_src1))|daemon/libvirtd|tools/console|tests/(shunload|virnettlscontext)test)\.c$$
>  
> @@ -776,7 +778,7 @@ exclude_file_name_regexp--sc_prohibit_close = \
>  exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
>    (^tests/(qemuhelp|nodeinfo)data/|\.(gif|ico|png|diff)$$)
>  
> -_src2=src/(util/command|libvirt|lxc/lxc_controller)
> +_src2=src/(util/command|libvirt|lxc/lxc_controller|locking/lock_daemon)
>  exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
>    (^($(_src2)|tests/testutils|daemon/libvirtd)\.c$$)
>  
> diff --git a/libvirt.spec.in b/libvirt.spec.in
> index d6e1fbe..e12fca4 100644
> --- a/libvirt.spec.in
> +++ b/libvirt.spec.in
> @@ -1661,9 +1661,11 @@ fi
>  %{_unitdir}/libvirtd.service
>  %else
>  %{_sysconfdir}/rc.d/init.d/libvirtd
> +%{_sysconfdir}/rc.d/init.d/virtlockd
>  %endif
>  %doc daemon/libvirtd.upstart
>  %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
> +%config(noreplace) %{_sysconfdir}/sysconfig/virtlockd
>  %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
>  %if 0%{?fedora} >= 14 || 0%{?rhel} >= 6
>  %config(noreplace) %{_sysconfdir}/sysctl.d/libvirtd
> @@ -1730,6 +1732,10 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd
>  %dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/dnsmasq/
>  %endif
>  
> +%if %{with_libvirtd}
> +%dir %attr(0755, root, root) %{_libdir}/libvirt/lock-driver
> +%endif
> +
>  %if %{with_qemu}
>  %{_datadir}/augeas/lenses/libvirtd_qemu.aug
>  %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
> @@ -1763,6 +1769,7 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd
>  
>  %attr(0755, root, root) %{_libexecdir}/libvirt_iohelper
>  %attr(0755, root, root) %{_sbindir}/libvirtd
> +%attr(0755, root, root) %{_sbindir}/virtlockd
>  
>  %{_mandir}/man8/libvirtd.8*
>  
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index 51a1f5c..34c688c 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -48,6 +48,8 @@ src/interface/interface_backend_udev.c
>  src/internal.h
>  src/libvirt.c
>  src/libvirt-qemu.c
> +src/locking/lock_daemon.c
> +src/locking/lock_daemon_config.c
>  src/locking/lock_driver_sanlock.c
>  src/locking/lock_manager.c
>  src/locking/sanlock_helper.c
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 6d2816d..6a66efd 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -148,6 +148,13 @@ LOCK_DRIVER_SANLOCK_SOURCES = \
>  LOCK_DRIVER_SANLOCK_HELPER_SOURCES = \
>  		locking/sanlock_helper.c
>  
> +LOCK_DAEMON_SOURCES = \
> +		locking/lock_daemon.h \
> +		locking/lock_daemon.c \
> +		locking/lock_daemon_config.h \
> +		locking/lock_daemon_config.c \
> +		$(NULL)
> +
>  NETDEV_CONF_SOURCES =						\
>  		conf/netdev_bandwidth_conf.h conf/netdev_bandwidth_conf.c \
>  		conf/netdev_vport_profile_conf.h conf/netdev_vport_profile_conf.c \
> @@ -1508,6 +1515,76 @@ libvirt_qemu_la_CFLAGS = $(AM_CFLAGS)
>  libvirt_qemu_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
>  EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE)
>  
> +if WITH_LIBVIRTD
> +sbin_PROGRAMS = virtlockd
> +
> +virtlockd_SOURCES = $(LOCK_DAEMON_SOURCES)
> +virtlockd_CFLAGS = \
> +		$(AM_CFLAGS) \
> +		$(NULL)
> +virtlockd_LDFLAGS = \
> +		$(AM_LDFLAGS) \
> +		$(CYGWIN_EXTRA_LDFLAGS) \
> +		$(MINGW_EXTRA_LDFLAGS) \
> +		$(NULL)
> +virtlockd_LDADD = \
> +		libvirt-net-rpc-server.la \
> +		libvirt-net-rpc.la \
> +		libvirt_util.la \
> +		../gnulib/lib/libgnu.la \
> +		$(CYGWIN_EXTRA_LIBADD) \
> +		$(NULL)
> +if WITH_DTRACE_PROBES
> +virtlockd_LDADD += libvirt_probes.lo
> +endif
> +
> +else
> +EXTRA_DIST += $(LOCK_DAEMON_SOURCES)
> +endif
> +
> +EXTRA_DIST += locking/virtlockd.sysconf
> +
> +install-sysconfig:
> +	mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig
> +	$(INSTALL_DATA) $(srcdir)/locking/virtlockd.sysconf \
> +	  $(DESTDIR)$(sysconfdir)/sysconfig/virtlockd
> +
> +uninstall-sysconfig:
> +	rm -f $(DESTDIR)$(sysconfdir)/sysconfig/virtlockd
> +
> +EXTRA_DIST += locking/virtlockd.init.in
> +
> +if WITH_LIBVIRTD
> +if LIBVIRT_INIT_SCRIPT_RED_HAT
> +install-init:: virtlockd.init install-sysconfig
> +	mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d
> +	$(INSTALL_SCRIPT) virtlockd.init \
> +	  $(DESTDIR)$(sysconfdir)/rc.d/init.d/virtlockd
> +
> +uninstall-init:: uninstall-sysconfig
> +	rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd
> +
> +BUILT_SOURCES += virtlockd.init
> +else
> +install-init::
> +uninstall-init::
> +endif
> +else
> +install-init::
> +uninstall-init::
> +endif
> +
> +virtlockd.init: locking/virtlockd.init.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
> @@ -1745,7 +1822,11 @@ endif
>  endif
>  EXTRA_DIST += $(SECURITY_DRIVER_APPARMOR_HELPER_SOURCES)
>  
> -install-data-local:
> +install-data-local: install-init
> +if WITH_LIBVIRTD
> +	$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd"
> +	$(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/lockd"
> +endif
>  	$(MKDIR_P) "$(DESTDIR)$(localstatedir)/cache/libvirt"
>  	$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/images"
>  	$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/filesystems"
> @@ -1794,7 +1875,11 @@ if WITH_NETWORK
>  	    $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
>  endif
>  
> -uninstall-local::
> +uninstall-local:: uninstall-init
> +if WITH_LIBVIRTD
> +	rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd" ||:
> +	rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/lockd" ||:
> +endif
>  	rmdir "$(DESTDIR)$(localstatedir)/cache/libvirt" ||:
>  	rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/images" ||:
>  	rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/filesystems" ||:
> diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
> new file mode 100644
> index 0000000..f821d2e
> --- /dev/null
> +++ b/src/locking/lock_daemon.c
> @@ -0,0 +1,850 @@
> +/*
> + * lock_daemon.c: lock management daemon
> + *
> + * Copyright (C) 2006-2012 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/>.
> + *
> + * Author: Daniel P. Berrange <berrange at redhat.com>
> + */
> +
> +#include <config.h>
> +
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <sys/wait.h>
> +#include <sys/stat.h>
> +#include <getopt.h>
> +#include <stdlib.h>
> +#include <locale.h>
> +
> +
> +#include "lock_daemon.h"
> +#include "lock_daemon_config.h"
> +#include "util.h"
> +#include "virfile.h"
> +#include "virpidfile.h"
> +#include "virterror_internal.h"
> +#include "logging.h"
> +#include "memory.h"
> +#include "conf.h"
> +#include "rpc/virnetserver.h"
> +#include "virrandom.h"
> +#include "virhash.h"

You may want to sort these so we don't introduce yet another file which
needs sorting - assuming we will stick to your idea of sorting header
files include after the release.

> +
> +#include "configmake.h"
> +
> +#define VIR_FROM_THIS VIR_FROM_LOCKING
> +
> +struct _virLockDaemon {
> +    virMutex lock;
> +    virNetServerPtr srv;
> +};
> +
> +virLockDaemonPtr lockDaemon = NULL;
> +
> +enum {
> +    VIR_LOCK_DAEMON_ERR_NONE = 0,
> +    VIR_LOCK_DAEMON_ERR_PIDFILE,
> +    VIR_LOCK_DAEMON_ERR_RUNDIR,
> +    VIR_LOCK_DAEMON_ERR_INIT,
> +    VIR_LOCK_DAEMON_ERR_SIGNAL,
> +    VIR_LOCK_DAEMON_ERR_PRIVS,
> +    VIR_LOCK_DAEMON_ERR_NETWORK,
> +    VIR_LOCK_DAEMON_ERR_CONFIG,
> +    VIR_LOCK_DAEMON_ERR_HOOKS,
> +
> +    VIR_LOCK_DAEMON_ERR_LAST
> +};
> +
> +VIR_ENUM_DECL(virDaemonErr)
> +VIR_ENUM_IMPL(virDaemonErr, VIR_LOCK_DAEMON_ERR_LAST,
> +              "Initialization successful",
> +              "Unable to obtain pidfile",
> +              "Unable to create rundir",
> +              "Unable to initialize libvirt",
> +              "Unable to setup signal handlers",
> +              "Unable to drop privileges",
> +              "Unable to initialize network sockets",
> +              "Unable to load configuration file",
> +              "Unable to look for hook scripts");
> +
> +static void *
> +virLockDaemonClientNew(virNetServerClientPtr client,
> +                       void *opaque);
> +static void
> +virLockDaemonClientFree(void *opaque);
> +
> +static void
> +virLockDaemonFree(virLockDaemonPtr lockd)
> +{
> +    if (!lockd)
> +        return;
> +
> +    virObjectUnref(lockd->srv);
> +
> +    VIR_FREE(lockd);
> +}
> +
> +
> +static virLockDaemonPtr
> +virLockDaemonNew(bool privileged)
> +{
> +    virLockDaemonPtr lockd;
> +
> +    if (VIR_ALLOC(lockd) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    if (virMutexInit(&lockd->lock) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("Unable to initialize mutex"));
> +        VIR_FREE(lockd);
> +        return NULL;
> +    }
> +
> +    if (!(lockd->srv = virNetServerNew(1, 1, 0, 20,
> +                                       -1, 0,
> +                                       false, NULL,
> +                                       virLockDaemonClientNew,
> +                                       NULL,
> +                                       virLockDaemonClientFree,
> +                                       (void*)(intptr_t)(privileged ? 0x1 : 0x0))))
> +        goto error;
> +
> +    return lockd;
> +
> +error:
> +    virLockDaemonFree(lockd);
> +    return NULL;
> +}
> +
> +
> +static int
> +virLockDaemonForkIntoBackground(const char *argv0)
> +{
> +    int statuspipe[2];
> +    if (pipe(statuspipe) < 0)
> +        return -1;
> +
> +    pid_t pid = fork();
> +    switch (pid) {
> +    case 0:
> +        {
> +            int stdinfd = -1;
> +            int stdoutfd = -1;
> +            int nextpid;
> +
> +            VIR_FORCE_CLOSE(statuspipe[0]);
> +
> +            if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
> +                goto cleanup;
> +            if ((stdoutfd = open("/dev/null", O_WRONLY)) < 0)
> +                goto cleanup;
> +            if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
> +                goto cleanup;
> +            if (dup2(stdoutfd, STDOUT_FILENO) != STDOUT_FILENO)
> +                goto cleanup;
> +            if (dup2(stdoutfd, STDERR_FILENO) != STDERR_FILENO)
> +                goto cleanup;
> +            if (VIR_CLOSE(stdinfd) < 0)
> +                goto cleanup;
> +            if (VIR_CLOSE(stdoutfd) < 0)
> +                goto cleanup;
> +
> +            if (setsid() < 0)
> +                goto cleanup;
> +
> +            nextpid = fork();
> +            switch (nextpid) {
> +            case 0:
> +                return statuspipe[1];
> +            case -1:
> +                return -1;
> +            default:
> +                _exit(0);
> +            }
> +
> +        cleanup:
> +            VIR_FORCE_CLOSE(stdoutfd);
> +            VIR_FORCE_CLOSE(stdinfd);
> +            return -1;
> +
> +        }
> +
> +    case -1:
> +        return -1;
> +
> +    default:
> +        {
> +            int got, exitstatus = 0;
> +            int ret;
> +            char status;
> +
> +            VIR_FORCE_CLOSE(statuspipe[1]);
> +
> +            /* We wait to make sure the first child forked successfully */
> +            if ((got = waitpid(pid, &exitstatus, 0)) < 0 ||
> +                got != pid ||
> +                exitstatus != 0) {
> +                return -1;
> +            }
> +
> +            /* Now block until the second child initializes successfully */
> +        again:
> +            ret = read(statuspipe[0], &status, 1);
> +            if (ret == -1 && errno == EINTR)
> +                goto again;
> +
> +            if (ret == 1 && status != 0) {
> +                fprintf(stderr,
> +                        _("%s: error: %s. Check /var/log/messages or run without "
> +                          "--daemon for more info.\n"), argv0,
> +                        virDaemonErrTypeToString(status));
> +            }
> +            _exit(ret == 1 && status == 0 ? 0 : 1);
> +        }
> +    }
> +}

This is basically a copy-paste of daemonForkIntoBackground(). I wonder
if we can use (modified) version of it instead of this.

> +
> +
> +static int
> +virLockDaemonPidFilePath(bool privileged,
> +                         char **pidfile)
> +{
> +    if (privileged) {
> +        if (!(*pidfile = strdup(LOCALSTATEDIR "/run/virtlockd.pid")))
> +            goto no_memory;
> +    } else {
> +        char *rundir = NULL;
> +        mode_t old_umask;
> +
> +        if (!(rundir = virGetUserRuntimeDirectory()))
> +            goto error;
> +
> +        old_umask = umask(077);
> +        if (virFileMakePath(rundir) < 0) {
> +            umask(old_umask);
> +            goto error;
> +        }
> +        umask(old_umask);
> +
> +        if (virAsprintf(pidfile, "%s/virtlockd.pid", rundir) < 0) {
> +            VIR_FREE(rundir);
> +            goto no_memory;
> +        }
> +
> +        VIR_FREE(rundir);
> +    }
> +
> +    return 0;
> +
> +no_memory:
> +    virReportOOMError();
> +error:
> +    return -1;
> +}
> +
> +
> +static int
> +virLockDaemonUnixSocketPaths(bool privileged,
> +                             char **sockfile)
> +{
> +    if (privileged) {
> +        if (!(*sockfile = strdup(LOCALSTATEDIR "/run/libvirt/virtlockd-sock")))
> +            goto no_memory;
> +    } else {
> +        char *rundir = NULL;
> +        mode_t old_umask;
> +
> +        if (!(rundir = virGetUserRuntimeDirectory()))
> +            goto error;
> +
> +        old_umask = umask(077);
> +        if (virFileMakePath(rundir) < 0) {
> +            umask(old_umask);
> +            goto error;
> +        }
> +        umask(old_umask);
> +
> +        if (virAsprintf(sockfile, "%s/virtlockd-sock", rundir) < 0) {
> +            VIR_FREE(rundir);
> +            goto no_memory;
> +        }
> +
> +        VIR_FREE(rundir);
> +    }
> +    return 0;
> +
> +no_memory:
> +    virReportOOMError();
> +error:
> +    return -1;
> +}
> +
> +
> +static void
> +virLockDaemonErrorHandler(void *opaque ATTRIBUTE_UNUSED,
> +                          virErrorPtr err ATTRIBUTE_UNUSED)
> +{
> +    /* Don't do anything, since logging infrastructure already
> +     * took care of reporting the error */
> +}
> +
> +
> +/*
> + * Set up the logging environment
> + * By default if daemonized all errors go to the logfile libvirtd.log,
> + * but if verbose or error debugging is asked for then also output
> + * informational and debug messages. Default size if 64 kB.
> + */
> +static int
> +virLockDaemonSetupLogging(virLockDaemonConfigPtr config,
> +                          bool privileged,
> +                          bool verbose,
> +                          bool godaemon)
> +{
> +    virLogReset();
> +
> +    /*
> +     * Libvirtd's order of precedence is:
> +     * cmdline > environment > config
> +     *
> +     * In order to achieve this, we must process configuration in
> +     * different order for the log level versus the filters and
> +     * outputs. Because filters and outputs append, we have to look at
> +     * the environment first and then only check the config file if
> +     * there was no result from the environment. The default output is
> +     * then applied only if there was no setting from either of the
> +     * first two. Because we don't have a way to determine if the log
> +     * level has been set, we must process variables in the opposite
> +     * order, each one overriding the previous.
> +     */
> +    if (config->log_level != 0)
> +        virLogSetDefaultPriority(config->log_level);
> +
> +    virLogSetFromEnv();
> +
> +    virLogSetBufferSize(config->log_buffer_size);
> +
> +    if (virLogGetNbFilters() == 0)
> +        virLogParseFilters(config->log_filters);
> +
> +    if (virLogGetNbOutputs() == 0)
> +        virLogParseOutputs(config->log_outputs);
> +
> +    /*
> +     * If no defined outputs, and either running
> +     * as daemon or not on a tty, then first try
> +     * to direct it to the systemd journal
> +     * (if it exists)....
> +     */
> +    if (virLogGetNbOutputs() == 0 &&
> +        (godaemon || !isatty(STDIN_FILENO))) {
> +        char *tmp;
> +        if (access("/run/systemd/journal/socket", W_OK) >= 0) {
> +            if (virAsprintf(&tmp, "%d:journald", virLogGetDefaultPriority()) < 0)
> +                goto no_memory;
> +            virLogParseOutputs(tmp);
> +            VIR_FREE(tmp);
> +        }
> +    }
> +
> +    /*
> +     * otherwise direct to libvirtd.log when running
> +     * as daemon. Otherwise the default output is stderr.
> +     */
> +    if (virLogGetNbOutputs() == 0) {
> +        char *tmp = NULL;
> +
> +        if (godaemon) {
> +            if (privileged) {
> +                if (virAsprintf(&tmp, "%d:file:%s/log/libvirt/virtlockd.log",
> +                                virLogGetDefaultPriority(),
> +                                LOCALSTATEDIR) == -1)
> +                    goto no_memory;
> +            } else {
> +                char *logdir = virGetUserCacheDirectory();
> +                mode_t old_umask;
> +
> +                if (!logdir)
> +                    goto error;
> +
> +                old_umask = umask(077);
> +                if (virFileMakePath(logdir) < 0) {
> +                    umask(old_umask);
> +                    goto error;
> +                }
> +                umask(old_umask);
> +
> +                if (virAsprintf(&tmp, "%d:file:%s/virtlockd.log",
> +                                virLogGetDefaultPriority(), logdir) == -1) {
> +                    VIR_FREE(logdir);
> +                    goto no_memory;
> +                }
> +                VIR_FREE(logdir);
> +            }
> +        } else {
> +            if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0)
> +                goto no_memory;
> +        }
> +        virLogParseOutputs(tmp);
> +        VIR_FREE(tmp);
> +    }
> +
> +    /*
> +     * Command line override for --verbose
> +     */
> +    if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO))
> +        virLogSetDefaultPriority(VIR_LOG_INFO);
> +
> +    return 0;
> +
> +no_memory:
> +    virReportOOMError();
> +error:
> +    return -1;
> +}

Same here. This one is even closer to daemonSetupLogging()

> +
> +
> +
> +/* Display version information. */
> +static void
> +virLockDaemonVersion(const char *argv0)
> +{
> +    printf("%s (%s) %s\n", argv0, PACKAGE_NAME, PACKAGE_VERSION);
> +}
> +
> +static void
> +virLockDaemonShutdownHandler(virNetServerPtr srv,
> +                             siginfo_t *sig ATTRIBUTE_UNUSED,
> +                             void *opaque ATTRIBUTE_UNUSED)
> +{
> +    virNetServerQuit(srv);
> +}
> +
> +static int
> +virLockDaemonSetupSignals(virNetServerPtr srv)
> +{
> +    if (virNetServerAddSignalHandler(srv, SIGINT, virLockDaemonShutdownHandler, NULL) < 0)
> +        return -1;
> +    if (virNetServerAddSignalHandler(srv, SIGQUIT, virLockDaemonShutdownHandler, NULL) < 0)
> +        return -1;
> +    if (virNetServerAddSignalHandler(srv, SIGTERM, virLockDaemonShutdownHandler, NULL) < 0)
> +        return -1;
> +    return 0;
> +}
> +
> +static int
> +virLockDaemonSetupNetworking(virNetServerPtr srv, const char *sock_path)
> +{
> +    virNetServerServicePtr svc;
> +
> +    VIR_DEBUG("Setting up networking natively");
> +
> +    if (!(svc = virNetServerServiceNewUNIX(sock_path, 0700, 0, 0, false, 1, NULL)))
> +        return -1;
> +
> +    if (virNetServerAddService(srv, svc, NULL) < 0) {
> +        virObjectUnref(svc);
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +
> +static void
> +virLockDaemonClientFree(void *opaque)
> +{
> +    virLockDaemonClientPtr priv = opaque;
> +
> +    if (!priv)
> +        return;
> +
> +    VIR_DEBUG("priv=%p client=%lld",
> +              priv,
> +              (unsigned long long)priv->clientPid);
> +
> +    virMutexDestroy(&priv->lock);
> +    VIR_FREE(priv);
> +}
> +
> +
> +static void *
> +virLockDaemonClientNew(virNetServerClientPtr client,
> +                       void *opaque)
> +{
> +    virLockDaemonClientPtr priv;
> +    uid_t clientuid;
> +    gid_t clientgid;
> +    bool privileged = opaque != NULL;
> +
> +    if (VIR_ALLOC(priv) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    if (virMutexInit(&priv->lock) < 0) {
> +        VIR_FREE(priv);
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    if (virNetServerClientGetUNIXIdentity(client,
> +                                          &clientuid,
> +                                          &clientgid,
> +                                          &priv->clientPid) < 0)
> +        goto error;
> +
> +    VIR_DEBUG("New client pid %llu uid %llu",
> +              (unsigned long long)priv->clientPid,
> +              (unsigned long long)clientuid);
> +
> +    if (!privileged) {
> +        if (geteuid() != clientuid) {
> +            virReportError(VIR_ERR_OPERATION_DENIED,
> +                           _("Disallowing client %llu with uid %llu"),
> +                           (unsigned long long)priv->clientPid,
> +                           (unsigned long long)clientuid);
> +            goto error;
> +        }
> +    } else {
> +        if (clientuid != 0) {
> +            virReportError(VIR_ERR_OPERATION_DENIED,
> +                           _("Disallowing client %llu with uid %llu"),
> +                           (unsigned long long)priv->clientPid,
> +                           (unsigned long long)clientuid);
> +            goto error;
> +        }
> +    }
> +
> +    return priv;
> +
> +error:
> +    virMutexDestroy(&priv->lock);
> +    VIR_FREE(priv);
> +    return NULL;
> +}
> +
> +
> +static void
> +virLockDaemonUsage(const char *argv0, bool privileged)
> +{
> +    fprintf(stderr,
> +            _("\n"
> +              "Usage:\n"
> +              "  %s [options]\n"
> +              "\n"
> +              "Options:\n"
> +              "  -v | --verbose         Verbose messages.\n"
> +              "  -d | --daemon          Run as a daemon & write PID file.\n"
> +              "  -t | --timeout <secs>  Exit after timeout period.\n"
> +              "  -f | --config <file>   Configuration file.\n"
> +              "     | --version         Display version information.\n"
> +              "  -p | --pid-file <file> Change name of PID file.\n"
> +              "\n"
> +              "libvirt lock management daemon:\n"), argv0);
> +
> +    if (privileged) {
> +        fprintf(stderr,
> +                _("\n"
> +                  "  Default paths:\n"
> +                  "\n"
> +                  "    Configuration file (unless overridden by -f):\n"
> +                  "      %s/libvirt/virtlockd.conf\n"
> +                  "\n"
> +                  "    Sockets:\n"
> +                  "      %s/run/libvirt/virtlockd-sock\n"
> +                  "\n"
> +                  "    PID file (unless overridden by -p):\n"
> +                  "      %s/run/virtlockd.pid\n"
> +                  "\n"),
> +                SYSCONFDIR,
> +                LOCALSTATEDIR,
> +                LOCALSTATEDIR);
> +    } else {
> +        fprintf(stderr,
> +                "%s", _("\n"
> +                        "  Default paths:\n"
> +                        "\n"
> +                        "    Configuration file (unless overridden by -f):\n"
> +                        "      $XDG_CONFIG_HOME/libvirt/virtlockd.conf\n"
> +                        "\n"
> +                        "    Sockets:\n"
> +                        "      $XDG_RUNTIME_DIR/libvirt/virtlockd-sock\n"
> +                        "\n"
> +                        "    PID file:\n"
> +                        "      $XDG_RUNTIME_DIR/libvirt/virtlockd.pid\n"
> +                        "\n"));

just a small nit, if you'd move "%s" to the previous line, this and the
previous blocks would be perfectly aligned.

> +    }
> +}
> +
> +enum {
> +    OPT_VERSION = 129
> +};
> +
> +#define MAX_LISTEN 5
> +int main(int argc, char **argv) {
> +    char *remote_config_file = NULL;
> +    int statuswrite = -1;
> +    int ret = 1;
> +    int verbose = 0;
> +    int godaemon = 0;
> +    int timeout = 0;

timeout seems dummy to me.

ACK if you either remove it or (more likely) implement it.




More information about the libvir-list mailing list