[libvirt] [PATCHv2 5/5] NOT_TO_BE_APPLIED_UPSTREAM: quick and dirty virsh client to test the stuff

Peter Krempa pkrempa at redhat.com
Mon Dec 10 08:29:44 UTC 2012


This patch adds a "remote netcat" functionality using for example:
virsh tcp-console --host localhost --port 1234 --ipv4
---
 tools/console.c      | 66 ++++++++++++++++++++++++++++------------------------
 tools/console.h      |  9 ++-----
 tools/virsh-domain.c | 17 +++++++++++---
 tools/virsh-host.c   | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 112 insertions(+), 40 deletions(-)

diff --git a/tools/console.c b/tools/console.c
index 40de8eb..e4e4fd7 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -325,38 +325,46 @@ vshMakeStdinRaw(struct termios *ttyattr, bool report_errors)
     return 0;
 }

-int vshRunConsole(virDomainPtr dom,
-                  const char *dev_name,
-                  const char *escape_seq,
-                  unsigned int flags)
+int
+vshRunConsole(virStreamPtr st,
+              const char *escape_seq,
+              bool raw)
 {
     int ret = -1;
     struct termios ttyattr;
-    void (*old_sigquit)(int);
-    void (*old_sigterm)(int);
-    void (*old_sigint)(int);
-    void (*old_sighup)(int);
-    void (*old_sigpipe)(int);
+    void (*old_sigquit)(int) = NULL;
+    void (*old_sigterm)(int) = NULL;
+    void (*old_sigint)(int) = NULL;
+    void (*old_sighup)(int) = NULL;
+    void (*old_sigpipe)(int) = NULL;
     virConsolePtr con = NULL;

+    if (!st) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Invalid stream"));
+        return -1;
+    }
+
     /* Put STDIN into raw mode so that stuff typed
        does not echo to the screen (the TTY reads will
        result in it being echoed back already), and
        also ensure Ctrl-C, etc is blocked, and misc
        other bits */
-    if (vshMakeStdinRaw(&ttyattr, true) < 0)
+    if (raw && vshMakeStdinRaw(&ttyattr, true) < 0)
         goto resettty;

     /* Trap all common signals so that we can safely restore
        the original terminal settings on STDIN before the
        process exits - people don't like being left with a
        messed up terminal ! */
-    old_sigquit = signal(SIGQUIT, do_signal);
-    old_sigterm = signal(SIGTERM, do_signal);
-    old_sigint = signal(SIGINT, do_signal);
-    old_sighup = signal(SIGHUP, do_signal);
-    old_sigpipe = signal(SIGPIPE, do_signal);
-    got_signal = 0;
+    if (raw) {
+        old_sigquit = signal(SIGQUIT, do_signal);
+        old_sigterm = signal(SIGTERM, do_signal);
+        old_sigint = signal(SIGINT, do_signal);
+        old_sighup = signal(SIGHUP, do_signal);
+        old_sigpipe = signal(SIGPIPE, do_signal);
+        got_signal = 0;
+    }

     if (VIR_ALLOC(con) < 0) {
         virReportOOMError();
@@ -364,13 +372,8 @@ int vshRunConsole(virDomainPtr dom,
     }

     con->escapeChar = vshGetEscapeChar(escape_seq);
-    con->st = virStreamNew(virDomainGetConnect(dom),
-                           VIR_STREAM_NONBLOCK);
-    if (!con->st)
-        goto cleanup;
-
-    if (virDomainOpenConsole(dom, dev_name, con->st, flags) < 0)
-        goto cleanup;
+    virStreamRef(st);
+    con->st = st;

     if (virCondInit(&con->cond) < 0 || virMutexInit(&con->lock) < 0)
         goto cleanup;
@@ -411,17 +414,20 @@ int vshRunConsole(virDomainPtr dom,
         VIR_FREE(con);
     }

-    /* Restore original signal handlers */
-    signal(SIGPIPE, old_sigpipe);
-    signal(SIGHUP, old_sighup);
-    signal(SIGINT, old_sigint);
-    signal(SIGTERM, old_sigterm);
-    signal(SIGQUIT, old_sigquit);
+    if (raw) {
+        /* Restore original signal handlers */
+        signal(SIGPIPE, old_sigpipe);
+        signal(SIGHUP, old_sighup);
+        signal(SIGINT, old_sigint);
+        signal(SIGTERM, old_sigterm);
+        signal(SIGQUIT, old_sigquit);
+    }

 resettty:
     /* Put STDIN back into the (sane?) state we found
        it in before starting */
-    tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
+    if (raw)
+        tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);

     return ret;
 }
diff --git a/tools/console.h b/tools/console.h
index 46255b8..c23acda 100644
--- a/tools/console.h
+++ b/tools/console.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2007, 2010, 2012 Red Hat, Inc.
  *
