Added per-VM logging

This commit is contained in:
Daniel P. Berrange 2007-05-18 18:36:24 +00:00
parent ef38afcfd4
commit 85e9f9fb47
6 changed files with 101 additions and 17 deletions

View File

@ -1,3 +1,9 @@
Fri May 18 14:36:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* qemud/conf.c, qemud/internal.h, qemud/qemud.c: Save VM output
in a logfile
* libvirt.spec.in: added /var/log/libvirt/qemud directory
Mon May 14 11:00:00 EST 2007 Daniel P. Berrange <berrange@redhat.com> Mon May 14 11:00:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* qemud/conf.c: Fix initialization of var to prevent stack * qemud/conf.c: Fix initialization of var to prevent stack

View File

@ -138,6 +138,7 @@ fi
%{_datadir}/libvirt/networks/default.xml %{_datadir}/libvirt/networks/default.xml
%dir %{_localstatedir}/run/libvirt/ %dir %{_localstatedir}/run/libvirt/
%dir %{_localstatedir}/lib/libvirt/ %dir %{_localstatedir}/lib/libvirt/
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy %attr(4755, root, root) %{_libexecdir}/libvirt_proxy
%attr(0755, root, root) %{_sbindir}/libvirt_qemud %attr(0755, root, root) %{_sbindir}/libvirt_qemud
%doc docs/libvirt.rng %doc docs/libvirt.rng

View File

@ -29,6 +29,7 @@ install-data-local:
sed -i -e "s,</name>,</name>\n <uuid>$(UUID)</uuid>," $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml sed -i -e "s,</name>,</name>\n <uuid>$(UUID)</uuid>," $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml
test -e $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml || \ test -e $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml || \
ln -s ../default.xml $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml ln -s ../default.xml $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/qemu
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt
@ -36,6 +37,7 @@ uninstall-local:
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || : rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
rmdir $(DESTDIR)$(localstatedir)/log/libvirt/qemu || :
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || : rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || : rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :

View File

