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 |