diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f2ddde7a3601a93c0b8a0547209443e49e6053a6..c71c28e8d21daa79181b3a25ac2989310a33f2dc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -27400,7 +27400,8 @@ virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def ATTRIBUTE_UNUSED, int virDomainDefCompatibleDevice(virDomainDefPtr def, - virDomainDeviceDefPtr dev) + virDomainDeviceDefPtr dev, + virDomainDeviceDefPtr oldDev ATTRIBUTE_UNUSED) { virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2350926e5bdc2cb0042080c647f15917ef0399ff..368f16f3fbf9480382f147b3b6c4707a1b92c084 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3014,7 +3014,8 @@ typedef enum { } virDomainDeviceAction; int virDomainDefCompatibleDevice(virDomainDefPtr def, - virDomainDeviceDefPtr dev); + virDomainDeviceDefPtr dev, + virDomainDeviceDefPtr oldDev); void virDomainRNGDefFree(virDomainRNGDefPtr def); diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 4c6f09a4352fe84638e0c7ce9f7cd0748fdeb50a..fa6fc4643ee2c705e0558def2b71ff4f96fd99d2 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3578,6 +3578,7 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef, { int ret = -1; virDomainNetDefPtr net; + virDomainDeviceDef oldDev = { .type = dev->type }; int idx; switch (dev->type) { @@ -3586,8 +3587,11 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef, if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) goto cleanup; - virDomainNetDefFree(vmdef->nets[idx]); + oldDev.data.net = vmdef->nets[idx]; + if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0) + return -1; + virDomainNetDefFree(vmdef->nets[idx]); vmdef->nets[idx] = net; dev->data.net = NULL; ret = 0; @@ -4820,7 +4824,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, if (!vmdef) goto endjob; - if (virDomainDefCompatibleDevice(vmdef, dev) < 0) + if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0) goto endjob; if ((ret = lxcDomainAttachDeviceConfig(vmdef, dev)) < 0) @@ -4828,7 +4832,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, } if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0) + if (virDomainDefCompatibleDevice(vm->def, dev_copy, NULL) < 0) goto endjob; if ((ret = lxcDomainAttachDeviceLive(dom->conn, driver, vm, dev_copy)) < 0) @@ -4931,9 +4935,8 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom, if (!vmdef) goto endjob; - if (virDomainDefCompatibleDevice(vmdef, dev) < 0) - goto endjob; - + /* virDomainDefCompatibleDevice call is delayed until we know the + * device we're going to update. */ if ((ret = lxcDomainUpdateDeviceConfig(vmdef, dev)) < 0) goto endjob; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 14c39b2610dda9a6661730305debeee022647972..313d730c791fe558a90da1e13f023cabc65311ad 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7844,6 +7844,7 @@ qemuDomainChangeDiskLive(virDomainObjPtr vm, { virDomainDiskDefPtr disk = dev->data.disk; virDomainDiskDefPtr orig_disk = NULL; + virDomainDeviceDef oldDev = { .type = dev->type }; int ret = -1; if (virDomainDiskTranslateSourcePool(disk) < 0) @@ -7861,6 +7862,10 @@ qemuDomainChangeDiskLive(virDomainObjPtr vm, goto cleanup; } + oldDev.data.disk = orig_disk; + if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0) + goto cleanup; + if (!qemuDomainDiskChangeSupported(disk, orig_disk)) goto cleanup; @@ -7903,19 +7908,36 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, bool force) { virQEMUDriverPtr driver = dom->conn->privateData; + virDomainDeviceDef oldDev = { .type = dev->type }; int ret = -1; + int idx; switch ((virDomainDeviceType) dev->type) { case VIR_DOMAIN_DEVICE_DISK: qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL); ret = qemuDomainChangeDiskLive(vm, dev, driver, force); break; + case VIR_DOMAIN_DEVICE_GRAPHICS: + if ((idx = qemuDomainFindGraphicsIndex(vm->def, dev->data.graphics) >= 0)) { + oldDev.data.graphics = vm->def->graphics[idx]; + if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0) + return -1; + } + ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics); break; + case VIR_DOMAIN_DEVICE_NET: + if ((idx = virDomainNetFindIdx(vm->def, dev->data.net)) >= 0) { + oldDev.data.net = vm->def->nets[idx]; + if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0) + return -1; + } + ret = qemuDomainChangeNet(driver, vm, dev); break; + case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: @@ -8329,6 +8351,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDiskDefPtr newDisk; virDomainGraphicsDefPtr newGraphics; virDomainNetDefPtr net; + virDomainDeviceDef oldDev = { .type = dev->type }; int pos; switch ((virDomainDeviceType) dev->type) { @@ -8340,6 +8363,10 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, return -1; } + oldDev.data.disk = vmdef->disks[pos]; + if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0) + return -1; + virDomainDiskDefFree(vmdef->disks[pos]); vmdef->disks[pos] = newDisk; dev->data.disk = NULL; @@ -8355,8 +8382,11 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, return -1; } - virDomainGraphicsDefFree(vmdef->graphics[pos]); + oldDev.data.graphics = vmdef->graphics[pos]; + if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0) + return -1; + virDomainGraphicsDefFree(vmdef->graphics[pos]); vmdef->graphics[pos] = newGraphics; dev->data.graphics = NULL; break; @@ -8366,8 +8396,11 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, if ((pos = virDomainNetFindIdx(vmdef, net)) < 0) return -1; - virDomainNetDefFree(vmdef->nets[pos]); + oldDev.data.net = vmdef->nets[pos]; + if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0) + return -1; + virDomainNetDefFree(vmdef->nets[pos]); vmdef->nets[pos] = net; dev->data.net = NULL; break; @@ -8454,7 +8487,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, if (!vmdef) goto cleanup; - if (virDomainDefCompatibleDevice(vmdef, dev) < 0) + if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0) goto cleanup; if ((ret = qemuDomainAttachDeviceConfig(vmdef, dev, caps, parse_flags, @@ -8463,7 +8496,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, } if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0) + if (virDomainDefCompatibleDevice(vm->def, dev_copy, NULL) < 0) goto cleanup; if ((ret = qemuDomainAttachDeviceLive(vm, dev_copy, driver)) < 0) @@ -8603,9 +8636,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, if (!vmdef) goto endjob; - if (virDomainDefCompatibleDevice(vmdef, dev) < 0) - goto endjob; - + /* virDomainDefCompatibleDevice call is delayed until we know the + * device we're going to update. */ if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps, parse_flags, driver->xmlopt)) < 0) @@ -8613,9 +8645,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, } if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0) - goto endjob; - + /* virDomainDefCompatibleDevice call is delayed until we know the + * device we're going to update. */ if ((ret = qemuDomainUpdateDeviceLive(vm, dev_copy, dom, force)) < 0) goto endjob; /*