[PATCH v4 5/8] domain_driver: extract DetachXXXDeviceConfig related functions and use them

Luke Yue lukedyue at gmail.com
Fri Dec 3 12:45:14 UTC 2021


libxl / LXC / QEMU drivers share some common codes in their
DomainDetachDeviceConfig functions, so extract them to domain_conf and
use them with xmlopt etc to deduplicate the bigger function.

At the same time, this will enable test driver to test these functions
in the future.

Signed-off-by: Luke Yue <lukedyue at gmail.com>
---
Compare to the previous version, I remove the random comments, and align the
error messages, also add virDomainDetachChrDeviceConfig by using xmlopt. Then
I got a lot of choices here:

1. Just cleanup these functions and using them in drivers, just like what I did
   in the previous patch.
2. Add a bigger de-duplicated function to de-duplicate the function in libxl /
   LXC / QEMU drivers, and this is what I choose in this patch.
3. Merge all the functions into the bigger one, instead of splitting them
   This would still de-duplicate the functions in libxl / LXC / QEMU drivers.

I choose the second here as I think there would be a situation that both
these single device detach functions and the bigger function would be used
in drivers.
---
 src/conf/domain_conf.c   | 487 +++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |  78 +++++++
 src/libvirt_private.syms |  18 ++
 src/libxl/libxl_driver.c |  73 +-----
 src/lxc/lxc_driver.c     |  62 +----
 src/qemu/qemu_driver.c   | 205 +---------------
 6 files changed, 609 insertions(+), 314 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 30b06c45e5..8017896fd0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31656,3 +31656,490 @@ virDomainObjGetMessages(virDomainObj *vm,

     return rv;
 }
