[PATCH 06/15] qemu: move qemuDomainChrDefValidate() to qemu_validate.c

Daniel Henrique Barboza danielhb413 at gmail.com
Thu Mar 26 21:31:16 UTC 2020


qemuDomainChrDefValidate() has a lot of static helpers functions
that needed to be moved as well.

Other functions from qemuDomainDeviceDefValidate() that were
also moved:
- qemuValidateDomainSmartcardDef
- qemuValidateDomainRNGDef
- qemuValidateDomainRedirdevDef
- qemuValidateDomainWatchdogDef

Signed-off-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
---
 src/qemu/qemu_domain.c   | 383 +--------------------------------------
 src/qemu/qemu_validate.c | 373 ++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_validate.h |  11 ++
 3 files changed, 389 insertions(+), 378 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index caf5c5b73d..4726fa015d 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5150,379 +5150,6 @@ qemuDomainDeviceDefValidateMemory(virDomainMemoryDefPtr mem,
 }
 
 
-static int
-qemuDomainChrSourceReconnectDefValidate(const virDomainChrSourceReconnectDef *def)
-{
-    if (def->enabled == VIR_TRISTATE_BOOL_YES &&
-        def->timeout == 0) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("chardev reconnect source timeout cannot be '0'"));
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-qemuDomainChrSourceDefValidate(const virDomainChrSourceDef *def,
-                               virQEMUCapsPtr qemuCaps)
-{
-    switch ((virDomainChrType)def->type) {
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-        if (qemuDomainChrSourceReconnectDefValidate(&def->data.tcp.reconnect) < 0)
-            return -1;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-        if (qemuDomainChrSourceReconnectDefValidate(&def->data.nix.reconnect) < 0)
-            return -1;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-        if (def->data.file.append != VIR_TRISTATE_SWITCH_ABSENT &&
-            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FILE_APPEND)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("append not supported in this QEMU binary"));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_NULL:
-    case VIR_DOMAIN_CHR_TYPE_VC:
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-    case VIR_DOMAIN_CHR_TYPE_STDIO:
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
-    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
-    case VIR_DOMAIN_CHR_TYPE_NMDM:
-    case VIR_DOMAIN_CHR_TYPE_LAST:
-        break;
-    }
-
-    if (def->logfile) {
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_LOGFILE)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("logfile not supported in this QEMU binary"));
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-qemuDomainChrSerialTargetTypeToAddressType(int targetType)
-{
-    switch ((virDomainChrSerialTargetType)targetType) {
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
-        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
-        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
-        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO:
-        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE:
-        break;
-    }
-
-    return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
-}
-
-
-static int
-qemuDomainChrSerialTargetModelToTargetType(int targetModel)
-{
-    switch ((virDomainChrSerialTargetModel) targetModel) {
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
-        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP;
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
-    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
-        break;
-    }
-
-    return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE;
-}
-
-
-static int
-qemuDomainChrTargetDefValidate(const virDomainChrDef *chr)
-{
-    int expected;
-
-    switch ((virDomainChrDeviceType)chr->deviceType) {
-    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
-
-        /* Validate target type */
-        switch ((virDomainChrSerialTargetType)chr->targetType) {
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO:
-
-            expected = qemuDomainChrSerialTargetTypeToAddressType(chr->targetType);
-
-            if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-                chr->info.type != expected) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("Target type '%s' requires address type '%s'"),
-                               virDomainChrSerialTargetTypeToString(chr->targetType),
-                               virDomainDeviceAddressTypeToString(expected));
-                return -1;
-            }
-            break;
-
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
-            if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("Target type '%s' cannot have an "
-                                 "associated address"),
-                               virDomainChrSerialTargetTypeToString(chr->targetType));
-                return -1;
-            }
-            break;
-
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
-            break;
-        }
-
-        /* Validate target model */
-        switch ((virDomainChrSerialTargetModel) chr->targetModel) {
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
-
-            expected = qemuDomainChrSerialTargetModelToTargetType(chr->targetModel);
-
-            if (chr->targetType != expected) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("Target model '%s' requires target type '%s'"),
-                               virDomainChrSerialTargetModelTypeToString(chr->targetModel),
-                               virDomainChrSerialTargetTypeToString(expected));
-                return -1;
-            }
-            break;
-
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
-        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
-            break;
-        }
-        break;
-
-    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
-    case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
-    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
-    case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
-        /* Nothing to do */
-        break;
-    }
-
-    return 0;
-}
-
-
-static int
-qemuDomainChrDefValidate(const virDomainChrDef *dev,
-                         const virDomainDef *def,
-                         virQEMUCapsPtr qemuCaps)
-{
-    if (qemuDomainChrSourceDefValidate(dev->source, qemuCaps) < 0)
-        return -1;
-
-    if (qemuDomainChrTargetDefValidate(dev) < 0)
-        return -1;
-
-    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL &&
-        (ARCH_IS_S390(def->os.arch) || qemuDomainIsPSeries(def))) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("parallel ports are not supported"));
-            return -1;
-    }
-
-    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
-        bool isCompatible = true;
-
-        if (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM) {
-            if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011 &&
-                !qemuDomainIsARMVirt(def)) {
-                isCompatible = false;
-            }
-            if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A &&
-                !qemuDomainIsRISCVVirt(def)) {
-                isCompatible = false;
-            }
-        }
-
-        if (!qemuDomainIsPSeries(def) &&
-            (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO ||
-             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY)) {
-            isCompatible = false;
-        }
-
-        if (!ARCH_IS_S390(def->os.arch) &&
-            (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP ||
-             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE ||
-             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE)) {
-            isCompatible = false;
-        }
-
-        if (!isCompatible) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Serial device with target type '%s' and "
-                             "target model '%s' not compatible with guest "
-                             "architecture or machine type"),
-                           virDomainChrSerialTargetTypeToString(dev->targetType),
-                           virDomainChrSerialTargetModelTypeToString(dev->targetModel));
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-qemuDomainSmartcardDefValidate(const virDomainSmartcardDef *def,
-                               virQEMUCapsPtr qemuCaps)
-{
-    switch (def->type) {
-    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("this QEMU binary lacks smartcard host "
-                             "mode support"));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("this QEMU binary lacks smartcard host "
-                             "mode support"));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_PASSTHRU)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("this QEMU binary lacks smartcard "
-                             "passthrough mode support"));
-            return -1;
-        }
-        break;
-
-    default:
-        virReportEnumRangeError(virDomainSmartcardType, def->type);
-        return -1;
-    }
-
-    if (def->type == VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH &&
-        qemuDomainChrSourceDefValidate(def->data.passthru, qemuCaps) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-qemuDomainRNGDefValidate(const virDomainRNGDef *def,
-                         virQEMUCapsPtr qemuCaps G_GNUC_UNUSED)
-{
-    if (def->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
-        qemuDomainChrSourceDefValidate(def->source.chardev, qemuCaps) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-qemuDomainRedirdevDefValidate(const virDomainRedirdevDef *def,
-                              virQEMUCapsPtr qemuCaps)
-{
-    if (qemuDomainChrSourceDefValidate(def->source, qemuCaps) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-qemuDomainWatchdogDefValidate(const virDomainWatchdogDef *dev,
-                              const virDomainDef *def)
-{
-    switch ((virDomainWatchdogModel) dev->model) {
-    case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB:
-        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-            dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s model of watchdog can go only on PCI bus"),
-                           virDomainWatchdogModelTypeToString(dev->model));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_WATCHDOG_MODEL_IB700:
-        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-            dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s model of watchdog can go only on ISA bus"),
-                           virDomainWatchdogModelTypeToString(dev->model));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_WATCHDOG_MODEL_DIAG288:
-        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s model of watchdog is virtual and cannot go on any bus."),
-                           virDomainWatchdogModelTypeToString(dev->model));
-            return -1;
-        }
-        if (!(ARCH_IS_S390(def->os.arch))) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s model of watchdog is allowed for s390 and s390x only"),
-                           virDomainWatchdogModelTypeToString(dev->model));
-            return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_WATCHDOG_MODEL_LAST:
-        break;
-    }
-
-    return 0;
-}
-
-
 int
 qemuDomainValidateActualNetDef(const virDomainNetDef *net,
                                virQEMUCapsPtr qemuCaps)
