You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2013/12/29 00:53:00 UTC

[1/2] git commit: Document some choices in the ssh client.

Updated Branches:
  refs/heads/trunk 6c1b9de65 -> a053cde54


Document some choices in the ssh client.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6e53bfff
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6e53bfff
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6e53bfff

Branch: refs/heads/trunk
Commit: 6e53bfff2edaee590cb1d70ba333e7a9a82c203a
Parents: 6c1b9de
Author: Tomaz Muraus <to...@apache.org>
Authored: Sat Dec 28 23:54:26 2013 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sun Dec 29 00:16:47 2013 +0100

----------------------------------------------------------------------
 libcloud/compute/ssh.py | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6e53bfff/libcloud/compute/ssh.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/ssh.py b/libcloud/compute/ssh.py
index d476e87..7cbcee6 100644
--- a/libcloud/compute/ssh.py
+++ b/libcloud/compute/ssh.py
@@ -239,20 +239,32 @@ class ParamikoSSHClient(BaseSSHClient):
         return True
 
     def run(self, cmd):
+        """
+        Note: This function is based on paramiko's exec_command()
+        method.
+        """
         extra = {'_cmd': cmd}
         self.logger.debug('Executing command', extra=extra)
 
-        # based on exec_command()
+        # Use the system default buffer size
         bufsize = -1
-        t = self.client.get_transport()
-        chan = t.open_session()
+
+        transport = self.client.get_transport()
+        chan = transport.open_session()
+
         chan.exec_command(cmd)
+
         stdin = chan.makefile('wb', bufsize)
         stdout = chan.makefile('rb', bufsize)
         stderr = chan.makefile_stderr('rb', bufsize)
-        #stdin, stdout, stderr = self.client.exec_command(cmd)
+
         stdin.close()
+
+        # Receive the exit status code of the command we ran.
+        # Note: If the command hasn't finished yet, this method will block
+        # until it does
         status = chan.recv_exit_status()
+
         so = stdout.read()
         se = stderr.read()
 


[2/2] git commit: Fix a deployment buffering issue spotted by @pquerna which could happen if the the executed command produced a lot of output.

Posted by to...@apache.org.
Fix a deployment buffering issue spotted by @pquerna which could happen if the
the executed command produced a lot of output.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a053cde5
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a053cde5
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a053cde5

Branch: refs/heads/trunk
Commit: a053cde54fb6fffe8666aa01de46a354115f4f40
Parents: 6e53bff
Author: Tomaz Muraus <to...@apache.org>
Authored: Sun Dec 29 00:31:20 2013 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sun Dec 29 00:43:12 2013 +0100

----------------------------------------------------------------------
 libcloud/compute/ssh.py | 52 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 43 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/a053cde5/libcloud/compute/ssh.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/ssh.py b/libcloud/compute/ssh.py
index 7cbcee6..88094a5 100644
--- a/libcloud/compute/ssh.py
+++ b/libcloud/compute/ssh.py
@@ -36,6 +36,11 @@ from os.path import split as psplit
 from os.path import join as pjoin
 
 from libcloud.utils.logging import ExtraLogFormatter
+from libcloud.utils.py3 import StringIO
+
+
+# Maximum number of bytes to read at once from a socket
+CHUNK_SIZE = 1024
 
 
 class BaseSSHClient(object):
@@ -254,24 +259,53 @@ class ParamikoSSHClient(BaseSSHClient):
 
         chan.exec_command(cmd)
 
-        stdin = chan.makefile('wb', bufsize)
-        stdout = chan.makefile('rb', bufsize)
-        stderr = chan.makefile_stderr('rb', bufsize)
+        stdout = StringIO()
+        stderr = StringIO()
 
+        # Create a stdin file and immediately close it to prevent any
+        # interactive script from hanging the process.
+        stdin = chan.makefile('wb', bufsize)
         stdin.close()
 
+        # Receive all the output
+        # Note: This is used instead of chan.makefile approach to prevent
+        # buffering issues and hanging if the executed command produces a lot
+        # of output.
+        while not chan.exit_status_ready():
+            if chan.recv_ready():
+                data = chan.recv(CHUNK_SIZE)
+
+                while data:
+                    stdout.write(data)
+                    ready = chan.recv_ready()
+
+                    if not ready:
+                        break
+
+                    data = chan.recv(CHUNK_SIZE)
+
+            if chan.recv_stderr_ready():
+                data = chan.recv_stderr(CHUNK_SIZE)
+
+                while data:
+                    stderr.write(data)
+                    ready = chan.recv_stderr_ready()
+
+                    if not ready:
+                        break
+
+                    data = chan.recv_stderr(CHUNK_SIZE)
+
         # Receive the exit status code of the command we ran.
-        # Note: If the command hasn't finished yet, this method will block
-        # until it does
         status = chan.recv_exit_status()
 
-        so = stdout.read()
-        se = stderr.read()
+        stdout = stdout.getvalue()
+        stderr = stderr.getvalue()
 
-        extra = {'_status': status, '_stdout': so, '_stderr': se}
+        extra = {'_status': status, '_stdout': stdout, '_stderr': stderr}
         self.logger.debug('Command finished', extra=extra)
 
-        return [so, se, status]
+        return [stdout, stderr, status]
 
     def close(self):
         self.logger.debug('Closing server connection')