weekly_report.py revision 95cd449e2f4ebef9c6277c525b7d18df40c1cc9a
1#!/usr/bin/python
2#
3# Copyright Google Inc. 2014
4
5import datetime
6import optparse
7import os
8import sys
9import time
10
11from utils import constants
12from utils import command_executer
13
14WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
15DATA_ROOT_DIR = os.path.join(constants.CROSTC_WORKSPACE,
16                             'weekly_test_data')
17EXPERIMENT_FILE = os.path.join(DATA_ROOT_DIR, 'weekly_report')
18MAIL_PROGRAM = "~/var/bin/mail-sheriff"
19
20
21def Generate_Vanilla_Report_File(vanilla_image_paths, board, remote,
22                                 chromeos_root, cmd_executer):
23
24    experiment_header = """
25name: weekly_vanilla_report
26cache_only: True
27same_specs: False
28board: %s
29remote: %s
30""" % (board, remote)
31
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        print >>f, experiment_header
47        print >>f, 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, os.path.join (test_path,
59                                               "chromiumos_test_image.bin"))
60            print >>f, test_image
61
62    return filename
63
64def Generate_Test_File(test_image_paths, vanilla_image_path, board, remote,
65                       chromeos_root, cmd_executer):
66
67    experiment_header = """
68name: weekly_report
69cache_only: True
70same_specs: False
71board: %s
72remote: %s
73""" % (board, remote)
74
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        print >>f, experiment_header
90        print >>f, 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],
99       chromeos_root, os.path.join(vanilla_image_path,
100                                   "chromiumos_test_image.bin"))
101
102        print >>f, vanilla_image
103
104        # Add each test image
105        for test_path in test_image_paths:
106            pieces = test_path.split("/")
107            test_name = pieces[-1]
108            test_image = """
109%s {
110  chromeos_root: %s
111  chromeos_image: %s
112}
113""" % (test_name, chromeos_root, os.path.join (test_path,
114                                               "chromiumos_test_image.bin"))
115            print >>f, test_image
116
117    return filename
118
119
120
121def Main(argv):
122
123    parser = optparse.OptionParser()
124    parser.add_option('-b', '--board', dest='board',
125                      help='Target board.')
126    parser.add_option("-r", "--remote", dest="remote",
127                    help="Target device.")
128    parser.add_option("-v", "--vanilla_only", dest="vanilla_only",
129                    action="store_true",
130                    default=False,
131                    help="Generate a report comparing only the vanilla images.")
132
133    options = parser.parse_args(argv[1:])[0]
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
158
159    # Find all the test image tar files, untar them and add them to
160    # the list. Also find and untar vanilla image tar files, and keep
161    # track of the first vanilla image.
162    report_image_paths = []
163    vanilla_image_paths = []
164    first_vanilla_image = None
165    for i in indices:
166        day = WEEKDAYS[i]
167        data_path = os.path.join(DATA_ROOT_DIR, options.board, day)
168        if os.path.exists(data_path):
169            # First, untar the test image.
170            tar_file_name = "%s_test_image.tar" % day
171            tar_file_path = os.path.join(data_path, tar_file_name)
172            image_dir = "%s_test_image" % day
173            image_path = os.path.join(data_path, image_dir)
174            if os.path.exists(tar_file_path):
175                if not os.path.exists(image_path):
176                    os.makedirs(image_path)
177                cmd = ("cd %s; tar -xvf %s -C %s --strip-components 1" %
178                       (data_path, tar_file_path, image_path))
179                ret = cmd_executer.RunCommand(cmd)
180                if not ret:
181                    report_image_paths.append(image_path)
182            # Next, untar the vanilla image.
183            vanilla_file = "%s_vanilla_image.tar" % day
184            v_file_path = os.path.join(data_path, vanilla_file)
185            image_dir = "%s_vanilla_image" % day
186            image_path = os.path.join(data_path, image_dir)
187            if os.path.exists(v_file_path):
188                if not os.path.exists(image_path):
189                    os.makedirs(image_path)
190                cmd = ("cd %s; tar -xvf %s -C %s --strip-components 1" %
191                       (data_path, v_file_path, image_path))
192                ret = cmd_executer.RunCommand(cmd)
193                if not ret:
194                    vanilla_image_paths.append(image_path)
195                if not first_vanilla_image:
196                    first_vanilla_image = image_path
197
198    # Find a chroot we can use.  Look for a directory containing both
199    # an experiment file and a chromeos directory (the experiment file will
200    # only be created if both images built successfully, i.e. the chroot is
201    # good).
202    chromeos_root = None
203    timestamp = datetime.datetime.strftime(datetime.datetime.now(),
204                                           "%Y-%m-%d_%H:%M:%S")
205    results_dir = os.path.join(os.path.expanduser("~/nightly_test_reports"),
206                                                  "%s.%s" % (timestamp,
207                                                             options.board),
208                                                  "weekly_tests")
209
210    for day in WEEKDAYS:
211        startdir = os.path.join(constants.CROSTC_WORKSPACE, day)
212        num_dirs = os.listdir(startdir)
213        for d in num_dirs:
214            exp_file = os.path.join(startdir, d, "toolchain_experiment.txt")
215            chroot = os.path.join(startdir, d, "chromeos")
216            if os.path.exists(chroot) and os.path.exists(exp_file):
217                chromeos_root = chroot
218            if chromeos_root:
219                break;
220        if chromeos_root:
221            break;
222
223    if not chromeos_root:
224        print "Unable to locate a usable chroot. Exiting without report."
225        return 1
226
227
228    # Create the Crosperf experiment file for generating the weekly report.
229    if not options.vanilla_only:
230        filename = Generate_Test_File (report_image_paths, first_vanilla_image,
231                                       options.board, options.remote,
232                                       chromeos_root, cmd_executer)
233    else:
234        filename = Generate_Vanilla_Report_File (vanilla_image_paths,
235                                                 options.board, options.remote,
236                                                 chromeos_root, cmd_executer)
237
238    # Run Crosperf on the file to generate the weekly report.
239    cmd = ("%s/toolchain-utils/crosperf/crosperf "
240           "%s --no_email=True --results_dir=%s" %
241           (constants.CROSTC_WORKSPACE, filename, results_dir))
242    retval = cmd_executer.RunCommand(cmd)
243    if retval == 0:
244      # Send the email, if the crosperf command worked.
245      filename = os.path.join(results_dir, "msg_body.html")
246      if (os.path.exists(filename) and
247          os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
248        vanilla_string = " "
249        if options.vanilla_only:
250          vanilla_string = " Vanilla "
251        command = ('cat %s | %s -s "Weekly%sReport results, %s" -team -html'
252                  % (filename, MAIL_PROGRAM, vanilla_string, options.board))
253      retval = cmd_executer.RunCommand(command)
254
255    return retval
256
257
258
259if __name__ == '__main__':
260    retval = Main(sys.argv)
261    sys.exit(retval)
262