mirror of
https://github.com/thead-yocto-mirror/skia
synced 2026-06-22 01:04:55 +02:00
197 lines
6.8 KiB
Python
197 lines
6.8 KiB
Python
#!/usr/bin/env python
|
|
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
""" This module contains tools related to ssh used by the buildbot scripts. """
|
|
|
|
import atexit
|
|
import os
|
|
import re
|
|
import shell_utils
|
|
import signal
|
|
|
|
def PutSCP(local_path, remote_path, username, host, port, recurse=False,
|
|
options=None):
|
|
""" Send a file to the given host over SCP. Assumes that public key
|
|
authentication is set up between the client and server.
|
|
|
|
local_path: path to the file to send on the client
|
|
remote_path: destination path for the file on the server
|
|
username: ssh login name
|
|
host: hostname or ip address of the server
|
|
port: port on the server to use
|
|
recurse: boolean indicating whether to transmit everything in a folder
|
|
options: list of extra options to pass to scp
|
|
"""
|
|
# TODO(borenet): This will hang for a while if the host does not recognize
|
|
# the client.
|
|
cmd = ['scp']
|
|
if options:
|
|
cmd.extend(options)
|
|
if recurse:
|
|
cmd.append('-r')
|
|
cmd.extend(
|
|
['-P', port, local_path, '%s@%s:%s' % (username, host, remote_path)])
|
|
shell_utils.run(cmd)
|
|
|
|
|
|
def MultiPutSCP(local_paths, remote_path, username, host, port, options=None):
|
|
""" Send files to the given host over SCP. Assumes that public key
|
|
authentication is set up between the client and server.
|
|
|
|
local_paths: list of paths of files and directories to send on the client
|
|
remote_path: destination directory path on the server
|
|
username: ssh login name
|
|
host: hostname or ip address of the server
|
|
port: port on the server to use
|
|
options: list of extra options to pass to scp
|
|
"""
|
|
# TODO(borenet): This will hang for a while if the host does not recognize
|
|
# the client.
|
|
cmd = ['scp']
|
|
if options:
|
|
cmd.extend(options)
|
|
cmd.extend(['-r', '-P', port])
|
|
cmd.extend(local_paths)
|
|
cmd.append('%s@%s:%s' % (username, host, remote_path))
|
|
shell_utils.run(cmd)
|
|
|
|
|
|
def GetSCP(local_path, remote_path, username, host, port, recurse=False,
|
|
options=None):
|
|
""" Retrieve a file from the given host over SCP. Assumes that public key
|
|
authentication is set up between the client and server.
|
|
|
|
local_path: destination path for the file on the client
|
|
remote_path: path to the file to retrieve on the server
|
|
username: ssh login name
|
|
host: hostname or ip address of the server
|
|
port: port on the server to use
|
|
recurse: boolean indicating whether to transmit everything in a folder
|
|
options: list of extra options to pass to scp
|
|
"""
|
|
# TODO(borenet): This will hang for a while if the host does not recognize
|
|
# the client.
|
|
cmd = ['scp']
|
|
if options:
|
|
cmd.extend(options)
|
|
if recurse:
|
|
cmd.append('-r')
|
|
cmd.extend(
|
|
['-P', port, '%s@%s:%s' % (username, host, remote_path), local_path])
|
|
shell_utils.run(cmd)
|
|
|
|
|
|
def RunSSHCmd(username, host, port, command, echo=True, options=None):
|
|
""" Login to the given host and run the given command.
|
|
|
|
username: ssh login name
|
|
host: hostname or ip address of the server
|
|
port: port on the server to use
|
|
command: (string) command to run on the server
|
|
options: list of extra options to pass to ssh
|
|
"""
|
|
# TODO(borenet): This will hang for a while if the host does not recognize
|
|
# the client.
|
|
cmd = ['ssh']
|
|
if options:
|
|
cmd.extend(options)
|
|
cmd.extend(['-p', port, '%s@%s' % (username, host), command])
|
|
return shell_utils.run(cmd, echo=echo)
|
|
|
|
|
|
def ShellEscape(arg):
|
|
""" Escape a single argument for passing into a remote shell
|
|
"""
|
|
arg = re.sub(r'(["\\])', r'\\\1', arg)
|
|
return '"%s"' % arg if re.search(r'[\' \t\r\n]', arg) else arg
|
|
|
|
|
|
def RunSSH(username, host, port, command, echo=True, options=None):
|
|
""" Login to the given host and run the given command.
|
|
|
|
username: ssh login name
|
|
host: hostname or ip address of the server
|
|
port: port on the server to use
|
|
command: command to run on the server in list format
|
|
options: list of extra options to pass to ssh
|
|
"""
|
|
cmd = ' '.join(ShellEscape(arg) for arg in command)
|
|
return RunSSHCmd(username, host, port, cmd, echo=echo, options=options)
|
|
|
|
|
|
class SshDestination(object):
|
|
""" Convenience class to remember a host, port, and username.
|
|
Wraps the other functions in this module.
|
|
"""
|
|
def __init__(self, host, port, username, options=None):
|
|
"""
|
|
host - (string) hostname of the target
|
|
port - (string or int) sshd port on the target
|
|
username - (string) remote username
|
|
options - (list of strings) extra options to pass to ssh and scp.
|
|
"""
|
|
self.host = host
|
|
self.port = str(port)
|
|
self.user = username
|
|
self.options = options
|
|
|
|
def Put(self, local_path, remote_path, recurse=False):
|
|
return PutSCP(local_path, remote_path, self.user, self.host,
|
|
self.port, recurse=recurse, options=self.options)
|
|
|
|
def MultiPut(self, local_paths, remote_path):
|
|
return MultiPutSCP(local_paths, remote_path, self.user, self.host,
|
|
self.port, options=self.options)
|
|
|
|
def Get(self, local_path, remote_path, recurse=False):
|
|
return GetSCP(local_path, remote_path, self.user,
|
|
self.host, self.port, recurse=recurse, options=self.options)
|
|
|
|
def RunCmd(self, command, echo=True):
|
|
return RunSSHCmd(self.user, self.host, self.port, command,
|
|
echo=echo, options=self.options)
|
|
|
|
def Run(self, command, echo=True):
|
|
return RunSSH(self.user, self.host, self.port, command,
|
|
echo=echo, options=self.options)
|
|
|
|
|
|
def search_within_string(input_string, pattern):
|
|
"""Search for regular expression in a string.
|
|
|
|
input_string: (string) to be searched
|
|
pattern: (string) to be passed to re.compile, with a symbolic
|
|
group named 'return'.
|
|
default: what to return if no match
|
|
|
|
Returns a string or None
|
|
"""
|
|
match = re.search(pattern, input_string)
|
|
return match.group('return') if match else None
|
|
|
|
def SSHAdd(key_file):
|
|
""" Call ssh-add, and call ssh-agent if necessary.
|
|
"""
|
|
assert os.path.isfile(key_file)
|
|
try:
|
|
shell_utils.run(['ssh-add', key_file],
|
|
log_in_real_time=False)
|
|
return
|
|
except shell_utils.CommandFailedException:
|
|
ssh_agent_output = shell_utils.run(['ssh-agent', '-s'],
|
|
log_in_real_time=False)
|
|
if not ssh_agent_output:
|
|
raise Exception('ssh-agent did not print anything')
|
|
ssh_auth_sock = search_within_string(
|
|
ssh_agent_output, r'SSH_AUTH_SOCK=(?P<return>[^;]*);')
|
|
ssh_agent_pid = search_within_string(
|
|
ssh_agent_output, r'SSH_AGENT_PID=(?P<return>[^;]*);')
|
|
if not (ssh_auth_sock and ssh_agent_pid):
|
|
raise Exception('ssh-agent did not print meaningful data')
|
|
os.environ['SSH_AUTH_SOCK'] = ssh_auth_sock
|
|
os.environ['SSH_AGENT_PID'] = ssh_agent_pid
|
|
atexit.register(os.kill, int(ssh_agent_pid), signal.SIGTERM)
|
|
shell_utils.run(['ssh-add', key_file])
|