diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index dcb7af887e..e6a8162f7f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1102,6 +1102,18 @@ qemu-kvm -net nic,model=? /dev/null The listen attribute is an IP address for the server to listen on. The passwd attribute provides a VNC password in clear text. The keymap attribute specifies the keymap + to use. + +
"spice"
+
+ Starts a SPICE server. The port attribute specifies the TCP + port number (with -1 as legacy syntax indicating that it should be + auto-allocated), while tlsPort gives an alternative + secure port number. The autoport attribute is the new + preferred syntax for indicating autoallocation of both port numbers. + The listen attribute is an IP address for the server to + listen on. The passwd attribute provides a SPICE password + in clear text. The keymap attribute specifies the keymap to use.
"rdp"
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 16fc444df7..7903000680 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1094,6 +1094,44 @@ + + + spice + + + + + + + + + + + + + + + yes + no + + + + + + + + + + + + + + + + + + + rdp diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 09f415b711..1f3bca8cad 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -268,7 +268,8 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, "sdl", "vnc", "rdp", - "desktop") + "desktop", + "spice") VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, "subsystem", @@ -451,6 +452,12 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: VIR_FREE(def->data.desktop.display); break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + VIR_FREE(def->data.spice.listenAddr); + VIR_FREE(def->data.spice.keymap); + VIR_FREE(def->data.spice.passwd); + break; } VIR_FREE(def); @@ -3204,6 +3211,50 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { def->data.desktop.fullscreen = 0; def->data.desktop.display = virXMLPropString(node, "display"); + } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + char *port = virXMLPropString(node, "port"); + char *tlsPort; + char *autoport; + + if (port) { + if (virStrToLong_i(port, NULL, 10, &def->data.spice.port) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse spice port %s"), port); + VIR_FREE(port); + goto error; + } + VIR_FREE(port); + } else { + def->data.spice.port = 5900; + } + + tlsPort = virXMLPropString(node, "tlsPort"); + if (tlsPort) { + if (virStrToLong_i(tlsPort, NULL, 10, &def->data.spice.tlsPort) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse spice tlsPort %s"), tlsPort); + VIR_FREE(tlsPort); + goto error; + } + VIR_FREE(tlsPort); + } else { + def->data.spice.tlsPort = 0; + } + + if ((autoport = virXMLPropString(node, "autoport")) != NULL) { + if (STREQ(autoport, "yes")) { + if (flags & VIR_DOMAIN_XML_INACTIVE) { + def->data.spice.port = 0; + def->data.spice.tlsPort = 0; + } + def->data.spice.autoport = 1; + } + VIR_FREE(autoport); + } + + def->data.spice.listenAddr = virXMLPropString(node, "listen"); + def->data.spice.passwd = virXMLPropString(node, "passwd"); + def->data.spice.keymap = virXMLPropString(node, "keymap"); } cleanup: @@ -6517,6 +6568,33 @@ virDomainGraphicsDefFormat(virBufferPtr buf, break; + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + if (def->data.spice.port) + virBufferVSprintf(buf, " port='%d'", + def->data.spice.port); + + if (def->data.spice.tlsPort) + virBufferVSprintf(buf, " tlsPort='%d'", + def->data.spice.tlsPort); + + virBufferVSprintf(buf, " autoport='%s'", + def->data.spice.autoport ? "yes" : "no"); + + if (def->data.spice.listenAddr) + virBufferVSprintf(buf, " listen='%s'", + def->data.spice.listenAddr); + + if (def->data.spice.keymap) + virBufferEscapeString(buf, " keymap='%s'", + def->data.spice.keymap); + + if (def->data.spice.passwd && + (flags & VIR_DOMAIN_XML_SECURE)) + virBufferEscapeString(buf, " passwd='%s'", + def->data.spice.passwd); + + break; + } virBufferAddLit(buf, "/>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 834eafeb23..c6699e2e54 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -512,6 +512,7 @@ enum virDomainGraphicsType { VIR_DOMAIN_GRAPHICS_TYPE_VNC, VIR_DOMAIN_GRAPHICS_TYPE_RDP, VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP, + VIR_DOMAIN_GRAPHICS_TYPE_SPICE, VIR_DOMAIN_GRAPHICS_TYPE_LAST, }; @@ -544,6 +545,14 @@ struct _virDomainGraphicsDef { char *display; unsigned int fullscreen :1; } desktop; + struct { + int port; + int tlsPort; + char *listenAddr; + char *keymap; + char *passwd; + unsigned int autoport :1; + } spice; } data; }; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index e0064f75e1..e8342be48b 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -5072,7 +5072,7 @@ int qemudBuildCommandLine(virConnectPtr conn, if (def->nvideos) { if (def->nvideos > 1) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only one video card is currently supported")); goto error; }