+
+
+int
+virDomainDetachDiskDeviceConfig(virDomainDef *vmdef,
+                                virDomainDeviceDef *dev)
+{
+    virDomainDiskDef *disk;
+    virDomainDiskDef *det_disk;
+
+    disk = dev->data.disk;
+    if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+        virReportError(VIR_ERR_DEVICE_MISSING,
+                       _("no matching disk device %s was found"),
+                       disk->dst);
+        return -1;
+    }
+
+    virDomainDiskDefFree(det_disk);
+
+    return 0;
+}
+
+
+int
+virDomainDetachNetDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev)
+{
+    virDomainNetDef *net;
+    int idx;
+
+    net = dev->data.net;
+    if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching net device was found"));
+        return -1;
+    }
+
+    virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachSoundDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev)
+{
+    virDomainSoundDef *sound;
+    int idx;
+
+    sound = dev->data.sound;
+    if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching sound device was found"));
+        return -1;
+    }
+
+    virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachHostdevDeviceConfig(virDomainDef *vmdef,
+                                   virDomainDeviceDef *dev)
+{
+    virDomainHostdevDef *hostdev;
+    virDomainHostdevDef *det_hostdev;
+    int idx;
+
+    hostdev = dev->data.hostdev;
+    if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching hostdev device was found"));
+        return -1;
+    }
+
+    virDomainHostdevDefFree(virDomainHostdevRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachLeaseDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev)
+{
+    virDomainLeaseDef *lease;
+    virDomainLeaseDef *det_lease;
+
+    lease = dev->data.lease;
+    if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+        virReportError(VIR_ERR_DEVICE_MISSING,
+                       _("no matching lease %s in lockspace %s was found"),
+                       lease->key, NULLSTR(lease->lockspace));
+        return -1;
+    }
+
+    virDomainLeaseDefFree(det_lease);
+
+    return 0;
+}
+
+
+int
+virDomainDetachControllerDeviceConfig(virDomainDef *vmdef,
+                                      virDomainDeviceDef *dev)
+{
+    virDomainControllerDef *cont;
+    int idx;
+
+    cont = dev->data.controller;
+    if ((idx = virDomainControllerFind(vmdef, cont->type, cont->idx)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching controller device was found"));
+        return -1;
+    }
+
+    virDomainControllerDefFree(virDomainControllerRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachFSDeviceConfig(virDomainDef *vmdef,
+                              virDomainDeviceDef *dev)
+{
+    virDomainFSDef *fs;
+    int idx;
+
+    fs = dev->data.fs;
+    if ((idx = virDomainFSIndexByName(vmdef, fs->dst)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching filesystem device was found"));
+        return -1;
+    }
+
+    virDomainFSDefFree(virDomainFSRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachRNGDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev)
+{
+    int idx;
+
+    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));
+
+    return 0;
+}
+
+
+int
+virDomainDetachMemoryDeviceConfig(virDomainDef *vmdef,
+                                  virDomainDeviceDef *dev)
+{
+    virDomainMemoryDef *mem;
+    int idx;
+
+    if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
+                                                dev->data.memory)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching memory device was found"));
+        return -1;
+    }
+
+    mem = virDomainMemoryRemove(vmdef, idx);
+    vmdef->mem.cur_balloon -= mem->size;
+    virDomainMemoryDefFree(mem);
+
+    return 0;
+}
+
+
+int
+virDomainDetachRedirdevDeviceConfig(virDomainDef *vmdef,
+                                    virDomainDeviceDef *dev)
+{
+    int idx;
+
+    if ((idx = virDomainRedirdevDefFind(vmdef,
+                                        dev->data.redirdev)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching redirdev was found"));
+        return -1;
+    }
+
+    virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachShmemDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev)
+{
+    int idx;
+
+    if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching shmem device was found"));
+        return -1;
+    }
+
+    virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachWatchdogDeviceConfig(virDomainDef *vmdef)
+{
+    if (!vmdef->watchdog) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching watch dog device was found"));
+        return -1;
+    }
+
+    virDomainWatchdogDefFree(vmdef->watchdog);
+    vmdef->watchdog = NULL;
+
+    return 0;
+}
+
+
+int
+virDomainDetachInputDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev)
+{
+    int idx;
+
+    if ((idx = virDomainInputDefFind(vmdef, dev->data.input)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching input device was found"));
+        return -1;
+    }
+
+    virDomainInputDefFree(virDomainInputDefRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachVsockDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev)
+{
+    if (!vmdef->vsock ||
+        !virDomainVsockDefEquals(dev->data.vsock, vmdef->vsock)) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching vsock device was found"));
+        return -1;
+    }
+
+    virDomainVsockDefFree(vmdef->vsock);
+    vmdef->vsock = NULL;
+
+    return 0;
+}
+
+
+int
+virDomainDetachTPMDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev)
+{
+    int idx;
+
+    if ((idx = virDomainTPMDefFind(vmdef, dev->data.tpm)) < 0) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching tpm device was found"));
+        return -1;
+    }
+
+    virDomainTPMDefFree(virDomainTPMDefRemove(vmdef, idx));
+
+    return 0;
+}
+
+
+int
+virDomainDetachChrDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev,
+                               virDomainXMLOption *xmlopt,
+                               unsigned int flags)
+{
+    virDomainChrDef *chr;
+
+    if (xmlopt && xmlopt->deviceOps.detachChr) {
+        return xmlopt->deviceOps.detachChr(vmdef, dev, flags);
+    }
+
+    if (!(chr = virDomainChrRemove(vmdef, dev->data.chr))) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching char device was found"));
+        return -1;
+    }
+
+    virDomainChrDefFree(chr);
+
+    return 0;
+}
+
+
+int
+virDomainDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+                                      virDomainXMLOption *xmlopt,
+                                      unsigned int flags)
+{
+    if (xmlopt && xmlopt->deviceOps.detachMemballoon) {
+        return xmlopt->deviceOps.detachMemballoon(vmdef, NULL, flags);
+    }
+
+    if (!vmdef->memballoon) {
+        virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+                       _("no matching memballoon device was found"));
+        return -1;
+    }
+
+    virDomainMemballoonDefFree(vmdef->memballoon);
+    vmdef->memballoon = NULL;
+
+    return 0;
+}
+
+
+int
+virDomainDetachDeviceConfig(virDomainDef *vmdef,
+                            virDomainDeviceDef *dev,
+                            void *parseOpaque,
+                            unsigned int flags,
+                            unsigned int parse_flags,
+                            virDomainXMLOption *xmlopt)
+{
+    int ret = 0;
+
+    if (!(xmlopt->deviceOps.detachFlags & (1 << dev->type))) {
+        ret = -1;
+        goto error;
+    }
+
+    switch ((virDomainDeviceType) dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+        if (virDomainDetachDiskDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_NET:
+        if (virDomainDetachNetDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_SOUND:
+        if (virDomainDetachSoundDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_HOSTDEV:
+        if (virDomainDetachHostdevDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_LEASE:
+        if (virDomainDetachLeaseDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+        if (virDomainDetachControllerDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_FS:
+        if (virDomainDetachFSDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_RNG:
+        if (virDomainDetachRNGDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_MEMORY:
+        if (virDomainDetachMemoryDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
+        if (virDomainDetachRedirdevDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_SHMEM:
+        if (virDomainDetachShmemDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_WATCHDOG:
+        if (virDomainDetachWatchdogDeviceConfig(vmdef) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_INPUT:
+        if (virDomainDetachInputDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_VSOCK:
+        if (virDomainDetachVsockDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_CHR:
+        if (virDomainDetachChrDeviceConfig(vmdef, dev, xmlopt, flags) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_TPM:
+        if (virDomainDetachTPMDeviceConfig(vmdef, dev) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_MEMBALLOON:
+        if (virDomainDetachMemballoonDeviceConfig(vmdef, xmlopt, flags) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_DEVICE_VIDEO:
+    case VIR_DOMAIN_DEVICE_GRAPHICS:
+    case VIR_DOMAIN_DEVICE_HUB:
+    case VIR_DOMAIN_DEVICE_SMARTCARD:
+    case VIR_DOMAIN_DEVICE_NVRAM:
+    case VIR_DOMAIN_DEVICE_NONE:
+    case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_IOMMU:
+    case VIR_DOMAIN_DEVICE_AUDIO:
+    case VIR_DOMAIN_DEVICE_LAST:
+        ret = -1;
+        goto error;
+    }
+
+    if (parseOpaque) {
+        if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, parseOpaque) < 0)
+            return -1;
+    }
+
+ error:
+    if (ret < 0) {
+        /* When using in test driver, flags may
+        contain VIR_DOMAIN_AFFECT_LIVE */
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("%sdetach of device '%s' is not supported"),
+                       (!(flags & VIR_DOMAIN_AFFECT_LIVE)) ? "persistent " : "",
+                       virDomainDeviceTypeToString(dev->type));
+        return -1;
+    }
+    return 0;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 08b6965ef5..12b2996538 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4275,3 +4275,81 @@ int
 virDomainObjGetMessages(virDomainObj *vm,
                         char ***msgs,
                         unsigned int flags);
+
+int
+virDomainDetachDiskDeviceConfig(virDomainDef *vmdef,
+                                virDomainDeviceDef *dev);
+
+int
+virDomainDetachNetDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev);
+
+int
+virDomainDetachSoundDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev);
+
+int
+virDomainDetachHostdevDeviceConfig(virDomainDef *vmdef,
+                                   virDomainDeviceDef *dev);
+
+int
+virDomainDetachLeaseDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev);
+
+int
+virDomainDetachControllerDeviceConfig(virDomainDef *vmdef,
+                                      virDomainDeviceDef *dev);
+
+int
+virDomainDetachFSDeviceConfig(virDomainDef *vmdef,
+                              virDomainDeviceDef *dev);
+
+int
+virDomainDetachRNGDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev);
+
+int
+virDomainDetachMemoryDeviceConfig(virDomainDef *vmdef,
+                                  virDomainDeviceDef *dev);
+
+int
+virDomainDetachRedirdevDeviceConfig(virDomainDef *vmdef,
+                                    virDomainDeviceDef *dev);
+
+int
+virDomainDetachShmemDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev);
+
+int
+virDomainDetachWatchdogDeviceConfig(virDomainDef *vmdef);
+
+int
+virDomainDetachInputDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev);
+
+int
+virDomainDetachVsockDeviceConfig(virDomainDef *vmdef,
+                                 virDomainDeviceDef *dev);
+
+int
+virDomainDetachTPMDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev);
+
+int
+virDomainDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+                                      virDomainXMLOption *xmlopt,
+                                      unsigned int flags);
+
+int
+virDomainDetachChrDeviceConfig(virDomainDef *vmdef,
+                               virDomainDeviceDef *dev,
+                               virDomainXMLOption *xmlopt,
+                               unsigned int flags);
+
+int
+virDomainDetachDeviceConfig(virDomainDef *vmdef,
+                            virDomainDeviceDef *dev,
+                            void *parseOpaque,
+                            unsigned int flags,
+                            unsigned int parse_flags,
+                            virDomainXMLOption *xmlopt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9b1e6a0d2a..d6f1da5e95 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -352,6 +352,24 @@ virDomainDefSetVcpus;
 virDomainDefSetVcpusMax;
 virDomainDefVcpuOrderClear;
 virDomainDeleteConfig;
+virDomainDetachChrDeviceConfig;
+virDomainDetachControllerDeviceConfig;
+virDomainDetachDeviceConfig;
+virDomainDetachDiskDeviceConfig;
+virDomainDetachFSDeviceConfig;
+virDomainDetachHostdevDeviceConfig;
+virDomainDetachInputDeviceConfig;
+virDomainDetachLeaseDeviceConfig;
+virDomainDetachMemballoonDeviceConfig;
+virDomainDetachMemoryDeviceConfig;
+virDomainDetachNetDeviceConfig;
+virDomainDetachRedirdevDeviceConfig;
+virDomainDetachRNGDeviceConfig;
+virDomainDetachShmemDeviceConfig;
+virDomainDetachSoundDeviceConfig;
+virDomainDetachTPMDeviceConfig;
+virDomainDetachVsockDeviceConfig;
+virDomainDetachWatchdogDeviceConfig;
 virDomainDeviceAliasIsUserAlias;
 virDomainDeviceDefCopy;
 virDomainDeviceDefFree;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 23a28dc124..dd123412ac 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -3905,68 +3905,14 @@ libxlDomainDetachDeviceLive(libxlDriverPrivate *driver,


 static int
-libxlDomainDetachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
+libxlDomainDetachDeviceConfig(virDomainDef *vmdef,
+                              virDomainDeviceDef *dev,
+                              unsigned int flags,
+                              unsigned int parse_flags,
+                              virDomainXMLOption *xmlopt)
 {
-    virDomainDiskDef *disk;
-    virDomainDiskDef *detach;
-    virDomainHostdevDef *hostdev;
-    virDomainHostdevDef *det_hostdev;
-    virDomainControllerDef *cont;
-    virDomainControllerDef *det_cont;
-    virDomainNetDef *net;
-    int idx;
-
-    switch (dev->type) {
-        case VIR_DOMAIN_DEVICE_DISK:
-            disk = dev->data.disk;
-            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
-                virReportError(VIR_ERR_INVALID_ARG,
-                               _("no target device %s"), disk->dst);
-                return -1;
-            }
-            virDomainDiskDefFree(detach);
-            break;
-
-        case VIR_DOMAIN_DEVICE_CONTROLLER:
-            cont = dev->data.controller;
-            if ((idx = virDomainControllerFind(vmdef, cont->type,
-                                               cont->idx)) < 0) {
-                virReportError(VIR_ERR_INVALID_ARG, "%s",
-                               _("device not present in domain configuration"));
-                return -1;
-            }
-            det_cont = virDomainControllerRemove(vmdef, idx);
-            virDomainControllerDefFree(det_cont);
-            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_HOSTDEV: {
-            hostdev = dev->data.hostdev;
-            if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
-                virReportError(VIR_ERR_INVALID_ARG, "%s",
-                               _("device not present in domain configuration"));
-                return -1;
-            }
-            virDomainHostdevRemove(vmdef, idx);
-            virDomainHostdevDefFree(det_hostdev);
-            break;
-        }
-
-        default:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("persistent detach of device is not supported"));
-            return -1;
-    }
-
-    return 0;
+    return virDomainDetachDeviceConfig(vmdef, dev, NULL, flags,
+                                       parse_flags, xmlopt);
 }

 static int
@@ -4199,7 +4145,10 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
         if (!(vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, NULL)))
             goto endjob;

-        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
+        if (libxlDomainDetachDeviceConfig(vmdef, dev, flags,
+                                          VIR_DOMAIN_DEF_PARSE_INACTIVE |
+                                          VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE,
+                                          driver->xmlopt) < 0)
             goto endjob;
     }

diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 3cdf73c69f..545fc9c9e2 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -3124,58 +3124,13 @@ lxcDomainUpdateDeviceConfig(virDomainDef *vmdef,

 static int
 lxcDomainDetachDeviceConfig(virDomainDef *vmdef,
-                            virDomainDeviceDef *dev)
+                            virDomainDeviceDef *dev,
+                            unsigned int flags,
+                            unsigned int parse_flags,
+                            virDomainXMLOption *xmlopt)
 {
-    int ret = -1;
-    virDomainDiskDef *disk;
-    virDomainDiskDef *det_disk;
-    virDomainNetDef *net;
-    virDomainHostdevDef *hostdev;
-    virDomainHostdevDef *det_hostdev;
-    int idx;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-        disk = dev->data.disk;
-        if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("no target device %s"), disk->dst);
-            return -1;
-        }
-        virDomainDiskDefFree(det_disk);
-        ret = 0;
-        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));
-        ret = 0;
-        break;
-
-    case VIR_DOMAIN_DEVICE_HOSTDEV: {
-        hostdev = dev->data.hostdev;
-        if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
-            virReportError(VIR_ERR_INVALID_ARG, "%s",
-                           _("device not present in domain configuration"));
-            return -1;
-        }
-        virDomainHostdevRemove(vmdef, idx);
-        virDomainHostdevDefFree(det_hostdev);
-        ret = 0;
-        break;
-    }
-
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("persistent detach of device is not supported"));
-        break;
-    }
-
-    return ret;
+    return virDomainDetachDeviceConfig(vmdef, dev, NULL, flags,
+                                       parse_flags, xmlopt);
 }