- * This library is free software; you can redistribute it and/or
+ * This library is free software you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
@@ -24,13 +24,8 @@
 # define __VIR_CONSOLE_H__

 # ifndef WIN32
-
 #  include <termios.h>
-
-int vshRunConsole(virDomainPtr dom,
-                  const char *dev_name,
-                  const char *escape_seq,
-                  unsigned int flags);
+int vshRunConsole(virStreamPtr st, const char *escape_seq, bool raw);

 int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors);

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 96e62fc..4a500e6 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1887,10 +1887,12 @@ static const vshCmdOptDef opts_console[] = {
 };

 static bool
-cmdRunConsole(vshControl *ctl, virDomainPtr dom,
+cmdRunConsole(vshControl *ctl,
+              virDomainPtr dom,
               const char *name,
               unsigned int flags)
 {
+    virStreamPtr st = NULL;
     bool ret = false;
     int state;

@@ -1905,17 +1907,26 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom,
     }

     if (!isatty(STDIN_FILENO)) {
-        vshError(ctl, "%s", _("Cannot run interactive console without a controlling TTY"));
+        vshError(ctl, "%s", _("Cannot run interactive console "
+                              "without a controlling TTY"));
         goto cleanup;
     }

+    if (!(st = virStreamNew(virDomainGetConnect(dom), VIR_STREAM_NONBLOCK)))
+        goto cleanup;
+
+    if (virDomainOpenConsole(dom, name, st, flags) < 0)
+        goto cleanup;
+
     vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
     vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
     fflush(stdout);
-    if (vshRunConsole(dom, name, ctl->escapeChar, flags) == 0)
+    if (vshRunConsole(st, ctl->escapeChar, true) == 0)
         ret = true;

  cleanup:
+    if (st)
+        virStreamFree(st);

     return ret;
 }
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 3d13e01..bf2a48f 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -31,6 +31,7 @@
 #include <libxml/xpath.h>
 #include <libxml/xmlsave.h>

+#include "console.h"
 #include "internal.h"
 #include "buf.h"
 #include "memory.h"
@@ -1073,6 +1074,64 @@ error:
     goto cleanup;
 }

+static const vshCmdInfo info_node_tcp_console[] = {
+    {"help", N_("Connect to a TCP port on the host using a console")},
+    {"desc", N_("Connect to a TCP port on the host using a console")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_node_tcp_console[] = {
+    {"port", VSH_OT_DATA, VSH_OFLAG_REQ, N_("port to connect to")},
+    {"host", VSH_OT_STRING, VSH_OFLAG_NONE, N_("hostname to connect to")},
+    {"ipv4", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("use IPv4")},
+    {"ipv6", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("use IPv6")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdNodeTCPConsole(vshControl *ctl, const vshCmd *cmd)
+{
+    bool ret = false;
+    const char *host;
+    const char *port;
+    unsigned int flags = 0;
+    virStreamPtr st = NULL;
+
+    if (vshCommandOptString(cmd, "host", &host) < 0) {
+        vshError(ctl, "%s", _("Invalid hostname"));
+        goto cleanup;
+    }
+
+    if (vshCommandOptString(cmd, "port", &port) < 0) {
+        vshError(ctl, "%s", _("Invalid port"));
+        goto cleanup;
+    }
+
+    if (vshCommandOptBool(cmd, "ipv4"))
+        flags |= VIR_NODE_TUNNEL_TCP_IPV4;
+
+    if (vshCommandOptBool(cmd, "ipv6"))
+        flags |= VIR_NODE_TUNNEL_TCP_IPV6;
+
+    if (!(st = virStreamNew(ctl->conn, VIR_STREAM_NONBLOCK)))
+        goto cleanup;
+
+    if (virNodeTunnelTCP(ctl->conn, st, host, port, flags) < 0)
+        goto cleanup;
+
+    vshPrintExtra(ctl, _("Connected to host '%s' port '%s'\n"), host, port);
+    vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
+    fflush(stdout);
+    if (vshRunConsole(st, ctl->escapeChar, false) == 0)
+        ret = true;
+
+cleanup:
+    if (st)
+        virStreamFree(st);
+
+    return ret;
+}
+
 const vshCmdDef hostAndHypervisorCmds[] = {
     {"capabilities", cmdCapabilities, NULL, info_capabilities, 0},
     {"connect", cmdConnect, opts_connect, info_connect,
@@ -1094,5 +1153,6 @@ const vshCmdDef hostAndHypervisorCmds[] = {
     {"sysinfo", cmdSysinfo, NULL, info_sysinfo, 0},
     {"uri", cmdURI, NULL, info_uri, 0},
     {"version", cmdVersion, opts_version, info_version, 0},
+    {"node-tcp-console", cmdNodeTCPConsole, opts_node_tcp_console, info_node_tcp_console, 0},
     {NULL, NULL, NULL, NULL, 0}
 };
-- 
1.8.0




More information about the libvir-list mailing list