mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu: introduce a qemuDomainLogContext object
Introduce a qemuDomainLogContext object to encapsulate handling of I/O to/from the domain log file. This will hide details of the log file implementation from the rest of the driver, making it easier to introduce support for virtlogd later. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
69b0992178
commit
4d1b771fbb
@ -40,6 +40,7 @@
|
||||
#include "virstoragefile.h"
|
||||
#include "virstring.h"
|
||||
#include "virthreadjob.h"
|
||||
#include "viratomic.h"
|
||||
|
||||
#include "storage/storage_driver.h"
|
||||
|
||||
@ -77,6 +78,13 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST,
|
||||
);
|
||||
|
||||
|
||||
struct _qemuDomainLogContext {
|
||||
int refs;
|
||||
int writefd;
|
||||
int readfd;
|
||||
off_t pos;
|
||||
};
|
||||
|
||||
const char *
|
||||
qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job,
|
||||
int phase ATTRIBUTE_UNUSED)
|
||||
@ -2249,6 +2257,183 @@ void qemuDomainObjCheckNetTaint(virQEMUDriverPtr driver,
|
||||
}
|
||||
|
||||
|
||||
qemuDomainLogContextPtr qemuDomainLogContextNew(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
qemuDomainLogContextMode mode)
|
||||
{
|
||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
qemuDomainLogContextPtr ctxt = NULL;
|
||||
char *logfile = NULL;
|
||||
|
||||
if (VIR_ALLOC(ctxt) < 0)
|
||||
goto error;
|
||||
|
||||
ctxt->writefd = -1;
|
||||
ctxt->readfd = -1;
|
||||
virAtomicIntSet(&ctxt->refs, 1);
|
||||
|
||||
if (virAsprintf(&logfile, "%s/%s.log", cfg->logDir, vm->def->name) < 0)
|
||||
goto error;
|
||||
|
||||
if ((ctxt->writefd = open(logfile, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) {
|
||||
virReportSystemError(errno, _("failed to create logfile %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
if (virSetCloseExec(ctxt->writefd) < 0) {
|
||||
virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* For unprivileged startup we must truncate the file since
|
||||
* we can't rely on logrotate. We don't use O_TRUNC since
|
||||
* it is better for SELinux policy if we truncate afterwards */
|
||||
if (mode == QEMU_DOMAIN_LOG_CONTEXT_MODE_START &&
|
||||
!virQEMUDriverIsPrivileged(driver) &&
|
||||
ftruncate(ctxt->writefd, 0) < 0) {
|
||||
virReportSystemError(errno, _("failed to truncate %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mode == QEMU_DOMAIN_LOG_CONTEXT_MODE_START) {
|
||||
if ((ctxt->readfd = open(logfile, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) {
|
||||
virReportSystemError(errno, _("failed to open logfile %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
if (virSetCloseExec(ctxt->readfd) < 0) {
|
||||
virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END)) < 0) {
|
||||
virReportSystemError(errno, _("failed to seek in log file %s"),
|
||||
logfile);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
virObjectUnref(cfg);
|
||||
return ctxt;
|
||||
|
||||
error:
|
||||
virObjectUnref(cfg);
|
||||
qemuDomainLogContextFree(ctxt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int qemuDomainLogContextWrite(qemuDomainLogContextPtr ctxt,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char *message = NULL;
|
||||
int ret = -1;
|
||||
|
||||
va_start(argptr, fmt);
|
||||
|
||||
if (virVasprintf(&message, fmt, argptr) < 0)
|
||||
goto cleanup;
|
||||
if (lseek(ctxt->writefd, 0, SEEK_END) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to see to end of domain logfile"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (safewrite(ctxt->writefd, message, strlen(message)) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to write to domain logfile"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
va_end(argptr);
|
||||
VIR_FREE(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ssize_t qemuDomainLogContextRead(qemuDomainLogContextPtr ctxt,
|
||||
char **msg)
|
||||
{
|
||||
char *buf;
|
||||
size_t buflen = 1024 * 128;
|
||||
ssize_t got;
|
||||
|
||||
/* Best effort jump to start of messages */
|
||||
ignore_value(lseek(ctxt->readfd, ctxt->pos, SEEK_SET));
|
||||
|
||||
if (VIR_ALLOC_N(buf, buflen) < 0)
|
||||
return -1;
|
||||
|
||||
got = saferead(ctxt->readfd, buf, buflen - 1);
|
||||
if (got < 0) {
|
||||
VIR_FREE(buf);
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to read from log file"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[got] = '\0';
|
||||
|
||||
ignore_value(VIR_REALLOC_N_QUIET(buf, got + 1));
|
||||
*msg = buf;
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
|
||||
int qemuDomainLogContextGetWriteFD(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
return ctxt->writefd;
|
||||
}
|
||||
|
||||
|
||||
int qemuDomainLogContextGetReadFD(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
return ctxt->readfd;
|
||||
}
|
||||
|
||||
|
||||
void qemuDomainLogContextMarkPosition(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END);
|
||||
}
|
||||
|
||||
|
||||
off_t qemuDomainLogContextGetPosition(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
return ctxt->pos;
|
||||
}
|
||||
|
||||
|
||||
void qemuDomainLogContextRef(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
virAtomicIntInc(&ctxt->refs);
|
||||
}
|
||||
|
||||
|
||||
void qemuDomainLogContextFree(qemuDomainLogContextPtr ctxt)
|
||||
{
|
||||
bool lastRef;
|
||||
|
||||
if (!ctxt)
|
||||
return;
|
||||
|
||||
lastRef = virAtomicIntDecAndTest(&ctxt->refs);
|
||||
if (!lastRef)
|
||||
return;
|
||||
|
||||
VIR_FORCE_CLOSE(ctxt->writefd);
|
||||
VIR_FORCE_CLOSE(ctxt->readfd);
|
||||
VIR_FREE(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuDomainOpenLogHelper(virQEMUDriverConfigPtr cfg,
|
||||
virDomainObjPtr vm,
|
||||
|
@ -245,6 +245,9 @@ struct qemuProcessEvent {
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct _qemuDomainLogContext qemuDomainLogContext;
|
||||
typedef qemuDomainLogContext *qemuDomainLogContextPtr;
|
||||
|
||||
const char *qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job,
|
||||
int phase);
|
||||
int qemuDomainAsyncJobPhaseFromString(qemuDomainAsyncJob job,
|
||||
@ -349,6 +352,25 @@ void qemuDomainObjCheckNetTaint(virQEMUDriverPtr driver,
|
||||
virDomainNetDefPtr net,
|
||||
int logFD);
|
||||
|
||||
typedef enum {
|
||||
QEMU_DOMAIN_LOG_CONTEXT_MODE_START,
|
||||
QEMU_DOMAIN_LOG_CONTEXT_MODE_ATTACH,
|
||||
QEMU_DOMAIN_LOG_CONTEXT_MODE_STOP,
|
||||
} qemuDomainLogContextMode;
|
||||
|
||||
qemuDomainLogContextPtr qemuDomainLogContextNew(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
qemuDomainLogContextMode mode);
|
||||
int qemuDomainLogContextWrite(qemuDomainLogContextPtr ctxt,
|
||||
const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(2, 3);
|
||||
ssize_t qemuDomainLogContextRead(qemuDomainLogContextPtr ctxt,
|
||||
char **msg);
|
||||
int qemuDomainLogContextGetWriteFD(qemuDomainLogContextPtr ctxt);
|
||||
int qemuDomainLogContextGetReadFD(qemuDomainLogContextPtr ctxt);
|
||||
void qemuDomainLogContextMarkPosition(qemuDomainLogContextPtr ctxt);
|
||||
off_t qemuDomainLogContextGetPosition(qemuDomainLogContextPtr ctxt);
|
||||
void qemuDomainLogContextRef(qemuDomainLogContextPtr ctxt);
|
||||
void qemuDomainLogContextFree(qemuDomainLogContextPtr ctxt);
|
||||
|
||||
int qemuDomainCreateLog(virQEMUDriverPtr driver, virDomainObjPtr vm, bool append);
|
||||
int qemuDomainOpenLog(virQEMUDriverPtr driver, virDomainObjPtr vm);
|
||||
|
Loading…
Reference in New Issue
Block a user