blob: 0f2ed1871ccc516a63ccea0058e527508f040fd6 [file] [log] [blame]
cmtice46093e52014-12-09 14:59:16 -08001#!/usr/bin/python
2
3# Copyright 2014 Google Inc. All Rights Reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import os
8import time
9import urllib2
10
11from utils import command_executer
12from utils import logger
13from utils import buildbot_json
14
15SLEEP_TIME = 600 # 10 minutes; time between polling of buildbot.
16TIME_OUT = 18000 # Decide the build is dead or will never finish
17 # after this time (5 hours).
18
19"""Utilities for launching and accessing ChromeOS buildbots."""
20
21def ParseReportLog (url, build):
22 """
23 Scrape the trybot image name off the Reports log page.
24
25 This takes the URL for a trybot Reports Stage web page,
26 and a trybot build type, such as 'daisy-release'. It
27 opens the web page and parses it looking for the trybot
28 artifact name (e.g. something like
29 'trybot-daisy-release/R40-6394.0.0-b1389'). It returns the
30 artifact name, if found.
31 """
32 trybot_image = ""
33 url += "/text"
34 newurl = url.replace ("uberchromegw", "chromegw")
35 webpage = urllib2.urlopen(newurl)
36 data = webpage.read()
37 lines = data.split('\n')
38 for l in lines:
cmtice1047b072015-02-10 09:33:21 -080039 if l.find("Artifacts") > 0 and l.find("trybot") > 0:
cmtice46093e52014-12-09 14:59:16 -080040 trybot_name = "trybot-%s" % build
41 start_pos = l.find(trybot_name)
42 end_pos = l.find("@https://storage")
43 trybot_image = l[start_pos:end_pos]
44
45 return trybot_image
46
cmtice46093e52014-12-09 14:59:16 -080047def GetBuildData (buildbot_queue, build_id):
48 """
49 Find the Reports stage web page for a trybot build.
50
51 This takes the name of a buildbot_queue, such as 'daisy-release'
52 and a build id (the build number), and uses the json buildbot api to
53 find the Reports stage web page for that build, if it exists.
54 """
55 builder = buildbot_json.Buildbot(
56 "http://chromegw/p/tryserver.chromiumos/").builders[buildbot_queue]
57 build_data = builder.builds[build_id].data
58 logs = build_data["logs"]
59 for l in logs:
60 fname = l[1]
61 if "steps/Report/" in fname:
62 return fname
63
64 return ""
65
66
67def FindBuildRecordFromLog(description, log_info):
68 """
69 Find the right build record in the build logs.
70
71 Get the first build record from build log with a reason field
72 that matches 'description'. ('description' is a special tag we
73 created when we launched the buildbot, so we could find it at this
74 point.)
75 """
76
77 current_line = 1
78 while current_line < len(log_info):
79 my_dict = {}
80 # Read all the lines from one "Build" to the next into my_dict
81 while True:
82 key = log_info[current_line].split(":")[0].strip()
83 value = log_info[current_line].split(":", 1)[1].strip()
84 my_dict[key] = value
85 current_line += 1
86 if "Build" in key or current_line == len(log_info):
87 break
88 try:
89 # Check to see of the build record is the right one.
90 if str(description) in my_dict["reason"]:
91 # We found a match; we're done.
92 return my_dict
93 except:
94 print "reason is not in dictionary: '%s'" % repr(my_dict)
95 else:
96 # Keep going.
97 continue
98
99 # We hit the bottom of the log without a match.
100 return {}
101
102
103def GetBuildInfo(file_dir):
104 """
105 Get all the build records for the trybot builds.
106
107 file_dir is the toolchain_utils directory.
108 """
109 ce = command_executer.GetCommandExecuter()
110 commands = ("{0}/utils/buildbot_json.py builds "
111 "http://chromegw/p/tryserver.chromiumos/"
112 .format(file_dir))
113
114 _, buildinfo, _ = ce.RunCommand(commands, return_output=True,
115 print_to_console=False)
116 build_log = buildinfo.splitlines()
117 return build_log
118
119
cmtice1047b072015-02-10 09:33:21 -0800120def FindArchiveImage(chromeos_root, build, build_id):
121 """
122 Given a build_id, search Google Storage for a trybot artifact
123 for the correct board with the correct build_id. Return the
124 name of the artifact, if found.
125 """
126 ce = command_executer.GetCommandExecuter()
127 command = ("gsutil ls gs://chromeos-image-archive/trybot-%s/*b%s"
128 "/chromiumos_test_image.tar.xz" % (build, build_id))
129 retval, out, err = ce.ChrootRunCommand(chromeos_root, command, return_output=True,
130 print_to_console=False)
131
132 trybot_image = ""
133 trybot_name = "trybot-%s" % build
134 if out and out.find(trybot_name) > 0:
135 start_pos = out.find(trybot_name)
136 end_pos = out.find("/chromiumos_test_image")
137 trybot_image = out[start_pos:end_pos]
138
139 return trybot_image
140
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700141def GetTrybotImage(chromeos_root, buildbot_name, patch_list, build_tag,
142 build_toolchain=False):
cmtice46093e52014-12-09 14:59:16 -0800143 """
144 Launch buildbot and get resulting trybot artifact name.
145
146 This function launches a buildbot with the appropriate flags to
147 build the test ChromeOS image, with the current ToT mobile compiler. It
148 checks every 10 minutes to see if the trybot has finished. When the trybot
149 has finished, it parses the resulting report logs to find the trybot
150 artifact (if one was created), and returns that artifact name.
151
152 chromeos_root is the path to the ChromeOS root, needed for finding chromite
153 and launching the buildbot.
154
155 buildbot_name is the name of the buildbot queue, such as lumpy-release or
156 daisy-paladin.
157
158 patch_list a python list of the patches, if any, for the buildbot to use.
159
160 build_tag is a (unique) string to be used to look up the buildbot results
161 from among all the build records.
162 """
163 ce = command_executer.GetCommandExecuter()
164 cbuildbot_path = os.path.join(chromeos_root, "chromite/cbuildbot")
165 base_dir = os.getcwd()
166 patch_arg = ""
167 if patch_list:
168 patch_arg = "-g "
169 for p in patch_list:
170 patch_arg = patch_arg + " " + repr(p)
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700171 toolchain_flags=""
172 if build_toolchain:
173 toolchain_flags += "--latest_toolchain"
cmtice46093e52014-12-09 14:59:16 -0800174 branch = "master"
175 os.chdir(cbuildbot_path)
176
177 # Launch buildbot with appropriate flags.
178 build = buildbot_name
179 description = build_tag
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700180 command = ("./cbuildbot --remote --nochromesdk --notests"
181 " --remote-description=%s %s %s %s"
182 % (description, toolchain_flags, patch_arg, build))
cmtice46093e52014-12-09 14:59:16 -0800183 ce.RunCommand(command)
184 os.chdir(base_dir)
185
186 build_id = 0
cmticed54f9802015-02-05 11:04:11 -0800187 build_status = None
cmticea63ffc02015-04-21 11:38:55 -0700188 # Wait for buildbot to finish running (check every 10 minutes). Wait
189 # 10 minutes before the first check to give the buildbot time to launch
190 # (so we don't start looking for build data before it's out there).
191 time.sleep(SLEEP_TIME)
cmtice46093e52014-12-09 14:59:16 -0800192 done = False
193 running_time = 0
cmticea63ffc02015-04-21 11:38:55 -0700194 pending_time = SLEEP_TIME
cmtice46093e52014-12-09 14:59:16 -0800195 while not done:
196 done = True
197 build_info = GetBuildInfo(base_dir)
198 if not build_info:
199 logger.GetLogger().LogFatal("Unable to get build logs for target %s"
200 % build)
201
202 data_dict = FindBuildRecordFromLog(description, build_info)
203 if not data_dict:
cmticece5ffa42015-02-12 15:18:43 -0800204 # Trybot job may be pending.
205 if pending_time > TIME_OUT:
206 logger.GetLogger().LogFatal("Unable to find build record for trybot %s"
207 % description)
208 else:
209 logger.GetLogger().LogOutput("Unable to find build record; job may be pending.")
210 logger.GetLogger().LogOutput("Current pending time: {0} minutes.".format(
211 pending_time / 60))
212 logger.GetLogger().LogOutput("Sleeping {0} seconds.".format(SLEEP_TIME))
213 time.sleep(SLEEP_TIME)
214 pending_time += SLEEP_TIME
215 done = False
cmtice46093e52014-12-09 14:59:16 -0800216
cmtice46093e52014-12-09 14:59:16 -0800217 else:
cmticece5ffa42015-02-12 15:18:43 -0800218 if "True" in data_dict["completed"]:
219 build_id = data_dict["number"]
220 build_status = int(data_dict["result"])
221 else:
222 done = False
cmtice46093e52014-12-09 14:59:16 -0800223
cmticece5ffa42015-02-12 15:18:43 -0800224 if not done:
225 logger.GetLogger().LogOutput("{0} minutes passed.".format(
226 running_time / 60))
227 logger.GetLogger().LogOutput("Sleeping {0} seconds.".format(SLEEP_TIME))
228 time.sleep(SLEEP_TIME)
229 running_time += SLEEP_TIME
230 if running_time > TIME_OUT:
cmtice46093e52014-12-09 14:59:16 -0800231 done = True
232
cmtice1047b072015-02-10 09:33:21 -0800233 trybot_image = FindArchiveImage(chromeos_root, build, build_id)
234 if not trybot_image:
235 logger.GetLogger().LogError("Trybot job %s failed with status %d;"
236 " no trybot image generated."
237 % (description, build_status))
cmtice46093e52014-12-09 14:59:16 -0800238
cmtice1047b072015-02-10 09:33:21 -0800239 logger.GetLogger().LogOutput("trybot_image is '%s'" % trybot_image)
240 logger.GetLogger().LogOutput( "build_status is %d" % build_status)
241 return trybot_image