1*9c5db199SXin Li# Copyright 2015 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Li 5*9c5db199SXin Li"""This class defines the TestStationHost class.""" 6*9c5db199SXin Li 7*9c5db199SXin Liimport logging 8*9c5db199SXin Liimport os 9*9c5db199SXin Li 10*9c5db199SXin Liimport common 11*9c5db199SXin Li 12*9c5db199SXin Lifrom autotest_lib.client.bin import local_host 13*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 14*9c5db199SXin Lifrom autotest_lib.client.common_lib.cros import retry 15*9c5db199SXin Lifrom autotest_lib.client.cros import constants as cros_constants 16*9c5db199SXin Lifrom autotest_lib.server.hosts import base_classes 17*9c5db199SXin Lifrom autotest_lib.server.hosts import moblab_host 18*9c5db199SXin Lifrom autotest_lib.server.hosts import ssh_host 19*9c5db199SXin Li 20*9c5db199SXin Li 21*9c5db199SXin Li# TODO(kevcheng): Update the creation method so it's not a research project 22*9c5db199SXin Li# determining the class inheritance model (same for factory.create_host). 23*9c5db199SXin Lidef create_teststationhost(hostname, **kwargs): 24*9c5db199SXin Li """Creates the TestStationHost object. 25*9c5db199SXin Li 26*9c5db199SXin Li @param hostname: Hostname of the test station. 27*9c5db199SXin Li @param kwargs: Keyword args to pass to the testbed initialization. 28*9c5db199SXin Li 29*9c5db199SXin Li @return: A Test Station Host object. 30*9c5db199SXin Li """ 31*9c5db199SXin Li classes = [TestStationHost] 32*9c5db199SXin Li if hostname == 'localhost': 33*9c5db199SXin Li classes.append(local_host.LocalHost) 34*9c5db199SXin Li else: 35*9c5db199SXin Li classes.append(ssh_host.SSHHost) 36*9c5db199SXin Li host_class = type('new_teststationhost', tuple(classes), {}) 37*9c5db199SXin Li return host_class(hostname, **kwargs) 38*9c5db199SXin Li 39*9c5db199SXin Li 40*9c5db199SXin Liclass TestStationHost(base_classes.Host): 41*9c5db199SXin Li """This class represents a linux box accessible via ssh.""" 42*9c5db199SXin Li 43*9c5db199SXin Li 44*9c5db199SXin Li def check_credentials(self, hostname): 45*9c5db199SXin Li """Make sure teststation credentials work if we're doing ssh. 46*9c5db199SXin Li 47*9c5db199SXin Li @param hostname: Hostname of the machine. 48*9c5db199SXin Li """ 49*9c5db199SXin Li if hostname != 'localhost': 50*9c5db199SXin Li try: 51*9c5db199SXin Li self.run('true') 52*9c5db199SXin Li except error.AutoservRunError: 53*9c5db199SXin Li # Some test stations may not have root access, try user adb. 54*9c5db199SXin Li logging.debug('Switching to user adb.') 55*9c5db199SXin Li self.user = 'adb' 56*9c5db199SXin Li 57*9c5db199SXin Li 58*9c5db199SXin Li def _initialize(self, hostname='localhost', *args, **dargs): 59*9c5db199SXin Li """Initialize a Test Station Host. 60*9c5db199SXin Li 61*9c5db199SXin Li This will create a Test Station Host. Hostname should always refer 62*9c5db199SXin Li to the host machine connected to the devices under test. 63*9c5db199SXin Li 64*9c5db199SXin Li @param hostname: Hostname of the machine, default to localhost. 65*9c5db199SXin Li """ 66*9c5db199SXin Li logging.debug('Initializing Test Station Host running on host: %s.', 67*9c5db199SXin Li hostname) 68*9c5db199SXin Li 69*9c5db199SXin Li # Do parent class initializations. 70*9c5db199SXin Li super(TestStationHost, self)._initialize(hostname=hostname, *args, 71*9c5db199SXin Li **dargs) 72*9c5db199SXin Li 73*9c5db199SXin Li self.check_credentials(hostname) 74*9c5db199SXin Li 75*9c5db199SXin Li # We'll want to do certain things differently if we're on a moblab. 76*9c5db199SXin Li self._is_host_moblab = None 77*9c5db199SXin Li # Keep track of whether the host was closed since multiple AdbHost 78*9c5db199SXin Li # might have an instance of this teststation. 79*9c5db199SXin Li self._is_closed = False 80*9c5db199SXin Li 81*9c5db199SXin Li 82*9c5db199SXin Li @property 83*9c5db199SXin Li def is_moblab(self): 84*9c5db199SXin Li """Check if the host running adb command is a Moblab. 85*9c5db199SXin Li 86*9c5db199SXin Li @return: True if the host running adb command is a Moblab, False 87*9c5db199SXin Li otherwise. 88*9c5db199SXin Li """ 89*9c5db199SXin Li if self._is_host_moblab is None: 90*9c5db199SXin Li try: 91*9c5db199SXin Li self.run('cat %s | grep -q moblab' % cros_constants.LSB_RELEASE) 92*9c5db199SXin Li self._is_host_moblab = True 93*9c5db199SXin Li except (error.AutoservRunError, error.AutotestHostRunError): 94*9c5db199SXin Li self._is_host_moblab = False 95*9c5db199SXin Li return self._is_host_moblab 96*9c5db199SXin Li 97*9c5db199SXin Li 98*9c5db199SXin Li def get_tmp_dir(self, parent='/var/tmp'): 99*9c5db199SXin Li """Return pathname of a temporary directory on the test station. 100*9c5db199SXin Li 101*9c5db199SXin Li If parent folder is supplied and the teststation is a moblab. Then 102*9c5db199SXin Li the parent will have the moblab tmp directory prepended to it. 103*9c5db199SXin Li 104*9c5db199SXin Li @param parent: The parent dir to create the temporary dir. 105*9c5db199SXin Li 106*9c5db199SXin Li @return: Path of the newly created temporary dir. 107*9c5db199SXin Li """ 108*9c5db199SXin Li if self.is_moblab: 109*9c5db199SXin Li parent = (moblab_host.MOBLAB_TMP_DIR if parent == '/tmp' 110*9c5db199SXin Li else os.path.join(moblab_host.MOBLAB_TMP_DIR, 111*9c5db199SXin Li parent.lstrip('/'))) 112*9c5db199SXin Li return super(TestStationHost, self).get_tmp_dir(parent=parent) 113*9c5db199SXin Li 114*9c5db199SXin Li 115*9c5db199SXin Li def run(self, cmd, force_tty=True, *args, **dargs): 116*9c5db199SXin Li """Run a command on the adb device. 117*9c5db199SXin Li 118*9c5db199SXin Li This will run the command on the test station. This method only 119*9c5db199SXin Li exists to modify the command supplied if we're running a fastboot 120*9c5db199SXin Li command on a moblab, otherwise we leave the command untouched. 121*9c5db199SXin Li 122*9c5db199SXin Li @param cmd: The command line string. 123*9c5db199SXin Li @param force_tty: Set to True to force pseudo-terminal allocation to 124*9c5db199SXin Li run the command. This allows the command running on remote host 125*9c5db199SXin Li to abort when the ssh command is timed out. Default is True. 126*9c5db199SXin Li 127*9c5db199SXin Li @returns A CMDResult object or None if the call timed out and 128*9c5db199SXin Li ignore_timeout is True. 129*9c5db199SXin Li """ 130*9c5db199SXin Li # TODO (sbasi/kevcheng) - Make teststation_host check if running 131*9c5db199SXin Li # on ChromeOS, rather than MobLab when prepending sudo to fastboot. 132*9c5db199SXin Li if cmd.startswith('fastboot ') and self.is_moblab: 133*9c5db199SXin Li cmd = 'sudo -n ' + cmd 134*9c5db199SXin Li if force_tty: 135*9c5db199SXin Li dargs['options'] = dargs.get('options', '') + ' -t ' 136*9c5db199SXin Li return super(TestStationHost, self).run(cmd, *args, **dargs) 137*9c5db199SXin Li 138*9c5db199SXin Li @retry.retry(error.GenericHostRunError, timeout_min=10) 139*9c5db199SXin Li def download_file(self, src_url, dest_file, unzip=False, unzip_dest=None): 140*9c5db199SXin Li """Download the given url. 141*9c5db199SXin Li 142*9c5db199SXin Li @param src_url: The url to download from. 143*9c5db199SXin Li @param dest_file: Destination for the file to be downloaded to. 144*9c5db199SXin Li @param unzip: If True, unzip the downloaded file. 145*9c5db199SXin Li @param unzip_dest: Location to unzip the downloaded file to. If not 146*9c5db199SXin Li provided, dest_file's directory is used. 147*9c5db199SXin Li 148*9c5db199SXin Li @returns: The path of the downloaded file on the teststation. 149*9c5db199SXin Li """ 150*9c5db199SXin Li try: 151*9c5db199SXin Li self.run('wget -q -O "%s" "%s"' % (dest_file, src_url)) 152*9c5db199SXin Li 153*9c5db199SXin Li readlink_result = self.run('readlink -f "%s"' % dest_file) 154*9c5db199SXin Li full_path = readlink_result.stdout.splitlines()[0] 155*9c5db199SXin Li 156*9c5db199SXin Li if unzip: 157*9c5db199SXin Li unzip_dest = unzip_dest or os.path.dirname(full_path) 158*9c5db199SXin Li self.run('unzip "%s" -x -d "%s"' % (dest_file, unzip_dest)) 159*9c5db199SXin Li 160*9c5db199SXin Li return full_path 161*9c5db199SXin Li except: 162*9c5db199SXin Li # Delete the destination file if download failed. 163*9c5db199SXin Li self.run('rm -f "%s"' % dest_file) 164*9c5db199SXin Li raise 165