1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 4*9c5db199SXin Li# found in the LICENSE file. 5*9c5db199SXin Li 6*9c5db199SXin Li 7*9c5db199SXin Lifrom __future__ import absolute_import 8*9c5db199SXin Lifrom __future__ import division 9*9c5db199SXin Lifrom __future__ import print_function 10*9c5db199SXin Li 11*9c5db199SXin Liimport optparse 12*9c5db199SXin Liimport pickle 13*9c5db199SXin Liimport re 14*9c5db199SXin Liimport six 15*9c5db199SXin Liimport subprocess 16*9c5db199SXin Li 17*9c5db199SXin Liimport common 18*9c5db199SXin Li 19*9c5db199SXin Lifrom autotest_lib.client.cros.cellular import cellular 20*9c5db199SXin Lifrom autotest_lib.client.cros.cellular import cellular_logging 21*9c5db199SXin Lifrom autotest_lib.client.cros.cellular import labconfig_data 22*9c5db199SXin Li 23*9c5db199SXin Lilog = cellular_logging.SetupCellularLogging('labconfig') 24*9c5db199SXin Li 25*9c5db199SXin Li 26*9c5db199SXin Liclass LabConfigError(Exception): 27*9c5db199SXin Li """Exception thrown on bad lab configuration""" 28*9c5db199SXin Li pass 29*9c5db199SXin Li 30*9c5db199SXin Li 31*9c5db199SXin Lidef get_interface_ip(interface='eth0'): 32*9c5db199SXin Li """Returns the IP address for an interface, or None if not found. 33*9c5db199SXin Li @param interface: the interface to request IP address for. 34*9c5db199SXin Li """ 35*9c5db199SXin Li 36*9c5db199SXin Li # We'd like to use 37*9c5db199SXin Li # utils.system_output('ifconfig eth0 2>&1', retain_output=True) 38*9c5db199SXin Li # but that gives us a dependency on the rest of autotest, which 39*9c5db199SXin Li # means that running the unit test requires pythonpath manipulation 40*9c5db199SXin Li stdout = subprocess.Popen(['ip', '-4', 'addr', 'show', 'dev', interface], 41*9c5db199SXin Li stdout=subprocess.PIPE).communicate()[0] 42*9c5db199SXin Li 43*9c5db199SXin Li if six.PY2: 44*9c5db199SXin Li # stdout is a string in py2, but we need it to match a byte pattern. 45*9c5db199SXin Li stdout = stdout.encode('ascii') 46*9c5db199SXin Li match = re.search(b'inet ([0-9.]+)[/ ]', stdout) 47*9c5db199SXin Li if not match: 48*9c5db199SXin Li return None 49*9c5db199SXin Li return match.group(1).decode() 50*9c5db199SXin Li 51*9c5db199SXin Li 52*9c5db199SXin Liclass Configuration(object): 53*9c5db199SXin Li """Configuration for a cellular test. 54*9c5db199SXin Li 55*9c5db199SXin Li This includes things like the address of the cell emulator device 56*9c5db199SXin Li and details of the RF switching between the emulated basestation 57*9c5db199SXin Li and the DUT.""" 58*9c5db199SXin Li 59*9c5db199SXin Li def __init__(self, args): 60*9c5db199SXin Li # For server tests, this constructor runs as part of the 61*9c5db199SXin Li # server control file, on whatever machine the test was 62*9c5db199SXin Li # started on. 63*9c5db199SXin Li parser = optparse.OptionParser() 64*9c5db199SXin Li 65*9c5db199SXin Li # Record our args so we can serialize ourself. 66*9c5db199SXin Li self.args = args 67*9c5db199SXin Li 68*9c5db199SXin Li self.ip = None 69*9c5db199SXin Li 70*9c5db199SXin Li parser.add_option('--cell', dest='cell', default=None, 71*9c5db199SXin Li help='Cellular test cell to use') 72*9c5db199SXin Li parser.add_option( 73*9c5db199SXin Li '--technology', dest='technology', default='all', 74*9c5db199SXin Li help='Radio access technologies to use (e.g. "WCDMA")') 75*9c5db199SXin Li (self.options, _) = parser.parse_args(args) 76*9c5db199SXin Li 77*9c5db199SXin Li self.cell = self._get_cell(self.options.cell) 78*9c5db199SXin Li 79*9c5db199SXin Li def _get_cell(self, name): 80*9c5db199SXin Li """Extracts the named cell from labconfig_data.CELLS.""" 81*9c5db199SXin Li if not name: 82*9c5db199SXin Li raise LabConfigError( 83*9c5db199SXin Li 'Could not find --cell argument. ' + 84*9c5db199SXin Li 'To specify a cell, pass --args=--cell=foo to test_that') 85*9c5db199SXin Li 86*9c5db199SXin Li if name not in labconfig_data.CELLS: 87*9c5db199SXin Li raise LabConfigError( 88*9c5db199SXin Li 'Could not find cell %s, valid cells are %s' % ( 89*9c5db199SXin Li name, list(labconfig_data.CELLS.keys()))) 90*9c5db199SXin Li 91*9c5db199SXin Li return labconfig_data.CELLS[name] 92*9c5db199SXin Li 93*9c5db199SXin Li def _get_dut(self, machine=None): 94*9c5db199SXin Li """Returns the DUT record for machine from cell["duts"] 95*9c5db199SXin Li Args: 96*9c5db199SXin Li machine: name or IP of machine. None: for "the current machine". 97*9c5db199SXin Li 98*9c5db199SXin Li Right now, we use the interface of eth0 to figure out which 99*9c5db199SXin Li machine we're running on. The important thing is that this 100*9c5db199SXin Li matches the IP address in the cell duts configuration. We'll 101*9c5db199SXin Li have to come up with a better way if this proves brittle.""" 102*9c5db199SXin Li 103*9c5db199SXin Li # TODO(byronk) : crosbug.com/235911: 104*9c5db199SXin Li # autotest: Getting IP address from eth0 by name is brittle 105*9c5db199SXin Li if self.ip and not machine: 106*9c5db199SXin Li machine = self.ip 107*9c5db199SXin Li ifconfig = '' 108*9c5db199SXin Li if not machine: 109*9c5db199SXin Li log.debug('self.ip is : %s ', self.ip) 110*9c5db199SXin Li # TODO(byronk): use sysfs to find network interface 111*9c5db199SXin Li possible_interfaces = ['eth0', 'eth1', 'eth_test'] 112*9c5db199SXin Li log.debug('Looking for an up network interface in : %s', 113*9c5db199SXin Li possible_interfaces) 114*9c5db199SXin Li for interface in possible_interfaces: 115*9c5db199SXin Li machine = get_interface_ip(interface) 116*9c5db199SXin Li if machine: 117*9c5db199SXin Li log.debug('Got an IP address: %s Stopping the search.. ', 118*9c5db199SXin Li machine) 119*9c5db199SXin Li self.ip = machine 120*9c5db199SXin Li break 121*9c5db199SXin Li else: 122*9c5db199SXin Li ifconfig = subprocess.Popen(['ip', 'addr', 'show'], 123*9c5db199SXin Li stdout=subprocess.PIPE).communicate()[0] 124*9c5db199SXin Li if not machine: 125*9c5db199SXin Li raise LabConfigError( 126*9c5db199SXin Li 'Could not determine which machine we are.\n' 127*9c5db199SXin Li ' Cell = %s \n' % self.options.cell + 128*9c5db199SXin Li 'Tried these interface names: %s \n' % possible_interfaces + 129*9c5db199SXin Li '`ip addr show` output:\n%s' % ifconfig 130*9c5db199SXin Li ) 131*9c5db199SXin Li 132*9c5db199SXin Li for dut in self.cell["duts"]: 133*9c5db199SXin Li if machine == dut["address"] or machine == dut["name"]: 134*9c5db199SXin Li return dut 135*9c5db199SXin Li 136*9c5db199SXin Li raise LabConfigError( 137*9c5db199SXin Li 'This machine %s not matching: (%s,%s) in config. Cell = %s: %s' % 138*9c5db199SXin Li (machine, dut['address'], 139*9c5db199SXin Li dut['name'], self.options.cell, self.cell['duts'])) 140*9c5db199SXin Li 141*9c5db199SXin Li def get_technologies(self, machine=None): 142*9c5db199SXin Li """Gets technologies to use for machine; defaults to all available. 143*9c5db199SXin Li @param machine: Machine to get technologies for. 144*9c5db199SXin Li """ 145*9c5db199SXin Li technologies_list = self.options.technology.split(',') 146*9c5db199SXin Li 147*9c5db199SXin Li if 'all' in technologies_list: 148*9c5db199SXin Li m = self._get_dut(machine) 149*9c5db199SXin Li technologies_list = m["technologies"] 150*9c5db199SXin Li 151*9c5db199SXin Li enums = [getattr(cellular.Technology, t, None) 152*9c5db199SXin Li for t in technologies_list] 153*9c5db199SXin Li 154*9c5db199SXin Li if None in enums: 155*9c5db199SXin Li raise LabConfigError( 156*9c5db199SXin Li 'Could not understand a technology in %s' % technologies_list) 157*9c5db199SXin Li 158*9c5db199SXin Li return enums 159*9c5db199SXin Li 160*9c5db199SXin Li def get_rf_switch_port(self, machine=None): 161*9c5db199SXin Li """Get the RF Switch Port for the specified machine. 162*9c5db199SXin Li @param machine: machine to get rf switch port for 163*9c5db199SXin Li """ 164*9c5db199SXin Li dut = self._get_dut(machine) 165*9c5db199SXin Li print(dut) 166*9c5db199SXin Li return dut['rf_switch_port'] 167*9c5db199SXin Li 168*9c5db199SXin Li def get_pickle(self): 169*9c5db199SXin Li """Get pickled object.""" 170*9c5db199SXin Li return pickle.dumps(self) 171