[libvirt] [PATCH 2/2] qemu: extend logging to record guest configuration events

Naoya Horiguchi n-horiguchi at ah.jp.nec.com
Mon Mar 28 08:13:47 UTC 2011


The following events can be logged onto /var/log/libvirt/qemu/<domain>.log:

  starting/shutting down/suspending/resuming/migrating domains
  changing the amount of memory
  changing the number of VCPUs
  inserting/ejecting a media into/from CDROM/Floppy devices
  attaching/detaching PCI/SCSI/USB devices (including NICs and disks.)

This patch generalizes qemudLog*() introduced in commit 93bc093ac
to handle the whole range of qemu driver's events.

This is useful for the same reason as explainged in the previous patch.

Signed-off-by: Naoya Horiguchi <n-horiguchi at ah.jp.nec.com>
---
 src/qemu/qemu_driver.c  |  110 +++++++++++++++++++++++++++++------------------
 src/qemu/qemu_driver.h  |    8 +++
 src/qemu/qemu_hotplug.c |   66 +++++++++++++++++++++++++++-
 3 files changed, 140 insertions(+), 44 deletions(-)

diff --git v0.8.8/src/qemu/qemu_driver.c v0.8.8/src/qemu/qemu_driver.c
index 3b30d0f..7df0023 100644
--- v0.8.8/src/qemu/qemu_driver.c
+++ v0.8.8/src/qemu/qemu_driver.c
@@ -247,6 +247,62 @@ qemudLogReadFD(const char* logDir, const char* name, off_t pos)
 }
 
 
+static int
+qemudLogWriteFD(int logfd, struct qemud_driver *driver,
+                virDomainObjPtr vm, bool append, const char *logstr)
+{
+    bool openfile = logfd < 0;
+    char *timestamp;
+    char ebuf[1024];
+
+    if (openfile &&
+        (logfd = qemudLogFD(driver, vm->def->name, append)) < 0) {
+        /* To not break the normal domain shutdown process, skip the
+         * timestamp log writing if failed on opening log file. */
+        VIR_WARN("Unable to open logfile: %s",
+                  virStrerror(errno, ebuf, sizeof ebuf));
+        return -1;
+    }
+
+    if ((timestamp = virTimestamp()) == NULL) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (safewrite(logfd, timestamp, strlen(timestamp)) < 0 ||
+        safewrite(logfd, logstr, strlen(logstr)) < 0) {
+        VIR_WARN("Unable to write timestamp to logfile: %s",
+                 virStrerror(errno, ebuf, sizeof ebuf));
+    }
+    VIR_FREE(timestamp);
+
+    if (openfile && VIR_CLOSE(logfd) < 0) {
+        VIR_WARN("Unable to close logfile: %s",
+             virStrerror(errno, ebuf, sizeof ebuf));
+    }
+
+    return 0;
+}
+
+
+void qemudLogWrite(struct qemud_driver *driver, virDomainObjPtr vm,
+                   bool append, const char *fmt, ...)
+{
+    char *buf;
+    va_list args;
+
+    va_start(args, fmt);
+    if (virVasprintf(&buf, fmt, args) < 0) {
+        VIR_WARN0("Out of memory while formatting log message");
+        buf = NULL;
+    }
+    va_end(args);
+
+    if (buf)
+        qemudLogWriteFD(-1, driver, vm, append, buf);
+}
+
+
 struct qemuAutostartData {
     struct qemud_driver *driver;
     virConnectPtr conn;
@@ -2610,9 +2666,6 @@ static int qemuDomainSnapshotSetCurrentInactive(virDomainObjPtr vm,
                                                 char *snapshotDir);
 
 
-#define START_POSTFIX ": starting up\n"
-#define SHUTDOWN_POSTFIX ": shutting down\n"
-
 static int qemudStartVMDaemon(virConnectPtr conn,
                               struct qemud_driver *driver,
                               virDomainObjPtr vm,
@@ -2627,7 +2680,6 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     char ebuf[1024];
     char *pidfile = NULL;
     int logfile = -1;
-    char *timestamp;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCommandPtr cmd = NULL;
 
@@ -2845,18 +2897,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
             goto cleanup;
     }
 
-    if ((timestamp = virTimestamp()) == NULL) {
-        virReportOOMError();
-        goto cleanup;
-    } else {
-        if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
-            safewrite(logfile, START_POSTFIX, strlen(START_POSTFIX)) < 0) {
-            VIR_WARN("Unable to write timestamp to logfile: %s",
-                     virStrerror(errno, ebuf, sizeof ebuf));
-        }
-
-        VIR_FREE(timestamp);
-    }
+    qemudLogWriteFD(logfile, driver, vm, false, START_POSTFIX);
 
     virCommandWriteArgLog(cmd, logfile);
 
