1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python 2*6777b538SAndroid Build Coastguard Worker# Copyright 2015 The Chromium Authors 3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 5*6777b538SAndroid Build Coastguard Worker 6*6777b538SAndroid Build Coastguard Workerimport json 7*6777b538SAndroid Build Coastguard Workerimport multiprocessing 8*6777b538SAndroid Build Coastguard Workerimport os 9*6777b538SAndroid Build Coastguard Workerimport platform 10*6777b538SAndroid Build Coastguard Workerimport sys 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker# Add src/testing/ into sys.path for importing common without pylint errors. 13*6777b538SAndroid Build Coastguard Workersys.path.append( 14*6777b538SAndroid Build Coastguard Worker os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))) 15*6777b538SAndroid Build Coastguard Workerfrom scripts import common 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Workerdef is_linux(): 19*6777b538SAndroid Build Coastguard Worker return sys.platform.startswith('linux') 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Workerdef get_free_disk_space(failures): 23*6777b538SAndroid Build Coastguard Worker """Returns the amount of free space on the current disk, in GiB. 24*6777b538SAndroid Build Coastguard Worker 25*6777b538SAndroid Build Coastguard Worker Returns: 26*6777b538SAndroid Build Coastguard Worker The amount of free space on the current disk, measured in GiB. 27*6777b538SAndroid Build Coastguard Worker """ 28*6777b538SAndroid Build Coastguard Worker if os.name == 'posix': 29*6777b538SAndroid Build Coastguard Worker # Stat the current path for info on the current disk. 30*6777b538SAndroid Build Coastguard Worker stat_result = os.statvfs('.') 31*6777b538SAndroid Build Coastguard Worker # Multiply block size by number of free blocks, express in GiB. 32*6777b538SAndroid Build Coastguard Worker return stat_result.f_frsize * stat_result.f_bavail / (1024.0 ** 3) 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Worker failures.append('get_free_disk_space: OS %s not supported.' % os.name) 35*6777b538SAndroid Build Coastguard Worker return 0 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Worker 38*6777b538SAndroid Build Coastguard Workerdef get_num_cpus(failures): 39*6777b538SAndroid Build Coastguard Worker """Returns the number of logical CPUs on this machine. 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker Returns: 42*6777b538SAndroid Build Coastguard Worker The number of logical CPUs on this machine, or 'unknown' if indeterminate. 43*6777b538SAndroid Build Coastguard Worker """ 44*6777b538SAndroid Build Coastguard Worker try: 45*6777b538SAndroid Build Coastguard Worker return multiprocessing.cpu_count() 46*6777b538SAndroid Build Coastguard Worker except NotImplementedError: 47*6777b538SAndroid Build Coastguard Worker failures.append('get_num_cpus') 48*6777b538SAndroid Build Coastguard Worker return 'unknown' 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Workerdef get_device_info(args, failures): 52*6777b538SAndroid Build Coastguard Worker """Parses the device info for each attached device, and returns a summary 53*6777b538SAndroid Build Coastguard Worker of the device info and any mismatches. 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker Returns: 56*6777b538SAndroid Build Coastguard Worker A dict indicating the result. 57*6777b538SAndroid Build Coastguard Worker """ 58*6777b538SAndroid Build Coastguard Worker if not is_linux(): 59*6777b538SAndroid Build Coastguard Worker return {} 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker with common.temporary_file() as tempfile_path: 62*6777b538SAndroid Build Coastguard Worker test_cmd = [ 63*6777b538SAndroid Build Coastguard Worker sys.executable, 64*6777b538SAndroid Build Coastguard Worker os.path.join(args.paths['checkout'], 65*6777b538SAndroid Build Coastguard Worker 'third_party', 66*6777b538SAndroid Build Coastguard Worker 'catapult', 67*6777b538SAndroid Build Coastguard Worker 'devil', 68*6777b538SAndroid Build Coastguard Worker 'devil', 69*6777b538SAndroid Build Coastguard Worker 'android', 70*6777b538SAndroid Build Coastguard Worker 'tools', 71*6777b538SAndroid Build Coastguard Worker 'device_status.py'), 72*6777b538SAndroid Build Coastguard Worker '--json-output', tempfile_path, 73*6777b538SAndroid Build Coastguard Worker '--denylist-file', os.path.join( 74*6777b538SAndroid Build Coastguard Worker args.paths['checkout'], 'out', 'bad_devices.json') 75*6777b538SAndroid Build Coastguard Worker ] 76*6777b538SAndroid Build Coastguard Worker if args.args: 77*6777b538SAndroid Build Coastguard Worker test_cmd.extend(args.args) 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker rc = common.run_command(test_cmd) 80*6777b538SAndroid Build Coastguard Worker if rc: 81*6777b538SAndroid Build Coastguard Worker failures.append('device_status') 82*6777b538SAndroid Build Coastguard Worker return {} 83*6777b538SAndroid Build Coastguard Worker 84*6777b538SAndroid Build Coastguard Worker with open(tempfile_path, 'r') as src: 85*6777b538SAndroid Build Coastguard Worker device_info = json.load(src) 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker results = {} 88*6777b538SAndroid Build Coastguard Worker results['devices'] = sorted(v['serial'] for v in device_info) 89*6777b538SAndroid Build Coastguard Worker 90*6777b538SAndroid Build Coastguard Worker details = [ 91*6777b538SAndroid Build Coastguard Worker v['ro.build.fingerprint'] for v in device_info if not v['denylisted']] 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Worker def unique_build_details(index): 94*6777b538SAndroid Build Coastguard Worker return sorted(list({v.split(':')[index] for v in details})) 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker parsed_details = { 97*6777b538SAndroid Build Coastguard Worker 'device_names': unique_build_details(0), 98*6777b538SAndroid Build Coastguard Worker 'build_versions': unique_build_details(1), 99*6777b538SAndroid Build Coastguard Worker 'build_types': unique_build_details(2), 100*6777b538SAndroid Build Coastguard Worker } 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker for k, v in parsed_details.items(): 103*6777b538SAndroid Build Coastguard Worker if len(v) == 1: 104*6777b538SAndroid Build Coastguard Worker results[k] = v[0] 105*6777b538SAndroid Build Coastguard Worker else: 106*6777b538SAndroid Build Coastguard Worker results[k] = 'MISMATCH' 107*6777b538SAndroid Build Coastguard Worker results['%s_list' % k] = v 108*6777b538SAndroid Build Coastguard Worker failures.append(k) 109*6777b538SAndroid Build Coastguard Worker 110*6777b538SAndroid Build Coastguard Worker for v in device_info: 111*6777b538SAndroid Build Coastguard Worker if v['denylisted']: 112*6777b538SAndroid Build Coastguard Worker failures.append('Device %s denylisted' % v['serial']) 113*6777b538SAndroid Build Coastguard Worker 114*6777b538SAndroid Build Coastguard Worker return results 115*6777b538SAndroid Build Coastguard Worker 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Workerdef main_run(args): 118*6777b538SAndroid Build Coastguard Worker failures = [] 119*6777b538SAndroid Build Coastguard Worker host_info = {} 120*6777b538SAndroid Build Coastguard Worker host_info['os_system'] = platform.system() 121*6777b538SAndroid Build Coastguard Worker host_info['os_release'] = platform.release() 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker host_info['processor'] = platform.processor() 124*6777b538SAndroid Build Coastguard Worker host_info['num_cpus'] = get_num_cpus(failures) 125*6777b538SAndroid Build Coastguard Worker host_info['free_disk_space'] = get_free_disk_space(failures) 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker host_info['python_version'] = platform.python_version() 128*6777b538SAndroid Build Coastguard Worker host_info['python_path'] = sys.executable 129*6777b538SAndroid Build Coastguard Worker 130*6777b538SAndroid Build Coastguard Worker host_info['devices'] = get_device_info(args, failures) 131*6777b538SAndroid Build Coastguard Worker 132*6777b538SAndroid Build Coastguard Worker json.dump({ 133*6777b538SAndroid Build Coastguard Worker 'valid': True, 134*6777b538SAndroid Build Coastguard Worker 'failures': failures, 135*6777b538SAndroid Build Coastguard Worker '_host_info': host_info, 136*6777b538SAndroid Build Coastguard Worker }, args.output) 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker if len(failures) != 0: 139*6777b538SAndroid Build Coastguard Worker return common.INFRA_FAILURE_EXIT_CODE 140*6777b538SAndroid Build Coastguard Worker return 0 141*6777b538SAndroid Build Coastguard Worker 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard Workerdef main_compile_targets(args): 144*6777b538SAndroid Build Coastguard Worker json.dump([], args.output) 145*6777b538SAndroid Build Coastguard Worker 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__': 148*6777b538SAndroid Build Coastguard Worker funcs = { 149*6777b538SAndroid Build Coastguard Worker 'run': main_run, 150*6777b538SAndroid Build Coastguard Worker 'compile_targets': main_compile_targets, 151*6777b538SAndroid Build Coastguard Worker } 152*6777b538SAndroid Build Coastguard Worker sys.exit(common.run_script(sys.argv[1:], funcs)) 153