Index: build/android/buildbot/bb_device_status_check.py |
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py |
index 8561c0104b4724168cc20eda531e95f7849a6edb..8690a60a71409f3df38a6ce6a6a9ad384b9d2498 100755 |
--- a/build/android/buildbot/bb_device_status_check.py |
+++ b/build/android/buildbot/bb_device_status_check.py |
@@ -30,9 +30,14 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
from pylib import android_commands |
from pylib import constants |
from pylib.cmd_helper import GetCmdOutput |
+from pylib.device import battery_utils |
from pylib.device import device_blacklist |
+from pylib.device import device_errors |
from pylib.device import device_list |
from pylib.device import device_utils |
+from pylib.utils import run_tests_helper |
+ |
+_RE_DEVICE_ID = re.compile('Device ID = (\d+)') |
def DeviceInfo(serial, options): |
"""Gathers info on a device via various adb calls. |
@@ -44,73 +49,62 @@ def DeviceInfo(serial, options): |
Tuple of device type, build id, report as a string, error messages, and |
boolean indicating whether or not device can be used for testing. |
""" |
+ device = device_utils.DeviceUtils(serial) |
+ battery = battery_utils.BatteryUtils(device) |
- device_adb = device_utils.DeviceUtils(serial) |
- device_type = device_adb.build_product |
- device_build = device_adb.build_id |
- device_build_type = device_adb.build_type |
- device_product_name = device_adb.product_name |
- |
- try: |
- battery_info = device_adb.old_interface.GetBatteryInfo() |
- except Exception as e: |
- battery_info = {} |
- logging.error('Unable to obtain battery info for %s, %s', serial, e) |
- |
- def _GetData(re_expression, line, lambda_function=lambda x: x): |
- if not line: |
- return 'Unknown' |
- found = re.findall(re_expression, line) |
- if found and len(found): |
- return lambda_function(found[0]) |
- return 'Unknown' |
- |
- battery_level = int(battery_info.get('level', 100)) |
- imei_slice = _GetData(r'Device ID = (\d+)', |
- device_adb.old_interface.GetSubscriberInfo(), |
- lambda x: x[-6:]) |
+ battery_info = {} |
+ battery_level = 100 |
+ errors = [] |
+ dev_good = True |
json_data = { |
'serial': serial, |
- 'type': device_type, |
- 'build': device_build, |
- 'build_detail': device_adb.GetProp('ro.build.fingerprint'), |
- 'battery': battery_info, |
- 'imei_slice': imei_slice, |
- 'wifi_ip': device_adb.GetProp('dhcp.wlan0.ipaddress'), |
+ 'type': device.build_product, |
+ 'build': device.build_id, |
+ 'build_detail': device.GetProp('ro.build.fingerprint'), |
+ 'battery': {}, |
+ 'imei_slice': 'Unknown', |
+ 'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'), |
} |
- report = ['Device %s (%s)' % (serial, device_type), |
- ' Build: %s (%s)' % |
- (device_build, json_data['build_detail']), |
- ' Current Battery Service state: ', |
- '\n'.join([' %s: %s' % (k, v) |
- for k, v in battery_info.iteritems()]), |
- ' IMEI slice: %s' % imei_slice, |
- ' Wifi IP: %s' % json_data['wifi_ip'], |
- ''] |
- errors = [] |
- dev_good = True |
- if battery_level < 15: |
- errors += ['Device critically low in battery. Will add to blacklist.'] |
- dev_good = False |
- if not device_adb.old_interface.IsDeviceCharging(): |
- if device_adb.old_interface.CanControlUsbCharging(): |
- device_adb.old_interface.EnableUsbCharging() |
- else: |
- logging.error('Device %s is not charging' % serial) |
- if not options.no_provisioning_check: |
- setup_wizard_disabled = ( |
- device_adb.GetProp('ro.setupwizard.mode') == 'DISABLED') |
- if not setup_wizard_disabled and device_build_type != 'user': |
- errors += ['Setup wizard not disabled. Was it provisioned correctly?'] |
- if (device_product_name == 'mantaray' and |
- battery_info.get('AC powered', None) != 'true'): |
- errors += ['Mantaray device not connected to AC power.'] |
+ try: |
+ try: |
+ battery_info = battery.GetBatteryInfo(timeout=5) |
+ battery_level = int(battery_info.get('level', battery_level)) |
+ json_data['battery'] = battery_info |
+ except device_errors.CommandFailedError: |
+ logging.exception('Failed to get battery information for %s', serial) |
- full_report = '\n'.join(report) |
+ try: |
+ for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'], |
+ check_return=True, timeout=5): |
+ m = _RE_DEVICE_ID.match(l) |
+ if m: |
+ json_data['imei_slice'] = m.group(1)[-6:] |
+ except device_errors.CommandFailedError: |
+ logging.exception('Failed to get IMEI slice for %s', serial) |
+ |
+ if battery_level < 15: |
+ errors += ['Device critically low in battery.'] |
+ dev_good = False |
+ if not battery.GetCharging(): |
+ battery.SetCharging(True) |
+ if not options.no_provisioning_check: |
+ setup_wizard_disabled = ( |
+ device.GetProp('ro.setupwizard.mode') == 'DISABLED') |
+ if not setup_wizard_disabled and device.build_type != 'user': |
+ errors += ['Setup wizard not disabled. Was it provisioned correctly?'] |
+ if (device.product_name == 'mantaray' and |
+ battery_info.get('AC powered', None) != 'true'): |
+ errors += ['Mantaray device not connected to AC power.'] |
+ except device_errors.CommandFailedError: |
+ logging.exception('Failure while getting device status.') |
+ dev_good = False |
+ except device_errors.CommandTimeoutError: |
+ logging.exception('Timeout while getting device status.') |
+ dev_good = False |
- return (device_type, device_build, battery_level, full_report, errors, |
- dev_good, json_data) |
+ return (device.build_product, device.build_id, battery_level, errors, |
+ dev_good, json_data) |
def CheckForMissingDevices(options, adb_online_devs): |
@@ -122,11 +116,6 @@ def CheckForMissingDevices(options, adb_online_devs): |
adb_online_devs: A list of serial numbers of the currently visible |
and online attached devices. |
""" |
- # TODO(navabi): remove this once the bug that causes different number |
- # of devices to be detected between calls is fixed. |
- logger = logging.getLogger() |
- logger.setLevel(logging.INFO) |
- |
out_dir = os.path.abspath(options.out_dir) |
# last_devices denotes all known devices prior to this run |
@@ -189,10 +178,10 @@ def CheckForMissingDevices(options, adb_online_devs): |
os.environ.get('BUILDBOT_SLAVENAME'), |
os.environ.get('BUILDBOT_BUILDNUMBER'))))) |
return ['Current online devices: %s' % adb_online_devs, |
- '%s are no longer visible. Were they removed?\n' % missing_devs, |
- 'SHERIFF:\n', |
- '@@@STEP_LINK@Click here to file a bug@%s@@@\n' % crbug_link, |
- 'Cache file: %s\n\n' % last_devices_path, |
+ '%s are no longer visible. Were they removed?' % missing_devs, |
+ 'SHERIFF:', |
+ '@@@STEP_LINK@Click here to file a bug@%s@@@' % crbug_link, |
+ 'Cache file: %s' % last_devices_path, |
'adb devices: %s' % GetCmdOutput(['adb', 'devices']), |
'adb devices(GetAttachedDevices): %s' % adb_online_devs] |
else: |
@@ -201,8 +190,9 @@ def CheckForMissingDevices(options, adb_online_devs): |
bb_annotations.PrintWarning() |
bb_annotations.PrintSummaryText( |
'%d new devices detected' % len(new_devs)) |
- print ('New devices detected %s. And now back to your ' |
- 'regularly scheduled program.' % list(new_devs)) |
+ logging.info('New devices detected:') |
+ for d in new_devs: |
+ logging.info(' %s', d) |
def SendEmail(from_address, to_addresses, cc_addresses, subject, msg): |
@@ -214,20 +204,20 @@ def SendEmail(from_address, to_addresses, cc_addresses, subject, msg): |
server = smtplib.SMTP('localhost') |
server.sendmail(from_address, to_addresses, msg_body) |
server.quit() |
- except Exception as e: |
- print 'Failed to send alert email. Error: %s' % e |
+ except Exception: |
+ logging.exception('Failed to send alert email.') |
def RestartUsb(): |
if not os.path.isfile('/usr/bin/restart_usb'): |
- print ('ERROR: Could not restart usb. /usr/bin/restart_usb not installed ' |
- 'on host (see BUG=305769).') |
+ logging.error('Could not restart usb. ''/usr/bin/restart_usb not ' |
+ 'installed on host (see BUG=305769).') |
return False |
lsusb_proc = bb_utils.SpawnCmd(['lsusb'], stdout=subprocess.PIPE) |
lsusb_output, _ = lsusb_proc.communicate() |
if lsusb_proc.returncode: |
- print 'Error: Could not get list of USB ports (i.e. lsusb).' |
+ logging.error('Could not get list of USB ports (i.e. lsusb).') |
return lsusb_proc.returncode |
usb_devices = [re.findall(r'Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0] |
@@ -243,10 +233,11 @@ def RestartUsb(): |
if dev != '001': |
return_code = bb_utils.RunCmd(['/usr/bin/restart_usb', bus, dev]) |
if return_code: |
- print 'Error restarting USB device /dev/bus/usb/%s/%s' % (bus, dev) |
+ logging.error('Error restarting USB device /dev/bus/usb/%s/%s', |
+ bus, dev) |
all_restarted = False |
else: |
- print 'Restarted USB device /dev/bus/usb/%s/%s' % (bus, dev) |
+ logging.info('Restarted USB device /dev/bus/usb/%s/%s', bus, dev) |
return all_restarted |
@@ -263,14 +254,15 @@ def KillAllAdb(): |
for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]: |
for p in GetAllAdb(): |
try: |
- print 'kill %d %d (%s [%s])' % (sig, p.pid, p.name, |
- ' '.join(p.cmdline)) |
+ logging.info('kill %d %d (%s [%s])', sig, p.pid, p.name, |
+ ' '.join(p.cmdline)) |
p.send_signal(sig) |
except (psutil.NoSuchProcess, psutil.AccessDenied): |
pass |
for p in GetAllAdb(): |
try: |
- print 'Unable to kill %d (%s [%s])' % (p.pid, p.name, ' '.join(p.cmdline)) |
+ logging.error('Unable to kill %d (%s [%s])', p.pid, p.name, |
+ ' '.join(p.cmdline)) |
except (psutil.NoSuchProcess, psutil.AccessDenied): |
pass |
@@ -288,11 +280,15 @@ def main(): |
help='Restart USB ports before running device check.') |
parser.add_option('--json-output', |
help='Output JSON information into a specified file.') |
+ parser.add_option('-v', '--verbose', action='count', default=1, |
+ help='Log more information.') |
options, args = parser.parse_args() |
if args: |
parser.error('Unknown options %s' % args) |
+ run_tests_helper.SetLogLevel(options.verbose) |
+ |
# Remove the last build's "bad devices" before checking device statuses. |
device_blacklist.ResetBlacklist() |
@@ -304,7 +300,8 @@ def main(): |
devices = android_commands.GetAttachedDevices() |
# Only restart usb if devices are missing. |
if set(expected_devices) != set(devices): |
- print 'expected_devices: %s, devices: %s' % (expected_devices, devices) |
+ logging.warning('expected_devices: %s', expected_devices) |
+ logging.warning('devices: %s', devices) |
KillAllAdb() |
retries = 5 |
usb_restarted = True |
@@ -312,9 +309,10 @@ def main(): |
if not RestartUsb(): |
usb_restarted = False |
bb_annotations.PrintWarning() |
- print 'USB reset stage failed, wait for any device to come back.' |
+ logging.error('USB reset stage failed, ' |
+ 'wait for any device to come back.') |
while retries: |
- print 'retry adb devices...' |
+ logging.info('retry adb devices...') |
time.sleep(1) |
devices = android_commands.GetAttachedDevices() |
if set(expected_devices) == set(devices): |
@@ -330,10 +328,10 @@ def main(): |
offline_devices = android_commands.GetAttachedDevices( |
hardware=False, emulator=False, offline=True) |
- types, builds, batteries, reports, errors, json_data = [], [], [], [], [], [] |
- fail_step_lst = [] |
+ types, builds, batteries, errors, devices_ok, json_data = ( |
+ [], [], [], [], [], []) |
if devices: |
- types, builds, batteries, reports, errors, fail_step_lst, json_data = ( |
+ types, builds, batteries, errors, devices_ok, json_data = ( |
zip(*[DeviceInfo(dev, options) for dev in devices])) |
# Write device info to file for buildbot info display. |
@@ -354,7 +352,16 @@ def main(): |
bb_annotations.PrintMsg('Online devices: %d. Device types %s, builds %s' |
% (len(devices), unique_types, unique_builds)) |
- print '\n'.join(reports) |
+ |
+ for j in json_data: |
+ logging.info('Device %s (%s)', j.get('serial'), j.get('type')) |
+ logging.info(' Build: %s (%s)', j.get('build'), j.get('build_detail')) |
+ logging.info(' Current Battery Service state:') |
+ for k, v in j.get('battery', {}).iteritems(): |
+ logging.info(' %s: %s', k, v) |
+ logging.info(' IMEI slice: %s', j.get('imei_slice')) |
+ logging.info(' WiFi IP: %s', j.get('wifi_ip')) |
+ |
for serial, dev_errors in zip(devices, errors): |
if dev_errors: |
@@ -363,14 +370,14 @@ def main(): |
if err_msg: |
bb_annotations.PrintWarning() |
- msg = '\n'.join(err_msg) |
- print msg |
+ for e in err_msg: |
+ logging.error(e) |
from_address = 'buildbot@chromium.org' |
to_addresses = ['chromium-android-device-alerts@google.com'] |
bot_name = os.environ.get('BUILDBOT_BUILDERNAME') |
slave_name = os.environ.get('BUILDBOT_SLAVENAME') |
subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name) |
- SendEmail(from_address, to_addresses, [], subject, msg) |
+ SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg)) |
if options.device_status_dashboard: |
perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices', |
@@ -388,8 +395,9 @@ def main(): |
f.write(json.dumps(json_data, indent=4)) |
num_failed_devs = 0 |
- for fail_status, device in zip(fail_step_lst, devices): |
- if not fail_status: |
+ for device_ok, device in zip(devices_ok, devices): |
+ if not device_ok: |
+ logging.warning('Blacklisting %s', str(device)) |
device_blacklist.ExtendBlacklist([str(device)]) |
num_failed_devs += 1 |