[libvirt] [PATCHv4 0/2] vnc/spice listen address as a network name

This is the latest reincarnation of this patch series: https://www.redhat.com/archives/libvir-list/2011-July/msg01717.html In the previous version, I had created a new subelement of <graphics>, called <listen>, and placed all listen address and port attributes there. After discussion on the list and in IRC with Dan Berrange and Eric Blake, I became convinced that was overdoing things, and that really only the address or network name should be in the <listen> element, but that port/tlsPort/autoport should stay put. This version removes all changes to port-related attributes, paring it down to just the listen address (and the new listen network) attribute. This greatly simplifies the patch, so new review of it should be easier. Based on Eric's review, the nwe version tries to be more concise about what is accepted, what is ignored, and what is rejected in the XML, both by the parser and by the RNG. (since there is less to deal with, this is also easier.) Having a single port value but multiple addresses does create some potential future restrictions, which we can deal with an eliminate later if they become problematic. In particular, each graphics device will have only a single port, but could have multiple listen addresses; in this case, all the listen addresses would have to listen on the same port. (This isn't a problem right now, because all of our drivers can only listen on a single address anyway). (Note to Eric: I did consider putting the switch to helper functions into its own patch, but after removing all the ports from <listen>, the number of helper functions (and thus the number of changes created by switching to using them, has been reduced considerably, so the gain wouldn't be as much. (also, it's very late, and I'd like to get some sleep tonight :-)

