[libvirt] [PATCH 2/3] Add ability to attach host USB devices using serial id

Ján Tomko jtomko at redhat.com
Thu Jun 5 18:59:43 UTC 2014


From: David Waring <davidjw at rd.bbc.co.uk>

This allows specific USB devices to attached to guests when there may
be more than one of the same USB device attached to a host.

The serial number is optional so that without it existing behaviour is
maintained.

https://bugzilla.redhat.com/show_bug.cgi?id=914883

Signed-off-by: Ján Tomko <jtomko at redhat.com>
---
 src/util/virhostdev.c                              | 17 +++----
 src/util/virusb.c                                  | 56 +++++++++++++++++++---
 src/util/virusb.h                                  |  2 +
 tests/virusbtest.c                                 | 40 +++++++++++-----
 .../sys_bus_usb/devices/1-1.5.3.1/serial           |  1 +
 .../sys_bus_usb/devices/1-1.5.3.3/serial           |  1 +
 .../sys_bus_usb/devices/1-1.5.5/serial             |  1 +
 .../sys_bus_usb/devices/1-1.5.6/serial             |  1 +
 .../sys_bus_usb/devices/1-1.5/serial               |  1 +
 .../sys_bus_usb/devices/1-1.6/serial               |  1 +
 .../virusbtestdata/sys_bus_usb/devices/1-1/serial  |  1 +
 .../sys_bus_usb/devices/2-1.2/serial               |  1 +
 .../virusbtestdata/sys_bus_usb/devices/2-1/serial  |  1 +
 .../virusbtestdata/sys_bus_usb/devices/usb1/serial |  1 +
 .../virusbtestdata/sys_bus_usb/devices/usb2/serial |  1 +
 .../virusbtestdata/sys_bus_usb/devices/usb3/serial |  1 +
 .../virusbtestdata/sys_bus_usb/devices/usb4/serial |  1 +
 17 files changed, 102 insertions(+), 26 deletions(-)
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.6/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1.2/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb1/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb2/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb3/serial
 create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb4/serial

diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 9dd1df2..ad652c7 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -1049,6 +1049,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
 {
     unsigned vendor = hostdev->source.subsys.u.usb.vendor;
     unsigned product = hostdev->source.subsys.u.usb.product;
+    const char *serial = hostdev->source.subsys.u.usb.serial;
     unsigned bus = hostdev->source.subsys.u.usb.bus;
     unsigned device = hostdev->source.subsys.u.usb.device;
     bool autoAddress = hostdev->source.subsys.u.usb.autoAddress;
@@ -1057,7 +1058,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
     *usb = NULL;
 
     if (vendor && bus) {
-        rc = virUSBDeviceFind(vendor, product, bus, device,
+        rc = virUSBDeviceFind(vendor, product, serial, bus, device,
                               NULL,
                               autoAddress ? false : mandatory,
                               usb);
@@ -1066,9 +1067,9 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
         } else if (!autoAddress) {
             goto out;
         } else {
-            VIR_INFO("USB device %x:%x could not be found at previous"
-                     " address (bus:%u device:%u)",
-                     vendor, product, bus, device);
+            VIR_INFO("USB device %x:%x (serial: %s) could not be found"
+                     " at previous address (bus:%u device:%u)",
+                     vendor, product, serial ? serial : _("none"), bus, device);
         }
     }
 
@@ -1079,7 +1080,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
     if (vendor) {
         virUSBDeviceListPtr devs;
 
-        rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs);
+        rc = virUSBDeviceFindByVendor(vendor, product, serial, NULL, mandatory, &devs);
         if (rc < 0)
             return -1;
 
@@ -1100,7 +1101,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
             } else {
                 virReportError(VIR_ERR_OPERATION_FAILED,
                                _("Multiple USB devices for %x:%x, "
-                                 "use <address> to specify one"),
+                                 "use <address> or <serial> to specify one"),
                                vendor, product);
             }
             return -1;
