1# Copyright 2017 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 5"""Check USB device by running linux command on CfM""" 6 7from __future__ import print_function 8 9import logging 10import re 11import six 12import time 13import common 14from autotest_lib.client.common_lib.cros.manual import get_usb_devices 15from autotest_lib.client.common_lib.cros import cros_config 16from autotest_lib.client.common_lib.cros import power_cycle_usb_util 17 18CORE_DIR_LINES = 3 19ATRUS = '18d1:8001' 20 21def check_chrome_logfile(dut): 22 """ 23 Get the latest chrome log file. 24 @param dut: The handle of the device under test. 25 @returns: the latest chrome log file 26 """ 27 output = None 28 logging.info('---Get the latest chrome log file') 29 cmd = 'ls -latr /var/log/chrome/chrome' 30 try: 31 output = dut.run(cmd, ignore_status=True).stdout 32 except Exception as e: 33 logging.exception('Fail to run command %s.', cmd) 34 return None 35 logging.info('---cmd: %s', cmd) 36 logging.info('---output: %s', output.lower().strip()) 37 return output 38 39def check_last_reboot(dut): 40 """ 41 Get the last line of eventlog.txt 42 @param dut: The handle of the device under test. 43 @returns: the last line in eventlog.txt 44 """ 45 output = None 46 cmd = 'tail -1 /var/log/eventlog.txt' 47 logging.info('---Get the latest reboot log') 48 try: 49 output = dut.run(cmd, ignore_status=True).stdout 50 except Exception as e: 51 logging.exception('Fail to run command %s.', cmd) 52 return None 53 logging.info('---cmd: %s', cmd) 54 logging.info('---output: %s', output.lower().strip()) 55 return output 56 57def check_is_platform(dut, name): 58 """ 59 Check whether CfM is expected platform. 60 @param dut: The handle of the device under test. 61 @param name: The name of platform 62 @returns: True, if CfM's platform is same as expected. 63 False, if not. 64 """ 65 cros_config_args = '/identity platform-name' 66 output = cros_config.call_cros_config_get_output(cros_config_args, 67 dut.run, ignore_status=True) 68 logging.info('---cmd: cros_config %s', cros_config_args) 69 logging.info('---output: %s', output.lower()) 70 return output.lower() == name 71 72 73def get_mgmt_ipv4(dut): 74 """ 75 Get mgmt ipv4 address 76 @param dut: The handle of the device under test. Should be initialized in 77 autotest. 78 @return: ipv4 address for mgmt interface. 79 """ 80 cmd = 'ifconfig -a | grep eth0 -A 2 | grep netmask' 81 try: 82 output = dut.run(cmd, ignore_status=True).stdout 83 except Exception as e: 84 logging.exception('Fail to run command %s.', cmd) 85 return None 86 ipv4 = re.findall(r"inet\s*([0-9.]+)\s*netmask.*", output)[0] 87 return ipv4 88 89 90def retrieve_usb_devices(dut): 91 """ 92 Populate output of usb-devices on CfM. 93 @param dut: handle of CfM under test 94 @returns dict of all usb devices detected on CfM. 95 """ 96 usb_devices = (dut.run('usb-devices', ignore_status=True). 97 stdout.strip().split('\n\n')) 98 usb_data = get_usb_devices.extract_usb_data( 99 '\nUSB-Device\n'+'\nUSB-Device\n'.join(usb_devices)) 100 return usb_data 101 102 103def extract_peripherals_for_cfm(usb_data): 104 """ 105 Check CfM has camera, speaker and Mimo connected. 106 @param usb_data: dict extracted from output of "usb-devices" 107 """ 108 peripheral_map = {} 109 get_devices_funcs = (get_usb_devices.get_speakers, 110 get_usb_devices.get_cameras, get_usb_devices.get_display_mimo, 111 get_usb_devices.get_controller_mimo) 112 for get_devices in get_devices_funcs: 113 device_list = get_devices(usb_data) 114 for pid_vid, device_count in six.iteritems(device_list): 115 if device_count > 0: 116 peripheral_map[pid_vid] = device_count 117 118 for pid_vid, device_count in six.iteritems(peripheral_map): 119 logging.info('---device: %s (%s), count: %d', 120 pid_vid, get_usb_devices.get_device_prod(pid_vid), 121 device_count) 122 123 return peripheral_map 124 125 126def check_peripherals_for_cfm(peripheral_map): 127 """ 128 Check CfM has one and only one camera, 129 one and only one speaker, 130 or one and only one mimo. 131 @param peripheral_map: dict for connected camera, speaker, or mimo. 132 @returns: True if check passes, 133 False if check fails. 134 """ 135 peripherals = peripheral_map.keys() 136 137 type_camera = set(peripherals).intersection(get_usb_devices.CAMERA_LIST) 138 type_speaker = set(peripherals).intersection(get_usb_devices.SPEAKER_LIST) 139 type_controller = set(peripherals).intersection(\ 140 get_usb_devices.TOUCH_CONTROLLER_LIST) 141 type_panel = set(peripherals).intersection(\ 142 get_usb_devices.TOUCH_DISPLAY_LIST) 143 144 # check CfM have one, and only one type camera, huddly and mimo 145 if len(type_camera) == 0: 146 logging.info('No camera is found on CfM.') 147 return False 148 149 if not len(type_camera) == 1: 150 logging.info('More than one type of cameras are found on CfM.') 151 return False 152 153 if len(type_speaker) == 0: 154 logging.info('No speaker is found on CfM.') 155 return False 156 157 if not len(type_speaker) == 1: 158 logging.info('More than one type of speakers are found on CfM.') 159 return False 160 161 if len(type_controller) == 0: 162 logging.info('No controller is found on CfM.') 163 return False 164 165 166 if not len(type_controller) == 1: 167 logging.info('More than one type of controller are found on CfM.') 168 return False 169 170 if len(type_panel) == 0: 171 logging.info('No Display is found on CfM.') 172 return False 173 174 if not len(type_panel) == 1: 175 logging.info('More than one type of displays are found on CfM.') 176 return False 177 178 # check CfM have only one camera, huddly and mimo 179 for pid_vid, device_count in six.iteritems(peripheral_map): 180 if device_count > 1: 181 logging.info('Number of device %s connected to CfM : %d', 182 get_usb_devices.get_device_prod(pid_vid), 183 device_count) 184 return False 185 186 return True 187 188 189def check_usb_enumeration(dut, puts): 190 """ 191 Check USB enumeration for devices 192 @param dut: the handle of CfM under test 193 @param puts: the list of peripherals under test 194 @returns True, none if test passes 195 False, errMsg if test test fails 196 """ 197 usb_data = retrieve_usb_devices(dut) 198 if not usb_data: 199 logging.warning('No usb devices found on DUT') 200 return False, 'No usb device found on DUT.' 201 else: 202 usb_device_list = extract_peripherals_for_cfm(usb_data) 203 logging.info('---usb device = %s', usb_device_list) 204 if not set(puts).issubset(set(usb_device_list.keys())): 205 logging.info('Detect device fails for usb enumeration') 206 logging.info('Expect enumerated devices: %s', puts) 207 logging.info('Actual enumerated devices: %s', 208 usb_device_list.keys()) 209 return False, 'Some usb devices are not found.' 210 return True, None 211 212 213def check_usb_interface_initializion(dut, puts): 214 """ 215 Check CfM shows valid interface for all peripherals connected. 216 @param dut: the handle of CfM under test 217 @param puts: the list of peripherals under test 218 @returns True, none if test passes 219 False, errMsg if test test fails 220 """ 221 usb_data = retrieve_usb_devices(dut) 222 for put in puts: 223 number, health = get_usb_devices.is_usb_device_ok(usb_data, put) 224 logging.info('---device interface = %d, %s for %s', 225 number, health, get_usb_devices.get_device_prod(put)) 226 if '0' in health: 227 logging.warning('Device %s has invalid interface', put) 228 return False, 'Device {} has invalid interface.'.format(put) 229 return True, None 230 231 232def clear_core_file(dut): 233 """clear core files""" 234 cmd = "rm -rf /var/spool/crash/*.*" 235 try: 236 dut.run_output(cmd) 237 except Exception as e: 238 logging.exception('Fail to clean core files under ' 239 '/var/spool/crash') 240 logging.exception('Fail to execute %s :', cmd) 241 242 243def check_process_crash(dut, cdlines): 244 """Check whether there is core file.""" 245 cmd = 'ls -latr /var/spool/crash' 246 try: 247 core_files_output = dut.run_output(cmd).splitlines() 248 except Exception as e: 249 logging.exception('Can not find file under /var/spool/crash.') 250 logging.exception('Fail to execute %s:', cmd) 251 return True, CORE_DIR_LINES 252 logging.info('---%s\n---%s', cmd, core_files_output) 253 if len(core_files_output) - cdlines <= 0: 254 logging.info('---length of files: %d', len(core_files_output)) 255 return True, len(core_files_output) 256 else: 257 return False, len(core_files_output) 258 259 260def gpio_usb_test(dut, gpio_list, device_list, pause, board): 261 """ 262 Run GPIO test to powercycle usb port. 263 @parama dut: handler of CfM, 264 @param gpio_list: the list of gpio ports, 265 @param device_list: the list of usb devices, 266 @param pause: time needs to wait before restoring power to usb port, 267 in seconds 268 @param board: board name for CfM 269 @returns True 270 """ 271 for device in device_list: 272 vid, pid = device.split(':') 273 logging.info('---going to powercyle device %s:%s', vid, pid) 274 try: 275 power_cycle_usb_util.power_cycle_usb_vidpid(dut, board, 276 vid, pid, pause) 277 except Exception as e: 278 errmsg = 'Fail to power cycle device.' 279 logging.exception('%s.', errmsg) 280 return False, errmsg 281 282 return True, None 283 284 285def reboot_test(dut, pause): 286 """ 287 Reboot CfM. 288 @parama dut: handler of CfM, 289 @param pause: time needs to wait after issuing reboot command, in seconds, 290 291 """ 292 try: 293 dut.reboot() 294 except Exception as e: 295 logging.exception('Fail to reboot CfM.') 296 return False 297 logging.info('---reboot done') 298 time.sleep(pause) 299 return True 300 301 302 303def find_last_log(dut, speaker): 304 """ 305 Get the lastlast_lines line for log files. 306 @param dut: handler of CfM 307 @param speaker: vidpid if speaker. 308 @returns: the list of string of the last line of logs. 309 """ 310 last_lines = { 311 'messages':[], 312 'chrome':[], 313 'ui': [], 314 'atrus': [] 315 } 316 logging.debug('Get the last line of log file, speaker %s', speaker) 317 try: 318 cmd = "tail -1 /var/log/messages | awk -v N=1 '{print $N}'" 319 last_lines['messages'] = dut.run_output(cmd).strip().split()[0] 320 cmd = "tail -1 /var/log/chrome/chrome | awk -v N=1 '{print $N}'" 321 last_lines['chrome'] = dut.run_output(cmd).strip().split()[0] 322 cmd = "tail -1 /var/log/ui/ui.LATEST | awk -v N=1 '{print $N}'" 323 last_lines['ui']= dut.run_output(cmd) 324 if speaker == ATRUS and check_is_platform(dut, 'guado'): 325 logging.info('---atrus speaker %s connected to CfM', speaker) 326 cmd = 'tail -1 /var/log/atrus.log | awk -v N=1 "{print $N}"' 327 last_lines['atrus'] = dut.run_output(cmd).strip().split()[0] 328 except Exception as e: 329 logging.exception('Fail to get the last line from log files.') 330 for item, timestamp in six.iteritems(last_lines): 331 logging.debug('---%s: %s', item, timestamp) 332 return last_lines 333 334 335def collect_log_since_last_check(dut, lastlines, logfile): 336 """Collect log file since last check.""" 337 output = None 338 if logfile == "messages": 339 cmd ='awk \'/{}/,0\' /var/log/messages'.format(lastlines[logfile]) 340 if logfile == "chrome": 341 cmd ='awk \'/{}/,0\' /var/log/chrome/chrome'.format(lastlines[logfile]) 342 if logfile == "ui": 343 cmd ='awk \'/{}/,0\' /var/log/ui/ui.LATEST'.format(lastlines[logfile]) 344 if logfile == 'atrus': 345 cmd = 'awk \'/{}/,0\' /var/log/atrus.log'.format(lastlines[logfile]) 346 logging.info('---cmd = %s', cmd) 347 try: 348 output = dut.run_output(cmd).split('\n') 349 except Exception as e: 350 logging.exception('Fail to get output from log files.') 351 logging.info('---length of log: %d', len(output)) 352 if not output: 353 logging.info('--fail to find match log, check the latest log.') 354 355 if not output: 356 if logfile == "messages": 357 cmd ='cat /var/log/messages' 358 if logfile == "chrome": 359 cmd ='cat /var/log/chrome/chrome' 360 if logfile == "ui": 361 cmd ='cat /var/log/ui/ui.LATEST' 362 if logfile == 'atrus': 363 cmd ='cat /var/log/atrus.log' 364 output = dut.run_output(cmd).split('\n') 365 logging.info('---length of log: %d', len(output)) 366 return output 367 368def check_log(dut, timestamp, error_list, checkitem, logfile): 369 """ 370 Check logfile does not contain any element in error_list[checkitem]. 371 """ 372 error_log_list = [] 373 logging.info('---now check log %s in file %s', checkitem, logfile) 374 output = collect_log_since_last_check(dut, timestamp, logfile) 375 for _error in error_list[checkitem]: 376 error_log_list.extend([s for s in output if _error in str(s)]) 377 if not error_log_list: 378 return True, None 379 else: 380 tempmsg = '\n'.join(error_log_list) 381 errmsg = 'Error_Found:in_log_file:{}:{}.'.format(logfile, tempmsg) 382 logging.info('---%s', errmsg) 383 return False, errmsg 384