@ -1212,12 +1212,12 @@ int qemudBuildCommandLine(struct qemud_server *server,
uname(&ut); uname(&ut);
/* Nasty hack make i?86 look like i386 to simplify next comparison */ /* Nasty hack make i?86 look like i686 to simplify next comparison */
if (ut.machine[0] == 'i' && if (ut.machine[0] == 'i' &&
ut.machine[2] == '8' && ut.machine[2] == '8' &&
ut.machine[3] == '6' && ut.machine[3] == '6' &&
!ut.machine[4]) !ut.machine[4])
ut.machine[1] = '3'; ut.machine[1] = '6';
/* Need to explicitly disable KQEMU if /* Need to explicitly disable KQEMU if
* 1. Arch matches host arch * 1. Arch matches host arch

View File

@ -213,6 +213,7 @@ struct qemud_vm {
int stdout; int stdout;
int stderr; int stderr;
int monitor; int monitor;
int logfile;
int pid; int pid;
int id; int id;
int state; int state;
@ -319,6 +320,7 @@ struct qemud_server {
char *autostartDir; char *autostartDir;
char *networkConfigDir; char *networkConfigDir;
char *networkAutostartDir; char *networkAutostartDir;
char logDir[PATH_MAX];
char errorMessage[QEMUD_MAX_ERROR_LEN]; char errorMessage[QEMUD_MAX_ERROR_LEN];
int errorCode; int errorCode;
unsigned int shutdown : 1; unsigned int shutdown : 1;

View File

@ -439,6 +439,9 @@ static int qemudInitPaths(struct qemud_server *server,
goto snprintf_error; goto snprintf_error;
unlink(roSockname); unlink(roSockname);
if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
goto snprintf_error;
} else { } else {
if (!(pw = getpwuid(uid))) { if (!(pw = getpwuid(uid))) {
qemudLog(QEMUD_ERR, "Failed to find user record for uid '%d': %s", qemudLog(QEMUD_ERR, "Failed to find user record for uid '%d': %s",
@ -451,6 +454,9 @@ static int qemudInitPaths(struct qemud_server *server,
if (snprintf(base, PATH_MAX, "%s/.", pw->pw_dir) >= PATH_MAX) if (snprintf(base, PATH_MAX, "%s/.", pw->pw_dir) >= PATH_MAX)
goto snprintf_error; goto snprintf_error;
if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= PATH_MAX)
goto snprintf_error;
} }
for (i = 0; i < QEMUD_N_CONFIG_DIRS; i++) for (i = 0; i < QEMUD_N_CONFIG_DIRS; i++)
@ -647,6 +653,7 @@ qemudReadMonitorOutput(struct qemud_server *server,
#define MONITOR_TIMEOUT 3000 #define MONITOR_TIMEOUT 3000
int got = 0; int got = 0;
buffer[0] = '\0';
/* Consume & discard the initial greeting */ /* Consume & discard the initial greeting */
while (got < (buflen-1)) { while (got < (buflen-1)) {
@ -655,13 +662,15 @@ qemudReadMonitorOutput(struct qemud_server *server,
ret = read(fd, buffer+got, buflen-got-1); ret = read(fd, buffer+got, buflen-got-1);
if (ret == 0) { if (ret == 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"End-of-file while reading %s startup output", what); "QEMU quit during %s startup\n%s", what, buffer);
return -1; return -1;
} }
if (ret < 0) { if (ret < 0) {
struct pollfd pfd = { .fd = fd, .events = POLLIN }; struct pollfd pfd = { .fd = fd, .events = POLLIN };
if (errno != EAGAIN && if (errno == EINTR)
errno != EINTR) { continue;
if (errno != EAGAIN) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"Failure while reading %s startup output: %s", "Failure while reading %s startup output: %s",
what, strerror(errno)); what, strerror(errno));
@ -680,11 +689,12 @@ qemudReadMonitorOutput(struct qemud_server *server,
what, strerror(errno)); what, strerror(errno));
return -1; return -1;
} }
} else if (pfd.revents & POLLHUP) { } else {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, /* Make sure we continue loop & read any further data
"End-of-file while reading %s startup output", what); available before dealing with EOF */
return -1; if (pfd.revents & (POLLIN | POLLHUP))
} else if (pfd.revents != POLLIN) { continue;
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"Failure while reading %s startup output", what); "Failure while reading %s startup output", what);
return -1; return -1;
@ -794,11 +804,22 @@ qemudOpenMonitorPath(struct qemud_server *server,
static int qemudWaitForMonitor(struct qemud_server *server, struct qemud_vm *vm) { static int qemudWaitForMonitor(struct qemud_server *server, struct qemud_vm *vm) {
char buffer[1024]; /* Plenty of space to get startup greeting */ char buffer[1024]; /* Plenty of space to get startup greeting */
int ret = qemudReadMonitorOutput(server, vm, vm->stderr,
buffer, sizeof(buffer),
qemudOpenMonitorPath,
"console");
return qemudReadMonitorOutput(server, vm, vm->stderr, buffer[sizeof(buffer)-1] = '\0';
buffer, sizeof(buffer), retry:
qemudOpenMonitorPath, if (write(vm->logfile, buffer, strlen(buffer)) < 0) {
"PTY"); /* Log, but ignore failures to write logfile for VM */
if (errno == EINTR)
goto retry;
qemudLog(QEMUD_WARN, "Unable to log VM console data: %s",
strerror(errno));
}
return ret;
} }
static int qemudNextFreeVNCPort(struct qemud_server *server ATTRIBUTE_UNUSED) { static int qemudNextFreeVNCPort(struct qemud_server *server ATTRIBUTE_UNUSED) {
@ -839,8 +860,9 @@ static int qemudNextFreeVNCPort(struct qemud_server *server ATTRIBUTE_UNUSED) {
int qemudStartVMDaemon(struct qemud_server *server, int qemudStartVMDaemon(struct qemud_server *server,
struct qemud_vm *vm) { struct qemud_vm *vm) {
char **argv = NULL; char **argv = NULL, **tmp;
int i, ret = -1; int i, ret = -1;
char logfile[PATH_MAX];
if (qemudIsActiveVM(vm)) { if (qemudIsActiveVM(vm)) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR, qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
@ -859,8 +881,49 @@ int qemudStartVMDaemon(struct qemud_server *server,
} else } else
vm->def->vncActivePort = vm->def->vncPort; vm->def->vncActivePort = vm->def->vncPort;
if (qemudBuildCommandLine(server, vm, &argv) < 0) if ((strlen(server->logDir) + /* path */
1 + /* Separator */
strlen(vm->def->name) + /* basename */
4 + /* suffix .log */
1 /* NULL */) > PATH_MAX) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"config file path too long: %s/%s.log",
server->logDir, vm->def->name);
return -1; return -1;
}
strcpy(logfile, server->logDir);
strcat(logfile, "/");
strcat(logfile, vm->def->name);
strcat(logfile, ".log");
if (qemudEnsureDir(server->logDir) < 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"cannot create log directory %s: %s",
server->logDir, strerror(errno));
return -1;
}
if ((vm->logfile = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR)) < 0) {
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
"failed to create logfile %s: %s",
logfile, strerror(errno));
return -1;
}
if (qemudBuildCommandLine(server, vm, &argv) < 0) {
close(vm->logfile);
vm->logfile = -1;
return -1;
}
tmp = argv;
while (*tmp) {
write(vm->logfile, *tmp, strlen(*tmp));
write(vm->logfile, " ", 1);
tmp++;
}
write(vm->logfile, "\n", 1);
if (qemudExec(server, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) { if (qemudExec(server, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
vm->id = server->nextvmid++; vm->id = server->nextvmid++;
@ -1038,7 +1101,14 @@ static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
} }
buf[ret] = '\0'; buf[ret] = '\0';
qemudDebug("[%s]", buf); retry:
if (write(vm->logfile, buf, ret) < 0) {
/* Log, but ignore failures to write logfile for VM */
if (errno == EINTR)
goto retry;
qemudLog(QEMUD_WARN, "Unable to log VM console data: %s",
strerror(errno));
}
} }
} }
@ -1053,10 +1123,13 @@ int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
qemudVMData(server, vm, vm->stdout); qemudVMData(server, vm, vm->stdout);
qemudVMData(server, vm, vm->stderr); qemudVMData(server, vm, vm->stderr);
if (close(vm->logfile) < 0)
qemudLog(QEMUD_WARN, "Unable to close logfile %d: %s", errno, strerror(errno));
close(vm->stdout); close(vm->stdout);
close(vm->stderr); close(vm->stderr);
if (vm->monitor != -1) if (vm->monitor != -1)
close(vm->monitor); close(vm->monitor);
vm->logfile = -1;
vm->stdout = -1; vm->stdout = -1;
vm->stderr = -1; vm->stderr = -1;
vm->monitor = -1; vm->monitor = -1;