1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import subprocess 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.common_lib import utils 10from autotest_lib.server import test 11from autotest_lib.server import frontend 12 13class moblab_Setup(test.test): 14 """ Moblab server test that checks for a specified number of 15 connected DUTs and that those DUTs have specified labels. Used to 16 verify the setup before kicking off a long running test suite. 17 """ 18 version = 1 19 20 def run_once(self, required_duts=1, required_labels=[]): 21 """ Tests the moblab's connected DUTs to see if the current 22 configuration is valid for a specific test. 23 24 @param required_duts [int] number of _live_ DUTs required to run 25 the test in question. A DUT is not live if it is in a failed 26 repair state 27 @param required_labels [list<string>] list of labels that are 28 required to be on at least one _live_ DUT for this test. 29 """ 30 logging.info('required_duts=%d required_labels=%s' % 31 (required_duts, str(required_labels))) 32 33 # creating a client to connect to autotest rpc interface 34 # all available rpc calls are defined in 35 # src/third_party/autotest/files/server/frontend.py 36 afe = frontend.AFE(server='localhost', user='moblab') 37 38 # get autotest statuses that indicate a live host 39 live_statuses = afe.host_statuses(live=True) 40 hosts = [] 41 # get the hosts connected to autotest, find the live ones 42 for host in afe.get_hosts(): 43 if host.status in live_statuses: 44 logging.info('Host %s is live, status %s' % 45 (host.hostname, host.status)) 46 hosts.append(host) 47 else: 48 logging.info('Host %s is not live, status %s' % 49 (host.hostname, host.status)) 50 51 # check that we have the required number of live duts 52 if len(hosts) < required_duts: 53 raise error.TestFail(('Suite requires %d DUTs, only %d connected' % 54 (required_duts, len(hosts)))) 55 56 required_labels_found = {} 57 for label in required_labels: 58 required_labels_found[label] = False 59 60 # check that at least one DUT has each required label 61 for host in hosts: 62 for label in host.get_labels(): 63 if label.name in required_labels_found: 64 required_labels_found[label.name] = True 65 # note: pools are stored as specially formatted labels 66 # to find if a DUT is in a pool, 67 # check if it has the label pool:mypoolname 68 for key in required_labels_found: 69 if not required_labels_found[key]: 70 raise error.TestFail('No DUT with required label %s' % key) 71 72 return 73 74 # to have autotest reverify that hosts are live, use the reverify_hosts 75 # rpc call 76 # note: this schedules a background asynchronous job, and 77 # logic to check back in on hosts would need to be built 78 # reverify_hostnames = [host.hostname for host in hosts] 79 # afe.reverify_hosts(hostnames=reverify_hostnames) 80 81 # example of running a command on the dut and getting the output back 82 # def run_ssh_command_on_dut(hostname, cmd): 83 # """ Run a command on a DUT via ssh 84 # 85 # @return output of the command 86 # @raises subprocess.CalledProcessError if the ssh command fails, 87 # such as a connection couldn't be established 88 # """ 89 # ssh_cmd = ('ssh -o ConnectTimeout=2 -o StrictHostKeyChecking=no ' 90 # "root@%s '%s'") % (hostname, cmd) 91 # return subprocess.check_output(ssh_cmd, shell=True) 92 # for host in hosts: 93 # logging.info(run_ssh_command_on_dut( 94 # host.hostname, 'cat /etc/lsb-release')) 95