the big merge
[nepi.git] / src / nepi / util / sshfuncs.py
index 7587e97..1236ed5 100644 (file)
@@ -34,6 +34,8 @@ import threading
 import time
 import tempfile
 
+from six import PY2
+
 _re_inet = re.compile("\d+:\s+(?P<name>[a-z0-9_-]+)\s+inet6?\s+(?P<inet>[a-f0-9.:/]+)\s+(brd\s+[0-9.]+)?.*scope\s+global.*") 
 
 logger = logging.getLogger("sshfuncs")
@@ -79,11 +81,13 @@ def resolve_hostname(host):
     ip = None
 
     if host in ["localhost", "127.0.0.1", "::1"]:
+        extras = {} if PY2 else {'universal_newlines' : True}
         p = subprocess.Popen(
             "ip -o addr list",
             shell=True,
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE,
+            **extras
         )
         stdout, stderr = p.communicate()
         m = _re_inet.findall(stdout)
@@ -120,12 +124,14 @@ def openssh_has_persist():
     """
     global OPENSSH_HAS_PERSIST
     if OPENSSH_HAS_PERSIST is None:
+        extras = {} if PY2 else {'universal_newlines' : True}
         with open("/dev/null") as null:
             proc = subprocess.Popen(
                 ["ssh", "-v"],
                 stdout = subprocess.PIPE,
                 stderr = subprocess.STDOUT,
                 stdin = null,
+                **extras
             )
             out,err = proc.communicate()
             proc.wait()
@@ -701,6 +707,7 @@ def _retry_rexec(args,
         # display command actually invoked when debug is turned on
         message = " ".join( [ "'{}'".format(arg) for arg in args ] )
         log("sshfuncs: invoking {}".format(message), logging.DEBUG)
+        extras = {} if PY2 else {'universal_newlines' : True}
         # connects to the remote host and starts a remote connection
         proc = subprocess.Popen(
             args,
@@ -708,6 +715,7 @@ def _retry_rexec(args,
             stdout = stdout,
             stdin = stdin, 
             stderr = stderr,
+            **extras
         )        
         # attach tempfile object to the process, to make sure the file stays
         # alive until the process is finished with it
@@ -840,16 +848,21 @@ def _communicate(proc, input, timeout=None, err_on_timeout=True):
                 proc.stdin.close()
                 write_set.remove(proc.stdin)
 
+        # xxx possible distortion when upgrading to python3
+        # original py2 version used to do
+        # data = os.read(proc.stdout.fileno(), 1024)
+        # but this would return bytes, so..
         if proc.stdout in rlist:
-            data = os.read(proc.stdout.fileno(), 1024)
-            if data == "":
+            data = proc.stdout.read()
+            if not data:
                 proc.stdout.close()
                 read_set.remove(proc.stdout)
             stdout.append(data)
 
+        # likewise
         if proc.stderr in rlist:
-            data = os.read(proc.stderr.fileno(), 1024)
-            if data == "":
+            data = proc.stderr.read()
+            if not data:
                 proc.stderr.close()
                 read_set.remove(proc.stderr)
             stderr.append(data)
@@ -864,11 +877,13 @@ def _communicate(proc, input, timeout=None, err_on_timeout=True):
     # object do the translation: It is based on stdio, which is
     # impossible to combine with select (unless forcing no
     # buffering).
-    if proc.universal_newlines and hasattr(file, 'newlines'):
-        if stdout:
-            stdout = proc._translate_newlines(stdout)
-        if stderr:
-            stderr = proc._translate_newlines(stderr)
+    # this however seems to make no sense in the context of python3
+    if PY2:
+        if proc.universal_newlines and hasattr(file, 'newlines'):
+            if stdout:
+                stdout = proc._translate_newlines(stdout)
+            if stderr:
+                stderr = proc._translate_newlines(stderr)
 
     if killed and err_on_timeout:
         errcode = proc.poll()