[Libvir] PATCH: 3/4 Implement CDROM media change for QEMU/KVM driver

Daniel P. Berrange berrange at redhat.com
Tue Oct 16 20:52:37 UTC 2007


This patch implements the attach device API allowing CDROM devices to have
their media changed. It has switched to using asprintf() for constructing
the monitor command, the qemudEscapeMonitorArg on the file path. This is
consistent with the style of the save API.

Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
diff -r 0ca411fcf2dc src/qemu_driver.c
--- a/src/qemu_driver.c	Tue Oct 16 15:47:51 2007 -0400
+++ b/src/qemu_driver.c	Tue Oct 16 15:51:19 2007 -0400
@@ -1984,6 +1984,11 @@ static char *qemudEscape(const char *in,
     return out;
 }
 
+static char *qemudEscapeMonitorArg(const char *in)
+{
+    return qemudEscape(in, 0);
+}
+
 static char *qemudEscapeShellArg(const char *in)
 {
     return qemudEscape(in, 1);
@@ -2328,6 +2333,94 @@ static int qemudDomainUndefine(virDomain
 
     qemudRemoveInactiveVM(driver, vm);
 
+    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;
 }
 
@@ -2723,7 +2816,7 @@ static virDriver qemuDriver = {
     qemudDomainStart, /* domainCreate */
     qemudDomainDefine, /* domainDefineXML */
     qemudDomainUndefine, /* domainUndefine */
-    NULL, /* domainAttachDevice */
+    qemudDomainAttachDevice, /* domainAttachDevice */
     NULL, /* domainDetachDevice */
     qemudDomainGetAutostart, /* domainGetAutostart */
     qemudDomainSetAutostart, /* domainSetAutostart */


More information about the libvir-list mailing list