mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
conf: introduce reconnect element for chardev source
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
parent
5f7da98b3f
commit
9aa72a6dd5
@ -6298,6 +6298,17 @@ qemu-kvm -net nic,model=? /dev/null
|
||||
slot.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For character device with type <code>unix</code> or <code>tcp</code>
|
||||
the <code>source</code> has an optional element <code>reconnect</code>
|
||||
which configures reconnect timeout if the connection is lost.
|
||||
There are two attributes, <code>enabled</code> where possible
|
||||
values are "yes" and "no" and <code>timeout</code> which is in
|
||||
seconds. The <code>reconnect</code> attribute is valid only
|
||||
for <code>connect</code> mode.
|
||||
<span class="since">Since 3.7.0 (QEMU driver only)</span>.
|
||||
</p>
|
||||
|
||||
<h5><a id="elementsCharGuestInterface">Guest interface</a></h5>
|
||||
|
||||
<p>
|
||||
|
@ -3634,6 +3634,18 @@
|
||||
<ref name="virYesNo"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="reconnect">
|
||||
<attribute name="enabled">
|
||||
<ref name="virYesNo"/>
|
||||
</attribute>
|
||||
<optional>
|
||||
<attribute name="timeout">
|
||||
<ref name="unsignedInt"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
</element>
|
||||
</optional>
|
||||
<zeroOrMore>
|
||||
<ref name='devSeclabel'/>
|
||||
</zeroOrMore>
|
||||
|
@ -5130,6 +5130,12 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *def,
|
||||
_("Missing source service attribute for char device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (def->data.tcp.listen && def->data.tcp.reconnect.enabled) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("chardev reconnect is possible only for connect mode"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_CHR_TYPE_UDP:
|
||||
@ -5150,6 +5156,12 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *def,
|
||||
_("Missing source path attribute for char device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (def->data.nix.listen && def->data.nix.reconnect.enabled) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("chardev reconnect is possible only for connect mode"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
|
||||
@ -11115,6 +11127,56 @@ virDomainChrDefParseTargetXML(virDomainChrDefPtr def,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
|
||||
xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt)
|
||||
{
|
||||
int ret = -1;
|
||||
int tmpVal;
|
||||
char *tmp = NULL;
|
||||
xmlNodePtr saveNode = ctxt->node;
|
||||
xmlNodePtr cur;
|
||||
|
||||
ctxt->node = node;
|
||||
|
||||
if ((cur = virXPathNode("./reconnect", ctxt))) {
|
||||
if ((tmp = virXMLPropString(cur, "enabled"))) {
|
||||
if ((tmpVal = virTristateBoolTypeFromString(tmp)) < 0) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("invalid reconnect enabled value: '%s'"),
|
||||
tmp);
|
||||
goto cleanup;
|
||||
}
|
||||
def->enabled = tmpVal;
|
||||
VIR_FREE(tmp);
|
||||
}
|
||||
|
||||
if (def->enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
if ((tmp = virXMLPropString(cur, "timeout"))) {
|
||||
if (virStrToLong_ui(tmp, NULL, 10, &def->timeout) < 0) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("invalid reconnect timeout value: '%s'"),
|
||||
tmp);
|
||||
goto cleanup;
|
||||
}
|
||||
VIR_FREE(tmp);
|
||||
} else {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("missing timeout for chardev with "
|
||||
"reconnect enabled"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
ctxt->node = saveNode;
|
||||
VIR_FREE(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT,
|
||||
@ -11152,6 +11214,7 @@ virDomainChrSourceDefParseMode(xmlNodePtr source)
|
||||
static int
|
||||
virDomainChrSourceDefParseTCP(virDomainChrSourceDefPtr def,
|
||||
xmlNodePtr source,
|
||||
xmlXPathContextPtr ctxt,
|
||||
unsigned int flags)
|
||||
{
|
||||
int mode;
|
||||
@ -11187,6 +11250,12 @@ virDomainChrSourceDefParseTCP(virDomainChrSourceDefPtr def,
|
||||
VIR_FREE(tmp);
|
||||
}
|
||||
|
||||
if (virDomainChrSourceReconnectDefParseXML(&def->data.tcp.reconnect,
|
||||
source,
|
||||
ctxt) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@ -11220,7 +11289,8 @@ virDomainChrSourceDefParseUDP(virDomainChrSourceDefPtr def,
|
||||
|
||||
static int
|
||||
virDomainChrSourceDefParseUnix(virDomainChrSourceDefPtr def,
|
||||
xmlNodePtr source)
|
||||
xmlNodePtr source,
|
||||
xmlXPathContextPtr ctxt)
|
||||
{
|
||||
|
||||
int mode;
|
||||
@ -11231,6 +11301,12 @@ virDomainChrSourceDefParseUnix(virDomainChrSourceDefPtr def,
|
||||
def->data.nix.listen = mode == VIR_DOMAIN_CHR_SOURCE_MODE_BIND;
|
||||
def->data.nix.path = virXMLPropString(source, "path");
|
||||
|
||||
if (virDomainChrSourceReconnectDefParseXML(&def->data.nix.reconnect,
|
||||
source,
|
||||
ctxt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -11359,7 +11435,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
||||
if (virDomainChrSourceDefParseUnix(def, cur) < 0)
|
||||
if (virDomainChrSourceDefParseUnix(def, cur, ctxt) < 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
@ -11369,7 +11445,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_CHR_TYPE_TCP:
|
||||
if (virDomainChrSourceDefParseTCP(def, cur, flags) < 0)
|
||||
if (virDomainChrSourceDefParseTCP(def, cur, ctxt, flags) < 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
@ -11613,6 +11689,7 @@ virDomainChrDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
static virDomainSmartcardDefPtr
|
||||
virDomainSmartcardDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
unsigned int flags)
|
||||
{
|
||||
xmlNodePtr cur;
|
||||
@ -11705,7 +11782,7 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
|
||||
cur = node->children;
|
||||
if (virDomainChrSourceDefParseXML(def->data.passthru, cur, flags,
|
||||
NULL, NULL, NULL, 0) < 0)
|
||||
NULL, ctxt, NULL, 0) < 0)
|
||||
goto error;
|
||||
|
||||
if (def->data.passthru->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
|
||||
@ -14183,6 +14260,7 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
static virDomainRedirdevDefPtr
|
||||
virDomainRedirdevDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
virHashTablePtr bootHash,
|
||||
unsigned int flags)
|
||||
{
|
||||
@ -14224,7 +14302,7 @@ virDomainRedirdevDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
/* boot gets parsed in virDomainDeviceInfoParseXML
|
||||
* source gets parsed in virDomainChrSourceDefParseXML */
|
||||
if (virDomainChrSourceDefParseXML(def->source, cur, flags,
|
||||
NULL, NULL, NULL, 0) < 0)
|
||||
NULL, ctxt, NULL, 0) < 0)
|
||||
goto error;
|
||||
|
||||
if (def->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC)
|
||||
@ -14883,7 +14961,7 @@ virDomainDeviceDefParse(const char *xmlStr,
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
||||
if (!(dev->data.redirdev = virDomainRedirdevDefParseXML(xmlopt, node,
|
||||
NULL, flags)))
|
||||
ctxt, NULL, flags)))
|
||||
goto error;
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_RNG:
|
||||
@ -14902,7 +14980,7 @@ virDomainDeviceDefParse(const char *xmlStr,
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_SMARTCARD:
|
||||
if (!(dev->data.smartcard = virDomainSmartcardDefParseXML(xmlopt, node,
|
||||
flags)))
|
||||
ctxt, flags)))
|
||||
goto error;
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_MEMBALLOON:
|
||||
@ -18600,6 +18678,7 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
for (i = 0; i < n; i++) {
|
||||
virDomainSmartcardDefPtr card = virDomainSmartcardDefParseXML(xmlopt,
|
||||
nodes[i],
|
||||
ctxt,
|
||||
flags);
|
||||
if (!card)
|
||||
goto error;
|
||||
@ -18949,7 +19028,7 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
goto error;
|
||||
for (i = 0; i < n; i++) {
|
||||
virDomainRedirdevDefPtr redirdev =
|
||||
virDomainRedirdevDefParseXML(xmlopt, nodes[i], bootHash, flags);
|
||||
virDomainRedirdevDefParseXML(xmlopt, nodes[i], ctxt, bootHash, flags);
|
||||
if (!redirdev)
|
||||
goto error;
|
||||
|
||||
@ -23070,6 +23149,24 @@ virDomainChrAttrsDefFormat(virBufferPtr buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
|
||||
virDomainChrSourceReconnectDefPtr def)
|
||||
{
|
||||
if (def->enabled == VIR_TRISTATE_BOOL_ABSENT)
|
||||
return;
|
||||
|
||||
virBufferAsprintf(buf, "<reconnect enabled='%s'",
|
||||
virTristateBoolTypeToString(def->enabled));
|
||||
|
||||
if (def->enabled == VIR_TRISTATE_BOOL_YES)
|
||||
virBufferAsprintf(buf, " timeout='%u'", def->timeout);
|
||||
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virDomainChrSourceDefFormat(virBufferPtr buf,
|
||||
virDomainChrSourceDefPtr def,
|
||||
@ -23150,6 +23247,9 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
|
||||
virBufferAsprintf(&attrBuf, " tlsFromConfig='%d'",
|
||||
def->data.tcp.tlsFromConfig);
|
||||
|
||||
virDomainChrSourceReconnectDefFormat(&childBuf,
|
||||
&def->data.tcp.reconnect);
|
||||
|
||||
if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0)
|
||||
goto error;
|
||||
|
||||
@ -23166,6 +23266,9 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
|
||||
virDomainSourceDefFormatSeclabel(&childBuf, def->nseclabels,
|
||||
def->seclabels, flags);
|
||||
|
||||
virDomainChrSourceReconnectDefFormat(&childBuf,
|
||||
&def->data.nix.reconnect);
|
||||
|
||||
if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
@ -1137,6 +1137,15 @@ typedef enum {
|
||||
VIR_DOMAIN_CHR_SPICEVMC_LAST
|
||||
} virDomainChrSpicevmcName;
|
||||
|
||||
|
||||
struct _virDomainChrSourceReconnectDef {
|
||||
virTristateBool enabled;
|
||||
unsigned int timeout;
|
||||
};
|
||||
typedef struct _virDomainChrSourceReconnectDef virDomainChrSourceReconnectDef;
|
||||
typedef virDomainChrSourceReconnectDef *virDomainChrSourceReconnectDefPtr;
|
||||
|
||||
|
||||
/* The host side information for a character device. */
|
||||
struct _virDomainChrSourceDef {
|
||||
int type; /* virDomainChrType */
|
||||
@ -1159,6 +1168,7 @@ struct _virDomainChrSourceDef {
|
||||
bool tlscreds;
|
||||
int haveTLS; /* enum virTristateBool */
|
||||
bool tlsFromConfig;
|
||||
virDomainChrSourceReconnectDef reconnect;
|
||||
} tcp;
|
||||
struct {
|
||||
char *bindHost;
|
||||
@ -1169,6 +1179,7 @@ struct _virDomainChrSourceDef {
|
||||
struct {
|
||||
char *path;
|
||||
bool listen;
|
||||
virDomainChrSourceReconnectDef reconnect;
|
||||
} nix;
|
||||
int spicevmc;
|
||||
struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user