1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import os, urllib
17 from cPickle import load
18 from twisted.python import log
19 from twisted.persisted import styles
20 from twisted.internet import defer
21 from twisted.application import service
22 from zope.interface import implements
23 from buildbot import config, interfaces, util
24 from buildbot.util import bbcollections
25 from buildbot.util.eventual import eventually
26 from buildbot.changes import changes
27 from buildbot.status import buildset, builder, buildrequest
28
29 -class Status(config.ReconfigurableServiceMixin, service.MultiService):
30 implements(interfaces.IStatus)
31
44
45
46
63
64 @defer.deferredGenerator
85
93
94
95
96 @property
99
102
105
106
107
114
116
117
118
119 return self
120
123
125 prefix = self.getBuildbotURL()
126 return prefix + "builders/%s/builds/%d" % (
127 urllib.quote(builder_name, safe=''),
128 build_number)
129
131 prefix = self.getBuildbotURL()
132 if not prefix:
133 return None
134 if interfaces.IStatus.providedBy(thing):
135 return prefix
136 if interfaces.ISchedulerStatus.providedBy(thing):
137 pass
138 if interfaces.IBuilderStatus.providedBy(thing):
139 bldr = thing
140 return prefix + "builders/%s" % (
141 urllib.quote(bldr.getName(), safe=''),
142 )
143 if interfaces.IBuildStatus.providedBy(thing):
144 build = thing
145 bldr = build.getBuilder()
146 return self.getURLForBuild(bldr.getName(), build.getNumber())
147
148 if interfaces.IBuildStepStatus.providedBy(thing):
149 step = thing
150 build = step.getBuild()
151 bldr = build.getBuilder()
152 return prefix + "builders/%s/builds/%d/steps/%s" % (
153 urllib.quote(bldr.getName(), safe=''),
154 build.getNumber(),
155 urllib.quote(step.getName(), safe=''))
156
157
158
159
160
161 if interfaces.IStatusEvent.providedBy(thing):
162
163 if isinstance(thing, changes.Change):
164 change = thing
165 return "%schanges/%d" % (prefix, change.number)
166
167 if interfaces.IStatusLog.providedBy(thing):
168 loog = thing
169 step = loog.getStep()
170 build = step.getBuild()
171 bldr = build.getBuilder()
172
173 logs = step.getLogs()
174 for i in range(len(logs)):
175 if loog is logs[i]:
176 break
177 else:
178 return None
179 return prefix + "builders/%s/builds/%d/steps/%s/logs/%s" % (
180 urllib.quote(bldr.getName(), safe=''),
181 build.getNumber(),
182 urllib.quote(step.getName(), safe=''),
183 urllib.quote(loog.getName(), safe=''))
184
186 return list(self.master.change_svc)
187
195 d.addCallback(chdict2change)
196 return d
197
200
212
214 """
215 @rtype: L{BuilderStatus}
216 """
217 return self.botmaster.builders[name].builder_status
218
221
224
230 d.addCallback(make_status_objects)
231 return d
232
233 - def generateFinishedBuilds(self, builders=[], branches=[],
234 num_builds=None, finished_before=None,
235 max_search=200):
236
237 def want_builder(bn):
238 if builders:
239 return bn in builders
240 return True
241 builder_names = [bn
242 for bn in self.getBuilderNames()
243 if want_builder(bn)]
244
245
246
247
248 sources = []
249 for bn in builder_names:
250 b = self.getBuilder(bn)
251 g = b.generateFinishedBuilds(branches,
252 finished_before=finished_before,
253 max_search=max_search)
254 sources.append(g)
255
256
257 next_build = [None] * len(sources)
258
259 def refill():
260 for i,g in enumerate(sources):
261 if next_build[i]:
262
263 continue
264 if not g:
265
266 continue
267 try:
268 next_build[i] = g.next()
269 except StopIteration:
270 next_build[i] = None
271 sources[i] = None
272
273 got = 0
274 while True:
275 refill()
276
277 candidates = [(i, b, b.getTimes()[1])
278 for i,b in enumerate(next_build)
279 if b is not None]
280 candidates.sort(lambda x,y: cmp(x[2], y[2]))
281 if not candidates:
282 return
283
284
285 i, build, finshed_time = candidates[-1]
286 next_build[i] = None
287 got += 1
288 yield build
289 if num_builds is not None:
290 if got >= num_builds:
291 return
292
299
300
301
302
307
309 """
310 @rtype: L{BuilderStatus}
311 """
312 filename = os.path.join(self.basedir, basedir, "builder")
313 log.msg("trying to load status pickle from %s" % filename)
314 builder_status = None
315 try:
316 builder_status = load(open(filename, "rb"))
317 builder_status.master = self.master
318
319
320
321
322
323
324 versioneds = styles.versionedsToUpgrade
325 styles.doUpgrade()
326 if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]:
327 log.msg("re-writing upgraded builder pickle")
328 builder_status.saveYourself()
329
330 except IOError:
331 log.msg("no saved status pickle, creating a new one")
332 except:
333 log.msg("error while loading status pickle, creating a new one")
334 log.msg("error follows:")
335 log.err()
336 if not builder_status:
337 builder_status = builder.BuilderStatus(name, category, self.master)
338 builder_status.addPointEvent(["builder", "created"])
339 log.msg("added builder %s in category %s" % (name, category))
340
341
342 builder_status.master = self.master
343 builder_status.basedir = os.path.join(self.basedir, basedir)
344 builder_status.name = name
345 builder_status.status = self
346
347 if not os.path.isdir(builder_status.basedir):
348 os.makedirs(builder_status.basedir)
349 builder_status.determineNextBuildNumber()
350
351 builder_status.setBigState("offline")
352
353 for t in self.watchers:
354 self.announceNewBuilder(t, name, builder_status)
355
356 return builder_status
357
362
367
372
377
379 result = {}
380
381 result['title'] = self.getTitle()
382 result['titleURL'] = self.getTitleURL()
383 result['buildbotURL'] = self.getBuildbotURL()
384
385
386 return result
387
389 if brid in self._buildreq_observers:
390 for o in self._buildreq_observers[brid]:
391 eventually(o, build_status)
392
394 self._buildreq_observers.add(brid, observer)
395
397 self._buildreq_observers.discard(brid, observer)
398
400 d = defer.Deferred()
401 self._buildset_finished_waiters.add(bsid, d)
402 self._maybeBuildsetFinished(bsid)
403 return d
404
416 d.addCallback(do_notifies)
417 d.addErrback(log.err, 'while notifying for buildset finishes')
418
420
421 self._builder_observers.add(buildername, watcher)
422
424 self._builder_observers.discard(buildername, watcher)
425
434 d.addCallback(do_notifies)
435 d.addErrback(log.err, 'while notifying buildsetSubmitted')
436
438 self._maybeBuildsetFinished(bsid)
439
441 buildername = notif['buildername']
442 if buildername in self._builder_observers:
443 brs = buildrequest.BuildRequestStatus(buildername,
444 notif['brid'], self)
445 for observer in self._builder_observers[buildername]:
446 if hasattr(observer, 'requestSubmitted'):
447 eventually(observer.requestSubmitted, brs)
448