On 27.06.2012 15:28, Daniel Veillard wrote:
On Wed, Jun 27, 2012 at 03:21:48PM +0200, Michal Privoznik wrote:
> On 24.06.2012 23:14, Doug Goldstein wrote:
>> v2:
>> - Refactored to use virBuffer
>> - Refactored to use virXPath wrappers
>> - Added support for tls-port and password for SPICE
>> - Added optional flag to disable SPICE password to the URI
>> - Added support for RDP
>> - Fixed code reviews
>>
>> Add a new 'domdisplay' command that provides a URI for VNC, SPICE and
>> RDP connections. Presently the 'vncdisplay' command provides you with
>> the port info that QEMU is listening on but there is no counterpart for
>> SPICE and RDP. Additionally this provides you with the bind address as
>> specified in the XML, which the existing 'vncdisplay' lacks. For SPICE
>> connections it supports secure and unsecure channels and optionally
>> providing the password for the SPICE channel.
>>
>> Signed-off-by: Doug Goldstein <cardoe(a)cardoe.com>
>> ---
>> tools/virsh.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> tools/virsh.pod | 6 ++
>> 2 files changed, 179 insertions(+), 0 deletions(-)
>>
>> diff --git a/tools/virsh.c b/tools/virsh.c
>> index 0354822..da80477 100644
>> --- a/tools/virsh.c
>> +++ b/tools/virsh.c
>> @@ -13827,6 +13827,178 @@ cmdSysinfo (vshControl *ctl, const vshCmd *cmd
ATTRIBUTE_UNUSED)
>> }
>>
>> /*
>> + * "display" command
>> + */
>
> In fact it's domdisplay command.
>
>> +static const vshCmdInfo info_domdisplay[] = {
>> + {"help", N_("domain display connection URI")},
>> + {"desc", N_("Output the IP address and port number for the
graphical display.")},
>> + {NULL, NULL}
>> +};
>> +
>> +static const vshCmdOptDef opts_domdisplay[] = {
>> + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or
uuid")},
>> + {"include-password", VSH_OT_BOOL, VSH_OFLAG_NONE,
N_("includes the password into the connection URI if available")},
>> + {NULL, 0, 0, NULL}
>> +};
>> +
>> +static bool
>> +cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
>> +{
>> + xmlDocPtr xml = NULL;
>> + xmlXPathContextPtr ctxt = NULL;
>> + virDomainPtr dom;
>> + virBuffer buf = VIR_BUFFER_INITIALIZER;
>> + bool ret = false;
>> + char *doc;
>> + char *xpath;
>> + char *listen_addr;
>> + int port, tls_port = 0;
>> + char *passwd = NULL;
>> + const char *scheme[] = { "vnc", "spice",
"rdp", NULL };
>> + int iter = 0;
>> + int tmp;
>> +
>> + if (!vshConnectionUsability(ctl, ctl->conn))
>> + return false;
>> +
>> + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
>> + return false;
>> +
>> + if (!virDomainIsActive(dom)) {
>> + vshError(ctl, _("Domain is not running"));
>> + goto cleanup;
>> + }
>> +
>> + doc = virDomainGetXMLDesc(dom, 0);
>> + if (!doc)
>> + goto cleanup;
>> +
>> + xml = virXMLParseStringCtxt(doc, _("(domain_definition)"),
&ctxt);
>> + VIR_FREE(doc);
>> + if (!xml)
>> + goto cleanup;
>> +
>> + /* Attempt to grab our display info */
>> + for (iter = 0; scheme[iter] != NULL; iter++) {
>> + /* Create our XPATH lookup for the current display's port */
>> + virAsprintf(&xpath,
"string(/domain/devices/graphics[@type='%s']"
>> + "/@port)", scheme[iter]);
>> + if (!xpath) {
>> + virReportOOMError();
>> + goto cleanup;
>> + }
>> +
>> + /* Attempt to get the port number for the current graphics scheme */
>> + tmp = virXPathInt(xpath, ctxt, &port);
>> + VIR_FREE(xpath);
>> +
>> + /* If there is no port number for this type, then jump to the next
>> + * scheme
>> + */
>> + if (tmp)
>> + continue;
>> +
>> + /* Create our XPATH lookup for the current display's address */
>> + virAsprintf(&xpath,
"string(/domain/devices/graphics[@type='%s']"
>> + "/@listen)", scheme[iter]);
>> + if (!xpath) {
>> + virReportOOMError();
>> + goto cleanup;
>> + }
>> +
>> + /* Attempt to get the listening addr if set for the current
>> + * graphics scheme
>> + */
>> + listen_addr = virXPathString(xpath, ctxt);
>> + VIR_FREE(xpath);
>> +
>
> Adding a blank line ^^
>
>> + /* Per scheme data mangling */
>> + if (STREQ(scheme[iter], "vnc")) {
>> + /* VNC protocol handlers take their port number as 'port' -
5900 */
>> + port -= 5900;
>> + } else if (STREQ(scheme[iter], "spice")) {
>> + /* Create our XPATH lookup for the SPICE TLS Port */
>> + virAsprintf(&xpath,
"string(/domain/devices/graphics[@type='%s']"
>> + "/@tlsPort)", scheme[iter]);
>> + if (!xpath) {
>> + virReportOOMError();
>> + goto cleanup;
>> + }
>> +
>> + /* Attempt to get the TLS port number for SPICE */
>> + tmp = virXPathInt(xpath, ctxt, &tls_port);
>> + VIR_FREE(xpath);
>> + if (tmp)
>> + tls_port = 0;
>> +
>> + if (vshCommandOptBool(cmd, "daemon")) {
>
> s/daemon/include-password/
>
>> + /* Create our XPATH lookup for the SPICE password */
>> + virAsprintf(&xpath,
"string(/domain/devices/graphics"
>> + "[@type='%s']/@passwd)",
scheme[iter]);
>> + if (!xpath) {
>> + virReportOOMError();
>> + goto cleanup;
>> + }
>> +
>> + /* Attempt to get the SPICE password */
>> + passwd = virXPathString(xpath, ctxt);
>> + VIR_FREE(xpath);
>> + }
>> + }
>> +
>> + /* Build up the full URI, starting with the scheme */
>> + virBufferAsprintf(&buf, "%s://", scheme[iter]);
>> +
>> + /* Then host name or IP */
>> + if (!listen_addr || STREQ((const char *)listen_addr,
"0.0.0.0"))
>> + virBufferAddLit(&buf, "localhost");
>> + else
>> + virBufferAsprintf(&buf, "%s", listen_addr);
>> +
>> + /* Clean up our memory */
>> + if (listen_addr)
>> + VIR_FREE(listen_addr);
>
> This check is redundant. free(NULL) is safe.
>
>> +
>> + /* Add the port */
>> + if (STREQ(scheme[iter], "spice"))
>> + virBufferAsprintf(&buf, "?port=%d", port);
>> + else
>> + virBufferAsprintf(&buf, ":%d", port);
>> +
>> + /* TLS Port */
>> + if (tls_port)
>> + virBufferAsprintf(&buf, "&tls-port=%d",
tls_port);
>> +
>> + /* Password */
>> + if (passwd) {
>> + virBufferAsprintf(&buf, "&password=%s", passwd);
>> + VIR_FREE(passwd);
>> + }
>> +
>> + /* Ensure we can print our URI */
>> + if (virBufferError(&buf)) {
>> + vshPrint(ctl, "%s", _("Failed to create display
URI"));
>> + goto cleanup;
>> + }
>> +
>> + /* Print out our full URI */
>> + output = virBufferContentAndReset(&buf);
>> + vshPrint(ctl, "%s", output);
>> + VIR_FREE(output);
>> +
>> + /* We got what we came for so return successfully */
>> + ret = true;
>> + break;
>> + }
>> +
>> +cleanup:
>> + xmlXPathFreeContext(ctxt);
>> + xmlFreeDoc(xml);
>> + virDomainFree(dom);
>> + return ret;
>> +}
>> +
>> +/*
>> * "vncdisplay" command
>> */
>> static const vshCmdInfo info_vncdisplay[] = {
>> @@ -17974,6 +18146,7 @@ static const vshCmdDef domManagementCmds[] = {
>> {"detach-disk", cmdDetachDisk, opts_detach_disk, info_detach_disk,
0},
>> {"detach-interface", cmdDetachInterface, opts_detach_interface,
>> info_detach_interface, 0},
>> + {"domdisplay", cmdDomDisplay, opts_domdisplay, info_domdisplay,
0},
>> {"domid", cmdDomid, opts_domid, info_domid, 0},
>> {"domif-setlink", cmdDomIfSetLink, opts_domif_setlink,
info_domif_setlink, 0},
>> {"domiftune", cmdDomIftune, opts_domiftune, info_domiftune, 0},
>> diff --git a/tools/virsh.pod b/tools/virsh.pod
>> index f83a29d..558105f 100644
>> --- a/tools/virsh.pod
>> +++ b/tools/virsh.pod
>> @@ -820,6 +820,12 @@ I<size> is a scaled integer (see B<NOTES> above)
which defaults to KiB
>> "B" to get bytes (note that for historical reasons, this differs from
>> B<vol-resize> which defaults to bytes without a suffix).
>>
>> +=item B<domdisplay> I<domain-id> [I<--include-password>]
>> +
>> +Output a URI which can be used to connect to the graphical display of the
>> +domain via VNC, SPICE or RDP. If I<--include-password> is specified, the
>> +SPICE channel password will be included in the URI.
>> +
>> =item B<dominfo> I<domain-id>
>>
>> Returns basic information about the domain.
>>
>
> Otherwise looking good. ACK. I would pushed this but we are in freeze
> phase. On the other hand - v1 was sent before freeze. Combined with fact
> that number of patches sent into the list has fallen down I guess we can
> push this in. But I'd like to hear a second opinion.
it only touches virsh, so the risks are limited. And overall a new
command is really low risk too, so ACK, let's push it now.
I will probably make the rc2 in 12hours if you could push before fine
:-)
Daniel
Okay, pushed now. Thanks.
Michal