@@ -2985,9 +3026,6 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
     virErrorPtr orig_err;
     virDomainDefPtr def;
     int i;
-    int logfile = -1;
-    char *timestamp;
-    char ebuf[1024];
 
     VIR_DEBUG("Shutting down VM '%s' pid=%d migrated=%d",
               vm->def->name, vm->pid, migrated);
@@ -2997,29 +3035,7 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
         return;
     }
 
-    if ((logfile = qemudLogFD(driver, vm->def->name, true)) < 0) {
-        /* To not break the normal domain shutdown process, skip the
-         * timestamp log writing if failed on opening log file. */
-        VIR_WARN("Unable to open logfile: %s",
-                  virStrerror(errno, ebuf, sizeof ebuf));
-    } else {
-        if ((timestamp = virTimestamp()) == NULL) {
-            virReportOOMError();
-        } else {
-            if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
-                safewrite(logfile, SHUTDOWN_POSTFIX,
-                          strlen(SHUTDOWN_POSTFIX)) < 0) {
-                VIR_WARN("Unable to write timestamp to logfile: %s",
-                         virStrerror(errno, ebuf, sizeof ebuf));
-            }
-
-            VIR_FREE(timestamp);
-        }
-
-        if (VIR_CLOSE(logfile) < 0)
-             VIR_WARN("Unable to close logfile: %s",
-                      virStrerror(errno, ebuf, sizeof ebuf));
-    }
+    qemudLogWrite(driver, vm, true, SHUTDOWN_POSTFIX);
 
     /* This method is routinely used in clean up paths. Disable error
      * reporting so we don't squash a legit error. */
@@ -3713,6 +3729,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
         }
         if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
             goto endjob;
+        qemudLogWrite(driver, vm, true, ": suspending\n");
         ret = 0;
     }
 
@@ -3769,6 +3786,7 @@ static int qemudDomainResume(virDomainPtr dom) {
     }
     if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
         goto endjob;
+    qemudLogWrite(driver, vm, true, ": resuming\n");
     ret = 0;
 
 endjob:
@@ -3978,6 +3996,8 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
         goto endjob;
     }
 
+    qemudLogWrite(driver, vm, true, ": setting memory to %lu kB\n", newmem);
+
     ret = 0;
 endjob:
     if (qemuDomainObjEndJob(vm) == 0)
@@ -5198,6 +5218,9 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
         break;
     }
 
+    if (!ret)
+        qemudLogWrite(driver, vm, true, ": setting Num of VCPUs to %u\n", nvcpus);
+
     /* Save the persistent config to disk */
     if (flags & VIR_DOMAIN_VCPU_CONFIG)
         ret = virDomainSaveConfig(driver->configDir, persistentDef);
@@ -8963,6 +8986,9 @@ qemudDomainMigratePerform (virDomainPtr dom,
             virDomainRemoveInactive(&driver->domains, vm);
         vm = NULL;
     }
+
+    qemudLogWrite(driver, vm, true, ": migrating to %s\n", dname);
+
     ret = 0;
 
 endjob:
