Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: third_party/gsutil/boto/boto/manage/cmdshell.py

Issue 12317103: Added gsutil to depot tools (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/gsutil/boto/boto/manage/__init__.py ('k') | third_party/gsutil/boto/boto/manage/propget.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/gsutil/boto/boto/manage/cmdshell.py
diff --git a/third_party/gsutil/boto/boto/manage/cmdshell.py b/third_party/gsutil/boto/boto/manage/cmdshell.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ee013361cc3a15b75ad0543408fccaedd680319
--- /dev/null
+++ b/third_party/gsutil/boto/boto/manage/cmdshell.py
@@ -0,0 +1,241 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+from boto.mashups.interactive import interactive_shell
+import boto
+import os
+import time
+import shutil
+import StringIO
+import paramiko
+import socket
+import subprocess
+
+
+class SSHClient(object):
+
+ def __init__(self, server,
+ host_key_file='~/.ssh/known_hosts',
+ uname='root', ssh_pwd=None):
+ self.server = server
+ self.host_key_file = host_key_file
+ self.uname = uname
+ self._pkey = paramiko.RSAKey.from_private_key_file(server.ssh_key_file,
+ password=ssh_pwd)
+ self._ssh_client = paramiko.SSHClient()
+ self._ssh_client.load_system_host_keys()
+ self._ssh_client.load_host_keys(os.path.expanduser(host_key_file))
+ self._ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ self.connect()
+
+ def connect(self, num_retries=5):
+ retry = 0
+ while retry < num_retries:
+ try:
+ self._ssh_client.connect(self.server.hostname,
+ username=self.uname,
+ pkey=self._pkey)
+ return
+ except socket.error, (value, message):
+ if value in (51, 61, 111):
+ print 'SSH Connection refused, will retry in 5 seconds'
+ time.sleep(5)
+ retry += 1
+ else:
+ raise
+ except paramiko.BadHostKeyException:
+ print "%s has an entry in ~/.ssh/known_hosts and it doesn't match" % self.server.hostname
+ print 'Edit that file to remove the entry and then hit return to try again'
+ raw_input('Hit Enter when ready')
+ retry += 1
+ except EOFError:
+ print 'Unexpected Error from SSH Connection, retry in 5 seconds'
+ time.sleep(5)
+ retry += 1
+ print 'Could not establish SSH connection'
+
+ def open_sftp(self):
+ return self._ssh_client.open_sftp()
+
+ def get_file(self, src, dst):
+ sftp_client = self.open_sftp()
+ sftp_client.get(src, dst)
+
+ def put_file(self, src, dst):
+ sftp_client = self.open_sftp()
+ sftp_client.put(src, dst)
+
+ def open(self, filename, mode='r', bufsize=-1):
+ """
+ Open a file on the remote system and return a file-like object.
+ """
+ sftp_client = self.open_sftp()
+ return sftp_client.open(filename, mode, bufsize)
+
+ def listdir(self, path):
+ sftp_client = self.open_sftp()
+ return sftp_client.listdir(path)
+
+ def isdir(self, path):
+ status = self.run('[ -d %s ] || echo "FALSE"' % path)
+ if status[1].startswith('FALSE'):
+ return 0
+ return 1
+
+ def exists(self, path):
+ status = self.run('[ -a %s ] || echo "FALSE"' % path)
+ if status[1].startswith('FALSE'):
+ return 0
+ return 1
+
+ def shell(self):
+ """
+ Start an interactive shell session on the remote host.
+ """
+ channel = self._ssh_client.invoke_shell()
+ interactive_shell(channel)
+
+ def run(self, command):
+ """
+ Execute a command on the remote host. Return a tuple containing
+ an integer status and a two strings, the first containing stdout
+ and the second containing stderr from the command.
+ """
+ boto.log.debug('running:%s on %s' % (command, self.server.instance_id))
+ status = 0
+ try:
+ t = self._ssh_client.exec_command(command)
+ except paramiko.SSHException:
+ status = 1
+ std_out = t[1].read()
+ std_err = t[2].read()
+ t[0].close()
+ t[1].close()
+ t[2].close()
+ boto.log.debug('stdout: %s' % std_out)
+ boto.log.debug('stderr: %s' % std_err)
+ return (status, std_out, std_err)
+
+ def run_pty(self, command):
+ """
+ Execute a command on the remote host with a pseudo-terminal.
+ Returns a string containing the output of the command.
+ """
+ boto.log.debug('running:%s on %s' % (command, self.server.instance_id))
+ channel = self._ssh_client.get_transport().open_session()
+ channel.get_pty()
+ channel.exec_command(command)
+ return channel
+
+ def close(self):
+ transport = self._ssh_client.get_transport()
+ transport.close()
+ self.server.reset_cmdshell()
+
+class LocalClient(object):
+
+ def __init__(self, server, host_key_file=None, uname='root'):
+ self.server = server
+ self.host_key_file = host_key_file
+ self.uname = uname
+
+ def get_file(self, src, dst):
+ shutil.copyfile(src, dst)
+
+ def put_file(self, src, dst):
+ shutil.copyfile(src, dst)
+
+ def listdir(self, path):
+ return os.listdir(path)
+
+ def isdir(self, path):
+ return os.path.isdir(path)
+
+ def exists(self, path):
+ return os.path.exists(path)
+
+ def shell(self):
+ raise NotImplementedError('shell not supported with LocalClient')
+
+ def run(self):
+ boto.log.info('running:%s' % self.command)
+ log_fp = StringIO.StringIO()
+ process = subprocess.Popen(self.command, shell=True, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ while process.poll() == None:
+ time.sleep(1)
+ t = process.communicate()
+ log_fp.write(t[0])
+ log_fp.write(t[1])
+ boto.log.info(log_fp.getvalue())
+ boto.log.info('output: %s' % log_fp.getvalue())
+ return (process.returncode, log_fp.getvalue())
+
+ def close(self):
+ pass
+
+class FakeServer(object):
+ """
+ A little class to fake out SSHClient (which is expecting a
+ :class`boto.manage.server.Server` instance. This allows us
+ to
+ """
+ def __init__(self, instance, ssh_key_file):
+ self.instance = instance
+ self.ssh_key_file = ssh_key_file
+ self.hostname = instance.dns_name
+ self.instance_id = self.instance.id
+
+def start(server):
+ instance_id = boto.config.get('Instance', 'instance-id', None)
+ if instance_id == server.instance_id:
+ return LocalClient(server)
+ else:
+ return SSHClient(server)
+
+def sshclient_from_instance(instance, ssh_key_file,
+ host_key_file='~/.ssh/known_hosts',
+ user_name='root', ssh_pwd=None):
+ """
+ Create and return an SSHClient object given an
+ instance object.
+
+ :type instance: :class`boto.ec2.instance.Instance` object
+ :param instance: The instance object.
+
+ :type ssh_key_file: str
+ :param ssh_key_file: A path to the private key file used
+ to log into instance.
+
+ :type host_key_file: str
+ :param host_key_file: A path to the known_hosts file used
+ by the SSH client.
+ Defaults to ~/.ssh/known_hosts
+ :type user_name: str
+ :param user_name: The username to use when logging into
+ the instance. Defaults to root.
+
+ :type ssh_pwd: str
+ :param ssh_pwd: The passphrase, if any, associated with
+ private key.
+ """
+ s = FakeServer(instance, ssh_key_file)
+ return SSHClient(s, host_key_file, user_name, ssh_pwd)
« no previous file with comments | « third_party/gsutil/boto/boto/manage/__init__.py ('k') | third_party/gsutil/boto/boto/manage/propget.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698