On 11/12/2015 12:18 PM, Daniel P. Berrange wrote: > Copy the virtlockd codebase across to form the initial virlogd > code. Simple search & replace of s/lock/log/ and gut the remote > protocol & dispatcher. This gives us a daemon that starts up > and listens for connections, but does nothing with them. > > Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> > --- > .gitignore | 7 + > cfg.mk | 4 +- > include/libvirt/virterror.h | 1 + > libvirt.spec.in | 24 +- > po/POTFILES.in | 2 + > src/Makefile.am | 169 +++++- > src/logging/log_daemon.c | 1177 +++++++++++++++++++++++++++++++++++++ > src/logging/log_daemon.h | 42 ++ > src/logging/log_daemon_config.c | 203 +++++++ > src/logging/log_daemon_config.h | 50 ++ > src/logging/log_daemon_dispatch.c | 37 ++ > src/logging/log_daemon_dispatch.h | 31 + > src/logging/log_protocol.x | 22 + > src/logging/test_virtlogd.aug.in | 12 + > src/logging/virtlogd.aug | 45 ++ > src/logging/virtlogd.conf | 67 +++ > src/logging/virtlogd.init.in | 94 +++ > src/logging/virtlogd.pod.in | 162 +++++ > src/logging/virtlogd.service.in | 17 + > src/logging/virtlogd.socket.in | 8 + > src/logging/virtlogd.sysconf | 3 + > src/util/virerror.c | 1 + > 22 files changed, 2156 insertions(+), 22 deletions(-) > create mode 100644 src/logging/log_daemon.c > create mode 100644 src/logging/log_daemon.h > create mode 100644 src/logging/log_daemon_config.c > create mode 100644 src/logging/log_daemon_config.h > create mode 100644 src/logging/log_daemon_dispatch.c > create mode 100644 src/logging/log_daemon_dispatch.h > create mode 100644 src/logging/log_protocol.x > create mode 100644 src/logging/test_virtlogd.aug.in > create mode 100644 src/logging/virtlogd.aug > create mode 100644 src/logging/virtlogd.conf > create mode 100644 src/logging/virtlogd.init.in > create mode 100644 src/logging/virtlogd.pod.in > create mode 100644 src/logging/virtlogd.service.in > create mode 100644 src/logging/virtlogd.socket.in > create mode 100644 src/logging/virtlogd.sysconf > Full disclosure - the aspects of Makefiles, cfg files, spec files, etc. - not my area of expertise... Looks like things were copied correctly though and it does build... Whether it builds on all platforms for all strange variants of make - I'll leave to existing build processes... [...] Hopefully some assumptions can be made regarding how much of this is copied from lockd ;-) > diff --git a/src/logging/log_daemon.c b/src/logging/log_daemon.c > new file mode 100644 > index 0000000..184076c > --- /dev/null > +++ b/src/logging/log_daemon.c > @@ -0,0 +1,1177 @@ > +/* > + * log_daemon.c: log management daemon > + * > + * Copyright (C) 2006-2015 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@xxxxxxxxxx> > + */ [...] > +static void > +virLogDaemonFree(virLogDaemonPtr logd) > +{ > + if (!logd) > + return; Should there be a virMutexDestroy(logd->lock); ? If so, it's also missing from lockd > + > + virObjectUnref(logd->srv); > + virObjectUnref(logd->dmn); > + > + VIR_FREE(logd); > +} > + > + [...] > + > +static int > +virLogDaemonUnixSocketPaths(bool privileged, > + char **sockfile) > +{ > + if (privileged) { > + if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock") < 0) > + goto error; > + } else { > + char *rundir = NULL; > + mode_t old_umask; > + > + if (!(rundir = virGetUserRuntimeDirectory())) > + goto error; > + > + old_umask = umask(077); > + if (virFileMakePath(rundir) < 0) { > + umask(old_umask); VIR_FREE(rundir); - I see this is true in lockd too... > + goto error; > + } > + umask(old_umask); > + > + if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0) { > + VIR_FREE(rundir); > + goto error; > + } > + > + VIR_FREE(rundir); > + } > + return 0; > + > + error: > + return -1; > +} > + > + > +static void > +virLogDaemonErrorHandler(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 > +virLogDaemonSetupLogging(virLogDaemonConfigPtr 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(); > + > + 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 error; > + 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/virtlogd.log", > + virLogGetDefaultPriority(), > + LOCALSTATEDIR) == -1) > + goto error; > + } else { > + char *logdir = virGetUserCacheDirectory(); > + mode_t old_umask; > + > + if (!logdir) > + goto error; > + > + old_umask = umask(077); > + if (virFileMakePath(logdir) < 0) { > + umask(old_umask); VIR_FREE(logdir); - same in lockd > + goto error; > + } > + umask(old_umask); > + > + if (virAsprintf(&tmp, "%d:file:%s/virtlogd.log", > + virLogGetDefaultPriority(), logdir) == -1) { > + VIR_FREE(logdir); > + goto error; > + } > + VIR_FREE(logdir); > + } > + } else { > + if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0) > + goto error; > + } > + virLogParseOutputs(tmp); > + VIR_FREE(tmp); > + } > + > + /* > + * Command line override for --verbose > + */ > + if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO)) > + virLogSetDefaultPriority(VIR_LOG_INFO); > + > + return 0; > + > + error: > + return -1; > +} > + > + > + [...] > +static void * > +virLogDaemonClientNew(virNetServerClientPtr client, > + void *opaque) > +{ > + virLogDaemonClientPtr priv; > + uid_t clientuid; > + gid_t clientgid; > + unsigned long long timestamp; > + bool privileged = opaque != NULL; > + > + if (VIR_ALLOC(priv) < 0) > + return NULL; > + > + if (virMutexInit(&priv->lock) < 0) { > + VIR_FREE(priv); > + virReportSystemError(errno, "%s", _("unable to init mutex")); > + return NULL; > + } > + > + if (virNetServerClientGetUNIXIdentity(client, > + &clientuid, > + &clientgid, > + &priv->clientPid, > + ×tamp) < 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) { > + virReportRestrictedError(_("Disallowing client %llu with uid %llu"), > + (unsigned long long)priv->clientPid, > + (unsigned long long)clientuid); > + goto error; > + } > + } else { > + if (clientuid != 0) { > + virReportRestrictedError(_("Disallowing client %llu with uid %llu"), > + (unsigned long long)priv->clientPid, > + (unsigned long long)clientuid); > + goto error; > + } > + } > + > + return priv; > + > + error: Could use virLogDaemonClientFree() > + virMutexDestroy(&priv->lock); > + VIR_FREE(priv); > + return NULL; > +} > + > + [...] > + > +static void > +virLogDaemonUsage(const char *argv0, bool privileged) > +{ > + fprintf(stderr, > + _("\n" > + "Usage:\n" > + " %s [options]\n" > + "\n" > + "Options:\n" > + " -h | --help Display program help:\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" > + " -V | --version Display version information.\n" > + " -p | --pid-file <file> Change name of PID file.\n" > + "\n" > + "libvirt lock management daemon:\n"), argv0); s/lock/log/ > + > + if (privileged) { > + fprintf(stderr, > + _("\n" > + " Default paths:\n" > + "\n" > + " Configuration file (unless overridden by -f):\n" > + " %s/libvirt/virtlogd.conf\n" > + "\n" > + " Sockets:\n" > + " %s/run/libvirt/virtlogd-sock\n" > + "\n" > + " PID file (unless overridden by -p):\n" > + " %s/run/virtlogd.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/virtlogd.conf\n" > + "\n" > + " Sockets:\n" > + " $XDG_RUNTIME_DIR/libvirt/virtlogd-sock\n" > + "\n" > + " PID file:\n" > + " $XDG_RUNTIME_DIR/libvirt/virtlogd.pid\n" > + "\n")); > + } > +} > + > +#define MAX_LISTEN 5 > +int main(int argc, char **argv) { > + virNetServerProgramPtr logProgram = NULL; > + char *remote_config_file = NULL; > + int statuswrite = -1; > + int ret = 1; > + int verbose = 0; > + int godaemon = 0; > + char *run_dir = NULL; > + char *pid_file = NULL; > + int pid_file_fd = -1; > + char *sock_file = NULL; > + int timeout = -1; /* -t: Shutdown timeout */ > + char *state_file = NULL; > + bool implicit_conf = false; > + mode_t old_umask; > + bool privileged = false; > + virLogDaemonConfigPtr config = NULL; > + int rv; > + > + struct option opts[] = { > + { "verbose", no_argument, &verbose, 'v'}, > + { "daemon", no_argument, &godaemon, 'd'}, > + { "config", required_argument, NULL, 'f'}, > + { "timeout", required_argument, NULL, 't'}, > + { "pid-file", required_argument, NULL, 'p'}, > + { "version", no_argument, NULL, 'V' }, > + { "help", no_argument, NULL, 'h' }, > + {0, 0, 0, 0} > + }; > + > + privileged = geteuid() == 0; > + > + if (setlocale(LC_ALL, "") == NULL || > + bindtextdomain(PACKAGE, LOCALEDIR) == NULL || > + textdomain(PACKAGE) == NULL || > + virThreadInitialize() < 0 || > + virErrorInitialize() < 0) { > + fprintf(stderr, _("%s: initialization failed\n"), argv[0]); > + exit(EXIT_FAILURE); > + } > + > + while (1) { > + int optidx = 0; > + int c; > + char *tmp; > + > + c = getopt_long(argc, argv, "ldf:p:t:vVh", opts, &optidx); ^ Is 'l' valid? Same for lockd BTW > + > + if (c == -1) > + break; > + > + switch (c) { > + case 0: > + /* Got one of the flags */ > + break; > + case 'v': > + verbose = 1; > + break; > + case 'd': > + godaemon = 1; > + break; > + > + case 't': > + if (virStrToLong_i(optarg, &tmp, 10, &timeout) != 0 > + || timeout <= 0 > + /* Ensure that we can multiply by 1000 without overflowing. */ > + || timeout > INT_MAX / 1000) { > + VIR_ERROR(_("Invalid value for timeout")); > + exit(EXIT_FAILURE); > + } > + break; > + > + case 'p': > + VIR_FREE(pid_file); > + if (VIR_STRDUP_QUIET(pid_file, optarg) < 0) > + goto no_memory; > + break; > + > + case 'f': > + VIR_FREE(remote_config_file); > + if (VIR_STRDUP_QUIET(remote_config_file, optarg) < 0) > + goto no_memory; > + break; > + > + case 'V': > + virLogDaemonVersion(argv[0]); > + exit(EXIT_SUCCESS); > + > + case 'h': > + virLogDaemonUsage(argv[0], privileged); > + exit(EXIT_SUCCESS); > + > + case '?': > + default: > + virLogDaemonUsage(argv[0], privileged); > + exit(EXIT_FAILURE); > + } > + } > + > + virFileActivateDirOverride(argv[0]); > + > + if (!(config = virLogDaemonConfigNew(privileged))) { > + VIR_ERROR(_("Can't create initial configuration")); > + exit(EXIT_FAILURE); > + } > + > + /* No explicit config, so try and find a default one */ > + if (remote_config_file == NULL) { > + implicit_conf = true; > + if (virLogDaemonConfigFilePath(privileged, > + &remote_config_file) < 0) { ^ Extra space > + VIR_ERROR(_("Can't determine config path")); > + exit(EXIT_FAILURE); > + } > + } > + > + /* Read the config file if it exists*/ > + if (remote_config_file && > + virLogDaemonConfigLoadFile(config, remote_config_file, implicit_conf) < 0) { > + virErrorPtr err = virGetLastError(); > + if (err && err->message) > + VIR_ERROR(_("Can't load config file: %s: %s"), > + err->message, remote_config_file); > + else > + VIR_ERROR(_("Can't load config file: %s"), remote_config_file); > + exit(EXIT_FAILURE); > + } > + > + if (virLogDaemonSetupLogging(config, privileged, verbose, godaemon) < 0) { > + VIR_ERROR(_("Can't initialize logging")); > + exit(EXIT_FAILURE); > + } > + > + if (!pid_file && > + virPidFileConstructPath(privileged, > + LOCALSTATEDIR, > + "virtlogd", > + &pid_file) < 0) { > + VIR_ERROR(_("Can't determine pid file path.")); > + exit(EXIT_FAILURE); > + } > + VIR_DEBUG("Decided on pid file path '%s'", NULLSTR(pid_file)); > + > + if (virLogDaemonUnixSocketPaths(privileged, > + &sock_file) < 0) { ^ Extra space (repeats a couple times...)) > + VIR_ERROR(_("Can't determine socket paths")); > + exit(EXIT_FAILURE); > + } > + VIR_DEBUG("Decided on socket paths '%s'", > + sock_file); > + > + if (virLogDaemonExecRestartStatePath(privileged, > + &state_file) < 0) { extra space > + VIR_ERROR(_("Can't determine restart state file path")); > + exit(EXIT_FAILURE); > + } > + VIR_DEBUG("Decided on restart state file path '%s'", > + state_file); > + > + /* Ensure the rundir exists (on tmpfs on some systems) */ > + if (privileged) { > + if (VIR_STRDUP_QUIET(run_dir, LOCALSTATEDIR "/run/libvirt") < 0) > + goto no_memory; > + } else { > + if (!(run_dir = virGetUserRuntimeDirectory())) { > + VIR_ERROR(_("Can't determine user directory")); > + goto cleanup; > + } > + } > + > + if (privileged) > + old_umask = umask(022); > + else > + old_umask = umask(077); > + VIR_DEBUG("Ensuring run dir '%s' exists", run_dir); > + if (virFileMakePath(run_dir) < 0) { > + char ebuf[1024]; > + VIR_ERROR(_("unable to create rundir %s: %s"), run_dir, > + virStrerror(errno, ebuf, sizeof(ebuf))); > + ret = VIR_LOG_DAEMON_ERR_RUNDIR; should we umask(old_umask) here? > + goto cleanup; > + } > + umask(old_umask); > + > + if ((rv = virLogDaemonPostExecRestart(state_file, > + pid_file, > + &pid_file_fd, > + privileged)) < 0) { > + ret = VIR_LOG_DAEMON_ERR_INIT; > + goto cleanup; > + } > + > + /* rv == 1, means we setup everything from saved state, > + * so only (possibly) daemonize and setup stuff from > + * scratch if rv == 0 > + */ > + if (rv == 0) { > + if (godaemon) { > + char ebuf[1024]; > + > + if (chdir("/") < 0) { > + VIR_ERROR(_("cannot change to root directory: %s"), > + virStrerror(errno, ebuf, sizeof(ebuf))); > + goto cleanup; > + } > + > + if ((statuswrite = virLogDaemonForkIntoBackground(argv[0])) < 0) { > + VIR_ERROR(_("Failed to fork as daemon: %s"), > + virStrerror(errno, ebuf, sizeof(ebuf))); > + goto cleanup; > + } > + } > + > + /* If we have a pidfile set, claim it now, exiting if already taken */ > + if ((pid_file_fd = virPidFileAcquirePath(pid_file, false, getpid())) < 0) { > + ret = VIR_LOG_DAEMON_ERR_PIDFILE; > + goto cleanup; > + } > + > + if (!(logDaemon = virLogDaemonNew(config, privileged))) { > + ret = VIR_LOG_DAEMON_ERR_INIT; > + goto cleanup; > + } > + > + if ((rv = virLogDaemonSetupNetworkingSystemD(logDaemon->srv)) < 0) { > + ret = VIR_LOG_DAEMON_ERR_NETWORK; > + goto cleanup; > + } > + > + /* Only do this, if systemd did not pass a FD */ > + if (rv == 0 && > + virLogDaemonSetupNetworkingNative(logDaemon->srv, sock_file) < 0) { > + ret = VIR_LOG_DAEMON_ERR_NETWORK; > + goto cleanup; > + } > + } > + > + if (timeout != -1) { > + VIR_DEBUG("Registering shutdown timeout %d", timeout); > + virNetDaemonAutoShutdown(logDaemon->dmn, > + timeout); > + } > + > + if ((virLogDaemonSetupSignals(logDaemon->dmn)) < 0) { > + ret = VIR_LOG_DAEMON_ERR_SIGNAL; > + goto cleanup; > + } > + > + if (!(logProgram = virNetServerProgramNew(VIR_LOG_MANAGER_PROTOCOL_PROGRAM, > + VIR_LOG_MANAGER_PROTOCOL_PROGRAM_VERSION, > + virLogManagerProtocolProcs, > + virLogManagerProtocolNProcs))) { > + ret = VIR_LOG_DAEMON_ERR_INIT; > + goto cleanup; > + } > + if (virNetServerAddProgram(logDaemon->srv, logProgram) < 0) { > + ret = VIR_LOG_DAEMON_ERR_INIT; > + goto cleanup; > + } > + > + /* Disable error func, now logging is setup */ > + virSetErrorFunc(NULL, virLogDaemonErrorHandler); > + > + > + There's an extra line here. /* Tell parent of daemon that basic initialization is complete > + * In particular we're ready to accept net connections & have > + * written the pidfile > + */ > + if (statuswrite != -1) { > + char status = 0; > + while (write(statuswrite, &status, 1) == -1 && > + errno == EINTR) > + ; > + VIR_FORCE_CLOSE(statuswrite); > + } > + > + /* Start accepting new clients from network */ > + > + virNetServerUpdateServices(logDaemon->srv, true); > + virNetDaemonRun(logDaemon->dmn); > + > + if (execRestart && > + virLogDaemonPreExecRestart(state_file, > + logDaemon->dmn, > + argv) < 0) > + ret = VIR_LOG_DAEMON_ERR_REEXEC; > + else > + ret = 0; > + > + cleanup: > + virObjectUnref(logProgram); > + virLogDaemonFree(logDaemon); > + if (statuswrite != -1) { > + if (ret != 0) { > + /* Tell parent of daemon what failed */ > + char status = ret; > + while (write(statuswrite, &status, 1) == -1 && > + errno == EINTR) > + ; > + } > + VIR_FORCE_CLOSE(statuswrite); > + } > + if (pid_file_fd != -1) > + virPidFileReleasePath(pid_file, pid_file_fd); > + VIR_FREE(pid_file); > + VIR_FREE(sock_file); > + VIR_FREE(state_file); > + VIR_FREE(run_dir); > + return ret; > + > + no_memory: > + VIR_ERROR(_("Can't allocate memory")); > + exit(EXIT_FAILURE); > +} [...] Admittedly I know very little about the log_protocol.x and other src/logging/* files from here... I do note that test_virtlogd.aug.in doesn't have 'max_clients', although virtlogd.aug has a reference. I also note there's a log_buffer_size listed, but no corresponding element in the virLogDaemonConfig (or of course read of such element). > diff --git a/src/logging/virtlogd.pod.in b/src/logging/virtlogd.pod.in > new file mode 100644 > index 0000000..bba7714 > --- /dev/null > +++ b/src/logging/virtlogd.pod.in > @@ -0,0 +1,162 @@ > +=head1 NAME > + > +virtlogd - libvirt log management daemon > + > +=head1 SYNOPSIS > + > +B<virtlogd> [ -dv ] [ -f config_file ] [ -p pid_file ] 't' timeout? 'V' version (yes, I see --version) > + > +B<virtlogd> --version > + > +=head1 DESCRIPTION > + > +The B<virtlogd> program is a server side daemon component of the libvirt > +virtualization management system that is used to manage logs from virtual > +machine consoles. > + > +This daemon is not used directly by libvirt client applications, rather it > +is called on their behalf by B<libvirtd>. By maintaining the logs in a > +standalone daemon, the main libvirtd daemon can be restarted without risk > +of losing logs. The B<virtlogd> daemon has the ability to re-exec() > +itself upon receiving SIGUSR1, to allow live upgrades without downtime. > + > +The virtlogd daemon listens for requests on a local Unix domain socket. > + > +=head1 OPTIONS > + > +=over > + > +=item B<-h, --help> > + > +Display command line help usage then exit. > + > +=item B<-d, --daemon> > + > +Run as a daemon and write PID file. > + > +=item B<-f, --config> I<FILE> > + > +Use this configuration file, overriding the default value. > + > +=item B<-p, --pid-file> I<FILE> > + > +Use this name for the PID file, overriding the default value. > + > +=item B<-v, --verbose> > + > +Enable output of verbose messages. > + > +=item B<-V, --version> > + 't' 'timeout'... > +Display version information then exit. > + > +=back > + > +=head1 SIGNALS > + > +On receipt of B<SIGUSR1> virtlogd will re-exec() its binary, while > +maintaining all current logs and clients. This allows for live > +upgrades of the virtlogd service. > + > +=head1 FILES > + > +=head2 When run as B<root>. > + > +=over > + > +=item F<SYSCONFDIR/virtlogd.conf> > + > +The default configuration file used by virtlogd, unless overridden on the > +command line using the B<-f>|B<--config> option. > + > +=item F<LOCALSTATEDIR/run/libvirt/virtlogd-sock> > + > +The sockets libvirtd will use. > + > +=item F<LOCALSTATEDIR/run/virtlogd.pid> > + > +The PID file to use, unless overridden by the B<-p>|B<--pid-file> option. > + > +=back > + > +=head2 When run as B<non-root>. > + > +=over > + > +=item F<$XDG_CONFIG_HOME/virtlogd.conf> > + > +The default configuration file used by libvirtd, unless overridden on the > +command line using the B<-f>|B<--config> option. > + > +=item F<$XDG_RUNTIME_DIR/libvirt/virtlogd-sock> > + > +The socket libvirtd will use. > + > +=item F<$XDG_RUNTIME_DIR/libvirt/virtlogd.pid> > + > +The PID file to use, unless overridden by the B<-p>|B<--pid-file> option. > + > +=item If $XDG_CONFIG_HOME is not set in your environment, libvirtd will use F<$HOME/.config> > + > +=item If $XDG_RUNTIME_DIR is not set in your environment, libvirtd will use F<$HOME/.cache> > + > +=back > + > +=head1 EXAMPLES > + > +To retrieve the version of virtlogd: > + > + # virtlogd --version > + virtlogd (libvirt) 1.1.1 > + # > + > +To start virtlogd, instructing it to daemonize and create a PID file: > + > + # virtlogd -d > + # ls -la LOCALSTATEDIR/run/virtlogd.pid > + -rw-r--r-- 1 root root 6 Jul 9 02:40 LOCALSTATEDIR/run/virtlogd.pid > + # > + > +=head1 BUGS > + > +Please report all bugs you discover. This should be done via either: > + > +=over > + > +=item a) the mailing list > + > +L<http://libvirt.org/contact.html> > + > +=item or, > + > +B<> > + > +=item b) the bug tracker > + > +L<http://libvirt.org/bugs.html> > + > +=item Alternatively, you may report bugs to your software distributor / vendor. > + > +=back > + > +=head1 AUTHORS > + > +Please refer to the AUTHORS file distributed with libvirt. > + > +=head1 COPYRIGHT > + > +Copyright (C) 2006-2015 Red Hat, Inc., and the authors listed in the > +libvirt AUTHORS file. > + > +=head1 LICENSE > + > +virtlogd is distributed under the terms of the GNU LGPL v2.1+. > +This is free software; see the source for copying conditions. There > +is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR > +PURPOSE > + > +=head1 SEE ALSO > + > +L<libvirtd(8)>, L<http://www.libvirt.org/> > + > +=cut ACK - with a couple of minor adjustments. John -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list