1#!/usr/bin/env python2 2# 3# Copyright Google Inc. 2014 4"""Module to generate the 7-day crosperf reports.""" 5 6from __future__ import print_function 7 8import argparse 9import datetime 10import os 11import sys 12 13from cros_utils import constants 14from cros_utils import command_executer 15 16WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] 17DATA_ROOT_DIR = os.path.join(constants.CROSTC_WORKSPACE, 'weekly_test_data') 18EXPERIMENT_FILE = os.path.join(DATA_ROOT_DIR, 'weekly_report') 19MAIL_PROGRAM = '~/var/bin/mail-sheriff' 20 21 22def Generate_Vanilla_Report_File(vanilla_image_paths, board, remote, 23 chromeos_root, cmd_executer): 24 25 experiment_header = """ 26name: weekly_vanilla_report 27cache_only: True 28same_specs: False 29board: %s 30remote: %s 31""" % (board, remote) 32 33 experiment_tests = """ 34benchmark: all_toolchain_perf { 35 suite: telemetry_Crosperf 36 iterations: 3 37} 38""" 39 40 filename = '%s_%s_vanilla.exp' % (EXPERIMENT_FILE, board) 41 if os.path.exists(filename): 42 cmd = 'rm %s' % filename 43 cmd_executer.RunCommand(cmd) 44 45 with open(filename, 'w') as f: 46 f.write(experiment_header) 47 f.write(experiment_tests) 48 49 # Add each vanilla image 50 for test_path in vanilla_image_paths: 51 pieces = test_path.split('/') 52 test_name = pieces[-1] 53 test_image = """ 54%s { 55 chromeos_root: %s 56 chromeos_image: %s 57} 58""" % (test_name, chromeos_root, 59 os.path.join(test_path, 'chromiumos_test_image.bin')) 60 f.write(test_image) 61 62 return filename 63 64 65def Generate_Test_File(test_image_paths, vanilla_image_path, board, remote, 66 chromeos_root, cmd_executer): 67 68 experiment_header = """ 69name: weekly_report 70cache_only: True 71same_specs: False 72board: %s 73remote: %s 74""" % (board, remote) 75 76 experiment_tests = """ 77benchmark: all_toolchain_perf { 78 suite: telemetry_Crosperf 79 iterations: 3 80} 81""" 82 83 filename = '%s_%s.exp' % (EXPERIMENT_FILE, board) 84 if os.path.exists(filename): 85 cmd = 'rm %s' % filename 86 cmd_executer.RunCommand(cmd) 87 88 with open(filename, 'w') as f: 89 f.write(experiment_header) 90 f.write(experiment_tests) 91 92 # Add vanilla image (first) 93 vanilla_image = """ 94%s { 95 chromeos_root: %s 96 chromeos_image: %s 97} 98""" % (vanilla_image_path.split('/')[-1], chromeos_root, 99 os.path.join(vanilla_image_path, 'chromiumos_test_image.bin')) 100 101 f.write(vanilla_image) 102 103 # Add each test image 104 for test_path in test_image_paths: 105 pieces = test_path.split('/') 106 test_name = pieces[-1] 107 test_image = """ 108%s { 109 chromeos_root: %s 110 chromeos_image: %s 111} 112""" % (test_name, chromeos_root, 113 os.path.join(test_path, 'chromiumos_test_image.bin')) 114 f.write(test_image) 115 116 return filename 117 118 119def Main(argv): 120 121 parser = argparse.ArgumentParser() 122 parser.add_argument('-b', '--board', dest='board', help='Target board.') 123 parser.add_argument('-r', '--remote', dest='remote', help='Target device.') 124 parser.add_argument( 125 '-v', 126 '--vanilla_only', 127 dest='vanilla_only', 128 action='store_true', 129 default=False, 130 help='Generate a report comparing only the vanilla ' 131 'images.') 132 133 options = parser.parse_args(argv[1:]) 134 135 if not options.board: 136 print('Must specify a board.') 137 return 1 138 139 if not options.remote: 140 print('Must specify at least one remote.') 141 return 1 142 143 cmd_executer = command_executer.GetCommandExecuter(log_level='average') 144 145 # Find starting index, for cycling through days of week, generating 146 # reports starting 6 days ago from today. Generate list of indices for 147 # order in which to look at weekdays for report: 148 todays_index = datetime.datetime.today().isoweekday() 149 indices = [] 150 start = todays_index + 1 151 end = start + 7 152 for i in range(start, end): 153 indices.append(i % 7) 154 # E.g. if today is Sunday, then start report with last Monday, so 155 # indices = [1, 2, 3, 4, 5, 6, 0]. 156 157 # Find all the test image tar files, untar them and add them to 158 # the list. Also find and untar vanilla image tar files, and keep 159 # track of the first vanilla image. 160 report_image_paths = [] 161 vanilla_image_paths = [] 162 first_vanilla_image = None 163 for i in indices: 164 day = WEEKDAYS[i] 165 data_path = os.path.join(DATA_ROOT_DIR, options.board, day) 166 if os.path.exists(data_path): 167 # First, untar the test image. 168 tar_file_name = '%s_test_image.tar' % day 169 tar_file_path = os.path.join(data_path, tar_file_name) 170 image_dir = '%s_test_image' % day 171 image_path = os.path.join(data_path, image_dir) 172 if os.path.exists(tar_file_path): 173 if not os.path.exists(image_path): 174 os.makedirs(image_path) 175 cmd = ('cd %s; tar -xvf %s -C %s --strip-components 1' % 176 (data_path, tar_file_path, image_path)) 177 ret = cmd_executer.RunCommand(cmd) 178 if not ret: 179 report_image_paths.append(image_path) 180 # Next, untar the vanilla image. 181 vanilla_file = '%s_vanilla_image.tar' % day 182 v_file_path = os.path.join(data_path, vanilla_file) 183 image_dir = '%s_vanilla_image' % day 184 image_path = os.path.join(data_path, image_dir) 185 if os.path.exists(v_file_path): 186 if not os.path.exists(image_path): 187 os.makedirs(image_path) 188 cmd = ('cd %s; tar -xvf %s -C %s --strip-components 1' % 189 (data_path, v_file_path, image_path)) 190 ret = cmd_executer.RunCommand(cmd) 191 if not ret: 192 vanilla_image_paths.append(image_path) 193 if not first_vanilla_image: 194 first_vanilla_image = image_path 195 196 # Find a chroot we can use. Look for a directory containing both 197 # an experiment file and a chromeos directory (the experiment file will 198 # only be created if both images built successfully, i.e. the chroot is 199 # good). 200 chromeos_root = None 201 timestamp = datetime.datetime.strftime(datetime.datetime.now(), 202 '%Y-%m-%d_%H:%M:%S') 203 results_dir = os.path.join( 204 os.path.expanduser('~/nightly_test_reports'), 205 '%s.%s' % (timestamp, options.board), 'weekly_tests') 206 207 for day in WEEKDAYS: 208 startdir = os.path.join(constants.CROSTC_WORKSPACE, day) 209 num_dirs = os.listdir(startdir) 210 for d in num_dirs: 211 exp_file = os.path.join(startdir, d, 'toolchain_experiment.txt') 212 chroot = os.path.join(startdir, d, 'chromeos') 213 if os.path.exists(chroot) and os.path.exists(exp_file): 214 chromeos_root = chroot 215 if chromeos_root: 216 break 217 if chromeos_root: 218 break 219 220 if not chromeos_root: 221 print('Unable to locate a usable chroot. Exiting without report.') 222 return 1 223 224 # Create the Crosperf experiment file for generating the weekly report. 225 if not options.vanilla_only: 226 filename = Generate_Test_File(report_image_paths, first_vanilla_image, 227 options.board, options.remote, chromeos_root, 228 cmd_executer) 229 else: 230 filename = Generate_Vanilla_Report_File(vanilla_image_paths, options.board, 231 options.remote, chromeos_root, 232 cmd_executer) 233 234 # Run Crosperf on the file to generate the weekly report. 235 cmd = ('%s/toolchain-utils/crosperf/crosperf ' 236 '%s --no_email=True --results_dir=%s' % (constants.CROSTC_WORKSPACE, 237 filename, results_dir)) 238 retv = cmd_executer.RunCommand(cmd) 239 if retv == 0: 240 # Send the email, if the crosperf command worked. 241 filename = os.path.join(results_dir, 'msg_body.html') 242 if (os.path.exists(filename) and 243 os.path.exists(os.path.expanduser(MAIL_PROGRAM))): 244 vanilla_string = ' ' 245 if options.vanilla_only: 246 vanilla_string = ' Vanilla ' 247 command = ('cat %s | %s -s "Weekly%sReport results, %s" -team -html' % 248 (filename, MAIL_PROGRAM, vanilla_string, options.board)) 249 retv = cmd_executer.RunCommand(command) 250 251 return retv 252 253 254if __name__ == '__main__': 255 retval = Main(sys.argv) 256 sys.exit(retval) 257