Skip to content

Commit 13f3f51

Browse files
russell-islambryteise
authored andcommitted
Enable event logging for cloud hypervisor
Signed-off-by: Muminul Islam <[email protected]>
1 parent 5c7fcf2 commit 13f3f51

File tree

5 files changed

+230
-3
lines changed

5 files changed

+230
-3
lines changed

src/ch/ch_conf.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ virCHDriverConfigNew(void)
146146
cfg->logDir = g_strdup(CH_LOG_DIR);
147147
cfg->configDir = g_strdup(CH_CONF_BASE_DIR);
148148
cfg->autostartDir = g_strdup_printf("%s/autostart", cfg->configDir);
149-
149+
cfg->logTimestamp = true;
150+
cfg->stdioLogD = false;
150151
cfg->cgroupControllers = -1; /* Auto detect */
151152

152153
return cfg;

src/ch/ch_conf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ struct _virCHDriverConfig {
4646
char *configDir;
4747
char *autostartDir;
4848
int cgroupControllers;
49-
49+
bool logTimestamp;
50+
bool stdioLogD;
5051
bool macFilter;
5152
};
5253

src/ch/ch_domain.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@
2323
#include "ch_domain.h"
2424
#include "datatypes.h"
2525
#include "domain_driver.h"
26+
#include "virfile.h"
2627
#include "viralloc.h"
2728
#include "virlog.h"
2829
#include "virtime.h"
2930
#include "virsystemd.h"
31+
#include "virutil.h"
32+
33+
#include <fcntl.h>
3034

3135
#define VIR_FROM_THIS VIR_FROM_CH
3236

