blob: e41490fdf1ded71709b044f2e4d022401539fdac [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
163 # Wait for buildbot to finish running (check every 10 minutes)
164 done = False
165 running_time = 0
166 while not done:
167 done = True
168 build_info = GetBuildInfo(base_dir)
169 if not build_info:
170 logger.GetLogger().LogFatal("Unable to get build logs for target %s"
171 % build)
172
173 data_dict = FindBuildRecordFromLog(description, build_info)
174 if not data_dict:
175 logger.GetLogger().LogFatal("Unable to find build record for trybot %s"
176 % description)
177
178 if "True" in data_dict["completed"]:
179 build_id = data_dict["number"]
180 else:
181 done = False
182
183 if not done:
184 logger.GetLogger().LogOutput("{0} minutes passed.".format(
185 running_time / 60))
186 logger.GetLogger().LogOutput("Sleeping {0} seconds.".format(SLEEP_TIME))
187 time.sleep(SLEEP_TIME)
188 running_time += SLEEP_TIME
189 if running_time > TIME_OUT:
190 done = True
191
192 trybot_image = ""
193 # Buildbot has finished. Look for the log and the trybot image.
194 if build_id:
195 log_name = GetBuildData(build, build_id)
196 if log_name:
197 trybot_image = ParseReportLog(log_name, build)
198
199 return trybot_image