On 7/1/24 22:29, John Levon wrote:
> Add basic coverage of device update; for now, only support disk updates
> until other types are needed or tested.
>
> Signed-off-by: John Levon <[email protected]>
> ---
> src/test/test_driver.c | 127 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 127 insertions(+)
>
> diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> index 40fb8a467d..213fbdbccb 100644
> --- a/src/test/test_driver.c
> +++ b/src/test/test_driver.c
> @@ -41,6 +41,7 @@
> #include "domain_conf.h"
> #include "domain_driver.h"
> #include "domain_event.h"
> +#include "domain_postparse.h"
> #include "domain_validate.h"
> #include "network_event.h"
> #include "snapshot_conf.h"
> @@ -10237,6 +10238,131 @@ testDomainAttachDevice(virDomainPtr domain, const
> char *xml)
> }
>
>
> +static int
> +testDomainUpdateDeviceConfig(virDomainDef *vmdef,
> + virDomainDeviceDef *dev,
> + unsigned int parse_flags,
> + virDomainXMLOption *xmlopt)
> +{
> + virDomainDiskDef *newDisk;
> + virDomainDeviceDef oldDev = { .type = dev->type };
> + int pos;
> +
> + switch (dev->type) {
> + case VIR_DOMAIN_DEVICE_DISK:
> + newDisk = dev->data.disk;
> + if ((pos = virDomainDiskIndexByName(vmdef, newDisk->dst, false)) <
> 0) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("target %1$s doesn't exist."), newDisk->dst);
> + return -1;
> + }
> +
> + oldDev.data.disk = vmdef->disks[pos];
> + if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
> + VIR_DOMAIN_DEVICE_ACTION_UPDATE,
> + false) < 0)
> + return -1;
> +
> + virDomainDiskDefFree(vmdef->disks[pos]);
> + vmdef->disks[pos] = newDisk;
> + dev->data.disk = NULL;
> + break;
> +
> + // TODO: support these here once tested.
> + case VIR_DOMAIN_DEVICE_GRAPHICS:
> + case VIR_DOMAIN_DEVICE_NET:
> + case VIR_DOMAIN_DEVICE_MEMORY:
> + virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
> + _("persistent update of device '%1$s' is not
> supported by test driver"),
> + virDomainDeviceTypeToString(dev->type));
> + return -1;
> +
It's perfectly okay if ...
> + case VIR_DOMAIN_DEVICE_FS:
> + case VIR_DOMAIN_DEVICE_INPUT:
> + case VIR_DOMAIN_DEVICE_SOUND:
> + case VIR_DOMAIN_DEVICE_VIDEO:
> + case VIR_DOMAIN_DEVICE_WATCHDOG:
> + case VIR_DOMAIN_DEVICE_HUB:
> + case VIR_DOMAIN_DEVICE_SMARTCARD:
> + case VIR_DOMAIN_DEVICE_MEMBALLOON:
> + case VIR_DOMAIN_DEVICE_NVRAM:
> + case VIR_DOMAIN_DEVICE_RNG:
> + case VIR_DOMAIN_DEVICE_SHMEM:
> + case VIR_DOMAIN_DEVICE_LEASE:
> + case VIR_DOMAIN_DEVICE_HOSTDEV:
> + case VIR_DOMAIN_DEVICE_CONTROLLER:
> + case VIR_DOMAIN_DEVICE_REDIRDEV:
> + case VIR_DOMAIN_DEVICE_CHR:
> + case VIR_DOMAIN_DEVICE_NONE:
> + case VIR_DOMAIN_DEVICE_TPM:
> + case VIR_DOMAIN_DEVICE_PANIC:
> + case VIR_DOMAIN_DEVICE_IOMMU:
> + case VIR_DOMAIN_DEVICE_VSOCK:
> + case VIR_DOMAIN_DEVICE_AUDIO:
> + case VIR_DOMAIN_DEVICE_CRYPTO:
> + case VIR_DOMAIN_DEVICE_LAST:
> + virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
> + _("persistent update of device '%1$s' is not
> supported"),
> + virDomainDeviceTypeToString(dev->type));
.. this error is reported instead.
> + return -1;
> + }
> +
> + if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, NULL) < 0)
> + return -1;
> +
> + return 0;
> +}
> +
> +
> +static int
> +testDomainUpdateDeviceFlags(virDomainPtr dom,
> + const char *xml,
> + unsigned int flags)
> +{
> + testDriver *driver = dom->conn->privateData;
> + virDomainObj *vm = NULL;
> + g_autoptr(virDomainDef) vmdef = NULL;
> + g_autoptr(virDomainDeviceDef) dev = NULL;
> + int ret = -1;
> + unsigned int parse_flags = 0;
> +
> + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
> + VIR_DOMAIN_AFFECT_CONFIG |
> + VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);
LIVE is not supported and thus shouldn't be in list of supported flags.
Neither MODIFY_FORCE.
> +
> + if (!(vm = testDomObjFromDomain(dom)))
> + goto cleanup;
> +
> + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
> + goto cleanup;
> +
> + if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
> + goto endjob;
After this, flags may contain LIVE and/or CONFIG. We need to recheck
whether LIVE is present and reject it.
> +
> + if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
> + !(flags & VIR_DOMAIN_AFFECT_LIVE))
> + parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
> +
> + if (!(dev = virDomainDeviceDefParse(xml, vm->def, driver->xmlopt,
> + NULL, parse_flags)))
> + goto endjob;
> +
> + /* virDomainDefCompatibleDevice call is delayed until we know the
> + * device we're going to update. */
> + if ((ret = testDomainUpdateDeviceConfig(vm->def, dev,
> + parse_flags,
> + driver->xmlopt)) < 0)
> + goto endjob;
An event should be emitted to mimic real hypervisor behavior.
I'm squashing in necessary changes and merging.
Reviewed-by: Michal Privoznik <[email protected]>
Michal