From: Daniel P. Berrange Date: Tue, 3 Nov 2015 11:01:21 +0000 (+0000) Subject: logging: introduce log handling protocol X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=19e5db4ae2cf8afea75b261258dd7327ed966cfc;p=people%2Fliuw%2Flibxenctrl-split%2Flibvirt.git logging: introduce log handling protocol Define a new RPC protocol for the virtlogd daemon that provides for handling of logs. The initial RPC method defined allows a client to obtain a file handle to use for writing to a log file for a guest domain. The file handle passed back will not actually refer to the log file, but rather an anonymous pipe. The virtlogd daemon will forward I/O between them, ensuring file rotation happens when required. Initially the log setup is hardcoded to cap log files at 128 KB, and keep 3 backups when rolling over, which gives a max usage of 512 KB per guest. Signed-off-by: Daniel P. Berrange --- diff --git a/po/POTFILES.in b/po/POTFILES.in index 33bc25869..725ec668c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -80,6 +80,8 @@ src/locking/lock_manager.c src/locking/sanlock_helper.c src/logging/log_daemon.c src/logging/log_daemon_config.c +src/logging/log_daemon_dispatch.c +src/logging/log_handler.c src/lxc/lxc_cgroup.c src/lxc/lxc_fuse.c src/lxc/lxc_hostdev.c diff --git a/src/Makefile.am b/src/Makefile.am index 3323bd138..c658204b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -268,6 +268,8 @@ LOG_PROTOCOL_GENERATED = \ logging/log_protocol.c \ $(NULL) +DRIVER_SOURCES += $(LOG_PROTOCOL_GENERATED) + LOG_PROTOCOL = $(srcdir)/logging/log_protocol.x EXTRA_DIST += $(LOG_PROTOCOL) \ $(LOG_PROTOCOL_GENERATED) @@ -289,6 +291,8 @@ LOG_DAEMON_SOURCES = \ logging/log_daemon_config.c \ logging/log_daemon_dispatch.c \ logging/log_daemon_dispatch.h \ + logging/log_handler.c \ + logging/log_handler.h \ $(NULL) logging/log_daemon_dispatch_stubs.h: $(LOG_PROTOCOL) \ diff --git a/src/logging/log_daemon.c b/src/logging/log_daemon.c index c3d7cbc83..7a1afecff 100644 --- a/src/logging/log_daemon.c +++ b/src/logging/log_daemon.c @@ -60,6 +60,7 @@ struct _virLogDaemon { virMutex lock; virNetDaemonPtr dmn; virNetServerPtr srv; + virLogHandlerPtr handler; }; virLogDaemonPtr logDaemon = NULL; @@ -114,6 +115,7 @@ virLogDaemonFree(virLogDaemonPtr logd) if (!logd) return; + virObjectUnref(logd->handler); virMutexDestroy(&logd->lock); virObjectUnref(logd->srv); virObjectUnref(logd->dmn); @@ -150,6 +152,9 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged) virNetDaemonAddServer(logd->dmn, logd->srv) < 0) goto error; + if (!(logd->handler = virLogHandlerNew(privileged))) + goto error; + return logd; error: @@ -158,6 +163,13 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged) } +virLogHandlerPtr +virLogDaemonGetHandler(virLogDaemonPtr daemon) +{ + return daemon->handler; +} + + static virLogDaemonPtr virLogDaemonNewPostExecRestart(virJSONValuePtr object, bool privileged) { @@ -191,6 +203,16 @@ virLogDaemonNewPostExecRestart(virJSONValuePtr object, bool privileged) (void*)(intptr_t)(privileged ? 0x1 : 0x0)))) goto error; + if (!(child = virJSONValueObjectGet(object, "handler"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed daemon data from JSON file")); + goto error; + } + + if (!(logd->handler = virLogHandlerNewPostExecRestart(child, + privileged))) + goto error; + return logd; error: @@ -774,6 +796,15 @@ virLogDaemonPreExecRestart(const char *state_file, goto cleanup; } + if (!(child = virLogHandlerPreExecRestart(logDaemon->handler))) + goto cleanup; + + if (virJSONValueObjectAppend(object, "handler", child) < 0) { + virJSONValueFree(child); + goto cleanup; + } + + if (!(state = virJSONValueToString(object, true))) goto cleanup; diff --git a/src/logging/log_daemon.h b/src/logging/log_daemon.h index a1531604d..b076a4f3b 100644 --- a/src/logging/log_daemon.h +++ b/src/logging/log_daemon.h @@ -24,6 +24,7 @@ # define __VIR_LOG_DAEMON_H__ # include "virthread.h" +# include "log_handler.h" typedef struct _virLogDaemon virLogDaemon; typedef virLogDaemon *virLogDaemonPtr; @@ -39,4 +40,6 @@ struct _virLogDaemonClient { extern virLogDaemonPtr logDaemon; +virLogHandlerPtr virLogDaemonGetHandler(virLogDaemonPtr daemon); + #endif /* __VIR_LOG_DAEMON_H__ */ diff --git a/src/logging/log_daemon_dispatch.c b/src/logging/log_daemon_dispatch.c index 98df178b7..269255ad5 100644 --- a/src/logging/log_daemon_dispatch.c +++ b/src/logging/log_daemon_dispatch.c @@ -29,9 +29,115 @@ #include "log_daemon.h" #include "log_protocol.h" #include "virerror.h" +#include "virthreadjob.h" +#include "virfile.h" #define VIR_FROM_THIS VIR_FROM_RPC VIR_LOG_INIT("logging.log_daemon_dispatch"); #include "log_daemon_dispatch_stubs.h" + +static int +virLogManagerProtocolDispatchDomainOpenLogFile(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg, + virNetMessageErrorPtr rerr, + virLogManagerProtocolDomainOpenLogFileArgs *args, + virLogManagerProtocolDomainOpenLogFileRet *ret) +{ + int fd = -1; + int rv = -1; + off_t offset; + ino_t inode; + + if ((fd = virLogHandlerDomainOpenLogFile(virLogDaemonGetHandler(logDaemon), + args->driver, + (unsigned char *)args->dom.uuid, + args->dom.name, + &inode, &offset)) < 0) + goto cleanup; + + ret->pos.inode = inode; + ret->pos.offset = offset; + + if (virNetMessageAddFD(msg, fd) < 0) + goto cleanup; + + rv = 1; /* '1' tells caller we added some FDs */ + + cleanup: + VIR_FORCE_CLOSE(fd); + if (rv < 0) + virNetMessageSaveError(rerr); + return rv; +} + + +static int +virLogManagerProtocolDispatchDomainGetLogFilePosition(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + virLogManagerProtocolDomainGetLogFilePositionArgs *args, + virLogManagerProtocolDomainGetLogFilePositionRet *ret) +{ + int rv = -1; + off_t offset; + ino_t inode; + + if (virLogHandlerDomainGetLogFilePosition(virLogDaemonGetHandler(logDaemon), + args->driver, + (unsigned char *)args->dom.uuid, + args->dom.name, + &inode, &offset) < 0) + goto cleanup; + + ret->pos.inode = inode; + ret->pos.offset = offset; + + rv = 0; + cleanup: + + if (rv < 0) + virNetMessageSaveError(rerr); + return rv; +} + + +static int +virLogManagerProtocolDispatchDomainReadLogFile(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + virLogManagerProtocolDomainReadLogFileArgs *args, + virLogManagerProtocolDomainReadLogFileRet *ret) +{ + int rv = -1; + char *data; + + if (args->maxlen > VIR_LOG_MANAGER_PROTOCOL_STRING_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Requested data len %zu is larger than maximum %d"), + args->maxlen, VIR_LOG_MANAGER_PROTOCOL_STRING_MAX); + goto cleanup; + } + + if ((data = virLogHandlerDomainReadLogFile(virLogDaemonGetHandler(logDaemon), + args->driver, + (unsigned char *)args->dom.uuid, + args->dom.name, + args->pos.inode, + args->pos.offset, + args->maxlen)) == NULL) + goto cleanup; + + ret->data = data; + + rv = 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + return rv; +} diff --git a/src/logging/log_handler.c b/src/logging/log_handler.c new file mode 100644 index 000000000..2acbca7de --- /dev/null +++ b/src/logging/log_handler.c @@ -0,0 +1,555 @@ +/* + * log_handler.c: log management daemon handler + * + * Copyright (C) 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 + * . + * + * Author: Daniel P. Berrange + */ + +#include + +#include "log_handler.h" +#include "virerror.h" +#include "virobject.h" +#include "virfile.h" +#include "viralloc.h" +#include "virstring.h" +#include "virlog.h" +#include "virrotatingfile.h" + +#include +#include + +#include "configmake.h" + +VIR_LOG_INIT("logging.log_handler"); + +#define VIR_FROM_THIS VIR_FROM_LOGGING + +#define DEFAULT_FILE_SIZE (128 * 1024) +#define DEFAULT_MAX_BACKUP 3 +#define DEFAULT_MODE 0600 + +typedef struct _virLogHandlerLogFile virLogHandlerLogFile; +typedef virLogHandlerLogFile *virLogHandlerLogFilePtr; + +struct _virLogHandlerLogFile { + virRotatingFileWriterPtr file; + int watch; + int pipefd; /* Read from QEMU via this */ +}; + +struct _virLogHandler { + virObjectLockable parent; + + bool privileged; + virLogHandlerLogFilePtr *files; + size_t nfiles; +}; + +static virClassPtr virLogHandlerClass; +static void virLogHandlerDispose(void *obj); + +static int +virLogHandlerOnceInit(void) +{ + if (!(virLogHandlerClass = virClassNew(virClassForObjectLockable(), + "virLogHandler", + sizeof(virLogHandler), + virLogHandlerDispose))) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virLogHandler) + + +static void +virLogHandlerLogFileFree(virLogHandlerLogFilePtr file) +{ + if (!file) + return; + + VIR_FORCE_CLOSE(file->pipefd); + virRotatingFileWriterFree(file->file); + + if (file->watch != -1) + virEventRemoveHandle(file->watch); + VIR_FREE(file); +} + + +static void +virLogHandlerLogFileClose(virLogHandlerPtr handler, + virLogHandlerLogFilePtr file) +{ + size_t i; + + for (i = 0; i < handler->nfiles; i++) { + if (handler->files[i] == file) { + VIR_DELETE_ELEMENT(handler->files, i, handler->nfiles); + virLogHandlerLogFileFree(file); + break; + } + } +} + + +static virLogHandlerLogFilePtr +virLogHandlerGetLogFileFromWatch(virLogHandlerPtr handler, + int watch) +{ + size_t i; + + for (i = 0; i < handler->nfiles; i++) { + if (handler->files[i]->watch == watch) + return handler->files[i]; + } + + return NULL; +} + + +static void +virLogHandlerDomainLogFileEvent(int watch, + int fd, + int events, + void *opaque) +{ + virLogHandlerPtr handler = opaque; + virLogHandlerLogFilePtr logfile; + char buf[1024]; + ssize_t len; + + virObjectLock(handler); + logfile = virLogHandlerGetLogFileFromWatch(handler, watch); + if (!logfile || logfile->pipefd != fd) { + virEventRemoveHandle(watch); + virObjectUnlock(handler); + return; + } + + reread: + len = read(fd, buf, sizeof(buf)); + if (len < 0) { + if (errno == EINTR) + goto reread; + + virReportSystemError(errno, "%s", + _("Unable to read from log pipe")); + goto error; + } + + if (virRotatingFileWriterAppend(logfile->file, buf, len) != len) + goto error; + + if (events & VIR_EVENT_HANDLE_HANGUP) + goto error; + + virObjectUnlock(handler); + return; + + error: + virLogHandlerLogFileClose(handler, logfile); + virObjectUnlock(handler); +} + + +virLogHandlerPtr +virLogHandlerNew(bool privileged) +{ + virLogHandlerPtr handler; + + if (virLogHandlerInitialize() < 0) + goto error; + + if (!(handler = virObjectLockableNew(virLogHandlerClass))) + goto error; + + handler->privileged = privileged; + + return handler; + + error: + return NULL; +} + + +static virLogHandlerLogFilePtr +virLogHandlerLogFilePostExecRestart(virJSONValuePtr object) +{ + virLogHandlerLogFilePtr file; + const char *path; + + if (VIR_ALLOC(file) < 0) + return NULL; + + if ((path = virJSONValueObjectGetString(object, "path")) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing file path in JSON document")); + goto error; + } + + if ((file->file = virRotatingFileWriterNew(path, + DEFAULT_FILE_SIZE, + DEFAULT_MAX_BACKUP, + false, + DEFAULT_MODE)) == NULL) + goto error; + + if (virJSONValueObjectGetNumberInt(object, "pipefd", &file->pipefd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing file pipefd in JSON document")); + goto error; + } + if (virSetInherit(file->pipefd, false) < 0) { + virReportSystemError(errno, "%s", + _("Cannot enable close-on-exec flag")); + goto error; + } + + return file; + + error: + virLogHandlerLogFileFree(file); + return NULL; +} + + +virLogHandlerPtr +virLogHandlerNewPostExecRestart(virJSONValuePtr object, + bool privileged) +{ + virLogHandlerPtr handler; + virJSONValuePtr files; + ssize_t n; + size_t i; + + if (!(handler = virLogHandlerNew(privileged))) + return NULL; + + if (!(files = virJSONValueObjectGet(object, "files"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing files data from JSON file")); + goto error; + } + + if ((n = virJSONValueArraySize(files)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed files data from JSON file")); + goto error; + } + + for (i = 0; i < n; i++) { + virLogHandlerLogFilePtr file; + virJSONValuePtr child = virJSONValueArrayGet(files, i); + + if (!(file = virLogHandlerLogFilePostExecRestart(child))) + goto error; + + if (VIR_APPEND_ELEMENT_COPY(handler->files, handler->nfiles, file) < 0) + goto error; + + if ((file->watch = virEventAddHandle(file->pipefd, + VIR_EVENT_HANDLE_READABLE, + virLogHandlerDomainLogFileEvent, + handler, + NULL)) < 0) { + VIR_DELETE_ELEMENT(handler->files, handler->nfiles - 1, handler->nfiles); + goto error; + } + } + + + return handler; + + error: + virObjectUnref(handler); + return NULL; +} + + +static void +virLogHandlerDispose(void *obj) +{ + virLogHandlerPtr handler = obj; + size_t i; + + for (i = 0; i < handler->nfiles; i++) + virLogHandlerLogFileFree(handler->files[i]); + VIR_FREE(handler->files); +} + + +static char * +virLogHandlerGetLogFilePathForDomain(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid ATTRIBUTE_UNUSED, + const char *domname) +{ + char *path; + if (handler->privileged) { + if (virAsprintf(&path, + LOCALSTATEDIR "/log/libvirt/%s/%s.log", + driver, domname) < 0) + return NULL; + } else { + char *cachedir; + + cachedir = virGetUserCacheDirectory(); + if (!cachedir) + return NULL; + + if (virAsprintf(&path, + "%s/%s/log/%s.log", cachedir, driver, domname) < 0) { + VIR_FREE(cachedir); + return NULL; + } + + } + return path; +} + + +int +virLogHandlerDomainOpenLogFile(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid ATTRIBUTE_UNUSED, + const char *domname, + ino_t *inode, + off_t *offset) +{ + size_t i; + virLogHandlerLogFilePtr file = NULL; + int pipefd[2] = { -1, -1 }; + char *path; + + virObjectLock(handler); + + if (!(path = virLogHandlerGetLogFilePathForDomain(handler, + driver, + domuuid, + domname))) + goto error; + + for (i = 0; i < handler->nfiles; i++) { + if (STREQ(virRotatingFileWriterGetPath(handler->files[i]->file), + path)) { + virReportSystemError(EBUSY, + _("Cannot open log file: '%s'"), + path); + goto error; + } + } + + if (pipe(pipefd) < 0) { + virReportSystemError(errno, "%s", + _("Cannot open fifo pipe")); + goto error; + } + if (VIR_ALLOC(file) < 0) + goto error; + + file->watch = -1; + file->pipefd = pipefd[0]; + pipefd[0] = -1; + + if ((file->file = virRotatingFileWriterNew(path, + DEFAULT_FILE_SIZE, + DEFAULT_MAX_BACKUP, + false, + DEFAULT_MODE)) == NULL) + goto error; + + if (VIR_APPEND_ELEMENT_COPY(handler->files, handler->nfiles, file) < 0) + goto error; + + if ((file->watch = virEventAddHandle(file->pipefd, + VIR_EVENT_HANDLE_READABLE, + virLogHandlerDomainLogFileEvent, + handler, + NULL)) < 0) { + VIR_DELETE_ELEMENT(handler->files, handler->nfiles - 1, handler->nfiles); + goto error; + } + + VIR_FREE(path); + + *inode = virRotatingFileWriterGetINode(file->file); + *offset = virRotatingFileWriterGetOffset(file->file); + + virObjectUnlock(handler); + return pipefd[1]; + + error: + VIR_FREE(path); + VIR_FORCE_CLOSE(pipefd[0]); + VIR_FORCE_CLOSE(pipefd[1]); + virLogHandlerLogFileFree(file); + virObjectUnlock(handler); + return -1; +} + + +int +virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid, + const char *domname, + ino_t *inode, + off_t *offset) +{ + char *path; + virLogHandlerLogFilePtr file = NULL; + int ret = -1; + size_t i; + + virObjectLock(handler); + + if (!(path = virLogHandlerGetLogFilePathForDomain(handler, + driver, + domuuid, + domname))) + goto cleanup; + + for (i = 0; i < handler->nfiles; i++) { + if (STREQ(virRotatingFileWriterGetPath(handler->files[i]->file), + path)) { + file = handler->files[i]; + break; + } + } + + if (!file) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No open log file for domain %s"), + domname); + goto cleanup; + } + + *inode = virRotatingFileWriterGetINode(file->file); + *offset = virRotatingFileWriterGetOffset(file->file); + + ret = 0; + + cleanup: + VIR_FREE(path); + virObjectUnlock(handler); + return ret; +} + + +char * +virLogHandlerDomainReadLogFile(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid, + const char *domname, + ino_t inode, + off_t offset, + size_t maxlen) +{ + char *path; + virRotatingFileReaderPtr file = NULL; + char *data = NULL; + ssize_t got; + + virObjectLock(handler); + + if (!(path = virLogHandlerGetLogFilePathForDomain(handler, + driver, + domuuid, + domname))) + goto error; + + if (!(file = virRotatingFileReaderNew(path, DEFAULT_MAX_BACKUP))) + goto error; + + if (virRotatingFileReaderSeek(file, inode, offset) < 0) + goto error; + + if (VIR_ALLOC_N(data, maxlen + 1) < 0) + goto error; + + got = virRotatingFileReaderConsume(file, data, maxlen); + if (got < 0) + goto error; + data[got] = '\0'; + + virRotatingFileReaderFree(file); + virObjectUnlock(handler); + VIR_FREE(path); + return data; + + error: + VIR_FREE(path); + VIR_FREE(data); + virRotatingFileReaderFree(file); + virObjectUnlock(handler); + return NULL; +} + + +virJSONValuePtr +virLogHandlerPreExecRestart(virLogHandlerPtr handler) +{ + virJSONValuePtr ret = virJSONValueNewObject(); + virJSONValuePtr files; + size_t i; + + if (!ret) + return NULL; + + if (!(files = virJSONValueNewArray())) + goto error; + + if (virJSONValueObjectAppend(ret, "files", files) < 0) { + virJSONValueFree(files); + goto error; + } + + for (i = 0; i < handler->nfiles; i++) { + virJSONValuePtr file = virJSONValueNewObject(); + if (!file) + goto error; + + if (virJSONValueArrayAppend(files, file) < 0) { + virJSONValueFree(file); + goto error; + } + + if (virJSONValueObjectAppendNumberInt(file, "pipefd", + handler->files[i]->pipefd) < 0) + goto error; + + if (virJSONValueObjectAppendString(file, "path", + virRotatingFileWriterGetPath(handler->files[i]->file)) < 0) + goto error; + + if (virSetInherit(handler->files[i]->pipefd, true) < 0) { + virReportSystemError(errno, "%s", + _("Cannot disable close-on-exec flag")); + goto error; + } + } + + return ret; + + error: + virJSONValueFree(ret); + return NULL; +} diff --git a/src/logging/log_handler.h b/src/logging/log_handler.h new file mode 100644 index 000000000..1ad755e92 --- /dev/null +++ b/src/logging/log_handler.h @@ -0,0 +1,63 @@ +/* + * log_handler.h: log management daemon handler + * + * Copyright (C) 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 + * . + * + * Author: Daniel P. Berrange + */ + +#ifndef __VIR_LOG_HANDLER_H__ +# define __VIR_LOG_HANDLER_H__ + +# include "internal.h" +# include "virjson.h" + +typedef struct _virLogHandler virLogHandler; +typedef virLogHandler *virLogHandlerPtr; + + +virLogHandlerPtr virLogHandlerNew(bool privileged); +virLogHandlerPtr virLogHandlerNewPostExecRestart(virJSONValuePtr child, + bool privileged); + +void virLogHandlerFree(virLogHandlerPtr handler); + +int virLogHandlerDomainOpenLogFile(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid, + const char *domname, + ino_t *inode, + off_t *offset); + +int virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid, + const char *domname, + ino_t *inode, + off_t *offset); + +char *virLogHandlerDomainReadLogFile(virLogHandlerPtr handler, + const char *driver, + const unsigned char *domuuid, + const char *domname, + ino_t inode, + off_t offset, + size_t maxlen); + +virJSONValuePtr virLogHandlerPreExecRestart(virLogHandlerPtr handler); + +#endif /** __VIR_LOG_HANDLER_H__ */ diff --git a/src/logging/log_protocol.x b/src/logging/log_protocol.x index 1481c301f..de57c69df 100644 --- a/src/logging/log_protocol.x +++ b/src/logging/log_protocol.x @@ -17,6 +17,99 @@ typedef string virLogManagerProtocolNonNullString specifies at which offset the stream parameter is inserted + * in the function parameter list. + * + * - @priority: low|high + * + * Each API that might eventually access hypervisor's monitor (and thus + * block) MUST fall into low priority. However, there are some exceptions + * to this rule, e.g. domainDestroy. Other APIs MAY be marked as high + * priority. If in doubt, it's safe to choose low. Low is taken as default, + * and thus can be left out. + */ + + /** + * @generate: none + * @acl: none + */ + VIR_LOG_MANAGER_PROTOCOL_PROC_DOMAIN_OPEN_LOG_FILE = 1, + + /** + * @generate: none + * @acl: none + */ + VIR_LOG_MANAGER_PROTOCOL_PROC_DOMAIN_GET_LOG_FILE_POSITION = 2, + + /** + * @generate: none + * @acl: none + */ + VIR_LOG_MANAGER_PROTOCOL_PROC_DOMAIN_READ_LOG_FILE = 3 +};