mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
Added per-VM logging
This commit is contained in:
parent
ef38afcfd4
commit
85e9f9fb47
@ -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>
|
||||
|
||||
* qemud/conf.c: Fix initialization of var to prevent stack
|
||||
|
@ -138,6 +138,7 @@ fi
|
||||
%{_datadir}/libvirt/networks/default.xml
|
||||
%dir %{_localstatedir}/run/libvirt/
|
||||
%dir %{_localstatedir}/lib/libvirt/
|
||||
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
|
||||
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy
|
||||
%attr(0755, root, root) %{_sbindir}/libvirt_qemud
|
||||
%doc docs/libvirt.rng
|
||||
|
@ -29,6 +29,7 @@ install-data-local:
|
||||
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 || \
|
||||
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)/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/default.xml
|
||||
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
|
||||
rmdir $(DESTDIR)$(localstatedir)/log/libvirt/qemu || :
|
||||
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
|
||||
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
|
||||
|
||||
|
@ -1212,12 +1212,12 @@ int qemudBuildCommandLine(struct qemud_server *server,
|
||||
|
||||
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' &&
|
||||
ut.machine[2] == '8' &&
|
||||
ut.machine[3] == '6' &&
|
||||
!ut.machine[4])
|
||||
ut.machine[1] = '3';
|
||||
ut.machine[1] = '6';
|
||||
|
||||
/* Need to explicitly disable KQEMU if
|
||||
* 1. Arch matches host arch
|
||||
|
@ -213,6 +213,7 @@ struct qemud_vm {
|
||||
int stdout;
|
||||
int stderr;
|
||||
int monitor;
|
||||
int logfile;
|
||||
int pid;
|
||||
int id;
|
||||
int state;
|
||||
@ -319,6 +320,7 @@ struct qemud_server {
|
||||
char *autostartDir;
|
||||
char *networkConfigDir;
|
||||
char *networkAutostartDir;
|
||||
char logDir[PATH_MAX];
|
||||
char errorMessage[QEMUD_MAX_ERROR_LEN];
|
||||
int errorCode;
|
||||
unsigned int shutdown : 1;
|
||||
|
103
qemud/qemud.c
103
qemud/qemud.c
@ -439,6 +439,9 @@ static int qemudInitPaths(struct qemud_server *server,
|
||||
goto snprintf_error;
|
||||
|
||||
unlink(roSockname);
|
||||
|
||||
if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
|
||||
goto snprintf_error;
|
||||
} else {
|
||||
if (!(pw = getpwuid(uid))) {
|
||||
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)
|
||||
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++)
|
||||
@ -647,6 +653,7 @@ qemudReadMonitorOutput(struct qemud_server *server,
|
||||
#define MONITOR_TIMEOUT 3000
|
||||
|
||||
int got = 0;
|
||||
buffer[0] = '\0';
|
||||
|
||||
/* Consume & discard the initial greeting */
|
||||
while (got < (buflen-1)) {
|
||||
@ -655,13 +662,15 @@ qemudReadMonitorOutput(struct qemud_server *server,
|
||||
ret = read(fd, buffer+got, buflen-got-1);
|
||||
if (ret == 0) {
|
||||
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;
|
||||
}
|
||||
if (ret < 0) {
|
||||
struct pollfd pfd = { .fd = fd, .events = POLLIN };
|
||||
if (errno != EAGAIN &&
|
||||
errno != EINTR) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (errno != EAGAIN) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failure while reading %s startup output: %s",
|
||||
what, strerror(errno));
|
||||
@ -680,11 +689,12 @@ qemudReadMonitorOutput(struct qemud_server *server,
|
||||
what, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else if (pfd.revents & POLLHUP) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"End-of-file while reading %s startup output", what);
|
||||
return -1;
|
||||
} else if (pfd.revents != POLLIN) {
|
||||
} else {
|
||||
/* Make sure we continue loop & read any further data
|
||||
available before dealing with EOF */
|
||||
if (pfd.revents & (POLLIN | POLLHUP))
|
||||
continue;
|
||||
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failure while reading %s startup output", what);
|
||||
return -1;
|
||||
@ -794,11 +804,22 @@ qemudOpenMonitorPath(struct qemud_server *server,
|
||||
|
||||
static int qemudWaitForMonitor(struct qemud_server *server, struct qemud_vm *vm) {
|
||||
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),
|
||||
qemudOpenMonitorPath,
|
||||
"PTY");
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
retry:
|
||||
if (write(vm->logfile, buffer, strlen(buffer)) < 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));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,
|
||||
struct qemud_vm *vm) {
|
||||
char **argv = NULL;
|
||||
char **argv = NULL, **tmp;
|
||||
int i, ret = -1;
|
||||
char logfile[PATH_MAX];
|
||||
|
||||
if (qemudIsActiveVM(vm)) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
@ -859,8 +881,49 @@ int qemudStartVMDaemon(struct qemud_server *server,
|
||||
} else
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
vm->id = server->nextvmid++;
|
||||
@ -1038,7 +1101,14 @@ static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
}
|
||||
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->stderr);
|
||||
if (close(vm->logfile) < 0)
|
||||
qemudLog(QEMUD_WARN, "Unable to close logfile %d: %s", errno, strerror(errno));
|
||||
close(vm->stdout);
|
||||
close(vm->stderr);
|
||||
if (vm->monitor != -1)
|
||||
close(vm->monitor);
|
||||
vm->logfile = -1;
|
||||
vm->stdout = -1;
|
||||
vm->stderr = -1;
|
||||
vm->monitor = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user