From 738b201aad48dd0f1af8465adbda0d056213d521 Mon Sep 17 00:00:00 2001 From: John Levon Date: Mon, 1 Jul 2024 21:29:55 +0100 Subject: [PATCH] test_driver: add testUpdateDeviceFlags implementation Add basic coverage of device update; for now, only support disk updates until other types are needed or tested. Signed-off-by: John Levon Signed-off-by: Michal Privoznik Reviewed-by: Michal Privoznik --- src/test/test_driver.c | 150 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 40fb8a467d..712bb20563 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,154 @@ 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; + + case VIR_DOMAIN_DEVICE_GRAPHICS: + case VIR_DOMAIN_DEVICE_NET: + case VIR_DOMAIN_DEVICE_MEMORY: + 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)); + 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; + virObjectEvent *event = NULL; + g_autoptr(virDomainDef) vmdef = NULL; + g_autoptr(virDomainDeviceDef) dev = NULL; + int ret = -1; + unsigned int parse_flags = 0; + + virCheckFlags(VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjUpdateModificationImpact(vm, &flags) < 0) + goto endjob; + + 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; + } + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ + vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, NULL); + if (!vmdef) + goto endjob; + + /* virDomainDefCompatibleDevice call is delayed until we know the + * device we're going to update. */ + if ((ret = testDomainUpdateDeviceConfig(vmdef, dev, + parse_flags, + driver->xmlopt)) < 0) + goto endjob; + } + + if (flags & VIR_DOMAIN_AFFECT_LIVE) { + ret = -1; + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("live update of device '%1$s' is not supported"), + virDomainDeviceTypeToString(dev->type)); + goto endjob; + } + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + if (!ret) { + virDomainObjAssignDef(vm, &vmdef, false, NULL); + + /* Event sending if persistent config has changed */ + event = virDomainEventLifecycleNewFromObj(vm, + VIR_DOMAIN_EVENT_DEFINED, + VIR_DOMAIN_EVENT_DEFINED_UPDATED); + + virObjectEventStateQueue(driver->eventState, event); + } + } + + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + /* search for a hostdev matching dev and detach it */ static int testDomainDetachPrepHostdev(virDomainObj *vm, @@ -10456,6 +10605,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainAttachDevice = testDomainAttachDevice, /* 10.0.0 */ .domainAttachDeviceFlags = testDomainAttachDeviceFlags, /* 10.0.0 */ .domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 10.0.0 */ + .domainUpdateDeviceFlags = testDomainUpdateDeviceFlags, /* 10.6.0 */ .domainCreateXML = testDomainCreateXML, /* 0.1.4 */ .domainCreateXMLWithFiles = testDomainCreateXMLWithFiles, /* 5.7.0 */ .domainLookupByID = testDomainLookupByID, /* 0.1.1 */