]> xenbits.xensource.com Git - libvirt.git/commitdiff
* src/qemu_driver.c: add scsi/virtio hotplug support for KVM
authorDaniel Veillard <veillard@redhat.com>
Fri, 17 Oct 2008 12:36:39 +0000 (12:36 +0000)
committerDaniel Veillard <veillard@redhat.com>
Fri, 17 Oct 2008 12:36:39 +0000 (12:36 +0000)
  patch by Guido Günther
daniel

ChangeLog
src/qemu_driver.c

index 3c678fac98b2b92f204c5d79685ca51d7ce5912e..6b056d63ef9cc2f7f64a27f413db7fe42618dbf6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Oct 17 14:30:48 CEST 2008 Daniel Veillard <veillard@redhat.com>
+
+       * src/qemu_driver.c: add scsi/virtio hotplug support for KVM
+         patch by Guido Günther
+
 Fri Oct 17 11:58:31 +0200 Jim Meyering <meyering@redhat.com>
 
        Makefile.maint (sync-vcs-ignore-files): avoid risk of abuse
index 0a8a6ed81829281c5cf4ae948db9b08c594c0e69..904fe0068a671d99a4f5108f8ef14f36b1603094 100644 (file)
@@ -2509,6 +2509,75 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
     return 0;
 }
 
+static int qemudDomainAttachDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
+{
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    int ret, i;
+    char *cmd, *reply;
+    char *safe_path;
+    const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
+
+    if (!vm) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+                         "%s", _("no domain with matching uuid"));
+        return -1;
+    }
+
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
+            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                           _("target %s already exists"), dev->data.disk->dst);
+            return -1;
+        }
+    }
+
+    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
+        qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+        return -1;
+    }
+
+    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
+    if (!safe_path) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         "%s", _("out of memory"));
+        return -1;
+    }
+
+    ret = asprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
+                         safe_path, type);
+    VIR_FREE(safe_path);
+    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,
+                         _("cannot attach %s disk"), type);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    DEBUG ("pci_add reply: %s", reply);
+    /* If the command succeeds qemu prints:
+     * OK bus 0... */
+    if (!strstr(reply, "OK bus 0")) {
+        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                          _("adding %s disk failed"), type);
+        VIR_FREE(reply);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    vm->def->disks[vm->def->ndisks++] = dev->data.disk;
+    qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
+          virDomainDiskQSort);
+
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+    return 0;
+}
 
 static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
 {
@@ -2624,7 +2693,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
     virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
     virDomainDeviceDefPtr dev;
-    int ret = 0;
+    int ret = 0, supported = 0;
 
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2643,19 +2712,32 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
         return -1;
     }
 
-    if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
-        (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
-         dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        switch (dev->data.disk->device) {
+            case VIR_DOMAIN_DISK_DEVICE_CDROM:
+            case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+                supported = 1;
                 ret = qemudDomainChangeEjectableMedia(dom, dev);
-    } else if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
-        dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
-        dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
-                ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
+                break;
+            case VIR_DOMAIN_DISK_DEVICE_DISK:
+                if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
+                    supported = 1;
+                    ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
+                } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
+                           dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
+                    supported = 1;
+                    ret = qemudDomainAttachDiskDevice(dom, dev);
+                }
+                break;
+        }
     } 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) {
+                supported = 1;
                 ret = qemudDomainAttachHostDevice(dom, dev);
-    } else {
+    }
+
+    if (!supported) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s", _("this device type cannot be attached"));
         ret = -1;