diff --git v0.8.8/src/qemu/qemu_driver.h v0.8.8/src/qemu/qemu_driver.h
index dac0935..bdd8072 100644
--- v0.8.8/src/qemu/qemu_driver.h
+++ v0.8.8/src/qemu/qemu_driver.h
@@ -30,6 +30,7 @@
 # include <libxml/xpath.h>
 
 # include "internal.h"
+# include "qemu_conf.h"
 
 # if HAVE_LINUX_KVM_H
 #  include <linux/kvm.h>
@@ -51,4 +52,11 @@
 
 int qemuRegister(void);
 
+# define START_POSTFIX ": starting up\n"
+# define SHUTDOWN_POSTFIX ": shutting down\n"
+
+void qemudLogWrite(struct qemud_driver *driver, virDomainObjPtr vm,
+                   bool append, const char *fmt, ...)
+    ATTRIBUTE_FMT_PRINTF(4, 5);
+
 #endif /* QEMUD_DRIVER_H */
diff --git v0.8.8/src/qemu/qemu_hotplug.c v0.8.8/src/qemu/qemu_hotplug.c
index fb9db5a..edeeeb7 100644
--- v0.8.8/src/qemu/qemu_hotplug.c
+++ v0.8.8/src/qemu/qemu_hotplug.c
@@ -28,6 +28,7 @@
 #include "qemu_capabilities.h"
 #include "qemu_domain.h"
 #include "qemu_command.h"
+#include "qemu_driver.h"
 #include "qemu_bridge_filter.h"
 #include "qemu_audit.h"
 #include "qemu_hostdev.h"
@@ -113,6 +114,14 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
+    if (disk->src) {
+        qemudLogWrite(driver, vm, true, ": inserting '%s' to %s device\n",
+                      disk->src, virDomainDiskDeviceTypeToString(disk->device));
+    } else {
+        qemudLogWrite(driver, vm, true, ": ejecting media from %s device\n",
+                      virDomainDiskDeviceTypeToString(disk->device));
+    }
+
     if (virSecurityManagerRestoreImageLabel(driver->securityManager,
                                             vm, origdisk) < 0)
         VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);
@@ -208,6 +217,9 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
+    qemudLogWrite(driver, vm, true, ": attach PCI disk %s %s (%s)\n",
+                  type, drivestr, devstr);
+
     virDomainDiskInsertPreAlloced(vm->def, disk);
 
     VIR_FREE(devstr);
@@ -282,6 +294,9 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver,
     if (ret == 0) {
         controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
         virDomainControllerInsertPreAlloced(vm->def, controller);
+        qemudLogWrite(driver, vm, true,
+                      ": attaching PCI controller device %s:%d\n",
+                      type, controller->idx);
     }
 
 cleanup:
@@ -440,6 +455,10 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
+    qemudLogWrite(driver, vm, true, ": attaching SCSI disk %s %s (%s)\n",
+                  virDomainDeviceAddressTypeToString(disk->info.type),
+                  drivestr, devstr);
+
     virDomainDiskInsertPreAlloced(vm->def, disk);
 
     VIR_FREE(devstr);
@@ -523,6 +542,9 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
+    qemudLogWrite(driver, vm, true, ": attaching USB storage %s %s (%s)\n",
+                  disk->dst, drivestr, devstr);
+
     virDomainDiskInsertPreAlloced(vm->def, disk);
 
     VIR_FREE(devstr);
@@ -702,6 +724,11 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
 
     qemuDomainNetAudit(vm, NULL, net, "attach", true);
 
+    qemudLogWrite(driver, vm, true,
+                  ": attaching network device %s, %s, %s, %s %s\n",
+                  nicstr, netstr, virDomainNetTypeToString(net->type),
+                  net->ifname, net->mac);
+
     ret = 0;
 
     vm->def->nets[vm->def->nnets++] = net;
@@ -847,6 +874,8 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver,
 
     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
 
+    qemudLogWrite(driver, vm, true, ": attaching host PCI device\n");
+
     VIR_FREE(devstr);
     VIR_FREE(configfd_name);
     VIR_FORCE_CLOSE(configfd);
