Daniel P. Berrange wrote: > On Mon, Aug 25, 2008 at 01:41:24PM -0400, Cole Robinson wrote: >> + >> + int idx = virDiskNameToIndex(newdisk->dst); >> + switch (newdisk->bus) { >> + /* Assume that if we are here, device targets don't exceed hypervisor >> + * limits, and we are already an appropriate device type */ >> + case VIR_DOMAIN_DISK_BUS_IDE: >> + /* Device name of the form 'ide{0-1}-cd{0-1}' */ >> + ret = asprintf(&devname, "ide%d-cd%d", ((idx - (idx % 2)) / 2), >> + (idx % 2)); >> + break; >> + case VIR_DOMAIN_DISK_BUS_SCSI: >> + /* Device name of the form 'scsi{bus#}-cd{0-6} >> + * Each bus holds seven devs */ >> + ret = asprintf(&devname, "scsi%d-cd%d", ((idx - (idx % 7)) / 7), >> + (idx % 7)); >> + break; >> + case VIR_DOMAIN_DISK_BUS_FDC: >> + /* Device name is 'floppy{0-1}' */ >> + ret = asprintf(&devname, "floppy%d", idx); >> + break; >> + >> + default: >> + qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, >> + _("Cannot hotplug device with bus '%s'"), >> + virDomainDiskBusTypeToString(newdisk->bus)); >> + return -1; >> + } > > I think this block could be re-factored a little into one or more helper > methods, because I think we'll need to re-use this for hot-unplug of > disks. I'd suggest a helper to turn the plain integer index into the > (bus,device) index pair > > virDiskNameToBusDeviceIndex(virDomainDiskDefPtr disk, > int *busIdx, > int *devIdx); > > And then a QEMU specific function > > char *virQEMUDeviceName(virDomainDiskDefPtr disk); > > and have this call virDiskNameToBusDeviceIndex() and return the 'ide1-2' > type string. > Okay, second cut attached. I followed your recommendations: virDiskNameToBusDeviceIndex added to domain_conf.c qemudDiskDeviceName added to qemu_driver.c I also hopefully solved the back compatibility issue. Seems -drive was added to qemu in Dec 07 (qemu commit 3759) and the device naming scheme was updated at the end of that month (qemu commit 3846), so checking for -drive should be a sufficient indicator that we need to use the new device name format. So if drive was detected (using the already present qemu_conf flag), we revert to the old style cdrom/fda naming style. I tested this on f8 using plain qemu (which lacks the -drive option) and it appeared to work as expected for cdrom and floppy devices. Thanks, Cole
diff --git a/src/domain_conf.c b/src/domain_conf.c index dc5eb0c..95277c3 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -3411,5 +3411,38 @@ char *virDomainConfigFile(virConnectPtr conn, return ret; } +/* Translates a device name of the form (regex) "[fhv]d[a-z]+" into + * the corresponding bus,index combination (e.g. sda => (0,0), sdi (1,1), + * hdd => (1,1), vdaa => (0,27)) + * @param disk The disk device + * @param busIdx parsed bus number + * @param devIdx parsed device number + * @return 0 on success, -1 on failure + */ +int virDiskNameToBusDeviceIndex(virDomainDiskDefPtr disk, + int *busIdx, + int *devIdx) { + + int idx = virDiskNameToIndex(disk->dst); + + switch (disk->bus) { + case VIR_DOMAIN_DISK_BUS_IDE: + *busIdx = ((idx - (idx % 2)) / 2); + *devIdx = (idx % 2); + break; + case VIR_DOMAIN_DISK_BUS_SCSI: + *busIdx = ((idx - (idx % 7)) / 7); + *devIdx = (idx % 7); + break; + case VIR_DOMAIN_DISK_BUS_FDC: + case VIR_DOMAIN_DISK_BUS_VIRTIO: + default: + *busIdx = 0; + *devIdx = idx; + break; + } + + return 0; +} #endif /* ! PROXY */ diff --git a/src/domain_conf.h b/src/domain_conf.h index cfa2a90..de8a043 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -555,6 +555,10 @@ char *virDomainConfigFile(virConnectPtr conn, const char *dir, const char *name); +int virDiskNameToBusDeviceIndex(virDomainDiskDefPtr disk, + int *busIdx, + int *devIdx); + virDomainNetDefPtr virDomainNetDefParseXML(virConnectPtr conn, xmlNodePtr node); diff --git a/src/qemu_driver.c b/src/qemu_driver.c index ad14d02..d842217 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -2943,36 +2943,134 @@ static int qemudDomainUndefine(virDomainPtr dom) { return 0; } -static int qemudDomainChangeCDROM(virDomainPtr dom, - virDomainObjPtr vm, - virDomainDiskDefPtr olddisk, - virDomainDiskDefPtr newdisk) { +/* Return the disks name for use in monitor commands */ +static char *qemudDiskDeviceName(virDomainPtr dom, + virDomainDiskDefPtr disk) { + + int busid, devid; + int ret; + char *devname; + + virDiskNameToBusDeviceIndex(disk, &busid, &devid); + + switch (disk->bus) { + case VIR_DOMAIN_DISK_BUS_IDE: + ret = asprintf(&devname, "ide%d-cd%d", busid, devid); + break; + case VIR_DOMAIN_DISK_BUS_SCSI: + ret = asprintf(&devname, "scsi%d-cd%d", busid, devid); + break; + case VIR_DOMAIN_DISK_BUS_FDC: + ret = asprintf(&devname, "floppy%d", devid); + break; + case VIR_DOMAIN_DISK_BUS_VIRTIO: + ret = asprintf(&devname, "virtio%d", devid); + break; + default: + qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, + _("Unknown disk name mapping for bus '%s'"), + virDomainDiskBusTypeToString(disk->bus)); + return NULL; + } + + if (ret == -1) { + qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + return devname; +} + +static int qemudDomainChangeEjectableMedia(virDomainPtr dom, + virDomainDeviceDefPtr dev) +{ struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); + virDomainDiskDefPtr origdisk, newdisk; char *cmd, *reply, *safe_path; + char *devname = NULL; + int qemuCmdFlags; + + if (!vm) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + return -1; + } + + newdisk = dev->data.disk; + origdisk = vm->def->disks; + while (origdisk) { + if (origdisk->bus == newdisk->bus && + STREQ(origdisk->dst, newdisk->dst)) + break; + origdisk = origdisk->next; + } + + if (!origdisk) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("No device with bus '%s' and target '%s'"), + virDomainDiskBusTypeToString(newdisk->bus), + newdisk->dst); + return -1; + } + + if (qemudExtractVersionInfo(vm->def->emulator, + NULL, + &qemuCmdFlags) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Cannot determine QEMU argv syntax %s"), + vm->def->emulator); + return -1; + } + + if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) { + devname = qemudDiskDeviceName(dom, newdisk); + } else { + /* Back compat for no -drive option */ + if (newdisk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) + devname = strdup(newdisk->dst); + else if (newdisk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + STREQ(newdisk->dst, "hdc")) + devname = strdup("cdrom"); + else { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Emulator version does not support removable " + "media for device '%s' and target '%s'"), + virDomainDiskDeviceTypeToString(newdisk->device), + newdisk->dst); + return -1; + } + } + + if (!devname) { + qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + return -1; + } if (newdisk->src) { safe_path = qemudEscapeMonitorArg(newdisk->src); if (!safe_path) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); + VIR_FREE(devname); return -1; } - if (asprintf (&cmd, "change %s \"%s\"", - /* XXX qemu may support multiple CDROM in future */ - /* olddisk->dst */ "cdrom", - safe_path) == -1) { + if (asprintf (&cmd, "change %s \"%s\"", devname, safe_path) == -1) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); VIR_FREE(safe_path); + VIR_FREE(devname); return -1; } VIR_FREE(safe_path); - } else if (asprintf(&cmd, "eject cdrom") == -1) { + } else if (asprintf(&cmd, "eject %s", devname) == -1) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); + VIR_FREE(devname); return -1; } + VIR_FREE(devname); if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, @@ -2984,7 +3082,7 @@ static int qemudDomainChangeCDROM(virDomainPtr dom, /* If the command failed qemu prints: * device not found, device is locked ... * No message is printed on success it seems */ - DEBUG ("cdrom change reply: %s", reply); + DEBUG ("ejectable media change reply: %s", reply); if (strstr(reply, "\ndevice ")) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("changing cdrom media failed")); @@ -2992,49 +3090,16 @@ static int qemudDomainChangeCDROM(virDomainPtr dom, VIR_FREE(cmd); return -1; } - VIR_FREE(reply); VIR_FREE(cmd); - VIR_FREE(olddisk->src); - olddisk->src = newdisk->src; + VIR_FREE(origdisk->src); + origdisk->src = newdisk->src; newdisk->src = NULL; - olddisk->type = newdisk->type; + origdisk->type = newdisk->type; return 0; } -static int qemudDomainAttachCdromDevice(virDomainPtr dom, - virDomainDeviceDefPtr dev) -{ - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); - virDomainDiskDefPtr disk; - - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } - - disk = vm->def->disks; - while (disk) { - if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && - STREQ(disk->dst, dev->data.disk->dst)) - break; - disk = disk->next; - } - - if (!disk) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, - "%s", _("CDROM not attached, cannot change media")); - return -1; - } - - if (qemudDomainChangeCDROM(dom, vm, disk, dev->data.disk) < 0) { - return -1; - } - return 0; -} static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) { @@ -3186,10 +3251,11 @@ 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); + (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM || + dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) { + ret = qemudDomainChangeEjectableMedia(dom, dev); } else if (dev->type == VIR_DOMAIN_DEVICE_DISK && - dev->data.disk->device == 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); } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list