@@ -4510,7 +4465,10 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom,
         if (!vmdef)
             goto endjob;

-        if ((ret = lxcDomainDetachDeviceConfig(vmdef, dev)) < 0)
+        if ((ret = lxcDomainDetachDeviceConfig(vmdef, dev, flags,
+                                               VIR_DOMAIN_DEF_PARSE_INACTIVE |
+                                               VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE,
+                                               driver->xmlopt)) < 0)
             goto endjob;
     }

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bef2465e57..503b0973ab 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7468,207 +7468,12 @@ static int
 qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
                              virDomainDeviceDef *dev,
                              virQEMUCaps *qemuCaps,
+                             unsigned int flags,
                              unsigned int parse_flags,
                              virDomainXMLOption *xmlopt)
 {
-    virDomainDiskDef *disk;
-    virDomainDiskDef *det_disk;
-    virDomainNetDef *net;
-    virDomainSoundDef *sound;
-    virDomainHostdevDef *hostdev;
-    virDomainHostdevDef *det_hostdev;
-    virDomainLeaseDef *lease;
-    virDomainLeaseDef *det_lease;
-    virDomainControllerDef *cont;
-    virDomainControllerDef *det_cont;
-    virDomainChrDef *chr;
-    virDomainFSDef *fs;
-    virDomainMemoryDef *mem;
-    int idx;
-
-    switch ((virDomainDeviceType)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_CHR:
-        if (!(chr = qemuDomainChrRemove(vmdef, dev->data.chr)))
-            return -1;
-
-        virDomainChrDefFree(chr);
-        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(virDomainInputDefRemove(vmdef, idx));
-        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_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;
-    }
-
-    if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, qemuCaps) < 0)
-        return -1;
-
-    return 0;
+    return virDomainDetachDeviceConfig(vmdef, dev, qemuCaps, flags,
+                                       parse_flags, xmlopt);
 }

 static int
@@ -8113,7 +7918,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
             goto cleanup;

         if (qemuDomainDetachDeviceConfig(vmdef, dev, priv->qemuCaps,
-                                         parse_flags,
+                                         flags, parse_flags,
                                          driver->xmlopt) < 0)
             goto cleanup;
     }
@@ -8182,7 +7987,7 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriver *driver,
         if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0)
             return -1;

-        if (qemuDomainDetachDeviceConfig(vmdef, &dev, priv->qemuCaps,
+        if (qemuDomainDetachDeviceConfig(vmdef, &dev, priv->qemuCaps, flags,
                                          parse_flags, driver->xmlopt) < 0)
             return -1;
     }
--
2.34.1




More information about the libvir-list mailing list