]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Added per-VM logging
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 18 May 2007 18:36:24 +0000 (18:36 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 18 May 2007 18:36:24 +0000 (18:36 +0000)
ChangeLog
libvirt.spec.in
qemud/Makefile.am
qemud/conf.c
qemud/internal.h
qemud/qemud.c

index 21159f6dcfaa3691529b8cfa0536015dd7f88475..c1d42a9d4807c1a5eb1c32234f7aa5b8b436ba7f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 3e57f16151081ac964fe5ab7cfc46cbe744b30f9..2a74c496a6e0ed3ff9bfb5e6a84029ada75ee259 100644 (file)
@@ -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
index 78114a377ee25e7a2672713ae8df0fe620171291..f4daaf4650d483e751c448a9f61a835927eccf8b 100644 (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
        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 || :
 
index 9e81cb365c3fbd059c8b801c2e238a2478878747..c2fe4f41f127ca73b191aead68ea8b54835e6f08 100644 (file)
@@ -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
index c406752830a2ea7d823ff7fa2efd22692e09a7ba..3d7a9266652c325b63f8cd6028ba95e4c7faf89c 100644 (file)
@@ -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;
index e2f28180fad56b20f3e98c43a5d45f7b2668c51e..7dcb9a2c54796de202aa8cee2836400ccee9bf9a 100644 (file)
@@ -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;