Support to update the disk's bootindex using 'virsh update-device'. Using flag --config or --persistent to change the boot index and the change will be affected after reboot. With --persistent, we can get the result of change immediently, but it still takes effect after reboot. Currently, support update bootindex of disk type as cdrom or disk. Signed-off-by: Jiang Jiacheng <jiangjiacheng@xxxxxxxxxx> --- src/qemu/qemu_domain.c | 37 ++++++++++++++++++++++++++++++++++++- src/qemu/qemu_domain.h | 5 +++++ src/qemu/qemu_driver.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6ec3be14c0..dfc4d15387 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8235,7 +8235,8 @@ qemuDomainDiskChangeSupported(virDomainDiskDef *disk, /* device alias is checked already in virDomainDefCompatibleDevice */ - CHECK_EQ(info.bootIndex, "boot order", true); + if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) + CHECK_EQ(info.bootIndex, "boot order", true); CHECK_EQ(rawio, "rawio", true); CHECK_EQ(sgio, "sgio", true); CHECK_EQ(discard, "discard", true); @@ -12309,3 +12310,37 @@ qemuCheckBootIndex(virDomainDeviceInfo *devInfo, return 0; } + +/** + * qemuChangeDiskBootIndex: + * @vm: domain object + * @orig_disk: the origin disk + * @disk: the new disk to be updated to + * + * check device's type and if its type support update bootIndex, update it. + * + */ +int +qemuChangeDiskBootIndex(virDomainObj *vm, + virDomainDiskDef *orig_disk, + virDomainDiskDef *disk) +{ + switch (disk->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_DISK: + case VIR_DOMAIN_DISK_DEVICE_LUN: + if (qemuDomainChangeBootIndex(vm, &orig_disk->info, + disk->info.bootIndex) < 0) + return -1; + + orig_disk->info.bootIndex = disk->info.bootIndex; + break; + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + case VIR_DOMAIN_DISK_DEVICE_LAST: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The boot index of disk bus '%s' cannot be changed."), + virDomainDiskBusTypeToString(disk->bus)); + return -1; + } + return 0; +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 5869771a0d..da661d11da 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -1144,3 +1144,8 @@ qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv); int qemuCheckBootIndex(virDomainDeviceInfo *devInfo, const int new_bootindex); + +int +qemuChangeDiskBootIndex(virDomainObj *vm, + virDomainDiskDef *orig_disk, + virDomainDiskDef *disk); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d509582719..d5fa9c022c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6795,6 +6795,7 @@ qemuDomainChangeDiskLive(virDomainObj *vm, virDomainDiskDef *orig_disk = NULL; virDomainStartupPolicy origStartupPolicy; virDomainDeviceDef oldDev = { .type = dev->type }; + int needChangeIndex = 0; if (!(orig_disk = virDomainDiskByTarget(vm->def, disk->dst))) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -6812,6 +6813,10 @@ qemuDomainChangeDiskLive(virDomainObj *vm, if (!qemuDomainDiskChangeSupported(disk, orig_disk)) return -1; + if ((needChangeIndex = qemuCheckBootIndex(&orig_disk->info, + disk->info.bootIndex)) < 0) + return -1; + if (!virStorageSourceIsSameLocation(disk->src, orig_disk->src)) { /* Disk source can be changed only for removable devices */ if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM && @@ -6835,6 +6840,11 @@ qemuDomainChangeDiskLive(virDomainObj *vm, dev->data.disk->src = NULL; } + if (needChangeIndex) { + if (qemuChangeDiskBootIndex(vm, orig_disk, disk) < 0) + return -1; + } + /* in case when we aren't updating disk source we update startup policy here */ orig_disk->startupPolicy = dev->data.disk->startupPolicy; orig_disk->snapshot = dev->data.disk->snapshot; @@ -7531,6 +7541,24 @@ qemuDomainUpdateDeviceConfig(virDomainDef *vmdef, false) < 0) return -1; + switch (vmdef->disks[pos]->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_DISK: + case VIR_DOMAIN_DISK_DEVICE_LUN: + if (qemuCheckBootIndex(&vmdef->disks[pos]->info, + newDisk->info.bootIndex) < 0) + return -1; + break; + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + case VIR_DOMAIN_DISK_DEVICE_LAST: + if ((newDisk->info.bootIndex) && + (vmdef->disks[pos]->info.bootIndex != newDisk->info.bootIndex)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("this disk doesn't support update")); + return -1; + } + } + virDomainDiskDefFree(vmdef->disks[pos]); vmdef->disks[pos] = newDisk; dev->data.disk = NULL; -- 2.33.0