]> xenbits.xensource.com Git - libvirt.git/commitdiff
* src/domain_conf.h src/qemu_driver.c: patch adding hor removal of
authorDaniel Veillard <veillard@redhat.com>
Wed, 29 Oct 2008 14:32:40 +0000 (14:32 +0000)
committerDaniel Veillard <veillard@redhat.com>
Wed, 29 Oct 2008 14:32:40 +0000 (14:32 +0000)
  scsi/virtio disks for KVM, patch by Guido Günther
daniel

ChangeLog
src/domain_conf.h
src/qemu_driver.c

index ee119e6c6e184099f2b8bab58feaa4c50c8e8235..50a5747b54c05cef7079f610b922c1caa3c9dd69 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed Oct 29 15:25:28 CET 2008 Daniel Veillard <veillard@redhat.com>
+
+       * src/domain_conf.h src/qemu_driver.c: patch adding hor removal of
+         scsi/virtio disks for KVM, patch by Guido Günther
+
 Tue Oct 28 19:17:20 +0100 2008 Jim Meyering <meyering@redhat.com>
 
        remove src/socketcompat.h;  no longer needed
index 62731e6c5563d4ea2e4e921776b93298901b2dcc..cd6658a08e8aaec22a5ce62a68566c473ac303e5 100644 (file)
@@ -90,6 +90,7 @@ struct _virDomainDiskDef {
     char *driverType;
     unsigned int readonly : 1;
     unsigned int shared : 1;
+    int slotnum; /* pci slot number for unattach */
 };
 
 
index e21f3fdb6c3477e73a12df7296ecccd695fa6c0f..591322a622d13ab7353ce069d121036311d089d1 100644 (file)
@@ -2537,12 +2537,12 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
     return 0;
 }
 
-static int qemudDomainAttachDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
+static int qemudDomainAttachPciDiskDevice(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 *cmd, *reply, *s;
     char *safe_path;
     const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
 
@@ -2590,7 +2590,14 @@ static int qemudDomainAttachDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr d
     DEBUG ("pci_add reply: %s", reply);
     /* If the command succeeds qemu prints:
      * OK bus 0... */
-    if (!strstr(reply, "OK bus 0")) {
+#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
+    if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
+        char* dummy = s;
+        s += strlen(PCI_ATTACH_OK_MSG);
+
+        if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
+            qemudLog(QEMUD_WARN, _("Unable to parse slot number\n"));
+    } else {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                           _("adding %s disk failed"), type);
         VIR_FREE(reply);
@@ -2773,7 +2780,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
                 } 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);
+                    ret = qemudDomainAttachPciDiskDevice(dom, dev);
                 }
                 break;
         }
@@ -2794,6 +2801,123 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
     return ret;
 }
 
+static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
+{
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    int i, ret = -1;
+    char *cmd, *reply;
+    virDomainDiskDefPtr detach = NULL;
+
+    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)) {
+            detach = vm->def->disks[i];
+            break;
+        }
+    }
+
+    if (!detach) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         _("disk %s not found"), dev->data.disk->dst);
+        return -1;
+    }
+
+    if (detach->slotnum < 1) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         _("disk %s cannot be detached - invalid slot number %d"), 
+                           detach->dst, detach->slotnum);
+        return -1;
+    }
+
+    ret = asprintf(&cmd, "pci_del 0 %d", detach->slotnum);
+    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,
+                          _("failed to execute detach disk %s command"), detach->dst);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    DEBUG ("pci_del reply: %s", reply);
+    /* If the command fails due to a wrong slot qemu prints: invalid slot,
+     * nothing is printed on success */
+    if (strstr(reply, "invalid slot")) {
+        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                          _("failed to detach disk %s: invalid slot %d"), 
+                            detach->dst, detach->slotnum);
+        ret = -1;
+        goto out;
+    }
+
+    if (vm->def->ndisks > 1) {
+        vm->def->disks[i] = vm->def->disks[--vm->def->ndisks];
+        if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
+            qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+            ret = -1;
+            goto out;
+        }
+        qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
+              virDomainDiskQSort);
+    } else {
+        VIR_FREE(vm->def->disks[0]);
+        vm->def->ndisks = 0;
+    }
+    ret = 0;
+out:
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+    return ret;
+}
+
+static int qemudDomainDetachDevice(virDomainPtr dom,
+                                   const char *xml) {
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    virDomainDeviceDefPtr dev;
+    int ret = 0;
+
+    if (!vm) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+                         "%s", _("no domain with matching uuid"));
+        return -1;
+    }
+
+    if (!virDomainIsActive(vm)) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("cannot attach device on inactive domain"));
+        return -1;
+    }
+
+    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml);
+    if (dev == NULL) {
+        return -1;
+    }
+
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
+        dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
+        (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
+         dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO))
+                    ret = qemudDomainDetachPciDiskDevice(dom, dev);
+    else {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+                         "%s", _("only SCSI or virtio disk device can be detached dynamically"));
+        ret = -1;
+    }
+
+    VIR_FREE(dev);
+    return ret;
+}
+
 static int qemudDomainGetAutostart(virDomainPtr dom,
                             int *autostart) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
@@ -3278,7 +3402,7 @@ static virDriver qemuDriver = {
     qemudDomainDefine, /* domainDefineXML */
     qemudDomainUndefine, /* domainUndefine */
     qemudDomainAttachDevice, /* domainAttachDevice */
-    NULL, /* domainDetachDevice */
+    qemudDomainDetachDevice, /* domainDetachDevice */
     qemudDomainGetAutostart, /* domainGetAutostart */
     qemudDomainSetAutostart, /* domainSetAutostart */
     NULL, /* domainGetSchedulerType */