@@ -7609,23 +7236,23 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
         break;
 
     case VIR_DOMAIN_DEVICE_CHR:
-        ret = qemuDomainChrDefValidate(dev->data.chr, def, qemuCaps);
+        ret = qemuValidateDomainChrDef(dev->data.chr, def, qemuCaps);
         break;
 
     case VIR_DOMAIN_DEVICE_SMARTCARD:
-        ret = qemuDomainSmartcardDefValidate(dev->data.smartcard, qemuCaps);
+        ret = qemuValidateDomainSmartcardDef(dev->data.smartcard, qemuCaps);
         break;
 
     case VIR_DOMAIN_DEVICE_RNG:
-        ret = qemuDomainRNGDefValidate(dev->data.rng, qemuCaps);
+        ret = qemuValidateDomainRNGDef(dev->data.rng, qemuCaps);
         break;
 
     case VIR_DOMAIN_DEVICE_REDIRDEV:
-        ret = qemuDomainRedirdevDefValidate(dev->data.redirdev, qemuCaps);
+        ret = qemuValidateDomainRedirdevDef(dev->data.redirdev, qemuCaps);
         break;
 
     case VIR_DOMAIN_DEVICE_WATCHDOG:
-        ret = qemuDomainWatchdogDefValidate(dev->data.watchdog, def);
+        ret = qemuValidateDomainWatchdogDef(dev->data.watchdog, def);
         break;
 
     case VIR_DOMAIN_DEVICE_HOSTDEV:
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 528170ac94..9b67c753c2 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1158,3 +1158,376 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
 
     return 0;
 }
