blob: 6bd431be333a9fd85d3566e689fb299bad4cb1a7 [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:
39 if l.find("Artifacts") and l.find("trybot"):
40 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
47
48def GetBuildData (buildbot_queue, build_id):
49 """
50 Find the Reports stage web page for a trybot build.
51
52 This takes the name of a buildbot_queue, such as 'daisy-release'
53 and a build id (the build number), and uses the json buildbot api to
54 find the Reports stage web page for that build, if it exists.
55 """
56 builder = buildbot_json.Buildbot(
57 "http://chromegw/p/tryserver.chromiumos/").builders[buildbot_queue]
58 build_data = builder.builds[build_id].data
59 logs = build_data["logs"]
60 for l in logs:
61 fname = l[1]
62 if "steps/Report/" in fname:
63 return fname
64
65 return ""
66
67
68def FindBuildRecordFromLog(description, log_info):
69 """
70 Find the right build record in the build logs.
71
72 Get the first build record from build log with a reason field
73 that matches 'description'. ('description' is a special tag we
74 created when we launched the buildbot, so we could find it at this
75 point.)
76 """
77
78 current_line = 1
79 while current_line < len(log_info):
80 my_dict = {}
81 # Read all the lines from one "Build" to the next into my_dict
82 while True:
83 key = log_info[current_line].split(":")[0].strip()
84 value = log_info[current_line].split(":", 1)[1].strip()
85 my_dict[key] = value
86 current_line += 1
87 if "Build" in key or current_line == len(log_info):
88 break
89 try:
90 # Check to see of the build record is the right one.
91 if str(description) in my_dict["reason"]:
92 # We found a match; we're done.
93 return my_dict
94 except:
95 print "reason is not in dictionary: '%s'" % repr(my_dict)
96 else:
97 # Keep going.
98 continue
99
100 # We hit the bottom of the log without a match.
101 return {}
102
103
104def GetBuildInfo(file_dir):
105 """
106 Get all the build records for the trybot builds.
107
108 file_dir is the toolchain_utils directory.
109 """
110 ce = command_executer.GetCommandExecuter()
111 commands = ("{0}/utils/buildbot_json.py builds "
112 "http://chromegw/p/tryserver.chromiumos/"
113 .format(file_dir))
114
115 _, buildinfo, _ = ce.RunCommand(commands, return_output=True,
116 print_to_console=False)
117 build_log = buildinfo.splitlines()
118 return build_log
119
120
121def GetTrybotImage(chromeos_root, buildbot_name, patch_list, build_tag):
122 """
123 Launch buildbot and get resulting trybot artifact name.
124
125 This function launches a buildbot with the appropriate flags to
126 build the test ChromeOS image, with the current ToT mobile compiler. It
127 checks every 10 minutes to see if the trybot has finished. When the trybot
128 has finished, it parses the resulting report logs to find the trybot
129 artifact (if one was created), and returns that artifact name.
130
131 chromeos_root is the path to the ChromeOS root, needed for finding chromite
132 and launching the buildbot.
133
134 buildbot_name is the name of the buildbot queue, such as lumpy-release or
135 daisy-paladin.
136
137 patch_list a python list of the patches, if any, for the buildbot to use.
138
139 build_tag is a (unique) string to be used to look up the buildbot results
140 from among all the build records.
141 """
142 ce = command_executer.GetCommandExecuter()
143 cbuildbot_path = os.path.join(chromeos_root, "chromite/cbuildbot")
144 base_dir = os.getcwd()
145 patch_arg = ""
146 if patch_list:
147 patch_arg = "-g "
148 for p in patch_list:
149 patch_arg = patch_arg + " " + repr(p)
150 branch = "master"
151 os.chdir(cbuildbot_path)
152
153 # Launch buildbot with appropriate flags.
154 build = buildbot_name
155 description = build_tag
156 command = ("./cbuildbot --remote --nochromesdk --notests %s %s"
157 " --remote-description=%s"
158 " --chrome_rev=tot" % (patch_arg, build, description))
159 ce.RunCommand(command)
160 os.chdir(base_dir)
161
162 build_id = 0
cmticed54f9802015-02-05 11:04:11 -0800163 build_status = None
cmtice46093e52014-12-09 14:59:16 -0800164 # Wait for buildbot to finish running (check every 10 minutes)
165 done = False
166 running_time = 0
167 while not done:
168 done = True
169 build_info = GetBuildInfo(base_dir)
170 if not build_info:
171 logger.GetLogger().LogFatal("Unable to get build logs for target %s"
172 % build)
173
174 data_dict = FindBuildRecordFromLog(description, build_info)
175 if not data_dict:
176 logger.GetLogger().LogFatal("Unable to find build record for trybot %s"
177 % description)
178
179 if "True" in data_dict["completed"]:
180 build_id = data_dict["number"]
cmticed54f9802015-02-05 11:04:11 -0800181 build_status = data_dict["result"]
cmtice46093e52014-12-09 14:59:16 -0800182 else:
183 done = False
184
185 if not done:
186 logger.GetLogger().LogOutput("{0} minutes passed.".format(
187 running_time / 60))
188 logger.GetLogger().LogOutput("Sleeping {0} seconds.".format(SLEEP_TIME))
189 time.sleep(SLEEP_TIME)
190 running_time += SLEEP_TIME
191 if running_time > TIME_OUT:
192 done = True
193
cmticed54f9802015-02-05 11:04:11 -0800194 if done and build_status != 0:
195 logger.GetLogger().LogError("Trybot job %s failed with status %s."
196 % (description, repr(build_status)))
197 return ""
198 else:
199 trybot_image = ""
200 # Buildbot has finished. Look for the log and the trybot image.
201 if build_id:
202 log_name = GetBuildData(build, build_id)
203 if log_name:
204 trybot_image = ParseReportLog(log_name, build)
cmtice46093e52014-12-09 14:59:16 -0800205
cmticed54f9802015-02-05 11:04:11 -0800206 print "trybot_image is '%s'" % trybot_image
207 print "build_status is %s" % repr(build_status)
208 return trybot_image