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/03/09 07:05:41 UTC
svn commit: r1454660 - /libcloud/trunk/libcloud/compute/ssh.py
Author: tomaz
Date: Sat Mar 9 06:05:40 2013
New Revision: 1454660
URL: http://svn.apache.org/r1454660
Log:
W.I.P. ShellOutSSHClient.
Part of LIBCLOUD-303.
Modified:
libcloud/trunk/libcloud/compute/ssh.py
Modified: libcloud/trunk/libcloud/compute/ssh.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/ssh.py?rev=1454660&r1=1454659&r2=1454660&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/ssh.py (original)
+++ libcloud/trunk/libcloud/compute/ssh.py Sat Mar 9 06:05:40 2013
@@ -28,6 +28,10 @@ except ImportError:
# warning on Python 2.6.
# Ref: https://bugs.launchpad.net/paramiko/+bug/392973
+import os
+import subprocess
+import logging
+
from os.path import split as psplit
from os.path import join as pjoin
@@ -220,9 +224,97 @@ class ParamikoSSHClient(BaseSSHClient):
class ShellOutSSHClient(BaseSSHClient):
- # TODO: write this one
+ """
+ This client shells out to "ssh" binary to run commands on the remote
+ server.
+
+ Note: This client should not be used in production.
+ """
+
+ def __init__(self, hostname, port=22, username='root', password=None,
+ key=None, timeout=None):
+ super(ShellOutSSHClient, self).__init__(hostname, port, username,
+ password, key, timeout)
+ if self.password:
+ raise ValueError('ShellOutSSHClient only supports key auth')
+
+ child = subprocess.Popen(['ssh'], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ child.communicate()
+
+ if child.returncode == 127:
+ raise ValueError('ssh client is not available')
+
+ self.logger = self._get_and_setup_logger()
+
+ def connect(self):
+ """
+ This client doesn't support persistent connections establish a new
+ connection every time "run" method is called.
+ """
+ return True
+
+ def run(self, cmd):
+ return self._run_remote_shell_command(cmd)
+
+ def put(self, path, contents=None, chmod=None, mode='w'):
+ if mode == 'w':
+ redirect = '>'
+ elif mode == 'a':
+ redirect = '>>'
+ else:
+ raise ValueError('Invalid mode: ' + mode)
+
+ cmd = ['echo "%s" %s %s' % (contents, redirect, path)]
+ self._run_remote_shell_command(cmd)
+
+ def delete(self, path):
+ cmd = ['rm', '-rf', path]
+ self._run_remote_shell_command(cmd)
+
+ def close(self):
+ pass
+
+ def _get_and_setup_logger(self):
+ logger = logging.getLogger('libcloud.compute.ssh')
+ path = os.getenv('LIBCLOUD_DEBUG')
+
+ if path:
+ handler = logging.FileHandler(path)
+ logger.addHandler(handler)
+ logger.setLevel(logging.DEBUG)
+
+ return logger
+
+ def _get_base_ssh_command(self):
+ cmd = ['ssh']
+
+ if self.key:
+ cmd += ['-i', self.key]
+
+ if self.timeout:
+ cmd += ['-oConnectTimeout=%s' % (self.timeout)]
+
+ cmd += ['%s@%s' % (self.username, self.hostname)]
+
+ return cmd
+
+ def _run_remote_shell_command(self, cmd):
+ base_cmd = self._get_base_ssh_command()
+ full_cmd = base_cmd + [' '.join(cmd)]
+
+ self.logger.debug('Executing command: "%s"' % (' '.join(full_cmd)))
+
+ child = subprocess.Popen(full_cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = child.communicate()
+ return (stdout, stderr, child.returncode)
+
+
+class MockSSHClient(BaseSSHClient):
pass
+
SSHClient = ParamikoSSHClient
if not have_paramiko:
- SSHClient = ShellOutSSHClient
+ SSHClient = MockSSHClient