[libvirt] [PATCH 4/4] remote: Detect 'nc' version incompatibilities

Cole Robinson crobinso at redhat.com
Fri Feb 12 15:32:17 UTC 2010


This ugly thing is a shell script to detect availability of
the -q option for 'nc': debian and suse based distros need this
flag to ensure the remote nc will exit on EOF, so it will go away
when we close the tunnel. If it doesn't go away, a useless 'nc'
process is left sitting on the remote host.

Fedora's 'nc' doesn't have this option, so we can't blindly pass -q.
More info here:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=564034

We also detect the -U option, since some nc versions don't support it, which
has caused quite some user confusion. Connecting to a box and using the
incorrect nc:

virsh --connect qemu+ssh://root@debhost/system?netcat=/bin/nc.traditional
error: server closed connection: /bin/nc.traditional: invalid option -- U
nc -h for help
openbsd nc is required

error: failed to connect to the hypervisor

Test with Fedora 12, RHEL 5.4, and Debian Lenny
---
 src/remote/remote_driver.c |   52 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 7f92fd0..c3258d3 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -732,8 +732,49 @@ doRemoteOpen (virConnectPtr conn,
     }
 
     case trans_ssh: {
-        int j, nr_args = 6;
+        int j, nr_args = 0;
+        char *nc_command;
+
+        const char *nc_bin = netcat ? netcat : "nc";
+        const char *sock_path = (sockname ? sockname :
+                                 (flags & VIR_CONNECT_RO
+                                  ? LIBVIRTD_PRIV_UNIX_SOCKET_RO
+                                  : LIBVIRTD_PRIV_UNIX_SOCKET));
+
+        /*
+         * Build 'nc' command run on the remote host
+         *
+         * This ugly thing is a shell script to detect availability of
+         * the -q option for 'nc': debian and suse based distros need this
+         * flag to ensure the remote nc will exit on EOF, so it will go away
+         * when we close the tunnel. If it doesn't go away, a useless 'nc'
+         * process is left sitting on the remote host.
+         *
+         * Fedora's 'nc' doesn't have this option, and apparently defaults
+         * to the desired behavior.
+         */
+        const char *nc_detect_template = (
+            "NCOUT=$(%s -U 2>&1);"
+            "echo \"$NCOUT\" | grep -q 'invalid option';"
+            "if [ $? -eq 0 ] ; then"
+            "   echo \"$NCOUT\" >&2;"
+            "   echo openbsd 'nc' is required >&2;"
+            "   exit 1;"
+            "fi;"
+            ""
+            "%s -q 2>&1 | grep -q 'requires an argument';"
+            "if [ $? -eq 0 ] ; then"
+            "   CMD='-q 0';"
+            "else"
+            "   CMD='';"
+            "fi;"
+            "%s $CMD -U %s;");
+
+        if (virAsprintf(&nc_command, nc_detect_template,
+                        nc_bin, nc_bin, nc_bin, sock_path) < 0)
+            goto out_of_memory;
 
+        nr_args += 4;               /* ssh $hostname $netcat_command NULL*/
         if (username) nr_args += 2; /* For -l username */
         if (no_tty) nr_args += 5;   /* For -T -o BatchMode=yes -e none */
         if (port) nr_args += 2;     /* For -p port */
@@ -765,12 +806,9 @@ doRemoteOpen (virConnectPtr conn,
             cmd_argv[j++] = strdup ("none");
         }
         cmd_argv[j++] = strdup (priv->hostname);
-        cmd_argv[j++] = strdup (netcat ? netcat : "nc");
-        cmd_argv[j++] = strdup ("-U");
-        cmd_argv[j++] = strdup (sockname ? sockname :
-                                (flags & VIR_CONNECT_RO
-                                 ? LIBVIRTD_PRIV_UNIX_SOCKET_RO
-                                 : LIBVIRTD_PRIV_UNIX_SOCKET));
+
+        cmd_argv[j++] = nc_command;
+
         cmd_argv[j++] = 0;
         assert (j == nr_args);
         for (j = 0; j < (nr_args-1); j++)
-- 
1.6.5.2




More information about the libvir-list mailing list