[PATCH 1/5] test_driver: Implement virDomainDetachDeviceFlags

Luke Yue lukedyue at gmail.com
Mon Aug 16 11:19:45 UTC 2021


Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Signed-off-by: Luke Yue <lukedyue at gmail.com>
---
 src/test/test_driver.c | 270 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 270 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 00cc13511a..2ebdbaa604 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9452,6 +9452,275 @@ testDomainGetMessages(virDomainPtr dom,
     return rv;
 }
 
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+                                    virDomainDeviceDef *dev)
+{
+    virDomainDiskDef *disk;
+    virDomainDiskDef *det_disk;
+    virDomainNetDef *net;
+    virDomainSoundDef *sound;
+    virDomainHostdevDef *hostdev;
+    virDomainHostdevDef *det_hostdev;
+    virDomainLeaseDef *lease;
+    virDomainLeaseDef *det_lease;
+    virDomainControllerDef *cont;
+    virDomainControllerDef *det_cont;
+    virDomainFSDef *fs;
+    virDomainMemoryDef *mem;
+    int idx;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+        disk = dev->data.disk;
+        if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+            virReportError(VIR_ERR_DEVICE_MISSING,
+                           _("no target device %s"), disk->dst);
+            return -1;
+        }
+        virDomainDiskDefFree(det_disk);
+        break;
+
+    case VIR_DOMAIN_DEVICE_NET:
+        net = dev->data.net;
+        if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+            return -1;
+
+        /* this is guaranteed to succeed */
+        virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+        break;
+
+    case VIR_DOMAIN_DEVICE_SOUND:
+        sound = dev->data.sound;
+        if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("device not present in domain configuration"));
+            return -1;
+        }
+        virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+        break;
+
+    case VIR_DOMAIN_DEVICE_HOSTDEV: {
+        hostdev = dev->data.hostdev;
+        if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("device not present in domain configuration"));
+            return -1;
+        }
+        virDomainHostdevRemove(vmdef, idx);
+        virDomainHostdevDefFree(det_hostdev);
+        break;
+    }
+
+    case VIR_DOMAIN_DEVICE_LEASE:
+        lease = dev->data.lease;
+        if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+            virReportError(VIR_ERR_DEVICE_MISSING,
+                           _("Lease %s in lockspace %s does not exist"),
+                           lease->key, NULLSTR(lease->lockspace));
+            return -1;
+        }
+        virDomainLeaseDefFree(det_lease);
+        break;
+
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+        cont = dev->data.controller;
+        if ((idx = virDomainControllerFind(vmdef, cont->type,
+                                           cont->idx)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("device not present in domain configuration"));
+            return -1;
+        }
+        det_cont = virDomainControllerRemove(vmdef, idx);
+        virDomainControllerDefFree(det_cont);
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_FS:
+        fs = dev->data.fs;
+        idx = virDomainFSIndexByName(vmdef, fs->dst);
+        if (idx < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("no matching filesystem device was found"));
+            return -1;
+        }
+
+        fs = virDomainFSRemove(vmdef, idx);
+        virDomainFSDefFree(fs);
+        break;
+
+    case VIR_DOMAIN_DEVICE_RNG:
+        if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("no matching RNG device was found"));
+            return -1;
+        }
+
+        virDomainRNGDefFree(virDomainRNGRemove(vmdef, idx));
+        break;
+
+    case VIR_DOMAIN_DEVICE_MEMORY:
+        if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
+                                                    dev->data.memory)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("matching memory device was not found"));
+            return -1;
+        }
+        mem = virDomainMemoryRemove(vmdef, idx);
+        vmdef->mem.cur_balloon -= mem->size;
+        virDomainMemoryDefFree(mem);
+        break;
+
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
+        if ((idx = virDomainRedirdevDefFind(vmdef,
+                                            dev->data.redirdev)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("no matching redirdev was not found"));
+            return -1;
+        }
+
+        virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx));
+        break;
+
+    case VIR_DOMAIN_DEVICE_SHMEM:
+        if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("matching shmem device was not found"));
+            return -1;
+        }
+
+        virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx));
+        break;
+
+
+    case VIR_DOMAIN_DEVICE_WATCHDOG:
+        if (!vmdef->watchdog) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("domain has no watchdog"));
+            return -1;
+        }
+        virDomainWatchdogDefFree(vmdef->watchdog);
+        vmdef->watchdog = NULL;
+        break;
+
+    case VIR_DOMAIN_DEVICE_INPUT:
+        if ((idx = virDomainInputDefFind(vmdef, dev->data.input)) < 0) {
+            virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                           _("matching input device not found"));
+            return -1;
+        }
+        virDomainInputDefFree(vmdef->inputs[idx]);
+        VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
+        break;
+
+    case VIR_DOMAIN_DEVICE_VSOCK:
+        if (!vmdef->vsock ||
+            !virDomainVsockDefEquals(dev->data.vsock, vmdef->vsock)) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("matching vsock device not found"));
+            return -1;
+        }
+        virDomainVsockDefFree(vmdef->vsock);
+        vmdef->vsock = NULL;
+        break;
+
+    case VIR_DOMAIN_DEVICE_CHR:
+    case VIR_DOMAIN_DEVICE_VIDEO:
+    case VIR_DOMAIN_DEVICE_GRAPHICS:
+    case VIR_DOMAIN_DEVICE_HUB:
+    case VIR_DOMAIN_DEVICE_SMARTCARD:
+    case VIR_DOMAIN_DEVICE_MEMBALLOON:
+    case VIR_DOMAIN_DEVICE_NVRAM:
+    case VIR_DOMAIN_DEVICE_NONE:
+    case VIR_DOMAIN_DEVICE_TPM:
+    case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_IOMMU:
+    case VIR_DOMAIN_DEVICE_AUDIO:
+    case VIR_DOMAIN_DEVICE_LAST:
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("persistent detach of device '%s' is not supported"),
+                       virDomainDeviceTypeToString(dev->type));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+testDomainChgDevice(virDomainPtr dom,
+                    virDomainDeviceAction action,
+                    const char *xml,
+                    const char *alias,
+                    unsigned int flags)
+{
+    testDriver *driver = dom->conn->privateData;
+    virDomainObj *vm = NULL;
+    virDomainDef *def;
+    virDomainDeviceDef *dev = NULL;
+    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    if (!(vm = testDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+        goto cleanup;
+
+    if (!(def = virDomainObjGetOneDef(vm, flags)))
+        goto cleanup;
+
+    if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
+        parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+
+    if (xml) {
+        if (!(dev = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+                                            driver->caps, parse_flags)))
+            goto cleanup;
+    } else if (alias) {
+        dev = g_new0(virDomainDeviceDef, 1);
+        if (virDomainDefFindDevice(def, alias, dev, true) < 0)
+            goto cleanup;
+    }
+
+    if (dev == NULL)
+        goto cleanup;
+
+    switch (action) {
+    case VIR_DOMAIN_DEVICE_ACTION_ATTACH:
+        break;
+
+    case VIR_DOMAIN_DEVICE_ACTION_DETACH:
+        if (testDomainDetachDeviceLiveAndConfig(def, dev) < 0)
+            goto cleanup;
+        break;
+
+    case VIR_DOMAIN_DEVICE_ACTION_UPDATE:
+        break;
+    }
+
+    ret = 0;
+
+ cleanup:
+    if (xml) {
+        virDomainDeviceDefFree(dev);
+    } else {
+        g_free(dev);
+    }
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
+static int
+testDomainDetachDeviceFlags(virDomainPtr dom,
+                            const char *xml,
+                            unsigned int flags)
+{
+    return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+                               xml, NULL, flags);
+}
 /*
  * Test driver
  */
@@ -9541,6 +9810,7 @@ static virHypervisorDriver testHypervisorDriver = {
     .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
     .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
     .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+    .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.7.0 */
     .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
     .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
     .domainGetDiskErrors = testDomainGetDiskErrors, /* 5.4.0 */
-- 
2.32.0




More information about the libvir-list mailing list