Package buildbot :: Package status :: Package web :: Module xmlrpc
[frames] | no frames]

Source Code for Module buildbot.status.web.xmlrpc

  1  from twisted.python import log 
  2  from twisted.web import xmlrpc 
  3  from buildbot.status.builder import Results 
  4  from itertools import count 
  5   
6 -class XMLRPCServer(xmlrpc.XMLRPC):
7 - def __init__(self):
8 xmlrpc.XMLRPC.__init__(self)
9
10 - def render(self, req):
11 # extract the IStatus object for later use, since it comes from the 12 # request object. It'll be the same each time, but it isn't available 13 # until the first request arrives. 14 self.status = req.site.buildbot_service.getStatus() 15 return xmlrpc.XMLRPC.render(self, req)
16
17 - def xmlrpc_getAllBuilders(self):
18 """Return a list of all builder names 19 """ 20 log.msg("getAllBuilders") 21 return self.status.getBuilderNames()
22
23 - def xmlrpc_getLastBuildResults(self, builder_name):
24 """Return the result of the last build for the given builder 25 """ 26 builder = self.status.getBuilder(builder_name) 27 lastbuild = builder.getBuild(-1) 28 return Results[lastbuild.getResults()]
29
30 - def xmlrpc_getLastBuildsAllBuilders(self, num_builds):
31 """Return the last N completed builds for all builders. 32 33 'num_builds' is the number of builds for each builder to 34 return 35 36 """ 37 all_builds = [] 38 for name in self.status.getBuilderNames(): 39 all_builds.extend(self.xmlrpc_getLastBuilds(name, num_builds)) 40 return all_builds
41
42 - def xmlrpc_getLastBuilds(self, builder_name, num_builds):
43 """Return the last N completed builds for the given builder. 44 'builder_name' is the name of the builder to query 45 'num_builds' is the number of builds to return 46 47 Each build is returned in the same form as xmlrpc_getAllBuildsInInterval 48 """ 49 log.msg("getLastBuilds: %s - %d" % (builder_name, num_builds)) 50 builder = self.status.getBuilder(builder_name) 51 all_builds = [] 52 for build_number in range(1, num_builds+1): 53 build = builder.getBuild(-build_number) 54 if not build: 55 break 56 if not build.isFinished(): 57 continue 58 (build_start, build_end) = build.getTimes() 59 60 ss = build.getSourceStamp() 61 branch = ss.branch 62 if branch is None: 63 branch = "" 64 try: 65 revision = build.getProperty("got_revision") 66 except KeyError: 67 revision = "" 68 revision = str(revision) 69 70 result = Results[build.getResults()] 71 if result == 'failure': 72 fail_names = result = build.getText()[1:] 73 reasons = [] 74 for s in build.getSteps(): 75 if s.getName() in fail_names: 76 reasons.append(s.getText()) 77 else: 78 result = build.getText() 79 reasons = [] 80 answer = (builder_name, 81 build.getNumber(), 82 build_start, 83 build_end, 84 branch, 85 revision, 86 Results[build.getResults()], 87 result, 88 reasons, 89 ) 90 all_builds.append((build_end, answer)) 91 92 # now we've gotten all the builds we're interested in. Sort them by 93 # end time. 94 all_builds.sort(lambda a,b: cmp(a[0], b[0])) 95 # and remove the timestamps 96 all_builds = [t[1] for t in all_builds] 97 98 log.msg("ready to go: %s" % (all_builds,)) 99 100 return all_builds
101 102
103 - def xmlrpc_getAllBuildsInInterval(self, start, stop):
104 """Return a list of builds that have completed after the 'start' 105 timestamp and before the 'stop' timestamp. This looks at all 106 Builders. 107 108 The timestamps are integers, interpreted as standard unix timestamps 109 (seconds since epoch). 110 111 Each Build is returned as a tuple in the form:: 112 (buildername, buildnumber, build_end, branchname, revision, 113 results, text) 114 115 The buildnumber is an integer. 'build_end' is an integer (seconds 116 since epoch) specifying when the build finished. 117 118 The branchname is a string, which may be an empty string to indicate 119 None (i.e. the default branch). The revision is a string whose 120 meaning is specific to the VC system in use, and comes from the 121 'got_revision' build property. The results are expressed as a string, 122 one of ('success', 'warnings', 'failure', 'exception'). The text is a 123 list of short strings that ought to be joined by spaces and include 124 slightly more data about the results of the build. 125 """ 126 #log.msg("start: %s %s %s" % (start, type(start), start.__class__)) 127 log.msg("getAllBuildsInInterval: %d - %d" % (start, stop)) 128 all_builds = [] 129 130 for builder_name in self.status.getBuilderNames(): 131 builder = self.status.getBuilder(builder_name) 132 for build_number in count(1): 133 build = builder.getBuild(-build_number) 134 if not build: 135 break 136 if not build.isFinished(): 137 continue 138 (build_start, build_end) = build.getTimes() 139 # in reality, builds are mostly ordered by start time. For 140 # the purposes of this method, we pretend that they are 141 # strictly ordered by end time, so that we can stop searching 142 # when we start seeing builds that are outside the window. 143 if build_end > stop: 144 continue # keep looking 145 if build_end < start: 146 break # stop looking 147 148 ss = build.getSourceStamp() 149 branch = ss.branch 150 if branch is None: 151 branch = "" 152 try: 153 revision = build.getProperty("got_revision") 154 except KeyError: 155 revision = "" 156 revision = str(revision) 157 158 answer = (builder_name, 159 build.getNumber(), 160 build_end, 161 branch, 162 revision, 163 Results[build.getResults()], 164 build.getText(), 165 ) 166 all_builds.append((build_end, answer)) 167 # we've gotten all the builds that we care about from this 168 # particular builder, so now we can continue on the next builder 169 170 # now we've gotten all the builds we're interested in. Sort them by 171 # end time. 172 all_builds.sort(lambda a,b: cmp(a[0], b[0])) 173 # and remove the timestamps 174 all_builds = [t[1] for t in all_builds] 175 176 log.msg("ready to go: %s" % (all_builds,)) 177 178 return all_builds
179
180 - def xmlrpc_getBuild(self, builder_name, build_number):
181 """Return information about a specific build. 182 183 """ 184 builder = self.status.getBuilder(builder_name) 185 build = builder.getBuild(build_number) 186 info = {} 187 info['builder_name'] = builder.getName() 188 info['url'] = self.status.getURLForThing(build) or '' 189 info['reason'] = build.getReason() 190 info['slavename'] = build.getSlavename() 191 info['results'] = build.getResults() 192 info['text'] = build.getText() 193 info['reasons'] = [] 194 # Added to help out requests for build -N 195 info['number'] = build.number 196 ss = build.getSourceStamp() 197 branch = ss.branch 198 if branch is None: 199 branch = "" 200 info['branch'] = str(branch) 201 try: 202 revision = str(build.getProperty("got_revision")) 203 except KeyError: 204 revision = "" 205 info['revision'] = str(revision) 206 info['start'], info['end'] = build.getTimes() 207 208 step_names = {} 209 210 info_steps = [] 211 for s in build.getSteps(): 212 stepinfo = {} 213 stepinfo['name'] = s.getName() 214 stepinfo['start'], stepinfo['end'] = s.getTimes() 215 stepinfo['results'] = s.getResults() 216 stepinfo['text'] = s.getText() 217 info_steps.append(stepinfo) 218 if info['text'][0] == 'failed' and stepinfo['name'] in info['text']: 219 info['reasons'].append(stepinfo['text']) 220 step_names[stepinfo['name']] = stepinfo 221 info['steps'] = info_steps 222 223 info_logs = [] 224 info['full_error'] = {} 225 for l in build.getLogs(): 226 loginfo = {} 227 name = l.getStep().getName() 228 loginfo['name'] = name + "/" + l.getName() 229 #loginfo['text'] = l.getText() 230 loginfo['text'] = "HUGE" 231 if step_names.get(name): 232 if step_names[name]['text'][-1] == 'failed': 233 info['full_error'][name] = l.getText() 234 info_logs.append(loginfo) 235 info['logs'] = info_logs 236 return info
237