[libvirt] [PATCH v2 02/13] Import stripped down virtlockd code as basis of virtlogd
John Ferlan
jferlan at redhat.com
Wed Nov 18 16:11:44 UTC 2015
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 at redhat.com>
> ---
> .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 at redhat.com>
> + */
[...]
> +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
More information about the libvir-list
mailing list