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