+
+
+static int
+qemuValidateDomainChrSourceReconnectDef(const virDomainChrSourceReconnectDef *def)
+{
+    if (def->enabled == VIR_TRISTATE_BOOL_YES &&
+        def->timeout == 0) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("chardev reconnect source timeout cannot be '0'"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+qemuValidateChrSerialTargetTypeToAddressType(int targetType)
+{
+    switch ((virDomainChrSerialTargetType)targetType) {
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
+        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
+        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
+        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO:
+        return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE:
+        break;
+    }
+
+    return VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
+}
+
+
+static int
+qemuValidateChrSerialTargetModelToTargetType(int targetModel)
+{
+    switch ((virDomainChrSerialTargetModel) targetModel) {
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
+        return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP;
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
+    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
+        break;
+    }
+
+    return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE;
+}
+
+
+static int
+qemuValidateDomainChrTargetDef(const virDomainChrDef *chr)
+{
+    int expected;
+
+    switch ((virDomainChrDeviceType)chr->deviceType) {
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+
+        /* Validate target type */
+        switch ((virDomainChrSerialTargetType)chr->targetType) {
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO:
+
+            expected = qemuValidateChrSerialTargetTypeToAddressType(chr->targetType);
+
+            if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+                chr->info.type != expected) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("Target type '%s' requires address type '%s'"),
+                               virDomainChrSerialTargetTypeToString(chr->targetType),
+                               virDomainDeviceAddressTypeToString(expected));
+                return -1;
+            }
+            break;
+
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
+            if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("Target type '%s' cannot have an "
+                                 "associated address"),
+                               virDomainChrSerialTargetTypeToString(chr->targetType));
+                return -1;
+            }
+            break;
+
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
+            break;
+        }
+
+        /* Validate target model */
+        switch ((virDomainChrSerialTargetModel) chr->targetModel) {
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
+
+            expected = qemuValidateChrSerialTargetModelToTargetType(chr->targetModel);
+
+            if (chr->targetType != expected) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("Target model '%s' requires target type '%s'"),
+                               virDomainChrSerialTargetModelTypeToString(chr->targetModel),
+                               virDomainChrSerialTargetTypeToString(expected));
+                return -1;
+            }
+            break;
+
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
+        case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
+            break;
+        }
+        break;
+
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
+        /* Nothing to do */
+        break;
+    }
+
+    return 0;
+}
+
+
+static int
+qemuValidateDomainChrSourceDef(const virDomainChrSourceDef *def,
+                               virQEMUCapsPtr qemuCaps)
+{
+    switch ((virDomainChrType)def->type) {
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+        if (qemuValidateDomainChrSourceReconnectDef(&def->data.tcp.reconnect) < 0)
+            return -1;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+        if (qemuValidateDomainChrSourceReconnectDef(&def->data.nix.reconnect) < 0)
+            return -1;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+        if (def->data.file.append != VIR_TRISTATE_SWITCH_ABSENT &&
+            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FILE_APPEND)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("append not supported in this QEMU binary"));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_NULL:
+    case VIR_DOMAIN_CHR_TYPE_VC:
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+    case VIR_DOMAIN_CHR_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+    case VIR_DOMAIN_CHR_TYPE_LAST:
+        break;
+    }
+
+    if (def->logfile) {
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_LOGFILE)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("logfile not supported in this QEMU binary"));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+int
+qemuValidateDomainChrDef(const virDomainChrDef *dev,
+                         const virDomainDef *def,
+                         virQEMUCapsPtr qemuCaps)
+{
+    if (qemuValidateDomainChrSourceDef(dev->source, qemuCaps) < 0)
+        return -1;
+
+    if (qemuValidateDomainChrTargetDef(dev) < 0)
+        return -1;
+
+    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL &&
+        (ARCH_IS_S390(def->os.arch) || qemuDomainIsPSeries(def))) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("parallel ports are not supported"));
+            return -1;
+    }
+
+    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
+        bool isCompatible = true;
+
+        if (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM) {
+            if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011 &&
+                !qemuDomainIsARMVirt(def)) {
+                isCompatible = false;
+            }
+            if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A &&
+                !qemuDomainIsRISCVVirt(def)) {
+                isCompatible = false;
+            }
+        }
+
+        if (!qemuDomainIsPSeries(def) &&
+            (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO ||
+             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY)) {
+            isCompatible = false;
+        }
+
+        if (!ARCH_IS_S390(def->os.arch) &&
+            (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP ||
+             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE ||
+             dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE)) {
+            isCompatible = false;
+        }
+
+        if (!isCompatible) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Serial device with target type '%s' and "
+                             "target model '%s' not compatible with guest "
+                             "architecture or machine type"),
+                           virDomainChrSerialTargetTypeToString(dev->targetType),
+                           virDomainChrSerialTargetModelTypeToString(dev->targetModel));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+int
+qemuValidateDomainSmartcardDef(const virDomainSmartcardDef *def,
+                               virQEMUCapsPtr qemuCaps)
+{
+    switch (def->type) {
+    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("this QEMU binary lacks smartcard host "
+                             "mode support"));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("this QEMU binary lacks smartcard host "
+                             "mode support"));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_PASSTHRU)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("this QEMU binary lacks smartcard "
+                             "passthrough mode support"));
+            return -1;
+        }
+        break;
+
+    default:
+        virReportEnumRangeError(virDomainSmartcardType, def->type);
+        return -1;
+    }
+
+    if (def->type == VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH &&
+        qemuValidateDomainChrSourceDef(def->data.passthru, qemuCaps) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
+qemuValidateDomainRNGDef(const virDomainRNGDef *def,
+                         virQEMUCapsPtr qemuCaps G_GNUC_UNUSED)
+{
+    if (def->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
+        qemuValidateDomainChrSourceDef(def->source.chardev, qemuCaps) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
+qemuValidateDomainRedirdevDef(const virDomainRedirdevDef *def,
+                              virQEMUCapsPtr qemuCaps)
+{
+    if (qemuValidateDomainChrSourceDef(def->source, qemuCaps) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
+qemuValidateDomainWatchdogDef(const virDomainWatchdogDef *dev,
+                              const virDomainDef *def)
+{
+    switch ((virDomainWatchdogModel) dev->model) {
+    case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB:
+        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+            dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("%s model of watchdog can go only on PCI bus"),
+                           virDomainWatchdogModelTypeToString(dev->model));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_WATCHDOG_MODEL_IB700:
+        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+            dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("%s model of watchdog can go only on ISA bus"),
+                           virDomainWatchdogModelTypeToString(dev->model));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_WATCHDOG_MODEL_DIAG288:
+        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("%s model of watchdog is virtual and cannot go on any bus."),
+                           virDomainWatchdogModelTypeToString(dev->model));
+            return -1;
+        }
+        if (!(ARCH_IS_S390(def->os.arch))) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("%s model of watchdog is allowed for s390 and s390x only"),
+                           virDomainWatchdogModelTypeToString(dev->model));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_WATCHDOG_MODEL_LAST:
+        break;
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_validate.h b/src/qemu/qemu_validate.h
index 437daebecd..d2238445be 100644
--- a/src/qemu/qemu_validate.h
+++ b/src/qemu/qemu_validate.h
@@ -30,3 +30,14 @@ int qemuValidateDomainDeviceDefAddress(const virDomainDeviceDef *dev,
                                        virQEMUCapsPtr qemuCaps);
 int qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
                                        virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainChrDef(const virDomainChrDef *dev,
+                             const virDomainDef *def,
+                             virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainSmartcardDef(const virDomainSmartcardDef *def,
+                                   virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainRNGDef(const virDomainRNGDef *def,
+                             virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainRedirdevDef(const virDomainRedirdevDef *def,
+                                  virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainWatchdogDef(const virDomainWatchdogDef *dev,
+                                  const virDomainDef *def);
-- 
2.25.1





More information about the libvir-list mailing list