@@ -922,6 +951,8 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver,
 
     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
 
+    qemudLogWrite(driver, vm, true, ": attaching host USB device\n");
+
     VIR_FREE(devstr);
 
     return 0;
@@ -985,6 +1016,8 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver,
         goto error;
     }
 
+    qemudLogWrite(driver, vm, true, ": attaching host device\n");
+
     return 0;
 
 error:
@@ -1211,6 +1244,9 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
                      NULLSTR(dev->data.disk->src));
     }
 
+    qemudLogWrite(driver, vm, true, ": detaching PCI disk %s %s\n",
+                  NULLSTR(dev->data.disk->src), drivestr);
+
     ret = 0;
 
 cleanup:
@@ -1289,6 +1325,9 @@ int qemuDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
                      NULLSTR(dev->data.disk->src));
     }
 
+    qemudLogWrite(driver, vm, true, ": detaching SCSI disk %s %s\n",
+                  NULLSTR(dev->data.disk->src), drivestr);
+
     ret = 0;
 
 cleanup:
@@ -1369,6 +1408,11 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
 
     virDomainControllerDefFree(detach);
 
+    qemudLogWrite(driver, vm, true,
+                  ": detaching PCI controller device [%s:%d]\n",
+                  virDomainControllerTypeToString(dev->data.controller->type),
+                  dev->data.controller->idx);
+
     ret = 0;
 
 cleanup:
@@ -1456,6 +1500,13 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
 
     qemuDomainNetAudit(vm, detach, NULL, "detach", true);
 
+    qemudLogWrite(driver, vm, true,
+                  ": detaching network device %s %s %02x:%02x:%02x:%02x:%02x:%02x \n",
+                  virDomainNetTypeToString(detach->type), detach->model,
+                  detach->mac[0], detach->mac[1],
+                  detach->mac[2], detach->mac[3],
+                  detach->mac[4], detach->mac[5]);
+
     if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
         qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0)
         VIR_WARN0("Unable to release PCI address on NIC");
@@ -1599,6 +1650,9 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver,
     }
     virDomainHostdevDefFree(detach);
 
+    if (ret == 0)
+        qemudLogWrite(driver, vm, true, ": detaching host PCI device\n");
+
     return ret;
 }
 
@@ -1610,14 +1664,16 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver,
     virDomainHostdevDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int i, ret;
+    unsigned bus;
+    unsigned device;
 
     for (i = 0 ; i < vm->def->nhostdevs ; i++) {
         if (vm->def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
             vm->def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
             continue;
 
-        unsigned bus = vm->def->hostdevs[i]->source.subsys.u.usb.bus;
-        unsigned device = vm->def->hostdevs[i]->source.subsys.u.usb.device;
+        bus = vm->def->hostdevs[i]->source.subsys.u.usb.bus;
+        device = vm->def->hostdevs[i]->source.subsys.u.usb.device;
         unsigned product = vm->def->hostdevs[i]->source.subsys.u.usb.product;
         unsigned vendor = vm->def->hostdevs[i]->source.subsys.u.usb.vendor;
 
@@ -1666,6 +1722,9 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver,
 
     ret = 0;
 
+    qemudLogWrite(driver, vm, true, ": detaching host USB device %03d%03d\n",
+                  bus, device);
+
     if (vm->def->nhostdevs > 1) {
         memmove(vm->def->hostdevs + i,
                 vm->def->hostdevs + i + 1,
@@ -1717,6 +1776,9 @@ int qemuDomainDetachHostDevice(struct qemud_driver *driver,
                                               vm, dev->data.hostdev) < 0)
         VIR_WARN0("Failed to restore host device labelling");
 
+    if (ret == 0)
+        qemudLogWrite(driver, vm, true, ": detaching host device\n");
+
     return ret;
 }
 
-- 
1.7.3.4




More information about the libvir-list mailing list