Once it's plugged in, the <listen> element will be an optional replacement for the "listen" attribute that graphics elements already have. If the <listen> element is type='address', it will have an attribute called 'address' which will contain an IP address or dns name that the guest's display server should listen on. If, however, type='network', the <listen> element should have an attribute called 'network' that will be set to the name of a network configuration to get the IP address from. * docs/schemas/domain.rng: updated to allow the <listen> element * docs/formatdomain.html.in: document the <listen> element and its attributes. * src/conf/domain_conf.[hc]: 1) The domain parser, formatter, and data structure are modified to support 0 or more <listen> subelements to each <graphics> element. The old style "legacy" listen attribute is also still accepted, and will be stored internally just as if it were a separate <listen> element. On output (i.e. format), the address attribute of the first <listen> element of type 'address' will be duplicated in the legacy "listen" attribute of the <graphic> element. 2) The "listenAddr" attribute has been removed from the unions in virDomainGRaphicsDef for graphics types vnc, rdp, and spice. This attribute is now in the <listen> subelement (aka virDomainGraphicsListenDef) 3) Helper functions were written to provide simple access (both Get and Set) to the listen elements and their attributes. * src/libvirt_private.syms: export the listen helper functions * src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c, src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c Modify all these files to use the listen helper functions rather than directly referencing the (now missing) listenAddr attribute. There can be multiple <listen> elements to a single <graphics>, but the drivers all currently only support one, so all replacements of direct access with a helper function indicate index "0". * tests/* - only 3 of these are new files added explicitly to test the new <listen> element. All the others have been modified to reflect the fact that any legacy "listen" attributes passed in to the domain parse will be saved in a <listen> element (i.e. one of the virDomainGraphicsListenDefs), and during the domain format function, both the <listen> element as well as the legacy attributes will be output. --- docs/formatdomain.html.in | 54 +++ docs/schemas/domain.rng | 33 ++ src/conf/domain_conf.c | 408 ++++++++++++++++++-- src/conf/domain_conf.h | 43 ++- src/libvirt_private.syms | 6 + src/qemu/qemu_command.c | 42 ++- src/qemu/qemu_hotplug.c | 10 +- src/qemu/qemu_migration.c | 4 +- src/vbox/vbox_tmpl.c | 13 +- src/vmx/vmx.c | 16 +- src/xenxs/xen_sxpr.c | 23 +- src/xenxs/xen_xm.c | 33 ++- .../qemuxml2argv-graphics-listen-network.xml | 32 ++ .../qemuxml2argv-graphics-listen-network2.xml | 33 ++ .../qemuxml2argv-graphics-spice-compression.xml | 1 + .../qemuxml2argv-graphics-spice-qxl-vga.xml | 1 + .../qemuxml2argv-graphics-spice.xml | 1 + .../qemuxml2argv-graphics-vnc-sasl.xml | 4 +- .../qemuxml2argv-graphics-vnc-tls.xml | 4 +- .../qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml | 4 +- tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml | 4 +- .../qemuxml2xmlout-graphics-listen-network2.xml | 33 ++ tests/qemuxml2xmltest.c | 2 + .../sexpr2xml-pv-vfb-new-vncdisplay.xml | 4 +- tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml | 4 +- tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml | 4 +- tests/xmconfigdata/test-escape-paths.xml | 4 +- tests/xmconfigdata/test-fullvirt-force-hpet.xml | 4 +- tests/xmconfigdata/test-fullvirt-force-nohpet.xml | 4 +- tests/xmconfigdata/test-fullvirt-localtime.xml | 4 +- tests/xmconfigdata/test-fullvirt-net-ioemu.xml | 4 +- tests/xmconfigdata/test-fullvirt-net-netfront.xml | 4 +- tests/xmconfigdata/test-fullvirt-new-cdrom.xml | 4 +- tests/xmconfigdata/test-fullvirt-old-cdrom.xml | 4 +- tests/xmconfigdata/test-fullvirt-parallel-tcp.xml | 4 +- .../test-fullvirt-serial-dev-2-ports.xml | 4 +- .../test-fullvirt-serial-dev-2nd-port.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-file.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-null.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-pipe.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-pty.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-stdio.xml | 4 +- .../test-fullvirt-serial-tcp-telnet.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-tcp.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-udp.xml | 4 +- tests/xmconfigdata/test-fullvirt-serial-unix.xml | 4 +- tests/xmconfigdata/test-fullvirt-sound.xml | 4 +- tests/xmconfigdata/test-fullvirt-usbmouse.xml | 4 +- .../test-fullvirt-usbtablet-no-bus.xml | 4 +- tests/xmconfigdata/test-fullvirt-usbtablet.xml | 4 +- tests/xmconfigdata/test-fullvirt-utc.xml | 4 +- tests/xmconfigdata/test-paravirt-net-e1000.xml | 4 +- tests/xmconfigdata/test-paravirt-net-vifname.xml | 4 +- .../test-paravirt-new-pvfb-vncdisplay.xml | 4 +- tests/xmconfigdata/test-paravirt-new-pvfb.xml | 4 +- .../test-paravirt-old-pvfb-vncdisplay.xml | 4 +- tests/xmconfigdata/test-paravirt-old-pvfb.xml | 4 +- 57 files changed, 823 insertions(+), 117 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-listen-network2.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 50c11c3..74056ac 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2046,6 +2046,12 @@ qemu-kvm -net nic,model=? /dev/null <graphics type='vnc' port='5904'/> <graphics type='rdp' autoport='yes' multiUser='yes' /> <graphics type='desktop' fullscreen='yes'/> + <graphics type='vnc'> + <listen type='address' address='1.2.3.4'/> + </graphics> + <graphics type='spice'> + <listen type='network' network='rednet'/> + </graphics> </devices> ...</pre> @@ -2191,6 +2197,54 @@ qemu-kvm -net nic,model=? /dev/null </dd> </dl> + <p> + Rather than putting the address information used to set up the + listening socket for graphics types <code>vnc</code> + and <code>spice</code> in + the <code><graphics></code> <code>listen</code> attribute, + a separate subelement of <code><graphics></code>, + called <code><listen></code> can be specified (see the + examples above)<span class="since">since + 0.9.4</span>. <code><listen></code> accepts the following + attributes: + </p> + <dl> + <dt><code>type</code></dt> + <dd>Set to either <code>address</code> + or <code>network</code>. This tells whether this listen + element is specifying the address to be used directly, or by + naming a network (which will then be used to determine an + appropriate address for listening). + </dd> + </dl> + <dl> + <dt><code>address</code></dt> + <dd>if <code>type='address'</code>, the <code>address</code> + attribute will contain either an IP address or hostname (which + will be resolved to an IP address via a DNS query) to listen + on. In the "live" XML of a running domain, this attribute be + set to the IP address used for listening, even + if <code>type='network'</code>. + </dd> + </dl> + <dl> + <dt><code>network</code></dt> + <dd>if <code>type='network'</code>, the <code>network</code> + attribute will contain the name of a network in libvirt's list + of configured networks. The named network configuration will + be examined to determine an appropriate listen address. For + example, if the network has an IPv4 address in its + configuration (e.g. if it has a forward type + of <code>route</code>, <code>nat</code>, or no forward type + (isolated)), the first IPv4 address listed in the network's + configuration will be used. If the network is describing a + host bridge, the first IPv4 address associated with that + bridge device will be used, and if the network is describing + one of the 'direct' (macvtap) modes, the first IPv4 address of + the first forward dev will be used. + </dd> + </dl> + <h4><a name="elementsVideo">Video devices</a></h4> <p> A video device. diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index aa4ce69..6ccbeed 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1289,6 +1289,7 @@ </choice> </attribute> </optional> + <ref name="listenElements"/> </group> <group> <attribute name="type"> @@ -1342,6 +1343,7 @@ </attribute> </optional> <interleave> + <ref name="listenElements"/> <zeroOrMore> <element name="channel"> <attribute name="name"> @@ -1478,6 +1480,7 @@ <ref name="addrIPorName"/> </attribute> </optional> + <ref name="listenElements"/> </group> <group> <attribute name="type"> @@ -1500,6 +1503,36 @@ </choice> </element> </define> + + <define name="listenElements"> + <zeroOrMore> + <element name="listen"> + <choice> + <group> + <attribute name="type"> + <value>address</value> + </attribute> + <attribute name="address"> + <ref name="addrIPorName"/> + </attribute> + </group> + <group> + <attribute name="type"> + <value>network</value> + </attribute> + <attribute name="network"> + <text/> + </attribute> + <optional> + <attribute name="address"> + <ref name="addrIPorName"/> + </attribute> + </optional> + </group> + </choice> + </element> + </zeroOrMore> + </define> <!-- A video adapter description, allowing configuration of device model, number of virtual heads, and video ram size diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f99294c..257a1ea 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -331,6 +331,11 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, "desktop", "spice") +VIR_ENUM_IMPL(virDomainGraphicsListen, VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST, + "none", + "address", + "network") + VIR_ENUM_IMPL(virDomainGraphicsAuthConnected, VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST, "default", @@ -625,14 +630,26 @@ virDomainGraphicsAuthDefClear(virDomainGraphicsAuthDefPtr def) /* Don't free def */ } +static void +virDomainGraphicsListenDefClear(virDomainGraphicsListenDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->address); + VIR_FREE(def->network); + return; +} + void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) { + int ii; + if (!def) return; switch (def->type) { case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - VIR_FREE(def->data.vnc.listenAddr); VIR_FREE(def->data.vnc.socket); VIR_FREE(def->data.vnc.keymap); virDomainGraphicsAuthDefClear(&def->data.vnc.auth); @@ -644,7 +661,6 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: - VIR_FREE(def->data.rdp.listenAddr); break; case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -652,12 +668,15 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) break; case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: - VIR_FREE(def->data.spice.listenAddr); VIR_FREE(def->data.spice.keymap); virDomainGraphicsAuthDefClear(&def->data.spice.auth); break; } + for (ii = 0; ii < def->nListens; ii++) + virDomainGraphicsListenDefClear(&def->listens[ii]); + VIR_FREE(def->listens); + VIR_FREE(def); } @@ -4018,19 +4037,82 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, return 0; } +static int +virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, + xmlNodePtr node, + unsigned int flags) +{ + int ret = -1; + char *type = virXMLPropString(node, "type"); + char *address = virXMLPropString(node, "address"); + char *network = virXMLPropString(node, "network"); + + if (!type) { + virDomainReportError(VIR_ERR_XML_ERROR, "%s", + _("graphics listen type must be specified")); + goto error; + } + + if ((def->type = virDomainGraphicsListenTypeFromString(type)) < 0) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("unknown graphics listen type '%s'"), type); + goto error; + } + + /* address is recognized if either type='address', or if + * type='network' and we're looking at live XML (i.e. *not* + * inactive). It is otherwise ignored. */ + if (address && address[0] && + ((def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) || + ((def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK) && + !(flags & VIR_DOMAIN_XML_INACTIVE)))) { + def->address = address; + address = NULL; + } + + if (network && network[0]) { + if (def->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK) { + /* network='xxx' never makes sense with anything except + * type='address' */ + virDomainReportError(VIR_ERR_XML_ERROR, "%s", + _("network attribute not allowed when listen type is not network")); + goto error; + } + def->network = network; + network = NULL; + } + + ret = 0; +error: + if (ret < 0) + virDomainGraphicsListenDefClear(def); + VIR_FREE(type); + VIR_FREE(address); + VIR_FREE(network); + return ret; +} + /* Parse the XML definition for a graphics device */ static virDomainGraphicsDefPtr -virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) +virDomainGraphicsDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + unsigned int flags) { virDomainGraphicsDefPtr def; char *type = NULL; + int nListens; + xmlNodePtr *listenNodes = NULL; + char *listenAddr = NULL; + xmlNodePtr save = ctxt->node; if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } + ctxt->node = node; + type = virXMLPropString(node, "type"); if (!type) { @@ -4045,6 +4127,78 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) goto error; } + if ((def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) || + (def->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) || + (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)) { + + /* parse the <listen> subelements for graphics types that support it */ + nListens = virXPathNodeSet("./listen", ctxt, &listenNodes); + if (nListens < 0) + goto error; + + if (nListens > 0) { + int ii; + + if (VIR_ALLOC_N(def->listens, nListens) < 0) { + virReportOOMError(); + goto error; + } + + for (ii = 0; ii < nListens; ii++) { + int ret = virDomainGraphicsListenDefParseXML(&def->listens[ii], + listenNodes[ii], + flags); + if (ret < 0) + goto error; + def->nListens++; + } + VIR_FREE(listenNodes); + } + + /* listen attribute of <graphics> is also supported by these, + * but must match the 'address' attribute of the first listen + * that is type='address' (if present) */ + listenAddr = virXMLPropString(node, "listen"); + if (listenAddr && !listenAddr[0]) + VIR_FREE(listenAddr); + + if (listenAddr) { + if (def->nListens == 0) { + /* There were no <listen> elements, so we can just + * directly set listenAddr as listens[0]->address */ + if (virDomainGraphicsListenSetAddress(def, 0, listenAddr, + -1, true) < 0) + goto error; + } else { + /* There is at least 1 listen element, so we look for + * the first listen of type='address', and make sure + * its address matches the listen attribute from + * graphics. */ + bool matched = false; + const char *found = NULL; + int ii; + + for (ii = 0; ii < nListens; ii++) { + if (virDomainGraphicsListenGetType(def, ii) + == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) { + found = virDomainGraphicsListenGetAddress(def, ii); + if (STREQ_NULLABLE(found, listenAddr)) { + matched = true; + } + break; + } + } + if (!matched) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("graphics listen attribute %s must match address " + "attribute of first listen element (found %s)"), + listenAddr, found ? found : "none"); + goto error; + } + } + } + } + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { char *port = virXMLPropString(node, "port"); char *autoport; @@ -4077,14 +4231,9 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) VIR_FREE(autoport); } - def->data.vnc.listenAddr = virXMLPropString(node, "listen"); def->data.vnc.socket = virXMLPropString(node, "socket"); def->data.vnc.keymap = virXMLPropString(node, "keymap"); - if (def->data.vnc.listenAddr && - !def->data.vnc.listenAddr[0]) - VIR_FREE(def->data.vnc.listenAddr); - if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth, def->type) < 0) goto error; @@ -4149,11 +4298,6 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) VIR_FREE(multiUser); } - def->data.rdp.listenAddr = virXMLPropString(node, "listen"); - - if (def->data.rdp.listenAddr && - !def->data.rdp.listenAddr[0]) - VIR_FREE(def->data.rdp.listenAddr); } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) { char *fullscreen = virXMLPropString(node, "fullscreen"); @@ -4215,13 +4359,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) VIR_FREE(autoport); } - def->data.spice.listenAddr = virXMLPropString(node, "listen"); def->data.spice.keymap = virXMLPropString(node, "keymap"); - if (def->data.spice.listenAddr && - !def->data.spice.listenAddr[0]) - VIR_FREE(def->data.spice.listenAddr); - if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth, def->type) < 0) goto error; @@ -4395,7 +4534,10 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned int flags) cleanup: VIR_FREE(type); + VIR_FREE(listenNodes); + VIR_FREE(listenAddr); + ctxt->node = save; return def; error: @@ -5264,7 +5406,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, goto error; } else if (xmlStrEqual(node->name, BAD_CAST "graphics")) { dev->type = VIR_DOMAIN_DEVICE_GRAPHICS; - if (!(dev->data.graphics = virDomainGraphicsDefParseXML(node, flags))) + if (!(dev->data.graphics = virDomainGraphicsDefParseXML(node, ctxt, flags))) goto error; } else { virDomainReportError(VIR_ERR_XML_ERROR, @@ -6513,6 +6655,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, goto no_memory; for (i = 0 ; i < n ; i++) { virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(nodes[i], + ctxt, flags); if (!graphics) goto error; @@ -9423,12 +9566,44 @@ virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf, virDomainGraphicsAuthConnectedTypeToString(def->connected)); } + +static void +virDomainGraphicsListenDefFormat(virBufferPtr buf, + virDomainGraphicsListenDefPtr def, + unsigned int flags) +{ + virBufferAddLit(buf, " <listen"); + + if (def->type) { + virBufferAsprintf(buf, " type='%s'", + virDomainGraphicsListenTypeToString(def->type)); + } + + if (def->address && + ((def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) || + ((def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK) && + !(flags & VIR_DOMAIN_XML_INACTIVE)))) { + /* address may also be set to show current status when type='network', + * but we don't want to print that if INACTIVE data is requested. */ + virBufferAsprintf(buf, " address='%s'", def->address); + } + + if (def->network && + (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK)) { + virBufferAsprintf(buf, " network='%s'", def->network); + } + + virBufferAddLit(buf, "/>\n"); +} + + static int virDomainGraphicsDefFormat(virBufferPtr buf, virDomainGraphicsDefPtr def, unsigned int flags) { const char *type = virDomainGraphicsTypeToString(def->type); + const char *listenAddr = NULL; int children = 0; int i; @@ -9438,6 +9613,17 @@ virDomainGraphicsDefFormat(virBufferPtr buf, return -1; } + /* find the first listen element of type='address' and duplicate + * its address attribute as the listen attribute of + * <graphics>. This is done to improve backward compatibility. */ + for (i = 0; i < def->nListens; i++) { + if (virDomainGraphicsListenGetType(def, i) + == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) { + listenAddr = virDomainGraphicsListenGetAddress(def, i); + break; + } + } + virBufferAsprintf(buf, " <graphics type='%s'", type); switch (def->type) { @@ -9457,9 +9643,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " autoport='%s'", def->data.vnc.autoport ? "yes" : "no"); - if (def->data.vnc.listenAddr) - virBufferAsprintf(buf, " listen='%s'", - def->data.vnc.listenAddr); + if (listenAddr) + virBufferAsprintf(buf, " listen='%s'", listenAddr); } if (def->data.vnc.keymap) @@ -9498,8 +9683,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, if (def->data.rdp.multiUser) virBufferAsprintf(buf, " multiUser='yes'"); - if (def->data.rdp.listenAddr) - virBufferAsprintf(buf, " listen='%s'", def->data.rdp.listenAddr); + if (listenAddr) + virBufferAsprintf(buf, " listen='%s'", listenAddr); break; @@ -9525,9 +9710,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " autoport='%s'", def->data.spice.autoport ? "yes" : "no"); - if (def->data.spice.listenAddr) - virBufferAsprintf(buf, " listen='%s'", - def->data.spice.listenAddr); + if (listenAddr) + virBufferAsprintf(buf, " listen='%s'", listenAddr); if (def->data.spice.keymap) virBufferEscapeString(buf, " keymap='%s'", @@ -9538,6 +9722,17 @@ virDomainGraphicsDefFormat(virBufferPtr buf, } + for (i = 0; i < def->nListens; i++) { + if (virDomainGraphicsListenGetType(def, i) + == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE) + continue; + if (!children) { + virBufferAddLit(buf, ">\n"); + children = 1; + } + virDomainGraphicsListenDefFormat(buf, &def->listens[i], flags); + } + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { for (i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) { int mode = def->data.spice.channels[i]; @@ -11405,3 +11600,160 @@ virDomainNetGetActualBandwidth(virDomainNetDefPtr iface) } return iface->bandwidth; } + + +/* Return listens[ii] from the appropriate union for the graphics + * type, or NULL if this is an unsuitable type, or the index is out of + * bounds. If force0 is TRUE, ii == 0, and there is no listen array, + * allocate one with a single item. */ +static virDomainGraphicsListenDefPtr +virDomainGraphicsGetListen(virDomainGraphicsDefPtr def, size_t ii, bool force0) +{ + if ((def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) || + (def->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) || + (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)) { + + if (!def->listens && (ii == 0) && force0) { + if (VIR_ALLOC(def->listens) < 0) + virReportOOMError(); + else + def->nListens = 1; + } + + if (!def->listens || (def->nListens <= ii)) + return NULL; + + return &def->listens[ii]; + } + + /* it's a type that has no listens array */ + return NULL; +} + + +/* Access functions for the fields in a virDomainGraphicsDef's + * "listens" array. + * + * NB: For simple backward compatibility with existing code, any of + * the "Set" functions will auto-create listens[0] to store the new + * setting, when necessary. Auto-creation beyond the first item is not + * supported. + * + * Return values: All "Get" functions return the requested item, or + * 0/NULL. (in the case of returned const char *, the caller should + * make a copy if they want to keep it around). All "Set" functions + * return 0 on success, -1 on failure. */ + +int +virDomainGraphicsListenGetType(virDomainGraphicsDefPtr def, size_t ii) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, false); + + if (!listenInfo) + return VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE; + return listenInfo->type; +} + + +/* NB: This function assumes type has not previously been set. It + * *will not* free any existing address or network based on a change + * in value of type. */ +int +virDomainGraphicsListenSetType(virDomainGraphicsDefPtr def, size_t ii, int val) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, true); + + if (!listenInfo) + return -1; + listenInfo->type = val; + return 0; +} + + +const char * +virDomainGraphicsListenGetAddress(virDomainGraphicsDefPtr def, size_t ii) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, false); + + if (!listenInfo || + (listenInfo->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS)) + return NULL; + return listenInfo->address; +} + + +/* Make a copy of up to len characters of address, and store it in + * listens[ii].address. If setType is true, set the listen's type + * to 'address', otherwise leave type alone. */ +int +virDomainGraphicsListenSetAddress(virDomainGraphicsDefPtr def, + size_t ii, const char *address, + int len, bool setType) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, true); + + if (!listenInfo) + return -1; + + if (setType) + listenInfo->type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS; + + if (!address) { + listenInfo->address = NULL; + return 0; + } + + listenInfo->address = (len == -1) ? strdup(address) : strndup(address, len); + if (!listenInfo->address) { + virReportOOMError(); + return -1; + } + + return 0; +} + + +const char * +virDomainGraphicsListenGetNetwork(virDomainGraphicsDefPtr def, size_t ii) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, false); + + if (!listenInfo || + (listenInfo->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK)) + return NULL; + return listenInfo->network; +} + + +/* Make a copy of up to len characters of address, and store it in + * listens[ii].network */ +int +virDomainGraphicsListenSetNetwork(virDomainGraphicsDefPtr def, + size_t ii, const char *network, int len) +{ + virDomainGraphicsListenDefPtr listenInfo + = virDomainGraphicsGetListen(def, ii, true); + + if (!listenInfo) + return -1; + + listenInfo->type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK; + + if (!network) { + listenInfo->network = NULL; + return 0; + } + + listenInfo->network = (len == -1) ? strdup(network) : strndup(network, len); + if (!listenInfo->network) { + virReportOOMError(); + return -1; + } + + return 0; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 715d995..c748f52 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -761,6 +761,22 @@ enum virDomainGraphicsSpiceClipboardCopypaste { VIR_DOMAIN_GRAPHICS_SPICE_CLIPBOARD_COPYPASTE_LAST }; +enum virDomainGraphicsListenType { + VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE = 0, + VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS, + VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK, + + VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST, +}; + +typedef struct _virDomainGraphicsListenDef virDomainGraphicsListenDef; +typedef virDomainGraphicsListenDef *virDomainGraphicsListenDefPtr; +struct _virDomainGraphicsListenDef { + int type; /* enum virDomainGraphicsListenType */ + char *address; + char *network; +}; + typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; struct _virDomainGraphicsDef { @@ -769,7 +785,6 @@ struct _virDomainGraphicsDef { struct { int port; unsigned int autoport :1; - char *listenAddr; char *keymap; char *socket; virDomainGraphicsAuthDef auth; @@ -781,7 +796,6 @@ struct _virDomainGraphicsDef { } sdl; struct { int port; - char *listenAddr; unsigned int autoport :1; unsigned int replaceUser :1; unsigned int multiUser :1; @@ -793,7 +807,6 @@ struct _virDomainGraphicsDef { struct { int port; int tlsPort; - char *listenAddr; char *keymap; virDomainGraphicsAuthDef auth; unsigned int autoport :1; @@ -806,6 +819,11 @@ struct _virDomainGraphicsDef { int copypaste; } spice; } data; + /* nListens, listens, and *port are only useful if type is vnc, + * rdp, or spice. They've been extracted from the union only to + * simplify parsing code.*/ + size_t nListens; + virDomainGraphicsListenDefPtr listens; }; enum virDomainHostdevMode { @@ -1485,6 +1503,24 @@ int virDomainNetIndexByMac(virDomainDefPtr def, const unsigned char *mac); int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetRemoveByMac(virDomainDefPtr def, const unsigned char *mac); +int virDomainGraphicsListenGetType(virDomainGraphicsDefPtr def, size_t ii) + ATTRIBUTE_NONNULL(1); +int virDomainGraphicsListenSetType(virDomainGraphicsDefPtr def, size_t ii, int val) + ATTRIBUTE_NONNULL(1); +const char *virDomainGraphicsListenGetAddress(virDomainGraphicsDefPtr def, + size_t ii) + ATTRIBUTE_NONNULL(1); +int virDomainGraphicsListenSetAddress(virDomainGraphicsDefPtr def, + size_t ii, const char *address, + int len, bool setType) + ATTRIBUTE_NONNULL(1); +const char *virDomainGraphicsListenGetNetwork(virDomainGraphicsDefPtr def, + size_t ii) + ATTRIBUTE_NONNULL(1); +int virDomainGraphicsListenSetNetwork(virDomainGraphicsDefPtr def, + size_t ii, const char *network, int len) + ATTRIBUTE_NONNULL(1); + int virDomainNetGetActualType(virDomainNetDefPtr iface); char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface); char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface); @@ -1647,6 +1683,7 @@ VIR_ENUM_DECL(virDomainHostdevSubsys) VIR_ENUM_DECL(virDomainInput) VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) +VIR_ENUM_DECL(virDomainGraphicsListen) VIR_ENUM_DECL(virDomainGraphicsAuthConnected) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a406100..8b4d582 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -299,6 +299,12 @@ virDomainGetRootFilesystem; virDomainGraphicsAuthConnectedTypeFromString; virDomainGraphicsAuthConnectedTypeToString; virDomainGraphicsDefFree; +virDomainGraphicsListenGetAddress; +virDomainGraphicsListenGetNetwork; +virDomainGraphicsListenGetType; +virDomainGraphicsListenSetAddress; +virDomainGraphicsListenSetNetwork; +virDomainGraphicsListenSetType; virDomainGraphicsSpiceChannelModeTypeFromString; virDomainGraphicsSpiceChannelModeTypeToString; virDomainGraphicsSpiceChannelNameTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 35d6b1e..740468f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4127,14 +4127,18 @@ qemuBuildCommandLine(virConnectPtr conn, def->graphics[0]->data.vnc.socket); } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_VNC_COLON)) { - const char *addr = def->graphics[0]->data.vnc.listenAddr ? - def->graphics[0]->data.vnc.listenAddr : - driver->vncListen; - bool escapeAddr = strchr(addr, ':') != NULL; + const char *listenAddr = NULL; + bool escapeAddr; + + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + if (!listenAddr) + listenAddr = driver->vncListen; + + escapeAddr = strchr(listenAddr, ':') != NULL; if (escapeAddr) - virBufferAsprintf(&opt, "[%s]", addr); + virBufferAsprintf(&opt, "[%s]", listenAddr); else - virBufferAdd(&opt, addr, -1); + virBufferAdd(&opt, listenAddr, -1); virBufferAsprintf(&opt, ":%d", def->graphics[0]->data.vnc.port - 5900); @@ -4221,6 +4225,7 @@ qemuBuildCommandLine(virConnectPtr conn, } else if ((def->ngraphics == 1) && def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { virBuffer opt = VIR_BUFFER_INITIALIZER; + const char *listenAddr = NULL; if (!qemuCapsGet(qemuCaps, QEMU_CAPS_SPICE)) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -4233,10 +4238,11 @@ qemuBuildCommandLine(virConnectPtr conn, if (driver->spiceTLS && def->graphics[0]->data.spice.tlsPort != -1) virBufferAsprintf(&opt, ",tls-port=%u", def->graphics[0]->data.spice.tlsPort); - if (def->graphics[0]->data.spice.listenAddr) - virBufferAsprintf(&opt, ",addr=%s", def->graphics[0]->data.spice.listenAddr); - else if (driver->spiceListen) - virBufferAsprintf(&opt, ",addr=%s", driver->spiceListen); + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + if (!listenAddr) + listenAddr = driver->spiceListen; + if (listenAddr) + virBufferAsprintf(&opt, ",addr=%s", listenAddr); /* In the password case we set it via monitor command, to avoid * making it visible on CLI, so there's no use of password=XXX @@ -5978,7 +5984,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, /* -vnc unix:/some/big/path */ vnc->data.vnc.socket = strdup(val + 5); if (!vnc->data.vnc.socket) { - VIR_FREE(vnc); + virDomainGraphicsDefFree(vnc); goto no_memory; } } else { @@ -5993,24 +5999,26 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, sep = "]:"; tmp = strstr(val, sep); if (!tmp) { - VIR_FREE(vnc); + virDomainGraphicsDefFree(vnc); qemuReportError(VIR_ERR_INTERNAL_ERROR, _("missing VNC port number in '%s'"), val); goto error; } if (virStrToLong_i(tmp+strlen(sep), &opts, 10, &vnc->data.vnc.port) < 0) { - VIR_FREE(vnc); + virDomainGraphicsDefFree(vnc); qemuReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse VNC port '%s'"), tmp+1); goto error; } if (val[0] == '[') - vnc->data.vnc.listenAddr = strndup(val+1, tmp-(val+1)); + virDomainGraphicsListenSetAddress(vnc, 0, + val+1, tmp-(val+1), true); else - vnc->data.vnc.listenAddr = strndup(val, tmp-val); - if (!vnc->data.vnc.listenAddr) { - VIR_FREE(vnc); + virDomainGraphicsListenSetAddress(vnc, 0, + val, tmp-val, true); + if (!virDomainGraphicsListenGetAddress(vnc, 0)) { + virDomainGraphicsDefFree(vnc); goto no_memory; } vnc->data.vnc.port += 5900; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9746cb3..279f591 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1052,6 +1052,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, virDomainGraphicsDefPtr dev) { virDomainGraphicsDefPtr olddev = qemuDomainFindGraphics(vm, dev); + const char *oldListenAddr, *newListenAddr; int ret = -1; if (!olddev) { @@ -1060,6 +1061,9 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, return -1; } + oldListenAddr = virDomainGraphicsListenGetAddress(olddev, 0); + newListenAddr = virDomainGraphicsListenGetAddress(dev, 0); + switch (dev->type) { case VIR_DOMAIN_GRAPHICS_TYPE_VNC: if ((olddev->data.vnc.autoport != dev->data.vnc.autoport) || @@ -1069,8 +1073,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, _("cannot change port settings on vnc graphics")); return -1; } - if (STRNEQ_NULLABLE(olddev->data.vnc.listenAddr, - dev->data.vnc.listenAddr)) { + if (STRNEQ_NULLABLE(oldListenAddr,newListenAddr)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot change listen address setting on vnc graphics")); return -1; @@ -1118,8 +1121,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, _("cannot change port settings on spice graphics")); return -1; } - if (STRNEQ_NULLABLE(olddev->data.spice.listenAddr, - dev->data.spice.listenAddr)) { + if (STRNEQ_NULLABLE(oldListenAddr, newListenAddr)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot change listen address setting on spice graphics")); return -1; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 156dcf4..2843189 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -210,7 +210,7 @@ qemuMigrationCookieGraphicsAlloc(struct qemud_driver *driver, mig->type = def->type; if (mig->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { mig->port = def->data.vnc.port; - listenAddr = def->data.vnc.listenAddr; + listenAddr = virDomainGraphicsListenGetAddress(def, 0); if (!listenAddr) listenAddr = driver->vncListen; @@ -223,7 +223,7 @@ qemuMigrationCookieGraphicsAlloc(struct qemud_driver *driver, mig->tlsPort = def->data.spice.tlsPort; else mig->tlsPort = -1; - listenAddr = def->data.spice.listenAddr; + listenAddr = virDomainGraphicsListenGetAddress(def, 0); if (!listenAddr) listenAddr = driver->spiceListen; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index ee0720a..a7d354e 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -2501,7 +2501,8 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { if (netAddressUtf16) { VBOX_UTF16_TO_UTF8(netAddressUtf16, &netAddressUtf8); if (STRNEQ(netAddressUtf8, "")) - def->graphics[def->ngraphics]->data.rdp.listenAddr = strdup(netAddressUtf8); + virDomainGraphicsListenSetAddress(def->graphics[def->ngraphics], 0, + netAddressUtf8, -1, true); VBOX_UTF16_FREE(netAddressUtf16); VBOX_UTF8_FREE(netAddressUtf8); } @@ -4532,6 +4533,9 @@ vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) machine->vtbl->GetVRDEServer(machine, &VRDxServer); #endif /* VBOX_API_VERSION >= 4000 */ if (VRDxServer) { + const char *listenAddr + = virDomainGraphicsListenGetAddress(def->graphics[i], 0); + VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE); VIR_DEBUG("VRDP Support turned ON."); @@ -4576,14 +4580,13 @@ vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) VIR_DEBUG("VRDP set to allow multiple connection"); } - if (def->graphics[i]->data.rdp.listenAddr) { + if (listenAddr) { #if VBOX_API_VERSION >= 4000 PRUnichar *netAddressKey = NULL; #endif PRUnichar *netAddressUtf16 = NULL; - VBOX_UTF8_TO_UTF16(def->graphics[i]->data.rdp.listenAddr, - &netAddressUtf16); + VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); #if VBOX_API_VERSION < 4000 VRDxServer->vtbl->SetNetAddress(VRDxServer, netAddressUtf16); @@ -4594,7 +4597,7 @@ vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) VBOX_UTF16_FREE(netAddressKey); #endif /* VBOX_API_VERSION >= 4000 */ VIR_DEBUG("VRDP listen address is set to: %s", - def->graphics[i]->data.rdp.listenAddr); + listenAddr); VBOX_UTF16_FREE(netAddressUtf16); } diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index b37f03b..08c2716 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -1755,6 +1755,7 @@ virVMXParseVNC(virConfPtr conf, virDomainGraphicsDefPtr *def) { bool enabled = false; long long port = 0; + char *listenAddr = NULL; if (def == NULL || *def != NULL) { VMX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); @@ -1780,7 +1781,7 @@ virVMXParseVNC(virConfPtr conf, virDomainGraphicsDefPtr *def) if (virVMXGetConfigLong(conf, "RemoteDisplay.vnc.port", &port, -1, true) < 0 || virVMXGetConfigString(conf, "RemoteDisplay.vnc.ip", - &(*def)->data.vnc.listenAddr, true) < 0 || + &listenAddr, true) < 0 || virVMXGetConfigString(conf, "RemoteDisplay.vnc.keymap", &(*def)->data.vnc.keymap, true) < 0 || virVMXGetConfigString(conf, "RemoteDisplay.vnc.password", @@ -1788,6 +1789,12 @@ virVMXParseVNC(virConfPtr conf, virDomainGraphicsDefPtr *def) goto failure; } + if (listenAddr) { + if (virDomainGraphicsListenSetAddress(*def, 0, listenAddr, -1, true) < 0) + goto failure; + VIR_FREE(listenAddr); + } + if (port < 0) { VIR_WARN("VNC is enabled but VMX entry 'RemoteDisplay.vnc.port' " "is missing, the VNC port is unknown"); @@ -1806,6 +1813,7 @@ virVMXParseVNC(virConfPtr conf, virDomainGraphicsDefPtr *def) return 0; failure: + VIR_FREE(listenAddr); virDomainGraphicsDefFree(*def); *def = NULL; @@ -3196,6 +3204,8 @@ virVMXFormatConfig(virVMXContext *ctx, virCapsPtr caps, virDomainDefPtr def, int virVMXFormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer) { + const char *listenAddr; + if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { VMX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); return -1; @@ -3216,9 +3226,9 @@ virVMXFormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer) def->data.vnc.port); } - if (def->data.vnc.listenAddr != NULL) { + if ((listenAddr = virDomainGraphicsListenGetAddress(def, 0))) { virBufferAsprintf(buffer, "RemoteDisplay.vnc.ip = \"%s\"\n", - def->data.vnc.listenAddr); + listenAddr); } if (def->data.vnc.keymap != NULL) { diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 4245a64..1f5be5f 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -750,8 +750,8 @@ xenParseSxprGraphicsOld(virDomainDefPtr def, graphics->data.vnc.port = port; if (listenAddr && - !(graphics->data.vnc.listenAddr = strdup(listenAddr))) - goto no_memory; + virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, -1, true)) + goto error; if (vncPasswd && !(graphics->data.vnc.auth.passwd = strdup(vncPasswd))) @@ -794,6 +794,7 @@ xenParseSxprGraphicsOld(virDomainDefPtr def, no_memory: virReportOOMError(); +error: virDomainGraphicsDefFree(graphics); return -1; } @@ -866,8 +867,8 @@ xenParseSxprGraphicsNew(virDomainDefPtr def, graphics->data.vnc.port = port; if (listenAddr && - !(graphics->data.vnc.listenAddr = strdup(listenAddr))) - goto no_memory; + virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, -1, true)) + goto error; if (vncPasswd && !(graphics->data.vnc.auth.passwd = strdup(vncPasswd))) @@ -1437,6 +1438,8 @@ static int xenFormatSxprGraphicsNew(virDomainGraphicsDefPtr def, virBufferPtr buf) { + const char *listenAddr; + if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL && def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { XENXS_ERROR(VIR_ERR_INTERNAL_ERROR, @@ -1463,8 +1466,9 @@ xenFormatSxprGraphicsNew(virDomainGraphicsDefPtr def, virBufferAsprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900); } - if (def->data.vnc.listenAddr) - virBufferAsprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); + listenAddr = virDomainGraphicsListenGetAddress(def, 0); + if (listenAddr) + virBufferAsprintf(buf, "(vnclisten '%s')", listenAddr); if (def->data.vnc.auth.passwd) virBufferAsprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd); if (def->data.vnc.keymap) @@ -1482,6 +1486,8 @@ xenFormatSxprGraphicsOld(virDomainGraphicsDefPtr def, virBufferPtr buf, int xendConfigVersion) { + const char *listenAddr; + if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL && def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { XENXS_ERROR(VIR_ERR_INTERNAL_ERROR, @@ -1506,8 +1512,9 @@ xenFormatSxprGraphicsOld(virDomainGraphicsDefPtr def, virBufferAsprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900); } - if (def->data.vnc.listenAddr) - virBufferAsprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); + listenAddr = virDomainGraphicsListenGetAddress(def, 0); + if (listenAddr) + virBufferAsprintf(buf, "(vnclisten '%s')", listenAddr); if (def->data.vnc.auth.passwd) virBufferAsprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd); if (def->data.vnc.keymap) diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index 0ad2179..cb31226 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -213,6 +213,7 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, int vmlocaltime = 0; unsigned long count; char *script = NULL; + char *listenAddr = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -860,8 +861,16 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, goto cleanup; graphics->data.vnc.port = (int)vncdisplay + 5900; } - if (xenXMConfigCopyStringOpt(conf, "vnclisten", &graphics->data.vnc.listenAddr) < 0) + + if (xenXMConfigCopyStringOpt(conf, "vnclisten", &listenAddr) < 0) goto cleanup; + if (listenAddr && + virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, + -1, true) < 0) { + goto cleanup; + } + VIR_FREE(listenAddr); + if (xenXMConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.auth.passwd) < 0) goto cleanup; if (xenXMConfigCopyStringOpt(conf, "keymap", &graphics->data.vnc.keymap) < 0) @@ -931,8 +940,9 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, if (STREQ(key + 10, "1")) graphics->data.vnc.autoport = 1; } else if (STRPREFIX(key, "vnclisten=")) { - if (!(graphics->data.vnc.listenAddr = strdup(key + 10))) - goto no_memory; + if (virDomainGraphicsListenSetAddress(graphics, 0, key+10, + -1, true) < 0) + goto cleanup; } else if (STRPREFIX(key, "vncpasswd=")) { if (!(graphics->data.vnc.auth.passwd = strdup(key + 10))) goto no_memory; @@ -1067,6 +1077,7 @@ cleanup: virDomainDiskDefFree(disk); virDomainDefFree(def); VIR_FREE(script); + VIR_FREE(listenAddr); return NULL; } @@ -1646,6 +1657,8 @@ virConfPtr xenFormatXM(virConnectPtr conn, def->graphics[0]->data.sdl.xauth) < 0) goto no_memory; } else { + const char *listenAddr; + if (xenXMConfigSetInt(conf, "sdl", 0) < 0) goto no_memory; if (xenXMConfigSetInt(conf, "vnc", 1) < 0) @@ -1657,9 +1670,9 @@ virConfPtr xenFormatXM(virConnectPtr conn, xenXMConfigSetInt(conf, "vncdisplay", def->graphics[0]->data.vnc.port - 5900) < 0) goto no_memory; - if (def->graphics[0]->data.vnc.listenAddr && - xenXMConfigSetString(conf, "vnclisten", - def->graphics[0]->data.vnc.listenAddr) < 0) + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + if (listenAddr && + xenXMConfigSetString(conf, "vnclisten", listenAddr) < 0) goto no_memory; if (def->graphics[0]->data.vnc.auth.passwd && xenXMConfigSetString(conf, "vncpasswd", @@ -1683,15 +1696,17 @@ virConfPtr xenFormatXM(virConnectPtr conn, virBufferAsprintf(&buf, ",xauthority=%s", def->graphics[0]->data.sdl.xauth); } else { + const char *listenAddr + = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + virBufferAddLit(&buf, "type=vnc"); virBufferAsprintf(&buf, ",vncunused=%d", def->graphics[0]->data.vnc.autoport ? 1 : 0); if (!def->graphics[0]->data.vnc.autoport) virBufferAsprintf(&buf, ",vncdisplay=%d", def->graphics[0]->data.vnc.port - 5900); - if (def->graphics[0]->data.vnc.listenAddr) - virBufferAsprintf(&buf, ",vnclisten=%s", - def->graphics[0]->data.vnc.listenAddr); + if (listenAddr) + virBufferAsprintf(&buf, ",vnclisten=%s", listenAddr); if (def->graphics[0]->data.vnc.auth.passwd) virBufferAsprintf(&buf, ",vncpasswd=%s", def->graphics[0]->data.vnc.auth.passwd); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network.xml new file mode 100644 index 0000000..a49e5d3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5903' autoport='no'> + <listen type='network' network='Bobsnetwork'/> + </graphics> + <video> + <model type='cirrus' vram='9216' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network2.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network2.xml new file mode 100644 index 0000000..1c55eff --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-listen-network2.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' listen='1.2.3.4' autoport='yes'> + <listen type='address' address='1.2.3.4'/> + <listen type='network' network='Bobsnetwork'/> + </graphics> + <video> + <model type='cirrus' vram='9216' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml index 64a6890..d92211c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml @@ -22,6 +22,7 @@ <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> <image compression='auto_glz'/> <jpeg compression='auto'/> <zlib compression='auto'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml index a38550c..65fc2d9 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml @@ -22,6 +22,7 @@ <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> <channel name='main' mode='secure'/> <channel name='inputs' mode='insecure'/> </graphics> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml index 79780c6..5313b3a 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml @@ -22,6 +22,7 @@ <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> <channel name='main' mode='secure'/> <channel name='inputs' mode='insecure'/> <image compression='auto_glz'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-sasl.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-sasl.xml index eb6be7d..1f6c115 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-sasl.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-sasl.xml @@ -21,7 +21,9 @@ </disk> <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> <video> <model type='cirrus' vram='9216' heads='1'/> </video> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-tls.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-tls.xml index eb6be7d..1f6c115 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-tls.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-tls.xml @@ -21,7 +21,9 @@ </disk> <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> <video> <model type='cirrus' vram='9216' heads='1'/> </video> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml index 6304104..f93facc 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml @@ -21,7 +21,9 @@ </disk> <controller type='ide' index='0'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' autoport='no' listen='2001:1:2:3:4:5:1234:1234'/> + <graphics type='vnc' port='5903' autoport='no' listen='2001:1:2:3:4:5:1234:1234'> + <listen type='address' address='2001:1:2:3:4:5:1234:1234'/> + </graphics> <video> <model type='cirrus' vram='9216' heads='1'/> </video> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml b/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml index 8a5fcd7..fb42c95 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml @@ -21,7 +21,9 @@ </disk> <controller type='ide' index='0'/> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> <video> <model type='xen' vram='4096' heads='1'/> </video> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-listen-network2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-listen-network2.xml new file mode 100644 index 0000000..d369b89 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-listen-network2.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='1.2.3.4'> + <listen type='address' address='1.2.3.4'/> + <listen type='network' network='Bobsnetwork'/> + </graphics> + <video> + <model type='cirrus' vram='9216' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index f1900c5..44737d4 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -139,6 +139,7 @@ mymain(void) DO_TEST("disk-drive-cache-v1-wb"); DO_TEST("disk-drive-cache-v1-none"); DO_TEST("disk-scsi-device"); + DO_TEST("graphics-listen-network"); DO_TEST("graphics-vnc"); DO_TEST("graphics-vnc-sasl"); DO_TEST("graphics-vnc-tls"); @@ -194,6 +195,7 @@ mymain(void) DO_TEST_DIFFERENT("disk-scsi-device-auto"); DO_TEST_DIFFERENT("console-virtio"); DO_TEST_DIFFERENT("serial-target-port-auto"); + DO_TEST_DIFFERENT("graphics-listen-network2"); virCapabilitiesFree(driver.caps); diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new-vncdisplay.xml b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new-vncdisplay.xml index 0914bc9..f5e7843 100644 --- a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new-vncdisplay.xml +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new-vncdisplay.xml @@ -24,6 +24,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='5925' autoport='no' listen='0.0.0.0' keymap='ja'/> + <graphics type='vnc' port='5925' autoport='no' listen='0.0.0.0' keymap='ja'> + <listen type='address' address='0.0.0.0'/> + </graphics> </devices> </domain> diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml index 0657fba..70f44fc 100644 --- a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml @@ -24,6 +24,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'/> + <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'> + <listen type='address' address='0.0.0.0'/> + </graphics> </devices> </domain> diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml index 0657fba..70f44fc 100644 --- a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml @@ -24,6 +24,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'/> + <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'> + <listen type='address' address='0.0.0.0'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-escape-paths.xml b/tests/xmconfigdata/test-escape-paths.xml index 9eaf90c..05a4860 100644 --- a/tests/xmconfigdata/test-escape-paths.xml +++ b/tests/xmconfigdata/test-escape-paths.xml @@ -43,7 +43,9 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> <sound model='sb16'/> <sound model='es1370'/> </devices> diff --git a/tests/xmconfigdata/test-fullvirt-force-hpet.xml b/tests/xmconfigdata/test-fullvirt-force-hpet.xml index a662b97..20c6d94 100644 --- a/tests/xmconfigdata/test-fullvirt-force-hpet.xml +++ b/tests/xmconfigdata/test-fullvirt-force-hpet.xml @@ -40,6 +40,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-force-nohpet.xml b/tests/xmconfigdata/test-fullvirt-force-nohpet.xml index bcd9af6..4afe38a 100644 --- a/tests/xmconfigdata/test-fullvirt-force-nohpet.xml +++ b/tests/xmconfigdata/test-fullvirt-force-nohpet.xml @@ -40,6 +40,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-localtime.xml b/tests/xmconfigdata/test-fullvirt-localtime.xml index be4f119..6826cde 100644 --- a/tests/xmconfigdata/test-fullvirt-localtime.xml +++ b/tests/xmconfigdata/test-fullvirt-localtime.xml @@ -38,6 +38,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-net-ioemu.xml b/tests/xmconfigdata/test-fullvirt-net-ioemu.xml index 4a52a45..a8dfaf5 100644 --- a/tests/xmconfigdata/test-fullvirt-net-ioemu.xml +++ b/tests/xmconfigdata/test-fullvirt-net-ioemu.xml @@ -38,6 +38,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-net-netfront.xml b/tests/xmconfigdata/test-fullvirt-net-netfront.xml index efaf5b4..2b92033 100644 --- a/tests/xmconfigdata/test-fullvirt-net-netfront.xml +++ b/tests/xmconfigdata/test-fullvirt-net-netfront.xml @@ -38,6 +38,8 @@ <model type='netfront'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml index 4a52a45..a8dfaf5 100644 --- a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml +++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml @@ -38,6 +38,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml index 97965d5..5a7ebde 100644 --- a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml +++ b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml @@ -38,6 +38,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml index 22c6013..2c36bd5 100644 --- a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml +++ b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml @@ -43,6 +43,8 @@ <target port='0'/> </parallel> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml index be5f8ee..5dcb3ce 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml @@ -50,6 +50,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml b/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml index 03549f0..539aeae 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml @@ -46,6 +46,8 @@ <target type='serial' port='1'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-file.xml b/tests/xmconfigdata/test-fullvirt-serial-file.xml index 3e5aaf9..d9dfc74 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-file.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-file.xml @@ -46,6 +46,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-null.xml b/tests/xmconfigdata/test-fullvirt-serial-null.xml index 2fd9bf1..d7fd23d 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-null.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-null.xml @@ -44,6 +44,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml index 9292c25..fdfb344 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml @@ -46,6 +46,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-pty.xml b/tests/xmconfigdata/test-fullvirt-serial-pty.xml index c4b189f..0afe4e9 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-pty.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-pty.xml @@ -44,6 +44,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml index 3852977..91f4c1e 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml @@ -44,6 +44,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml index 4acdfc8..64d8183 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml @@ -48,6 +48,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml index 48d6cb5..9307710 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml @@ -48,6 +48,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-udp.xml b/tests/xmconfigdata/test-fullvirt-serial-udp.xml index 8c11b45..16abde3 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-udp.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-udp.xml @@ -48,6 +48,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-serial-unix.xml b/tests/xmconfigdata/test-fullvirt-serial-unix.xml index 3071c23..3ba9fc4 100644 --- a/tests/xmconfigdata/test-fullvirt-serial-unix.xml +++ b/tests/xmconfigdata/test-fullvirt-serial-unix.xml @@ -46,6 +46,8 @@ <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-sound.xml b/tests/xmconfigdata/test-fullvirt-sound.xml index f142bfc..6d82e38 100644 --- a/tests/xmconfigdata/test-fullvirt-sound.xml +++ b/tests/xmconfigdata/test-fullvirt-sound.xml @@ -38,7 +38,9 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> <sound model='sb16'/> <sound model='es1370'/> </devices> diff --git a/tests/xmconfigdata/test-fullvirt-usbmouse.xml b/tests/xmconfigdata/test-fullvirt-usbmouse.xml index c96e8f9..709f084 100644 --- a/tests/xmconfigdata/test-fullvirt-usbmouse.xml +++ b/tests/xmconfigdata/test-fullvirt-usbmouse.xml @@ -39,6 +39,8 @@ </interface> <input type='mouse' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml b/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml index 9370172..5eeb9c0 100644 --- a/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml +++ b/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml @@ -38,6 +38,8 @@ </interface> <input type='tablet'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-usbtablet.xml b/tests/xmconfigdata/test-fullvirt-usbtablet.xml index b7bdfd0..b4f309e 100644 --- a/tests/xmconfigdata/test-fullvirt-usbtablet.xml +++ b/tests/xmconfigdata/test-fullvirt-usbtablet.xml @@ -39,6 +39,8 @@ </interface> <input type='tablet' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-fullvirt-utc.xml b/tests/xmconfigdata/test-fullvirt-utc.xml index 4a52a45..a8dfaf5 100644 --- a/tests/xmconfigdata/test-fullvirt-utc.xml +++ b/tests/xmconfigdata/test-fullvirt-utc.xml @@ -38,6 +38,8 @@ <model type='e1000'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-net-e1000.xml b/tests/xmconfigdata/test-paravirt-net-e1000.xml index d709e69..9e6505e 100644 --- a/tests/xmconfigdata/test-paravirt-net-e1000.xml +++ b/tests/xmconfigdata/test-paravirt-net-e1000.xml @@ -28,6 +28,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-net-vifname.xml b/tests/xmconfigdata/test-paravirt-net-vifname.xml index b6c4739..22c908f 100644 --- a/tests/xmconfigdata/test-paravirt-net-vifname.xml +++ b/tests/xmconfigdata/test-paravirt-net-vifname.xml @@ -29,6 +29,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-new-pvfb-vncdisplay.xml b/tests/xmconfigdata/test-paravirt-new-pvfb-vncdisplay.xml index 39325ea..2c1d50e 100644 --- a/tests/xmconfigdata/test-paravirt-new-pvfb-vncdisplay.xml +++ b/tests/xmconfigdata/test-paravirt-new-pvfb-vncdisplay.xml @@ -27,6 +27,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='5925' autoport='no' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='5925' autoport='no' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-new-pvfb.xml b/tests/xmconfigdata/test-paravirt-new-pvfb.xml index 40c79cb..9cbaec0 100644 --- a/tests/xmconfigdata/test-paravirt-new-pvfb.xml +++ b/tests/xmconfigdata/test-paravirt-new-pvfb.xml @@ -27,6 +27,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-old-pvfb-vncdisplay.xml b/tests/xmconfigdata/test-paravirt-old-pvfb-vncdisplay.xml index 39325ea..2c1d50e 100644 --- a/tests/xmconfigdata/test-paravirt-old-pvfb-vncdisplay.xml +++ b/tests/xmconfigdata/test-paravirt-old-pvfb-vncdisplay.xml @@ -27,6 +27,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='5925' autoport='no' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='5925' autoport='no' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> diff --git a/tests/xmconfigdata/test-paravirt-old-pvfb.xml b/tests/xmconfigdata/test-paravirt-old-pvfb.xml index 40c79cb..9cbaec0 100644 --- a/tests/xmconfigdata/test-paravirt-old-pvfb.xml +++ b/tests/xmconfigdata/test-paravirt-old-pvfb.xml @@ -27,6 +27,8 @@ <target type='xen' port='0'/> </console> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> </devices> </domain> -- 1.7.3.4

On 07/28/2011 12:11 AM, Laine Stump wrote:
Once it's plugged in, the<listen> element will be an optional replacement for the "listen" attribute that graphics elements already have. If the<listen> element is type='address', it will have an attribute called 'address' which will contain an IP address or dns name that the guest's display server should listen on. If, however, type='network', the<listen> element should have an attribute called 'network' that will be set to the name of a network configuration to get the IP address from.
I think we're there. Thanks for putting up with the review churn.
+++ b/docs/formatdomain.html.in @@ -2046,6 +2046,12 @@ qemu-kvm -net nic,model=? /dev/null <graphics type='vnc' port='5904'/>
It looks fishy to have one...
<graphics type='rdp' autoport='yes' multiUser='yes' /> <graphics type='desktop' fullscreen='yes'/> +<graphics type='vnc'> +<listen type='address' address='1.2.3.4'/> +</graphics>
...and then a second type='vnc' description (do we support multiple vnc graphics adapters on any existing hypervisor?). How about consolidating this part of the example into just: <graphics type='vnc' port='5904'> <listen type='address' address='1.2.3.4'/> </graphics>
+<dt><code>address</code></dt> +<dd>if<code>type='address'</code>, the<code>address</code> + attribute will contain either an IP address or hostname (which + will be resolved to an IP address via a DNS query) to listen + on. In the "live" XML of a running domain, this attribute be
s/be/will be/ ACK with those nits fixed, no v5 needed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 07/28/2011 01:09 PM, Eric Blake wrote:
On 07/28/2011 12:11 AM, Laine Stump wrote:
Once it's plugged in, the<listen> element will be an optional replacement for the "listen" attribute that graphics elements already have. If the<listen> element is type='address', it will have an attribute called 'address' which will contain an IP address or dns name that the guest's display server should listen on. If, however, type='network', the<listen> element should have an attribute called 'network' that will be set to the name of a network configuration to get the IP address from.
I think we're there. Thanks for putting up with the review churn.
+++ b/docs/formatdomain.html.in @@ -2046,6 +2046,12 @@ qemu-kvm -net nic,model=? /dev/null <graphics type='vnc' port='5904'/>
It looks fishy to have one...
<graphics type='rdp' autoport='yes' multiUser='yes' /> <graphics type='desktop' fullscreen='yes'/> +<graphics type='vnc'> +<listen type='address' address='1.2.3.4'/> +</graphics>
...and then a second type='vnc' description (do we support multiple vnc graphics adapters on any existing hypervisor?). How about consolidating this part of the example into just:
<graphics type='vnc' port='5904'> <listen type='address' address='1.2.3.4'/> </graphics>
Good point. When I added the examples I was only thinking about putting in things that would demonstrate the syntax; I didn't think to consider if it was actually a practical setup.
+<dt><code>address</code></dt> +<dd>if<code>type='address'</code>, the<code>address</code> + attribute will contain either an IP address or hostname (which + will be resolved to an IP address via a DNS query) to listen + on. In the "live" XML of a running domain, this attribute be
s/be/will be/
ACK with those nits fixed, no v5 needed.
Pushed (!!) Thanks!

On Thu, Jul 28, 2011 at 11:09:40AM -0600, Eric Blake wrote:
On 07/28/2011 12:11 AM, Laine Stump wrote:
Once it's plugged in, the<listen> element will be an optional replacement for the "listen" attribute that graphics elements already have. If the<listen> element is type='address', it will have an attribute called 'address' which will contain an IP address or dns name that the guest's display server should listen on. If, however, type='network', the<listen> element should have an attribute called 'network' that will be set to the name of a network configuration to get the IP address from.
I think we're there. Thanks for putting up with the review churn.
+++ b/docs/formatdomain.html.in @@ -2046,6 +2046,12 @@ qemu-kvm -net nic,model=? /dev/null <graphics type='vnc' port='5904'/>
It looks fishy to have one...
<graphics type='rdp' autoport='yes' multiUser='yes' /> <graphics type='desktop' fullscreen='yes'/> +<graphics type='vnc'> +<listen type='address' address='1.2.3.4'/> +</graphics>
...and then a second type='vnc' description (do we support multiple vnc graphics adapters on any existing hypervisor?). How about consolidating this part of the example into just:
FYI with virtualbox you can have multiple <graphics> elements present, though they should be of different types. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

The domain XML now understands the <listen> subelement of its <graphics> element (including when listen type='network'), and the network driver has an internal API that will turn a network name into an IP address, so the final logical step is to put the glue into the qemu driver so that when it is starting up a domain, if it finds <listen type='network' network='xyz'/> in the XML, it will call the network driver to get an IPv4 address associated with network xyz, and tell qemu to listen for vnc (or spice) on that address rather than the default address (localhost). The motivation for this is that a large installation may want the guests' VNC servers listening on physical interfaces rather than localhost, so that users can connect directly from the outside; this requires sending qemu the appropriate IP address to listen on. But this address will of course be different for each host, and if a guest might be migrated around from one host to another, it's important that the guest's config not have any information embedded in it that is specific to one particular host. <listen type='network.../> can solve this problem in the following manner: 1) on each host, define a libvirt network of the same name, associated with the interface on that host that should be used for listening (for example, a simple macvtap network: <forward mode='bridge' dev='eth0'/>, or host bridge network: <forward mode='bridge'/> <bridge name='br0'/> 2) in the <graphics> element of each guest's domain xml, tell vnc to listen on the network name used in step 1: <graphics type='vnc' port='5922'> <listen type='network'network='example-net'/> </graphics> (all the above also applies for graphics type='spice'). --- src/qemu/qemu_command.c | 73 +++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_hotplug.c | 13 ++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 740468f..ee42f1d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4127,10 +4127,43 @@ qemuBuildCommandLine(virConnectPtr conn, def->graphics[0]->data.vnc.socket); } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_VNC_COLON)) { + const char *listenNetwork; const char *listenAddr = NULL; + char *netAddr = NULL; bool escapeAddr; + int ret; + + switch (virDomainGraphicsListenGetType(def->graphics[0], 0)) { + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS: + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + break; + + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK: + listenNetwork = virDomainGraphicsListenGetNetwork(def->graphics[0], 0); + if (!listenNetwork) + break; + ret = networkGetNetworkAddress(listenNetwork, &netAddr); + if (ret <= -2) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("network-based listen not possible, " + "network driver not present")); + goto error; + } + if (ret < 0) { + qemuReportError(VIR_ERR_XML_ERROR, + _("listen network '%s' had no usable address"), + listenNetwork); + goto error; + } + listenAddr = netAddr; + /* store the address we found in the <graphics> element so it will + * show up in status. */ + if (virDomainGraphicsListenSetAddress(def->graphics[0], 0, + listenAddr, -1, false) < 0) + goto error; + break; + } - listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); if (!listenAddr) listenAddr = driver->vncListen; @@ -4142,6 +4175,7 @@ qemuBuildCommandLine(virConnectPtr conn, virBufferAsprintf(&opt, ":%d", def->graphics[0]->data.vnc.port - 5900); + VIR_FREE(netAddr); } else { virBufferAsprintf(&opt, "%d", def->graphics[0]->data.vnc.port - 5900); @@ -4225,7 +4259,10 @@ qemuBuildCommandLine(virConnectPtr conn, } else if ((def->ngraphics == 1) && def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { virBuffer opt = VIR_BUFFER_INITIALIZER; + const char *listenNetwork; const char *listenAddr = NULL; + char *netAddr = NULL; + int ret; if (!qemuCapsGet(qemuCaps, QEMU_CAPS_SPICE)) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -4238,12 +4275,44 @@ qemuBuildCommandLine(virConnectPtr conn, if (driver->spiceTLS && def->graphics[0]->data.spice.tlsPort != -1) virBufferAsprintf(&opt, ",tls-port=%u", def->graphics[0]->data.spice.tlsPort); - listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + switch (virDomainGraphicsListenGetType(def->graphics[0], 0)) { + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS: + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + break; + + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK: + listenNetwork = virDomainGraphicsListenGetNetwork(def->graphics[0], 0); + if (!listenNetwork) + break; + ret = networkGetNetworkAddress(listenNetwork, &netAddr); + if (ret <= -2) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("network-based listen not possible, " + "network driver not present")); + goto error; + } + if (ret < 0) { + qemuReportError(VIR_ERR_XML_ERROR, + _("listen network '%s' had no usable address"), + listenNetwork); + goto error; + } + listenAddr = netAddr; + /* store the address we found in the <graphics> element so it will + * show up in status. */ + if (virDomainGraphicsListenSetAddress(def->graphics[0], 0, + listenAddr, -1, false) < 0) + goto error; + break; + } + if (!listenAddr) listenAddr = driver->spiceListen; if (listenAddr) virBufferAsprintf(&opt, ",addr=%s", listenAddr); + VIR_FREE(netAddr); + /* In the password case we set it via monitor command, to avoid * making it visible on CLI, so there's no use of password=XXX * in this bit of the code */ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 279f591..7dfbfcd 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1053,6 +1053,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, { virDomainGraphicsDefPtr olddev = qemuDomainFindGraphics(vm, dev); const char *oldListenAddr, *newListenAddr; + const char *oldListenNetwork, *newListenNetwork; int ret = -1; if (!olddev) { @@ -1063,6 +1064,8 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, oldListenAddr = virDomainGraphicsListenGetAddress(olddev, 0); newListenAddr = virDomainGraphicsListenGetAddress(dev, 0); + oldListenNetwork = virDomainGraphicsListenGetNetwork(olddev, 0); + newListenNetwork = virDomainGraphicsListenGetNetwork(dev, 0); switch (dev->type) { case VIR_DOMAIN_GRAPHICS_TYPE_VNC: @@ -1078,6 +1081,11 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, _("cannot change listen address setting on vnc graphics")); return -1; } + if (STRNEQ_NULLABLE(oldListenNetwork,newListenNetwork)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot change listen network setting on vnc graphics")); + return -1; + } if (STRNEQ_NULLABLE(olddev->data.vnc.keymap, dev->data.vnc.keymap)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot change keymap setting on vnc graphics")); @@ -1126,6 +1134,11 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, _("cannot change listen address setting on spice graphics")); return -1; } + if (STRNEQ_NULLABLE(oldListenNetwork,newListenNetwork)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot change listen network setting on vnc graphics")); + return -1; + } if (STRNEQ_NULLABLE(olddev->data.spice.keymap, dev->data.spice.keymap)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", -- 1.7.3.4

On 07/28/2011 12:11 AM, Laine Stump wrote:
The domain XML now understands the<listen> subelement of its <graphics> element (including when listen type='network'), and the network driver has an internal API that will turn a network name into an IP address, so the final logical step is to put the glue into the qemu driver so that when it is starting up a domain, if it finds <listen type='network' network='xyz'/> in the XML, it will call the network driver to get an IPv4 address associated with network xyz, and tell qemu to listen for vnc (or spice) on that address rather than the default address (localhost).
ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 07/28/2011 01:21 PM, Eric Blake wrote:
On 07/28/2011 12:11 AM, Laine Stump wrote:
The domain XML now understands the<listen> subelement of its <graphics> element (including when listen type='network'), and the network driver has an internal API that will turn a network name into an IP address, so the final logical step is to put the glue into the qemu driver so that when it is starting up a domain, if it finds <listen type='network' network='xyz'/> in the XML, it will call the network driver to get an IPv4 address associated with network xyz, and tell qemu to listen for vnc (or spice) on that address rather than the default address (localhost).
ACK.
Also Pushed. Thanks for all the review. Once again the final product is much better than the initial submission.

This failure was introduced by commit dacee3d, which removed listenAddr from the unions in virDomainGraphicsDef in favor of putting it in the address attribute of virDomainGraphicsListenDef. --- src/libxl/libxl_conf.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b74a4b1..09f3be8 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -651,6 +651,7 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { int port; + const char *listenAddr; switch (l_vfb->type) { case VIR_DOMAIN_GRAPHICS_TYPE_SDL: @@ -682,11 +683,11 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, } x_vfb->vncdisplay = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; - if (l_vfb->data.vnc.listenAddr) { + listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); + if (listenAddr) { /* libxl_device_vfb_init() does strdup("127.0.0.1") */ free(x_vfb->vnclisten); - if ((x_vfb->vnclisten = - strdup(l_vfb->data.vnc.listenAddr)) == NULL) { + if ((x_vfb->vnclisten = strdup(listenAddr)) == NULL) { virReportOOMError(); return -1; } -- 1.7.3.4

On 07/28/2011 12:41 PM, Laine Stump wrote:
This failure was introduced by commit dacee3d, which removed listenAddr from the unions in virDomainGraphicsDef in favor of putting it in the address attribute of virDomainGraphicsListenDef. --- src/libxl/libxl_conf.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 07/28/2011 02:49 PM, Eric Blake wrote:
On 07/28/2011 12:41 PM, Laine Stump wrote:
This failure was introduced by commit dacee3d, which removed listenAddr from the unions in virDomainGraphicsDef in favor of putting it in the address attribute of virDomainGraphicsListenDef. --- src/libxl/libxl_conf.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
ACK.
Pushed. "Sorry for the inconvenience."
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Laine Stump