[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] virsh: Add domdisplay command for VNC and SPICE



Add a new 'domdisplay' command that provides a URI for both VNC and
SPICE connections. Presently the 'vncdisplay' command provides you with
the port info that QEMU is listening on but there is no counterpart for
SPICE. Additionally this provides you with the bind address as specified
in the XML, which the existing 'vncdisplay' lacks.

Signed-off-by: Doug Goldstein <cardoe cardoe com>
---
 tools/virsh.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 128 insertions(+), 0 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index 4d34d49..88d4681 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -13624,6 +13624,133 @@ cmdSysinfo (vshControl *ctl, const vshCmd
*cmd ATTRIBUTE_UNUSED)
 }

 /*
+ * "display" 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")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
+{
+    xmlDocPtr xml = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    virDomainPtr dom;
+    bool ret = false;
+    int port = 0;
+    char *doc;
+    char *xpath;
+    const char *scheme[] = { "vnc", "spice", NULL };
+    int iter = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    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 */
+        virAsprintf(&xpath, "string(/domain/devices/graphics[ type='%s']"
+                "/@port)", scheme[iter]);
+        if (!xpath) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+        VIR_FREE(xpath);
+        if (obj == NULL || obj->type != XPATH_STRING ||
+                obj->stringval == NULL) {
+            if (obj) {
+                /* Clean up memory */
+                xmlXPathFreeObject(obj);
+                obj = NULL;
+            }
+            continue;
+        }
+
+        /* If there was a port number, then the guest uses the
current scheme */
+        if (obj->stringval[0] != 0) {
+
+            /* Make sure this is a valid port number */
+            if (virStrToLong_i((const char *)obj->stringval, NULL,
10, &port)) {
+                vshError(ctl, _("Unable to interpret '%s' as a port number."),
+                        obj->stringval);
+                goto cleanup;
+            }
+
+            if (port < 0) {
+                vshError(ctl, _("Invalid port '%d', guest likely not
started."),
+                        port);
+                goto cleanup;
+            }
+
+            /* Clean up memory */
+            xmlXPathFreeObject(obj);
+            obj = NULL;
+
+            virAsprintf(&xpath, "string(/domain/devices/graphics[ type='%s']"
+                    "/@listen)", scheme[iter]);
+            if (!xpath) {
+                virReportOOMError();
+                goto cleanup;
+            }
+
+            obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+            VIR_FREE(xpath);
+
+            /* VNC protocol handlers take their port number as X - 5900 */
+            if (scheme[iter] == "vnc")
+                port -= 5900;
+
+            if (obj == NULL || obj->type != XPATH_STRING ||
+                obj->stringval == NULL || obj->stringval[0] == 0 ||
+                STREQ((const char *)obj->stringval, "0.0.0.0")) {
+                vshPrint(ctl, "%s://localhost:%d\n", scheme[iter], port);
+            } else {
+                vshPrint(ctl, "%s://%s:%d\n", scheme[iter],
+                        (const char  *)obj->stringval, port);
+            }
+
+            /* Clean up memory */
+            xmlXPathFreeObject(obj);
+            obj = NULL;
+
+            /* We got what we came for so return successfully */
+            ret = true;
+            break;
+        }
+
+    }
+
+cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(xml);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
  * "vncdisplay" command
  */
 static const vshCmdInfo info_vncdisplay[] = {
@@ -17702,6 +17829,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},
-- 
1.7.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]