]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
llow to add a disk as an USB device (QEmu/KVM)
authorDaniel Veillard <veillard@redhat.com>
Fri, 8 Aug 2008 15:03:00 +0000 (15:03 +0000)
committerDaniel Veillard <veillard@redhat.com>
Fri, 8 Aug 2008 15:03:00 +0000 (15:03 +0000)
* src/domain_conf.c src/domain_conf.h src/qemu_conf.c
  src/qemu_driver.c: patch from Guido Günther allowing to add
  disk as USB devices
* docs/libvirt.rng: extend the schemas for the new value
* tests/qemuxml2argvdata/qemuxml2argv-disk-usb.args
  tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml
  tests/qemuxml2argvtest.c tests/qemuxml2xmltest.c: add a specific
  test to the regression suite
Daniel

ChangeLog
docs/libvirt.rng
src/domain_conf.c
src/domain_conf.h
src/qemu_conf.c
src/qemu_driver.c
tests/qemuxml2argvdata/qemuxml2argv-disk-usb.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index bed00cd7e2cf38b6406344483baa8532201ded9a..740b98ccf8bd8f635e80da2601cb2511d15ee352 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri Aug  8 16:53:24 CEST 2008 Daniel Veillard <veillard@redhat.com>
+
+       * src/domain_conf.c src/domain_conf.h src/qemu_conf.c
+         src/qemu_driver.c: patch from Guido Günther allowing to add
+         disk as USB devices
+       * docs/libvirt.rng: extend the schemas for the new value
+       * tests/qemuxml2argvdata/qemuxml2argv-disk-usb.args
+         tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml
+         tests/qemuxml2argvtest.c tests/qemuxml2xmltest.c: add a specific
+         test to the regression suite
+
 Fri Aug  8 16:15:55 CEST 2008 Daniel Veillard <veillard@redhat.com>
 
        * src/domain_conf.c src/domain_conf.h src/qemu_conf.c
index 60e181f41e3e966dc367839e1047e1151298c454..81ec33babcfaad218e16bed1e30ba9a1d7656f0b 100644 (file)
              <value>virtio</value>
              <value>fdc</value>
              <value>xen</value>
+             <value>usb</value>
            </choice>
          </attribute>
       </optional>
index 922cf76d4ccf4d1420294b1287e81cd5b0de49d8..237579ff1537a787b8f094ca88b11164edda41cb 100644 (file)
@@ -84,7 +84,8 @@ VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
               "fdc",
               "scsi",
               "virtio",
-              "xen")
+              "xen",
+              "usb")
 
 VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
               "mount",
index 8a9d1db0f75b6db7c9c44b1471fdedde84fb8833..9e7c524b75f227744ec22c2d35be6fa2f467f6c5 100644 (file)
@@ -72,6 +72,7 @@ enum virDomainDiskBus {
     VIR_DOMAIN_DISK_BUS_SCSI,
     VIR_DOMAIN_DISK_BUS_VIRTIO,
     VIR_DOMAIN_DISK_BUS_XEN,
+    VIR_DOMAIN_DISK_BUS_USB,
 
     VIR_DOMAIN_DISK_BUS_LAST
 };
index 46bb9f4c86d52c9f1c343e62e971744d109a3770..3ffabcce146cf1e7180b47687ecedd7d1f3ab8fb 100644 (file)
@@ -55,7 +55,8 @@ VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
               "floppy",
               "scsi",
               "virtio",
-              "xen")
+              "xen",
+              "usb")
 
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
@@ -772,6 +773,16 @@ int qemudBuildCommandLine(virConnectPtr conn,
             goto no_memory;                                             \
     } while (0)
 
+#define ADD_USBDISK(thisarg)                                            \
+    do {                                                                \
+        ADD_ARG_LIT("-usbdevice");                                      \
+        ADD_ARG_SPACE;                                                  \
+        if ((asprintf(&qargv[qargc++], "disk:%s", thisarg)) == -1) {    \
+            qargv[qargc-1] = NULL;                                      \
+            goto no_memory;                                             \
+        }                                                               \
+    } while (0)
+
     snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
     snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
 