@@ -40,6 +44,41 @@ VIR_ENUM_IMPL(virCHDomainJob,
4044

4145
VIR_LOG_INIT("ch.ch_domain");
4246

47+
struct _chDomainLogContext {
48+
GObject parent;
49+
50+
int writefd;
51+
int readfd; /* Only used if manager == NULL */
52+
off_t pos;
53+
ino_t inode; /* Only used if manager != NULL */
54+
char *path;
55+
virLogManagerPtr manager;
56+
};
57+
static void chDomainLogContextFinalize(GObject *obj);
58+
static void ch_domain_log_context_init(chDomainLogContext *logctxt G_GNUC_UNUSED)
59+
{
60+
}
61+
static void ch_domain_log_context_class_init(chDomainLogContextClass *klass)
62+
{
63+
GObjectClass *obj = G_OBJECT_CLASS(klass);
64+
65+
obj->finalize = chDomainLogContextFinalize;
66+
}
67+
68+
G_DEFINE_TYPE(chDomainLogContext, ch_domain_log_context, G_TYPE_OBJECT);
69+
70+
static void
71+
chDomainLogContextFinalize(GObject *object)
72+
{
73+
chDomainLogContextPtr ctxt = CH_DOMAIN_LOG_CONTEXT(object);
74+
VIR_DEBUG("ctxt=%p", ctxt);
75+
76+
virLogManagerFree(ctxt->manager);
77+
g_free(ctxt->path);
78+
VIR_FORCE_CLOSE(ctxt->writefd);
79+
VIR_FORCE_CLOSE(ctxt->readfd);
80+
G_OBJECT_CLASS(ch_domain_log_context_parent_class)->finalize(object);
81+
}
4382
static int
4483
virCHDomainObjInitJob(virCHDomainObjPrivatePtr priv)
4584
{
@@ -485,3 +524,146 @@ virCHDomainObjFromDomain(virDomainPtr domain)
485524

486525
return vm;
487526
}
527+
528+
529+
chDomainLogContextPtr chDomainLogContextNew(virCHDriverPtr driver,
530+
virDomainObjPtr vm,
531+
chDomainLogContextMode mode)
532+
{
533+
g_autoptr(virCHDriverConfig) cfg = virCHDriverGetConfig(driver);
534+
chDomainLogContextPtr ctxt = CH_DOMAIN_LOG_CONTEXT(g_object_new(CH_TYPE_DOMAIN_LOG_CONTEXT, NULL));
535+
536+
VIR_DEBUG("Context new %p stdioLogD=%d", ctxt, cfg->stdioLogD);
537+
ctxt->writefd = -1;
538+
ctxt->readfd = -1;
539+
540+
ctxt->path = g_strdup_printf("%s/%s.log", cfg->logDir, vm->def->name);
541+
542+
if (cfg->stdioLogD) {
543+
ctxt->manager = virLogManagerNew(driver->privileged);
544+
if (!ctxt->manager)
545+
goto error;
546+
547+
ctxt->writefd = virLogManagerDomainOpenLogFile(ctxt->manager,
548+
"ch",
549+
vm->def->uuid,
550+
vm->def->name,
551+
ctxt->path,
552+
0,
553+
&ctxt->inode,
554+
&ctxt->pos);
555+
if (ctxt->writefd < 0)
556+
goto error;
557+
} else {
558+
if ((ctxt->writefd = open(ctxt->path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) {
559+
virReportSystemError(errno, _("failed to create logfile %s"),
560+
ctxt->path);
561+
goto error;
562+
}
563+
if (virSetCloseExec(ctxt->writefd) < 0) {
564+
virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
565+
ctxt->path);
566+
goto error;
567+
}
568+
569+
/* For unprivileged startup we must truncate the file since
570+
* we can't rely on logrotate. We don't use O_TRUNC since
571+
* it is better for SELinux policy if we truncate afterwards */
572+
if (mode == CH_DOMAIN_LOG_CONTEXT_MODE_START &&
573+
!driver->privileged &&
574+
ftruncate(ctxt->writefd, 0) < 0) {
575+
virReportSystemError(errno, _("failed to truncate %s"),
576+
ctxt->path);
577+
goto error;
578+
}
579+
580+
if (mode == CH_DOMAIN_LOG_CONTEXT_MODE_START) {
581+
if ((ctxt->readfd = open(ctxt->path, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) {
582+
virReportSystemError(errno, _("failed to open logfile %s"),
583+
ctxt->path);
584+
goto error;
585+
}
586+
if (virSetCloseExec(ctxt->readfd) < 0) {
587+
virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
588+
ctxt->path);
589+
goto error;
590+
}
591+
}
592+
593+
if ((ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END)) < 0) {
594+
virReportSystemError(errno, _("failed to seek in log file %s"),
595+
ctxt->path);
596+
goto error;
597+
}
598+
}
599+
600+
return ctxt;
601+
602+
error:
603+
g_clear_object(&ctxt);
604+
return NULL;
605+
}
606+
607+
/**
608+
* chDomainLogAppendMessage:
609+
*
610+
* This is a best-effort attempt to add a log message to the ch log file
611+
* either by using virtlogd or the legacy approach */
612+
int
613+
chDomainLogAppendMessage(virCHDriverPtr driver,
614+
virDomainObjPtr vm,
615+
const char *fmt,
616+
...)
617+
{
618+
g_autoptr(virCHDriverConfig) cfg = virCHDriverGetConfig(driver);
619+
virLogManagerPtr manager = NULL;
620+
va_list ap;
621+
g_autofree char *path = NULL;
622+
int writefd = -1;
623+
g_autofree char *message = NULL;
624+
int ret = -1;
625+
626+
va_start(ap, fmt);
627+
628+
message = g_strdup_vprintf(fmt, ap);
629+
630+
VIR_DEBUG("Append log message (vm='%s' message='%s) stdioLogD=%d",
631+
vm->def->name, message, cfg->stdioLogD);
632+
633+
path = g_strdup_printf("%s/%s.log", cfg->logDir, vm->def->name);
634+
635+
if (cfg->stdioLogD) {
636+
if (!(manager = virLogManagerNew(driver->privileged)))
637+
goto cleanup;
638+
639+
if (virLogManagerDomainAppendMessage(manager, "ch", vm->def->uuid,
640+
vm->def->name, path, message, 0) < 0)
641+
goto cleanup;
642+
} else {
643+
if ((writefd = open(path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) {
644+
virReportSystemError(errno, _("failed to create logfile %s"),
645+
path);
646+
goto cleanup;
647+
}
648+
649+
if (safewrite(writefd, message, strlen(message)) < 0)
650+
goto cleanup;
651+
}
652+
653+
ret = 0;
654+
655+
cleanup:
656+
va_end(ap);
657+
VIR_FORCE_CLOSE(writefd);
658+
virLogManagerFree(manager);
659+
660+
return ret;
661+
}
662+
663+
664+
int chDomainLogContextGetWriteFD(chDomainLogContextPtr ctxt)
665+
{
666+
return ctxt->writefd;
667+
}
668+
669+

src/ch/ch_domain.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020

2121
#pragma once
2222

23+
#include <glib-object.h>
2324
#include "ch_conf.h"
2425
#include "ch_monitor.h"
2526
#include "virchrdev.h"
2627
#include "vircgroup.h"
28+
#include "logging/log_manager.h"
2729

2830
#define CH_DEV_VFIO "/dev/vfio/vfio"
2931

@@ -43,7 +45,16 @@ enum virCHDomainJob {
4345
};
4446
VIR_ENUM_DECL(virCHDomainJob);
4547

48+
typedef enum {
49+
CH_DOMAIN_LOG_CONTEXT_MODE_START,
50+
CH_DOMAIN_LOG_CONTEXT_MODE_ATTACH,
51+
CH_DOMAIN_LOG_CONTEXT_MODE_STOP,
52+
} chDomainLogContextMode;
4653

54+
55+
#define CH_TYPE_DOMAIN_LOG_CONTEXT ch_domain_log_context_get_type()
56+
G_DECLARE_FINAL_TYPE(chDomainLogContext, ch_domain_log_context, CH, DOMAIN_LOG_CONTEXT, GObject);
57+
typedef chDomainLogContext *chDomainLogContextPtr;
4758
struct _virCHDomainJobObj {
4859
virCond cond; /* Use to coordinate jobs */
4960
enum virCHDomainJob active; /* Currently running job */
@@ -103,6 +114,17 @@ struct _virCHDomainVcpuPrivate {
103114
extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
104115
extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
105116

117+
118+
chDomainLogContextPtr chDomainLogContextNew(virCHDriverPtr driver,
119+
virDomainObjPtr vm,
120+
chDomainLogContextMode mode);
121+
int chDomainLogContextGetWriteFD(chDomainLogContextPtr ctxt);
122+
123+
124+
int chDomainLogAppendMessage(virCHDriverPtr driver,
125+
virDomainObjPtr vm,
126+
const char *fmt,
127+
...) G_GNUC_PRINTF(3, 4);
106128
int
107129
virCHDomainObjBeginJob(virDomainObjPtr obj, enum virCHDomainJob job)
108130
G_GNUC_WARN_UNUSED_RESULT;

src/ch/ch_monitor.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ static int virCHMonitorProcessEvent(virCHMonitorPtr mon,
721721
const char *source;
722722
virDomainObjPtr vm = mon->vm;
723723
virCHMonitorEvent ev;
724+
g_autofree char *timestamp = NULL;
724725

725726
if (virJSONValueObjectHasKey(eventJSON, "source") == 0) {
726727
VIR_WARN("Invalid JSON from monitor, no source key");
@@ -735,6 +736,10 @@ static int virCHMonitorProcessEvent(virCHMonitorPtr mon,
735736

736737
ev = virCHMonitorEventFromString(source, event);
737738
VIR_DEBUG("Source: %s Event: %s, ev: %d", source, event, ev);
739+
virCHDriverPtr driver = CH_DOMAIN_PRIVATE(vm)->driver;
740+
741+
if ((timestamp = virTimeStringNow()) != NULL)
742+
chDomainLogAppendMessage(driver, vm, "%s: Source: %s Event: %s, ev: %d\n", timestamp,source, event, ev);
738743
switch (ev) {
739744
case virCHMonitorVmEventBooted:
740745
case virCHMonitorVmEventResumed:
@@ -752,7 +757,6 @@ static int virCHMonitorProcessEvent(virCHMonitorPtr mon,
752757
case virCHMonitorVmmEventShutdown: // shutdown inside vmm
753758
case virCHMonitorVmEventShutdown:
754759
{
755-
virCHDriverPtr driver = CH_DOMAIN_PRIVATE(vm)->driver;
756760
g_autoptr(virCHDriverConfig) cfg = virCHDriverGetConfig(driver);
757761
virDomainState state;
758762

@@ -1163,6 +1167,8 @@ virCHMonitorNew(virDomainObjPtr vm, virCHDriverPtr driver)
11631167
virCHMonitorPtr mon = NULL;
11641168
virCommandPtr cmd = NULL;
11651169
int i;
1170+
int logfile = -1;
1171+
g_autoptr(chDomainLogContext) logCtxt = NULL;
11661172

11671173
if (virCHMonitorInitialize() < 0)
11681174
goto cleanup;
@@ -1211,8 +1217,23 @@ virCHMonitorNew(virDomainObjPtr vm, virCHDriverPtr driver)
12111217

12121218
virCommandAddArg(cmd, "--event-monitor");
12131219
virCommandAddArgFormat(cmd, "path=%s", mon->monitorpath);
1220+
if (virFileMakePath(cfg->logDir) < 0) {
1221+
virReportSystemError(errno,
1222+
_("cannot create log directory %s"),
1223+
cfg->logDir);
1224+
goto cleanup;
1225+
}
12141226

1227+
VIR_DEBUG("Creating domain log file");
1228+
if (!(logCtxt = chDomainLogContextNew(driver, vm,
1229+
CH_DOMAIN_LOG_CONTEXT_MODE_START))) {
1230+
virLastErrorPrefixMessage("%s", _("can't connect to virtlogd"));
1231+
goto cleanup;
1232+
}
1233+
logfile = chDomainLogContextGetWriteFD(logCtxt);
12151234
/* TODO enable */
1235+
virCommandSetOutputFD(cmd, &logfile);
1236+
virCommandSetErrorFD(cmd, &logfile);
12161237
virCommandSetPidFile(cmd, priv->pidfile);
12171238
virCommandDaemonize(cmd);
12181239
virCommandRequireHandshake(cmd);

0 commit comments

Comments
 (0)