Home | History | Annotate | Download | only in flavor
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2016 Google Inc.
      4 #
      5 # Use of this source code is governed by a BSD-style license that can be
      6 # found in the LICENSE file.
      7 
      8 
      9 import default_flavor
     10 import os
     11 import posixpath
     12 import subprocess
     13 import ssh_devices
     14 
     15 
     16 """Utils for running tests remotely over SSH."""
     17 
     18 
     19 class SSHFlavorUtils(default_flavor.DefaultFlavorUtils):
     20   def __init__(self, *args, **kwargs):
     21     super(SSHFlavorUtils, self).__init__(*args, **kwargs)
     22     slave_info = ssh_devices.SLAVE_INFO.get(self._bot_info.slave_name,
     23                                             ssh_devices.SLAVE_INFO['default'])
     24     self._host = slave_info.ssh_host
     25     self._port = slave_info.ssh_port
     26     self._user = slave_info.ssh_user
     27 
     28   @property
     29   def host(self):
     30     return self._host
     31 
     32   @property
     33   def port(self):
     34     return self._port
     35 
     36   @property
     37   def user(self):
     38     return self._user
     39 
     40   def ssh(self, cmd, **kwargs):
     41     """Run the given SSH command."""
     42     ssh_cmd = ['ssh']
     43     if self.port:
     44       ssh_cmd.extend(['-p', self.port])
     45     dest = self.host
     46     if self.user:
     47       dest = self.user + '@' + dest
     48     ssh_cmd.append(dest)
     49     ssh_cmd.extend(cmd)
     50     return self._bot_info.run(ssh_cmd, **kwargs)
     51 
     52   def step(self, *args, **kwargs):
     53     """Run the given step over SSH."""
     54     self.ssh(*args, **kwargs)
     55 
     56   def device_path_join(self, *args):
     57     """Like os.path.join(), but for paths on a remote machine."""
     58     return posixpath.join(*args)
     59 
     60   def device_path_exists(self, path):  # pragma: no cover
     61     """Like os.path.exists(), but for paths on a remote device."""
     62     try:
     63       self.ssh(['test', '-e', path])
     64       return True
     65     except subprocess.CalledProcessError:
     66       return False
     67 
     68   def _remove_device_dir(self, path):
     69     """Remove the directory on the device."""
     70     self.ssh(['rm', '-rf', path])
     71 
     72   def _create_device_dir(self, path):
     73     """Create the directory on the device."""
     74     self.ssh(['mkdir', '-p', path])
     75 
     76   def create_clean_device_dir(self, path):
     77     """Like shutil.rmtree() + os.makedirs(), but on a remote device."""
     78     self._remove_device_dir(path)
     79     self._create_device_dir(path)
     80 
     81   def _make_scp_cmd(self, remote_path, recurse=True):
     82     """Prepare an SCP command.
     83 
     84     Returns a partial SCP command and an adjusted remote path.
     85     """
     86     cmd = ['scp']
     87     if recurse:
     88       cmd.append('-r')
     89     if self.port:
     90       cmd.extend(['-P', self.port])
     91     adj_remote_path = self.host + ':' + remote_path
     92     if self.user:
     93       adj_remote_path = self.user + '@' + adj_remote_path
     94     return cmd, adj_remote_path
     95 
     96   def copy_directory_contents_to_device(self, host_dir, device_dir):
     97     """Like shutil.copytree(), but for copying to a remote device."""
     98     _, remote_path = self._make_scp_cmd(device_dir)
     99     cmd = [os.path.join(self._bot_info.skia_dir, 'tools',
    100                         'scp_dir_contents.sh'),
    101            host_dir, remote_path]
    102     self._bot_info.run(cmd)
    103 
    104   def copy_directory_contents_to_host(self, device_dir, host_dir):
    105     """Like shutil.copytree(), but for copying from a remote device."""
    106     _, remote_path = self._make_scp_cmd(device_dir)
    107     cmd = [os.path.join(self._bot_info.skia_dir, 'tools',
    108                         'scp_dir_contents.sh'),
    109            remote_path, host_dir]
    110     self._bot_info.run(cmd)
    111 
    112   def copy_file_to_device(self, host_path, device_path):
    113     """Like shutil.copyfile, but for copying to a connected device."""
    114     cmd, remote_path = self._make_scp_cmd(device_path, recurse=False)
    115     cmd.extend([host_path, remote_path])
    116     self._bot_info.run(cmd)
    117 
    118   def read_file_on_device(self, path):
    119     return self.ssh(['cat', path]).rstrip()
    120 
    121   def remove_file_on_device(self, path):
    122     """Delete the given file."""
    123     return self.ssh(['rm', '-f', path])
    124