Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """A class to keep track of devices across builds and report state.""" | 7 """A class to keep track of devices across builds and report state.""" |
| 8 import json | 8 import json |
| 9 import logging | 9 import logging |
| 10 import optparse | 10 import optparse |
| 11 import os | 11 import os |
| 12 import psutil | 12 import psutil |
| 13 import re | 13 import re |
| 14 import signal | 14 import signal |
| 15 import smtplib | 15 import smtplib |
| 16 import subprocess | 16 import subprocess |
| 17 import sys | 17 import sys |
| 18 import time | 18 import time |
| 19 import urllib | 19 import urllib |
| 20 | 20 |
| 21 import bb_annotations | 21 import bb_annotations |
| 22 import bb_utils | 22 import bb_utils |
| 23 | 23 |
| 24 sys.path.append(os.path.join(os.path.dirname(__file__), | 24 sys.path.append(os.path.join(os.path.dirname(__file__), |
| 25 os.pardir, os.pardir, 'util', 'lib', | 25 os.pardir, os.pardir, 'util', 'lib', |
| 26 'common')) | 26 'common')) |
| 27 import perf_tests_results_helper # pylint: disable=F0401 | 27 import perf_tests_results_helper # pylint: disable=F0401 |
| 28 | 28 |
| 29 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) | 29 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
| 30 from pylib import android_commands | |
| 31 from pylib import constants | 30 from pylib import constants |
| 32 from pylib.cmd_helper import GetCmdOutput | 31 from pylib.cmd_helper import GetCmdOutput |
| 32 from pylib.device import adb_wrapper | |
| 33 from pylib.device import battery_utils | 33 from pylib.device import battery_utils |
| 34 from pylib.device import device_blacklist | 34 from pylib.device import device_blacklist |
| 35 from pylib.device import device_errors | 35 from pylib.device import device_errors |
| 36 from pylib.device import device_list | 36 from pylib.device import device_list |
| 37 from pylib.device import device_utils | 37 from pylib.device import device_utils |
| 38 from pylib.utils import run_tests_helper | 38 from pylib.utils import run_tests_helper |
| 39 | 39 |
| 40 _RE_DEVICE_ID = re.compile('Device ID = (\d+)') | 40 _RE_DEVICE_ID = re.compile('Device ID = (\d+)') |
| 41 | 41 |
| 42 def DeviceInfo(serial, options): | 42 def DeviceInfo(device, options): |
| 43 """Gathers info on a device via various adb calls. | 43 """Gathers info on a device via various adb calls. |
| 44 | 44 |
| 45 Args: | 45 Args: |
| 46 serial: The serial of the attached device to construct info about. | 46 device: A DeviceUtils instance for the device to construct info about. |
| 47 | 47 |
| 48 Returns: | 48 Returns: |
| 49 Tuple of device type, build id, report as a string, error messages, and | 49 Tuple of device type, build id, report as a string, error messages, and |
| 50 boolean indicating whether or not device can be used for testing. | 50 boolean indicating whether or not device can be used for testing. |
| 51 """ | 51 """ |
| 52 device = device_utils.DeviceUtils(serial) | |
| 53 battery = battery_utils.BatteryUtils(device) | 52 battery = battery_utils.BatteryUtils(device) |
| 54 | 53 |
| 55 battery_info = {} | 54 battery_info = {} |
| 56 battery_level = 100 | 55 battery_level = 100 |
| 57 errors = [] | 56 errors = [] |
| 58 dev_good = True | 57 dev_good = True |
| 59 json_data = { | 58 json_data = { |
| 60 'serial': serial, | 59 'serial': device.adb.GetDeviceSerial(), |
| 61 'type': device.build_product, | 60 'type': device.build_product, |
| 62 'build': device.build_id, | 61 'build': device.build_id, |
| 63 'build_detail': device.GetProp('ro.build.fingerprint'), | 62 'build_detail': device.GetProp('ro.build.fingerprint'), |
| 64 'battery': {}, | 63 'battery': {}, |
| 65 'imei_slice': 'Unknown', | 64 'imei_slice': 'Unknown', |
| 66 'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'), | 65 'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'), |
| 67 } | 66 } |
| 68 | 67 |
| 69 try: | 68 try: |
| 70 try: | 69 try: |
| 71 battery_info = battery.GetBatteryInfo(timeout=5) | 70 battery_info = battery.GetBatteryInfo(timeout=5) |
| 72 battery_level = int(battery_info.get('level', battery_level)) | 71 battery_level = int(battery_info.get('level', battery_level)) |
| 73 json_data['battery'] = battery_info | 72 json_data['battery'] = battery_info |
| 74 except device_errors.CommandFailedError: | 73 except device_errors.CommandFailedError: |
| 75 logging.exception('Failed to get battery information for %s', serial) | 74 logging.exception('Failed to get battery information for %s', str(device)) |
| 76 | 75 |
| 77 try: | 76 try: |
| 78 for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'], | 77 for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'], |
| 79 check_return=True, timeout=5): | 78 check_return=True, timeout=5): |
| 80 m = _RE_DEVICE_ID.match(l) | 79 m = _RE_DEVICE_ID.match(l) |
| 81 if m: | 80 if m: |
| 82 json_data['imei_slice'] = m.group(1)[-6:] | 81 json_data['imei_slice'] = m.group(1)[-6:] |
| 83 except device_errors.CommandFailedError: | 82 except device_errors.CommandFailedError: |
| 84 logging.exception('Failed to get IMEI slice for %s', serial) | 83 logging.exception('Failed to get IMEI slice for %s', str(device)) |
| 85 | 84 |
| 86 if battery_level < 15: | 85 if battery_level < 15: |
| 87 errors += ['Device critically low in battery.'] | 86 errors += ['Device critically low in battery.'] |
| 88 dev_good = False | 87 dev_good = False |
| 89 if not battery.GetCharging(): | 88 if not battery.GetCharging(): |
| 90 battery.SetCharging(True) | 89 battery.SetCharging(True) |
| 91 if not options.no_provisioning_check: | 90 if not options.no_provisioning_check: |
| 92 setup_wizard_disabled = ( | 91 setup_wizard_disabled = ( |
| 93 device.GetProp('ro.setupwizard.mode') == 'DISABLED') | 92 device.GetProp('ro.setupwizard.mode') == 'DISABLED') |
| 94 if not setup_wizard_disabled and device.build_type != 'user': | 93 if not setup_wizard_disabled and device.build_type != 'user': |
| 95 errors += ['Setup wizard not disabled. Was it provisioned correctly?'] | 94 errors += ['Setup wizard not disabled. Was it provisioned correctly?'] |
| 96 if (device.product_name == 'mantaray' and | 95 if (device.product_name == 'mantaray' and |
| 97 battery_info.get('AC powered', None) != 'true'): | 96 battery_info.get('AC powered', None) != 'true'): |
| 98 errors += ['Mantaray device not connected to AC power.'] | 97 errors += ['Mantaray device not connected to AC power.'] |
| 99 except device_errors.CommandFailedError: | 98 except device_errors.CommandFailedError: |
| 100 logging.exception('Failure while getting device status.') | 99 logging.exception('Failure while getting device status.') |
| 101 dev_good = False | 100 dev_good = False |
| 102 except device_errors.CommandTimeoutError: | 101 except device_errors.CommandTimeoutError: |
| 103 logging.exception('Timeout while getting device status.') | 102 logging.exception('Timeout while getting device status.') |
| 104 dev_good = False | 103 dev_good = False |
| 105 | 104 |
| 106 return (device.build_product, device.build_id, battery_level, errors, | 105 return (device.build_product, device.build_id, battery_level, errors, |
| 107 dev_good, json_data) | 106 dev_good, json_data) |
| 108 | 107 |
| 109 | 108 |
| 110 def CheckForMissingDevices(options, adb_online_devs): | 109 def CheckForMissingDevices(options, devices): |
| 111 """Uses file of previous online devices to detect broken phones. | 110 """Uses file of previous online devices to detect broken phones. |
| 112 | 111 |
| 113 Args: | 112 Args: |
| 114 options: out_dir parameter of options argument is used as the base | 113 options: out_dir parameter of options argument is used as the base |
| 115 directory to load and update the cache file. | 114 directory to load and update the cache file. |
| 116 adb_online_devs: A list of serial numbers of the currently visible | 115 devices: A list of DeviceUtils instance for the currently visible and |
| 117 and online attached devices. | 116 online attached devices. |
| 118 """ | 117 """ |
| 119 out_dir = os.path.abspath(options.out_dir) | 118 out_dir = os.path.abspath(options.out_dir) |
| 119 device_serials = set(d.adb.GetDeviceSerial() for d in devices) | |
| 120 | 120 |
| 121 # last_devices denotes all known devices prior to this run | 121 # last_devices denotes all known devices prior to this run |
| 122 last_devices_path = os.path.join(out_dir, device_list.LAST_DEVICES_FILENAME) | 122 last_devices_path = os.path.join(out_dir, device_list.LAST_DEVICES_FILENAME) |
| 123 last_missing_devices_path = os.path.join(out_dir, | 123 last_missing_devices_path = os.path.join(out_dir, |
| 124 device_list.LAST_MISSING_DEVICES_FILENAME) | 124 device_list.LAST_MISSING_DEVICES_FILENAME) |
| 125 try: | 125 try: |
| 126 last_devices = device_list.GetPersistentDeviceList(last_devices_path) | 126 last_devices = device_list.GetPersistentDeviceList(last_devices_path) |
| 127 except IOError: | 127 except IOError: |
| 128 # Ignore error, file might not exist | 128 # Ignore error, file might not exist |
| 129 last_devices = [] | 129 last_devices = [] |
| 130 | 130 |
| 131 try: | 131 try: |
| 132 last_missing_devices = device_list.GetPersistentDeviceList( | 132 last_missing_devices = device_list.GetPersistentDeviceList( |
| 133 last_missing_devices_path) | 133 last_missing_devices_path) |
| 134 except IOError: | 134 except IOError: |
| 135 last_missing_devices = [] | 135 last_missing_devices = [] |
| 136 | 136 |
| 137 missing_devs = list(set(last_devices) - set(adb_online_devs)) | 137 missing_devs = list(set(last_devices) - device_serials) |
| 138 new_missing_devs = list(set(missing_devs) - set(last_missing_devices)) | 138 new_missing_devs = list(set(missing_devs) - set(last_missing_devices)) |
| 139 | 139 |
| 140 if new_missing_devs and os.environ.get('BUILDBOT_SLAVENAME'): | 140 if new_missing_devs and os.environ.get('BUILDBOT_SLAVENAME'): |
| 141 logging.info('new_missing_devs %s' % new_missing_devs) | 141 logging.info('new_missing_devs %s' % new_missing_devs) |
| 142 devices_missing_msg = '%d devices not detected.' % len(missing_devs) | 142 devices_missing_msg = '%d devices not detected.' % len(missing_devs) |
| 143 bb_annotations.PrintSummaryText(devices_missing_msg) | 143 bb_annotations.PrintSummaryText(devices_missing_msg) |
| 144 | 144 |
| 145 from_address = 'chrome-bot@chromium.org' | 145 from_address = 'chrome-bot@chromium.org' |
| 146 to_addresses = ['chrome-labs-tech-ticket@google.com', | 146 to_addresses = ['chrome-labs-tech-ticket@google.com', |
| 147 'chrome-android-device-alert@google.com'] | 147 'chrome-android-device-alert@google.com'] |
| 148 cc_addresses = ['chrome-android-device-alert@google.com'] | 148 cc_addresses = ['chrome-android-device-alert@google.com'] |
| 149 subject = 'Devices offline on %s, %s, %s' % ( | 149 subject = 'Devices offline on %s, %s, %s' % ( |
| 150 os.environ.get('BUILDBOT_SLAVENAME'), | 150 os.environ.get('BUILDBOT_SLAVENAME'), |
| 151 os.environ.get('BUILDBOT_BUILDERNAME'), | 151 os.environ.get('BUILDBOT_BUILDERNAME'), |
| 152 os.environ.get('BUILDBOT_BUILDNUMBER')) | 152 os.environ.get('BUILDBOT_BUILDNUMBER')) |
| 153 msg = ('Please reboot the following devices:\n%s' % | 153 msg = ('Please reboot the following devices:\n%s' % |
| 154 '\n'.join(map(str, new_missing_devs))) | 154 '\n'.join(map(str, new_missing_devs))) |
| 155 SendEmail(from_address, to_addresses, cc_addresses, subject, msg) | 155 SendEmail(from_address, to_addresses, cc_addresses, subject, msg) |
| 156 | 156 |
| 157 all_known_devices = list(set(adb_online_devs) | set(last_devices)) | 157 all_known_devices = list(device_serials | set(last_devices)) |
| 158 device_list.WritePersistentDeviceList(last_devices_path, all_known_devices) | 158 device_list.WritePersistentDeviceList(last_devices_path, all_known_devices) |
| 159 device_list.WritePersistentDeviceList(last_missing_devices_path, missing_devs) | 159 device_list.WritePersistentDeviceList(last_missing_devices_path, missing_devs) |
| 160 | 160 |
| 161 if not all_known_devices: | 161 if not all_known_devices: |
| 162 # This can happen if for some reason the .last_devices file is not | 162 # This can happen if for some reason the .last_devices file is not |
| 163 # present or if it was empty. | 163 # present or if it was empty. |
| 164 return ['No online devices. Have any devices been plugged in?'] | 164 return ['No online devices. Have any devices been plugged in?'] |
| 165 if missing_devs: | 165 if missing_devs: |
| 166 devices_missing_msg = '%d devices not detected.' % len(missing_devs) | 166 devices_missing_msg = '%d devices not detected.' % len(missing_devs) |
| 167 bb_annotations.PrintSummaryText(devices_missing_msg) | 167 bb_annotations.PrintSummaryText(devices_missing_msg) |
| 168 | 168 return ['Current online devices: %s' % ', '.join(d for d in device_serials), |
| 169 # TODO(navabi): Debug by printing both output from GetCmdOutput and | 169 '%s are no longer visible. Were they removed?' % missing_devs] |
| 170 # GetAttachedDevices to compare results. | |
| 171 crbug_link = ('https://code.google.com/p/chromium/issues/entry?summary=' | |
| 172 '%s&comment=%s&labels=Restrict-View-Google,OS-Android,Infra' % | |
| 173 (urllib.quote('Device Offline'), | |
| 174 urllib.quote('Buildbot: %s %s\n' | |
| 175 'Build: %s\n' | |
| 176 '(please don\'t change any labels)' % | |
| 177 (os.environ.get('BUILDBOT_BUILDERNAME'), | |
| 178 os.environ.get('BUILDBOT_SLAVENAME'), | |
| 179 os.environ.get('BUILDBOT_BUILDNUMBER'))))) | |
| 180 return ['Current online devices: %s' % adb_online_devs, | |
| 181 '%s are no longer visible. Were they removed?' % missing_devs, | |
| 182 'SHERIFF:', | |
| 183 '@@@STEP_LINK@Click here to file a bug@%s@@@' % crbug_link, | |
| 184 'Cache file: %s' % last_devices_path, | |
| 185 'adb devices: %s' % GetCmdOutput(['adb', 'devices']), | |
| 186 'adb devices(GetAttachedDevices): %s' % adb_online_devs] | |
| 187 else: | 170 else: |
| 188 new_devs = set(adb_online_devs) - set(last_devices) | 171 new_devs = device_serials - set(last_devices) |
| 189 if new_devs and os.path.exists(last_devices_path): | 172 if new_devs and os.path.exists(last_devices_path): |
| 190 bb_annotations.PrintWarning() | 173 bb_annotations.PrintWarning() |
| 191 bb_annotations.PrintSummaryText( | 174 bb_annotations.PrintSummaryText( |
| 192 '%d new devices detected' % len(new_devs)) | 175 '%d new devices detected' % len(new_devs)) |
| 193 logging.info('New devices detected:') | 176 logging.info('New devices detected:') |
| 194 for d in new_devs: | 177 for d in new_devs: |
| 195 logging.info(' %s', d) | 178 logging.info(' %s', d) |
| 196 | 179 |
| 197 | 180 |
| 198 def SendEmail(from_address, to_addresses, cc_addresses, subject, msg): | 181 def SendEmail(from_address, to_addresses, cc_addresses, subject, msg): |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 run_tests_helper.SetLogLevel(options.verbose) | 273 run_tests_helper.SetLogLevel(options.verbose) |
| 291 | 274 |
| 292 # Remove the last build's "bad devices" before checking device statuses. | 275 # Remove the last build's "bad devices" before checking device statuses. |
| 293 device_blacklist.ResetBlacklist() | 276 device_blacklist.ResetBlacklist() |
| 294 | 277 |
| 295 try: | 278 try: |
| 296 expected_devices = device_list.GetPersistentDeviceList( | 279 expected_devices = device_list.GetPersistentDeviceList( |
| 297 os.path.join(options.out_dir, device_list.LAST_DEVICES_FILENAME)) | 280 os.path.join(options.out_dir, device_list.LAST_DEVICES_FILENAME)) |
| 298 except IOError: | 281 except IOError: |
| 299 expected_devices = [] | 282 expected_devices = [] |
| 300 devices = android_commands.GetAttachedDevices() | 283 devices = device_utils.DeviceUtils.HealthyDevices() |
| 284 device_serials = [d.adb.GetDeviceSerial() for d in devices] | |
| 301 # Only restart usb if devices are missing. | 285 # Only restart usb if devices are missing. |
| 302 if set(expected_devices) != set(devices): | 286 if set(expected_devices) != set(device_serials): |
| 303 logging.warning('expected_devices: %s', expected_devices) | 287 logging.warning('expected_devices: %s', expected_devices) |
| 304 logging.warning('devices: %s', devices) | 288 logging.warning('devices: %s', device_serials) |
| 305 KillAllAdb() | 289 KillAllAdb() |
| 306 retries = 5 | 290 retries = 5 |
| 307 usb_restarted = True | 291 usb_restarted = True |
| 308 if options.restart_usb: | 292 if options.restart_usb: |
| 309 if not RestartUsb(): | 293 if not RestartUsb(): |
| 310 usb_restarted = False | 294 usb_restarted = False |
| 311 bb_annotations.PrintWarning() | 295 bb_annotations.PrintWarning() |
| 312 logging.error('USB reset stage failed, ' | 296 logging.error('USB reset stage failed, ' |
| 313 'wait for any device to come back.') | 297 'wait for any device to come back.') |
| 314 while retries: | 298 while retries: |
| 315 logging.info('retry adb devices...') | 299 logging.info('retry adb devices...') |
| 316 time.sleep(1) | 300 time.sleep(1) |
| 317 devices = android_commands.GetAttachedDevices() | 301 devices = device_utils.DeviceUtils.HealthyDevices() |
| 318 if set(expected_devices) == set(devices): | 302 device_serials = [d.adb.GetDeviceSerial() for d in devices] |
| 303 if set(expected_devices) == set(device_serials): | |
| 319 # All devices are online, keep going. | 304 # All devices are online, keep going. |
| 320 break | 305 break |
| 321 if not usb_restarted and devices: | 306 if not usb_restarted and devices: |
| 322 # The USB wasn't restarted, but there's at least one device online. | 307 # The USB wasn't restarted, but there's at least one device online. |
| 323 # No point in trying to wait for all devices. | 308 # No point in trying to wait for all devices. |
| 324 break | 309 break |
| 325 retries -= 1 | 310 retries -= 1 |
| 326 | 311 |
| 327 # TODO(navabi): Test to make sure this fails and then fix call | 312 # TODO(navabi): Test to make sure this fails and then fix call |
|
navabi
2015/05/19 20:21:00
Remove this TODO. I assume it is referring to the
| |
| 328 offline_devices = android_commands.GetAttachedDevices( | |
| 329 hardware=False, emulator=False, offline=True) | |
| 330 | |
| 331 types, builds, batteries, errors, devices_ok, json_data = ( | 313 types, builds, batteries, errors, devices_ok, json_data = ( |
| 332 [], [], [], [], [], []) | 314 [], [], [], [], [], []) |
| 333 if devices: | 315 if devices: |
| 334 types, builds, batteries, errors, devices_ok, json_data = ( | 316 types, builds, batteries, errors, devices_ok, json_data = ( |
| 335 zip(*[DeviceInfo(dev, options) for dev in devices])) | 317 zip(*[DeviceInfo(dev, options) for dev in devices])) |
| 336 | 318 |
| 337 # Write device info to file for buildbot info display. | 319 # Write device info to file for buildbot info display. |
| 338 if os.path.exists('/home/chrome-bot'): | 320 if os.path.exists('/home/chrome-bot'): |
| 339 with open('/home/chrome-bot/.adb_device_info', 'w') as f: | 321 with open('/home/chrome-bot/.adb_device_info', 'w') as f: |
| 340 for device in json_data: | 322 for device in json_data: |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 356 for j in json_data: | 338 for j in json_data: |
| 357 logging.info('Device %s (%s)', j.get('serial'), j.get('type')) | 339 logging.info('Device %s (%s)', j.get('serial'), j.get('type')) |
| 358 logging.info(' Build: %s (%s)', j.get('build'), j.get('build_detail')) | 340 logging.info(' Build: %s (%s)', j.get('build'), j.get('build_detail')) |
| 359 logging.info(' Current Battery Service state:') | 341 logging.info(' Current Battery Service state:') |
| 360 for k, v in j.get('battery', {}).iteritems(): | 342 for k, v in j.get('battery', {}).iteritems(): |
| 361 logging.info(' %s: %s', k, v) | 343 logging.info(' %s: %s', k, v) |
| 362 logging.info(' IMEI slice: %s', j.get('imei_slice')) | 344 logging.info(' IMEI slice: %s', j.get('imei_slice')) |
| 363 logging.info(' WiFi IP: %s', j.get('wifi_ip')) | 345 logging.info(' WiFi IP: %s', j.get('wifi_ip')) |
| 364 | 346 |
| 365 | 347 |
| 366 for serial, dev_errors in zip(devices, errors): | 348 for dev, dev_errors in zip(devices, errors): |
| 367 if dev_errors: | 349 if dev_errors: |
| 368 err_msg += ['%s errors:' % serial] | 350 err_msg += ['%s errors:' % str(dev)] |
| 369 err_msg += [' %s' % error for error in dev_errors] | 351 err_msg += [' %s' % error for error in dev_errors] |
| 370 | 352 |
| 371 if err_msg: | 353 if err_msg: |
| 372 bb_annotations.PrintWarning() | 354 bb_annotations.PrintWarning() |
| 373 for e in err_msg: | 355 for e in err_msg: |
| 374 logging.error(e) | 356 logging.error(e) |
| 375 from_address = 'buildbot@chromium.org' | 357 from_address = 'buildbot@chromium.org' |
| 376 to_addresses = ['chromium-android-device-alerts@google.com'] | 358 to_addresses = ['chromium-android-device-alerts@google.com'] |
| 377 bot_name = os.environ.get('BUILDBOT_BUILDERNAME') | 359 bot_name = os.environ.get('BUILDBOT_BUILDERNAME') |
| 378 slave_name = os.environ.get('BUILDBOT_SLAVENAME') | 360 slave_name = os.environ.get('BUILDBOT_SLAVENAME') |
| 379 subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name) | 361 subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name) |
| 380 SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg)) | 362 SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg)) |
| 381 | 363 |
| 382 if options.device_status_dashboard: | 364 if options.device_status_dashboard: |
| 365 offline_devices = [ | |
| 366 device_utils.DeviceUtils(a) | |
| 367 for a in adb_wrapper.AdbWrapper.Devices(is_ready=False) | |
| 368 if a.GetState() == 'offline'] | |
| 369 | |
| 383 perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices', | 370 perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices', |
| 384 [len(devices)], 'devices') | 371 [len(devices)], 'devices') |
| 385 perf_tests_results_helper.PrintPerfResult('BotDevices', 'OfflineDevices', | 372 perf_tests_results_helper.PrintPerfResult('BotDevices', 'OfflineDevices', |
| 386 [len(offline_devices)], 'devices', | 373 [len(offline_devices)], 'devices', |
| 387 'unimportant') | 374 'unimportant') |
| 388 for serial, battery in zip(devices, batteries): | 375 for dev, battery in zip(devices, batteries): |
| 389 perf_tests_results_helper.PrintPerfResult('DeviceBattery', serial, | 376 perf_tests_results_helper.PrintPerfResult('DeviceBattery', str(dev), |
| 390 [battery], '%', | 377 [battery], '%', |
| 391 'unimportant') | 378 'unimportant') |
| 392 | 379 |
| 393 if options.json_output: | 380 if options.json_output: |
| 394 with open(options.json_output, 'wb') as f: | 381 with open(options.json_output, 'wb') as f: |
| 395 f.write(json.dumps(json_data, indent=4)) | 382 f.write(json.dumps(json_data, indent=4)) |
| 396 | 383 |
| 397 num_failed_devs = 0 | 384 num_failed_devs = 0 |
| 398 for device_ok, device in zip(devices_ok, devices): | 385 for device_ok, device in zip(devices_ok, devices): |
| 399 if not device_ok: | 386 if not device_ok: |
| 400 logging.warning('Blacklisting %s', str(device)) | 387 logging.warning('Blacklisting %s', str(device)) |
| 401 device_blacklist.ExtendBlacklist([str(device)]) | 388 device_blacklist.ExtendBlacklist([str(device)]) |
| 402 num_failed_devs += 1 | 389 num_failed_devs += 1 |
| 403 | 390 |
| 404 if num_failed_devs == len(devices): | 391 if num_failed_devs == len(devices): |
| 405 return 2 | 392 return 2 |
| 406 | 393 |
| 407 if not devices: | 394 if not devices: |
| 408 return 1 | 395 return 1 |
| 409 | 396 |
| 410 | 397 |
| 411 if __name__ == '__main__': | 398 if __name__ == '__main__': |
| 412 sys.exit(main()) | 399 sys.exit(main()) |
| OLD | NEW |