mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
Fix qemu media connect/eject to work with latest syntax. Add support for ejecting floppy devices and scsi cdroms.
This commit is contained in:
parent
fe7bb57a8b
commit
e0b4fcc280
@ -1,3 +1,9 @@
|
|||||||
|
Wed Sep 3 11:52:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
|
* src/domain_conf.c src/domain_conf.h src/qemu_driver.c:
|
||||||
|
Fix qemu media connect/eject to work with latest syntax. Add support
|
||||||
|
for ejecting floppy devices and scsi cdroms.
|
||||||
|
|
||||||
Wed Sep 3 10:57:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
Wed Sep 3 10:57:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
* src/domain_conf.c src/domain_conf.h src/qemu_driver.c:
|
* src/domain_conf.c src/domain_conf.h src/qemu_driver.c:
|
||||||
|
@ -3411,5 +3411,42 @@ char *virDomainConfigFile(virConnectPtr conn,
|
|||||||
return ret;
|
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);
|
||||||
|
if (idx < 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (disk->bus) {
|
||||||
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
||||||
|
*busIdx = idx / 2;
|
||||||
|
*devIdx = idx % 2;
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
||||||
|
*busIdx = idx / 7;
|
||||||
|
*devIdx = idx % 7;
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_DISK_BUS_FDC:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_USB:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_XEN:
|
||||||
|
default:
|
||||||
|
*busIdx = 0;
|
||||||
|
*devIdx = idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ! PROXY */
|
#endif /* ! PROXY */
|
||||||
|
@ -555,6 +555,10 @@ char *virDomainConfigFile(virConnectPtr conn,
|
|||||||
const char *dir,
|
const char *dir,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
||||||
|
int virDiskNameToBusDeviceIndex(virDomainDiskDefPtr disk,
|
||||||
|
int *busIdx,
|
||||||
|
int *devIdx);
|
||||||
|
|
||||||
virDomainNetDefPtr virDomainNetDefParseXML(virConnectPtr conn,
|
virDomainNetDefPtr virDomainNetDefParseXML(virConnectPtr conn,
|
||||||
xmlNodePtr node);
|
xmlNodePtr node);
|
||||||
|
|
||||||
|
@ -2936,36 +2936,137 @@ static int qemudDomainUndefine(virDomainPtr dom) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemudDomainChangeCDROM(virDomainPtr dom,
|
/* Return the disks name for use in monitor commands */
|
||||||
virDomainObjPtr vm,
|
static char *qemudDiskDeviceName(virDomainPtr dom,
|
||||||
virDomainDiskDefPtr olddisk,
|
virDomainDiskDefPtr disk) {
|
||||||
virDomainDiskDefPtr newdisk) {
|
|
||||||
|
int busid, devid;
|
||||||
|
int ret;
|
||||||
|
char *devname;
|
||||||
|
|
||||||
|
if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
|
||||||
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot convert disk '%s' to bus/device index"),
|
||||||
|
disk->dst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
_("Unsupported 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;
|
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 *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) {
|
||||||
|
if (!(devname = qemudDiskDeviceName(dom, newdisk)))
|
||||||
|
return -1;
|
||||||
|
} 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) {
|
if (newdisk->src) {
|
||||||
safe_path = qemudEscapeMonitorArg(newdisk->src);
|
safe_path = qemudEscapeMonitorArg(newdisk->src);
|
||||||
if (!safe_path) {
|
if (!safe_path) {
|
||||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
|
||||||
"%s", _("out of memory"));
|
VIR_FREE(devname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (asprintf (&cmd, "change %s \"%s\"",
|
if (asprintf (&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
|
||||||
/* XXX qemu may support multiple CDROM in future */
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
|
||||||
/* olddisk->dst */ "cdrom",
|
|
||||||
safe_path) == -1) {
|
|
||||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
|
||||||
"%s", _("out of memory"));
|
|
||||||
VIR_FREE(safe_path);
|
VIR_FREE(safe_path);
|
||||||
|
VIR_FREE(devname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
VIR_FREE(safe_path);
|
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,
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
|
||||||
"%s", _("out of memory"));
|
VIR_FREE(devname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
VIR_FREE(devname);
|
||||||
|
|
||||||
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
|
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
|
||||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||||||
@ -2977,7 +3078,7 @@ static int qemudDomainChangeCDROM(virDomainPtr dom,
|
|||||||
/* If the command failed qemu prints:
|
/* If the command failed qemu prints:
|
||||||
* device not found, device is locked ...
|
* device not found, device is locked ...
|
||||||
* No message is printed on success it seems */
|
* 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 ")) {
|
if (strstr(reply, "\ndevice ")) {
|
||||||
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||||||
"%s", _("changing cdrom media failed"));
|
"%s", _("changing cdrom media failed"));
|
||||||
@ -2985,49 +3086,16 @@ static int qemudDomainChangeCDROM(virDomainPtr dom,
|
|||||||
VIR_FREE(cmd);
|
VIR_FREE(cmd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FREE(reply);
|
VIR_FREE(reply);
|
||||||
VIR_FREE(cmd);
|
VIR_FREE(cmd);
|
||||||
|
|
||||||
VIR_FREE(olddisk->src);
|
VIR_FREE(origdisk->src);
|
||||||
olddisk->src = newdisk->src;
|
origdisk->src = newdisk->src;
|
||||||
newdisk->src = NULL;
|
newdisk->src = NULL;
|
||||||
olddisk->type = newdisk->type;
|
origdisk->type = newdisk->type;
|
||||||
return 0;
|
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)
|
static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev)
|
||||||
{
|
{
|
||||||
@ -3179,10 +3247,11 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
|
||||||
dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
(dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
|
||||||
ret = qemudDomainAttachCdromDevice(dom, dev);
|
dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
|
||||||
|
ret = qemudDomainChangeEjectableMedia(dom, dev);
|
||||||
} else if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
|
} 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) {
|
dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
|
||||||
ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
|
ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
|
||||||
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
|
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
|
||||||
|
Loading…
Reference in New Issue
Block a user