On 01/05/2015 02:29 AM, Wang Rui wrote:
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(a)huawei.com>
Signed-off-by: Zhou Yimin <zhouyimin(a)huawei.com>
---
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)))
Format/alignment issue (caps under dev)
+ 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