@@ -1111,9 +1112,9 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
         hostdev->source.subsys.u.usb.autoAddress = true;
 
         if (autoAddress) {
-            VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
+            VIR_INFO("USB device %x:%x (serial: %s) found at bus:%u device:%u (moved"
                      " from bus:%u device:%u)",
-                     vendor, product,
+                     vendor, product, serial ? serial : _("none"),
                      hostdev->source.subsys.u.usb.bus,
                      hostdev->source.subsys.u.usb.device,
                      bus, device);
diff --git a/src/util/virusb.c b/src/util/virusb.c
index 8244771..5dc24b5 100644
--- a/src/util/virusb.c
+++ b/src/util/virusb.c
@@ -56,6 +56,7 @@ struct _virUSBDevice {
 
     char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
     char          id[USB_ID_LEN];     /* product vendor */
+    char          *serial;            /* serial number */
     char          *path;
 
     /* driver:domain using this dev */
@@ -92,6 +93,34 @@ static int virUSBOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(virUSB)
 
+static int virUSBSysReadFileString(const char *f_name, const char *d_name, char **buf)
+{
+    int ret = -1, len;
+    char *filename = NULL;
+
+    *buf = NULL;
+
+    if (virAsprintf(&filename, USB_SYSFS "/devices/%s/%s", d_name, f_name) < 0)
+        return -1;
+
+    if (!virFileExists(filename)) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    if ((len = virFileReadAll(filename, 1024, buf)) < 0)
+        goto cleanup;
+
+    if (len > 0 && (*buf)[len - 1] == '\n')
+        (*buf)[len - 1] = '\0';
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(filename);
+    return ret;
+}
+
 static int virUSBSysReadFile(const char *f_name, const char *d_name,
                              int base, unsigned int *value)
 {
@@ -123,6 +152,7 @@ static int virUSBSysReadFile(const char *f_name, const char *d_name,
 static virUSBDeviceListPtr
 virUSBDeviceSearch(unsigned int vendor,
                    unsigned int product,
+                   const char *serial,
                    unsigned int bus,
                    unsigned int devno,
                    const char *vroot,
@@ -131,6 +161,7 @@ virUSBDeviceSearch(unsigned int vendor,
     DIR *dir = NULL;
     bool found = false;
     char *ignore = NULL;
+    char *found_serial = NULL;
     struct dirent *de;
     virUSBDeviceListPtr list = NULL, ret = NULL;
     virUSBDevicePtr usb;
@@ -162,6 +193,10 @@ virUSBDeviceSearch(unsigned int vendor,
                               16, &found_prod) < 0)
             goto cleanup;
 
+        VIR_FREE(found_serial);
+        if (virUSBSysReadFileString("serial", de->d_name, &found_serial) < 0)
+            goto cleanup;
+
         if (STRPREFIX(de->d_name, "usb"))
             tmpstr += 3;
 
@@ -177,7 +212,8 @@ virUSBDeviceSearch(unsigned int vendor,
             goto cleanup;
 
         if ((flags & USB_DEVICE_FIND_BY_VENDOR) &&
-            (found_prod != product || found_vend != vendor))
+            (found_prod != product || found_vend != vendor ||
+             (serial != NULL && !STREQ_NULLABLE(found_serial, serial))))
             continue;
 
         if (flags & USB_DEVICE_FIND_BY_BUS) {
@@ -203,6 +239,8 @@ virUSBDeviceSearch(unsigned int vendor,
     ret = list;
 
  cleanup:
+    VIR_FREE(found_serial);
+
     if (dir) {
         int saved_errno = errno;
         closedir(dir);
@@ -217,6 +255,7 @@ virUSBDeviceSearch(unsigned int vendor,
 int
 virUSBDeviceFindByVendor(unsigned int vendor,
                          unsigned int product,
+                         const char *serial,
                          const char *vroot,
                          bool mandatory,
                          virUSBDeviceListPtr *devices)
@@ -224,7 +263,7 @@ virUSBDeviceFindByVendor(unsigned int vendor,
     virUSBDeviceListPtr list;
     int count;
 
-    if (!(list = virUSBDeviceSearch(vendor, product, 0, 0,
+    if (!(list = virUSBDeviceSearch(vendor, product, serial, 0, 0,
                                     vroot,
                                     USB_DEVICE_FIND_BY_VENDOR)))
         return -1;
@@ -232,15 +271,16 @@ virUSBDeviceFindByVendor(unsigned int vendor,
     if (list->count == 0) {
         virObjectUnref(list);
         if (!mandatory) {
-            VIR_DEBUG("Did not find USB device %x:%x",
-                      vendor, product);
+            VIR_DEBUG("Did not find USB device %x:%x (serial: %s)",
+                      vendor, product, NULLSTR(serial));
             if (devices)
                 *devices = NULL;
             return 0;
         }
 
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Did not find USB device %x:%x"), vendor, product);
+                       _("Did not find USB device %x:%x (serial: %s)"),
+                       vendor, product, serial ? serial : _("none"));
         return -1;
     }
 
@@ -262,7 +302,7 @@ virUSBDeviceFindByBus(unsigned int bus,
 {
     virUSBDeviceListPtr list;
 
-    if (!(list = virUSBDeviceSearch(0, 0, bus, devno,
+    if (!(list = virUSBDeviceSearch(0, 0, NULL, bus, devno,
                                     vroot,
                                     USB_DEVICE_FIND_BY_BUS)))
         return -1;
@@ -295,6 +335,7 @@ virUSBDeviceFindByBus(unsigned int bus,
 int
 virUSBDeviceFind(unsigned int vendor,
                  unsigned int product,
+                 const char *serial,
                  unsigned int bus,
                  unsigned int devno,
                  const char *vroot,
@@ -304,7 +345,7 @@ virUSBDeviceFind(unsigned int vendor,
     virUSBDeviceListPtr list;
 
     unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
-    if (!(list = virUSBDeviceSearch(vendor, product, bus, devno,
+    if (!(list = virUSBDeviceSearch(vendor, product, serial, bus, devno,
                                     vroot, flags)))
         return -1;
 
@@ -382,6 +423,7 @@ virUSBDeviceFree(virUSBDevicePtr dev)
     if (!dev)
         return;
     VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
+    VIR_FREE(dev->serial);
     VIR_FREE(dev->path);
     VIR_FREE(dev->used_by_drvname);
     VIR_FREE(dev->used_by_domname);
diff --git a/src/util/virusb.h b/src/util/virusb.h
index f98ea21..bb7644f 100644
--- a/src/util/virusb.h
+++ b/src/util/virusb.h
@@ -47,12 +47,14 @@ int virUSBDeviceFindByBus(unsigned int bus,
 
 int virUSBDeviceFindByVendor(unsigned int vendor,
                              unsigned int product,
+                             const char *serial,
                              const char *vroot,
                              bool mandatory,
                              virUSBDeviceListPtr *devices);
 
 int virUSBDeviceFind(unsigned int vendor,
                      unsigned int product,
+                     const char *serial,
                      unsigned int bus,
                      unsigned int devno,
                      const char *vroot,
diff --git a/tests/virusbtest.c b/tests/virusbtest.c
index d08e03b..c1a07a1 100644
--- a/tests/virusbtest.c
+++ b/tests/virusbtest.c
@@ -40,6 +40,7 @@ struct findTestInfo {
     const char *name;
     unsigned int vendor;
     unsigned int product;
+    char *serial;
     unsigned int bus;
     unsigned int devno;
     const char *vroot;
@@ -82,11 +83,13 @@ static int testDeviceFind(const void *opaque)
     switch (info->how) {
     case FIND_BY_ALL:
         rv = virUSBDeviceFind(info->vendor, info->product,
+                              info->serial,
                               info->bus, info->devno,
                               info->vroot, info->mandatory, &dev);
         break;
     case FIND_BY_VENDOR:
         rv = virUSBDeviceFindByVendor(info->vendor, info->product,
+                                      info->serial,
                                       info->vroot, info->mandatory, &devs);
         break;
     case FIND_BY_BUS:
@@ -162,7 +165,7 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
         goto cleanup;
 
 #define EXPECTED_NDEVS_ONE 3
-    if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, true, &devlist) < 0)
+    if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, NULL, true, &devlist) < 0)
         goto cleanup;
 
     ndevs = virUSBDeviceListCount(devlist);
@@ -186,7 +189,7 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
         goto cleanup;
 
 #define EXPECTED_NDEVS_TWO 3
-    if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, true, &devlist) < 0)
+    if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, NULL, true, &devlist) < 0)
         goto cleanup;
 
     ndevs = virUSBDeviceListCount(devlist);
@@ -206,7 +209,7 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
                        EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO) < 0)
         goto cleanup;
 
-    if (virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, true, &dev) < 0)
+    if (virUSBDeviceFind(0x18d1, 0x4e22, NULL, 1, 20, NULL, true, &dev) < 0)
         goto cleanup;
 
     if (!virUSBDeviceListFind(list, dev)) {
@@ -239,9 +242,10 @@ mymain(void)
 {
     int rv = 0;
 
-#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, vroot, mand, how, fail) \
+#define DO_TEST_FIND_FULL(name, vend, prod, serial, bus, devno, vroot,      \
+                          mand, how, fail)                                  \
     do {                                                                    \
-        struct findTestInfo data = { name, vend, prod, bus,                 \
+        struct findTestInfo data = { name, vend, prod, serial, bus,         \
             devno, vroot, mand, how, fail                                   \
         };                                                                  \
         if (virtTestRun("USBDeviceFind " name, testDeviceFind, &data) < 0)  \
@@ -249,24 +253,31 @@ mymain(void)
     } while (0)
 
 #define DO_TEST_FIND(name, vend, prod, bus, devno)                          \
-    DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true,             \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, bus, devno, NULL, true,       \
                       FIND_BY_ALL, false)
 #define DO_TEST_FIND_FAIL(name, vend, prod, bus, devno)                     \
-    DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true,             \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, bus, devno, NULL, true,       \
                       FIND_BY_ALL, true)
 
 #define DO_TEST_FIND_BY_BUS(name, bus, devno)                               \
-    DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true,               \
+    DO_TEST_FIND_FULL(name, 101, 202, NULL, bus, devno, NULL, true,         \
                       FIND_BY_BUS, false)
 #define DO_TEST_FIND_BY_BUS_FAIL(name, bus, devno)                          \
-    DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true,               \
+    DO_TEST_FIND_FULL(name, 101, 202, NULL, bus, devno, NULL, true,         \
                       FIND_BY_BUS, true)
 
 #define DO_TEST_FIND_BY_VENDOR(name, vend, prod)                            \
-    DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true,               \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, 123, 456, NULL, true,         \
                       FIND_BY_VENDOR, false)
 #define DO_TEST_FIND_BY_VENDOR_FAIL(name, vend, prod)                       \
-    DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true,               \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, 123, 456, NULL, true,         \
+                      FIND_BY_VENDOR, true)
+
+#define DO_TEST_FIND_BY_SERIAL(name, vend, prod, serial)                    \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, 123, 456, NULL, true,         \
+                      FIND_BY_VENDOR, false)
+#define DO_TEST_FIND_BY_SERIAL_FAIL(name, vend, prod, serial)               \
+    DO_TEST_FIND_FULL(name, vend, prod, NULL, 123, 456, NULL, true,         \
                       FIND_BY_VENDOR, true)
 
     DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, 1, 20);
@@ -282,6 +293,13 @@ mymain(void)
     DO_TEST_FIND_BY_VENDOR_FAIL("Bogus vendor and product", 0xf00d, 0xbeef);
     DO_TEST_FIND_BY_VENDOR_FAIL("Valid vendor", 0x1d6b, 0xbeef);
 
+    DO_TEST_FIND_BY_SERIAL("Nexus (serial string)", 0x18d1, 0x4e22,
+                           "something something");
+    DO_TEST_FIND_BY_SERIAL("Nexus (serial number)", 0x18d1, 0x4e22,
+                           "0118999881999119725 3");
+    DO_TEST_FIND_BY_SERIAL_FAIL("Nexus (wrong serial)", 0x18d1, 0x4e22,
+                                "0118999881999119725 3");
+
     if (virtTestRun("USB List test", testUSBList, NULL) < 0)
         rv = -1;
 
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial
new file mode 100644
index 0000000..a8aae02
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial
@@ -0,0 +1 @@
+something something
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial
new file mode 100644
index 0000000..5b4cae7
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial
@@ -0,0 +1 @@
+0118999881999119725 3
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1/serial b/tests/virusbtestdata/sys_bus_usb/devices/1-1/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/serial b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1/serial b/tests/virusbtestdata/sys_bus_usb/devices/2-1/serial
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1/serial
@@ -0,0 +1 @@
+
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb1/serial b/tests/virusbtestdata/sys_bus_usb/devices/usb1/serial
new file mode 100644
index 0000000..7f434da
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb1/serial
@@ -0,0 +1 @@
+0000:00:1a.0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb2/serial b/tests/virusbtestdata/sys_bus_usb/devices/usb2/serial
new file mode 100644
index 0000000..3fed695
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb2/serial
@@ -0,0 +1 @@
+0000:00:1d.0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb3/serial b/tests/virusbtestdata/sys_bus_usb/devices/usb3/serial
new file mode 100644
index 0000000..0d45813
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb3/serial
@@ -0,0 +1 @@
+0000:0d:00.0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb4/serial b/tests/virusbtestdata/sys_bus_usb/devices/usb4/serial
new file mode 100644
index 0000000..0d45813
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb4/serial
@@ -0,0 +1 @@
+0000:0d:00.0
-- 
1.8.3.2




More information about the libvir-list mailing list