@@ -883,6 +894,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
             int idx = virDiskNameToIndex(disk->dst);
             const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
 
+            if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
+                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+                    ADD_USBDISK(disk->src);
+                } else {
+                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                     _("unsupported usb disk type for '%s'"), disk->src);
+                    goto error;
+                }
+                disk = disk->next;
+                continue;
+            }
+
             if (idx < 0) {
                 qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                  _("unsupported disk type '%s'"), disk->dst);
@@ -922,6 +945,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
             char dev[NAME_MAX];
             char file[PATH_MAX];
 
+            if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
+                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+                    ADD_USBDISK(disk->src);
+                } else {
+                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                     _("unsupported usb disk type for '%s'"), disk->src);
+                    goto error;
+                }
+                disk = disk->next;
+                continue;
+            }
+
             if (STREQ(disk->dst, "hdc") &&
                 disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                 if (disk->src) {
index 3c6d7c0346b14d5454a755391ebd02933418392e..a432e79a2dd892e5bbefa50d28d72def3b2b3d01 100644 (file)
@@ -2984,6 +2984,48 @@ static int qemudDomainAttachCdromDevice(virDomainPtr dom,
     return 0;
 }
 
+static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
+{
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+    int ret;
+    char *cmd, *reply;
+
+    if (!vm) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+                         "%s", _("no domain with matching uuid"));
+        return -1;
+    }
+
+    ret = asprintf(&cmd, "usb_add disk:%s", dev->data.disk->src);
+    if (ret == -1) {
+        qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+        return ret;
+    }
+
+    if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         "%s", _("cannot attach usb device"));
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    DEBUG ("attach_usb reply: %s", reply);
+    /* If the command failed qemu prints:
+     * Could not add ... */
+    if (strstr(reply, "Could not add ")) {
+        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                          "%s",
+                          _("adding usb device failed"));
+        VIR_FREE(reply);
+        VIR_FREE(cmd);
+        return -1;
+    }
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+    return 0;
+}
+
 static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
 {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
@@ -3061,6 +3103,10 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
     if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
         dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                 ret = qemudDomainAttachCdromDevice(dom, dev);
+    } else if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
+        dev->data.disk->device == VIR_DOMAIN_DEVICE_DISK &&
+        dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
+                ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
     } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
         dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
         dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb.args
new file mode 100644 (file)
index 0000000..60a8317
--- /dev/null
@@ -0,0 +1 @@
+/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usbdevice disk:/tmp/usbdisk.img -net none -serial none -parallel none -usb
\ No newline at end of file
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml
new file mode 100644 (file)
index 0000000..d59e1c0
--- /dev/null
@@ -0,0 +1,26 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
+    <disk type='file' device='disk'>
+      <source file='/tmp/usbdisk.img'/>
+      <target dev='sda' bus='usb'/>
+    </disk>
+  </devices>
+</domain>
index 458201b9cdfea793080ef053f14727a9071f765a..757d80440d572c442607343dcabfc0568b734155 100644 (file)
@@ -156,6 +156,7 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_DRIVE_BOOT);
     DO_TEST("disk-drive-boot-cdrom", QEMUD_CMD_FLAG_DRIVE |
             QEMUD_CMD_FLAG_DRIVE_BOOT);
+    DO_TEST("disk-usb", 0);
     DO_TEST("graphics-vnc", 0);
     DO_TEST("graphics-sdl", 0);
     DO_TEST("input-usbmouse", 0);
index 536c9bd876665f8ffd3b13b13bde160821577400..c810f78339e8fe1d003e5beb30933fc5a58555a8 100644 (file)
@@ -95,6 +95,7 @@ mymain(int argc, char **argv)
     DO_TEST("disk-floppy");
     DO_TEST("disk-many");
     DO_TEST("disk-xenvbd");
+    DO_TEST("disk-usb");
     DO_TEST("graphics-vnc");
     DO_TEST("graphics-sdl");
     DO_TEST("input-usbmouse");