]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Support CDROM media change for QEMU/KVM
authorDaniel P. Berrange <berrange@redhat.com>
Sat, 27 Oct 2007 01:21:09 +0000 (01:21 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Sat, 27 Oct 2007 01:21:09 +0000 (01:21 +0000)
ChangeLog
src/qemu_driver.c

index 93f9262841b3ed68e5441c8798543d40bc44be1f..44b98063502db708f057d3d767fd6e21faf5bf93 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Fri Oct 26 21:18:44 EST 2007 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/qemu_driver.c: Support CDROM media change for KVM/QEMU
+
 Fri Oct 26 21:17:44 EST 2007 Daniel P. Berrange <berrange@redhat.com>
 
        * src/qemu_driver.c: Refactor shell ecscaping function to reuse
index aa9745ab11a5f0972a1ee07c1dd8cc4e48b0f74a..c86edd3213866dd461dfe1a7824f6165521c27ec 100644 (file)
@@ -1984,6 +1984,11 @@ static char *qemudEscape(const char *in, int shell)
     return out;
 }
 
+static char *qemudEscapeMonitorArg(const char *in)
+{
+    return qemudEscape(in, 0);
+}
+
 static char *qemudEscapeShellArg(const char *in)
 {
     return qemudEscape(in, 1);
@@ -2331,6 +2336,94 @@ static int qemudDomainUndefine(virDomainPtr dom) {
     return 0;
 }
 
+static int qemudDomainChangeCDROM(virDomainPtr dom,
+                                  struct qemud_vm *vm,
+                                  struct qemud_vm_disk_def *olddisk,
+                                  struct qemud_vm_disk_def *newdisk) {
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    char *cmd, *reply, *safe_path;
+
+    /* Migrate to file */
+    safe_path = qemudEscapeMonitorArg(newdisk->src);
+    if (!safe_path) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         "out of memory");
+        return -1;
+    }
+    if (asprintf (&cmd, "change %s \"%s\"",
+                  /* XXX qemu may support multiple CDROM in future */
+                  /* olddisk->dst */ "cdrom",
+                  safe_path) == -1) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         "out of memory");
+        free(safe_path);
+        return -1;
+    }
+    free(safe_path);
+
+    if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "cannot change cdrom media");
+        free(cmd);
+        return -1;
+    }
+    free(reply);
+    free(cmd);
+    strcpy(olddisk->dst, newdisk->dst);
+    olddisk->type = newdisk->type;
+    return 0;
+}
+
+static int qemudDomainAttachDevice(virDomainPtr dom,
+                                   const char *xml) {
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+    struct qemud_vm_device_def *dev;
+    struct qemud_vm_disk_def *disk;
+
+    if (!vm) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid");
+        return -1;
+    }
+
+    if (!qemudIsActiveVM(vm)) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "cannot attach device on inactive domain");
+        return -1;
+    }
+
+    dev = qemudParseVMDeviceDef(dom->conn, driver, xml);
+    if (dev == NULL) {
+        return -1;
+    }
+
+    if (dev->type != QEMUD_DEVICE_DISK || dev->data.disk.device != QEMUD_DISK_CDROM) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "only CDROM disk devices can be attached");
+        free(dev);
+        return -1;
+    }
+
+    disk = vm->def->disks;
+    while (disk) {
+        if (disk->device == QEMUD_DISK_CDROM &&
+            STREQ(disk->dst, dev->data.disk.dst))
+            break;
+        disk = disk->next;
+    }
+
+    if (!disk) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "CDROM not attached, cannot change media");
+        free(dev);
+        return -1;
+    }
+
+    if (qemudDomainChangeCDROM(dom, vm, disk, &dev->data.disk) < 0) {
+        free(dev);
+        return -1;
+    }
+
+    free(dev);
+    return 0;
+}
+
 static int qemudDomainGetAutostart(virDomainPtr dom,
                             int *autostart) {
     struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
@@ -2723,7 +2816,7 @@ static virDriver qemuDriver = {
     qemudDomainStart, /* domainCreate */
     qemudDomainDefine, /* domainDefineXML */
     qemudDomainUndefine, /* domainUndefine */
-    NULL, /* domainAttachDevice */
+    qemudDomainAttachDevice, /* domainAttachDevice */
     NULL, /* domainDetachDevice */
     qemudDomainGetAutostart, /* domainGetAutostart */
     qemudDomainSetAutostart, /* domainSetAutostart */