diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a68ff717fdcc7e00f44bbc7e28b3722be7ac2453..53b79ac9763cb8aa980dd204b1bac6bf6341a91e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5044,6 +5044,19 @@ qemuBuildChrChardevFileStr(virLogManagerPtr logManager, return 0; } + +static void +qemuBuildChrChardevReconnectStr(virBufferPtr buf, + const virDomainChrSourceReconnectDef *def) +{ + if (def->enabled == VIR_TRISTATE_BOOL_YES) { + virBufferAsprintf(buf, ",reconnect=%u", def->timeout); + } else if (def->enabled == VIR_TRISTATE_BOOL_NO) { + virBufferAddLit(buf, ",reconnect=0"); + } +} + + /* This function outputs a -chardev command line option which describes only the * host side of the character device */ static char * @@ -5142,6 +5155,8 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, if (dev->data.tcp.listen) virBufferAdd(&buf, nowait ? ",server,nowait" : ",server", -1); + qemuBuildChrChardevReconnectStr(&buf, &dev->data.tcp.reconnect); + if (dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) { qemuDomainChrSourcePrivatePtr chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev); @@ -5175,6 +5190,8 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path); if (dev->data.nix.listen) virBufferAdd(&buf, nowait ? ",server,nowait" : ",server", -1); + + qemuBuildChrChardevReconnectStr(&buf, &dev->data.nix.reconnect); break; case VIR_DOMAIN_CHR_TYPE_SPICEVMC: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2c77a6442467d80a7ae9925e51fc79d22eced885..05bf1c7d0250bd4da3e364365e4dd1bd80a72efe 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3210,6 +3210,95 @@ qemuDomainNetSupportsCoalesce(virDomainNetType type) } +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) +{ + 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_NULL: + case VIR_DOMAIN_CHR_TYPE_VC: + case VIR_DOMAIN_CHR_TYPE_PTY: + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + 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; + } + + return 0; +} + + +static int +qemuDomainChrDefValidate(const virDomainChrDef *def) +{ + if (qemuDomainChrSourceDefValidate(def->source) < 0) + return -1; + + return 0; +} + + +static int +qemuDomainSmartcardDefValidate(const virDomainSmartcardDef *def) +{ + if (def->type == VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH && + qemuDomainChrSourceDefValidate(def->data.passthru) < 0) + return -1; + + return 0; +} + + +static int +qemuDomainRNGDefValidate(const virDomainRNGDef *def) +{ + if (def->backend == VIR_DOMAIN_RNG_BACKEND_EGD && + qemuDomainChrSourceDefValidate(def->source.chardev) < 0) + return -1; + + return 0; +} + + +static int +qemuDomainRedirdevDefValidate(const virDomainRedirdevDef *def) +{ + if (qemuDomainChrSourceDefValidate(def->source) < 0) + return -1; + + return 0; +} + + static int qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, const virDomainDef *def ATTRIBUTE_UNUSED, @@ -3257,6 +3346,18 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, virDomainNetTypeToString(net->type)); goto cleanup; } + } else if (dev->type == VIR_DOMAIN_DEVICE_CHR) { + if (qemuDomainChrDefValidate(dev->data.chr) < 0) + goto cleanup; + } else if (dev->type == VIR_DOMAIN_DEVICE_SMARTCARD) { + if (qemuDomainSmartcardDefValidate(dev->data.smartcard) < 0) + goto cleanup; + } else if (dev->type == VIR_DOMAIN_DEVICE_RNG) { + if (qemuDomainRNGDefValidate(dev->data.rng) < 0) + goto cleanup; + } else if (dev->type == VIR_DOMAIN_DEVICE_REDIRDEV) { + if (qemuDomainRedirdevDefValidate(dev->data.redirdev) < 0) + goto cleanup; } /* forbid capabilities mode hostdev in this kind of hypervisor */