When we attach a disk to a running VM with boot index, we can get a successful result. But in fact the boot index won't take effect. QEMU supported to set device's boot index online recently(since QEMU 2.2.0). After this patch, the boot index will take effect after virDomainAttachDevice(Flags) API returning success. If new disk is attached successfully but boot index is set failed, we'll remove the new disk to restore. Signed-off-by: Wang Rui <moon.wangrui@xxxxxxxxxx> Signed-off-by: Zhou Yimin <zhouyimin@xxxxxxxxxx> --- src/qemu/qemu_hotplug.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 2f84949..5eacfce 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2999,7 +2999,12 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, { virDomainDiskDefPtr disk = dev->data.disk; virDomainDiskDefPtr orig_disk = NULL; + virDomainDeviceDefPtr new_dev_copy = NULL; + virDomainDeviceDefPtr old_dev_copy = NULL; + virDomainDiskDefPtr tmp = NULL; + virCapsPtr caps = NULL; int ret = -1; + int removed = 0; const char *driverName = virDomainDiskGetDriver(disk); const char *src = virDomainDiskGetSource(disk); @@ -3022,6 +3027,13 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, if (qemuDomainDetermineDiskChain(driver, vm, disk, false, true) < 0) goto end; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto end; + + if (!(new_dev_copy = virDomainDeviceDefCopy(dev, vm->def, + caps, driver->xmlopt))) + goto end; + switch (disk->device) { case VIR_DOMAIN_DISK_DEVICE_CDROM: case VIR_DOMAIN_DISK_DEVICE_FLOPPY: @@ -3036,12 +3048,33 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, goto end; } + tmp = dev->data.disk; + dev->data.disk = orig_disk; + /* save a copy of old device to restore */ + if (!(old_dev_copy = virDomainDeviceDefCopy(dev, vm->def, + caps, driver->xmlopt))) { + dev->data.disk = tmp; + goto end; + } + dev->data.disk = tmp; + if (qemuDomainChangeEjectableMedia(driver, conn, vm, orig_disk, disk->src, false) < 0) goto end; disk->src = NULL; ret = 0; + + tmp = new_dev_copy->data.disk; + if (orig_disk->info.bootIndex != tmp->info.bootIndex) { + /* If boot index is to be changed to 0, we can pass "value":-1 to + qmp command("qom-set") to cancel boot index. */ + if (qemuDomainChangeBootIndex(driver, vm, &orig_disk->info, + tmp->info.bootIndex ? + tmp->info.bootIndex : -1) < 0) + goto try_remove; + orig_disk->info.bootIndex = tmp->info.bootIndex; + } break; case VIR_DOMAIN_DISK_DEVICE_DISK: @@ -3063,6 +3096,15 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, _("disk bus '%s' cannot be hotplugged."), virDomainDiskBusTypeToString(disk->bus)); } + + tmp = new_dev_copy->data.disk; + if (!ret && tmp->info.bootIndex > 0) { + if (qemuDomainChangeBootIndex(driver, vm, &disk->info, + tmp->info.bootIndex) < 0) + goto try_remove; + disk->info.bootIndex = tmp->info.bootIndex; + } + break; default: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, @@ -3074,7 +3116,53 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, end: if (ret != 0) ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name)); + virObjectUnref(caps); + virDomainDeviceDefFree(new_dev_copy); + virDomainDeviceDefFree(old_dev_copy); + if (removed) { + dev->data.disk = NULL; + ret = -1; + } return ret; + + try_remove: + if (!virDomainObjIsActive(vm)) { + removed = 1; + goto end; + } + + switch (new_dev_copy->data.disk->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + if (qemuAddSharedDevice(driver, old_dev_copy, vm->def->name) < 0) + break; + + tmp = old_dev_copy->data.disk; + if (qemuDomainChangeEjectableMedia(driver, conn, vm, orig_disk, tmp->src, false) < 0) { + VIR_WARN("Unable to recover original media with target '%s' and path '%s'", + tmp->dst, tmp->src->path); + ignore_value(qemuRemoveSharedDevice(driver, old_dev_copy, vm->def->name)); + } else { + tmp->src = NULL; + } + break; + case VIR_DOMAIN_DISK_DEVICE_DISK: + case VIR_DOMAIN_DISK_DEVICE_LUN: + if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { + if (qemuDomainDetachVirtioDiskDevice(driver, vm, disk) != 0) + VIR_WARN("Unable to detach new disk with bus '%s' and target '%s'", + virDomainDiskBusTypeToString(disk->bus), disk->dst); + } + else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || + disk->bus == VIR_DOMAIN_DISK_BUS_USB) + if (qemuDomainDetachDiskDevice(driver, vm, disk) != 0) + VIR_WARN("Unable to detach new disk with bus '%s' and target '%s'", + virDomainDiskBusTypeToString(disk->bus), disk->dst); + ret = -1; + break; + } + removed = 1; + goto end; } static int -- 1.7.12.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list