1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from __future__ import with_statement
17
18 import os, urllib
19 from cPickle import load
20 from twisted.python import log
21 from twisted.persisted import styles
22 from twisted.internet import defer
23 from twisted.application import service
24 from zope.interface import implements
25 from buildbot import config, interfaces, util
26 from buildbot.util import bbcollections
27 from buildbot.util.eventual import eventually
28 from buildbot.changes import changes
29 from buildbot.status import buildset, builder, buildrequest
30
31 -class Status(config.ReconfigurableServiceMixin, service.MultiService):
32 implements(interfaces.IStatus)
33
46
47
48
65
66 @defer.inlineCallbacks
89
97
98
99
100 @property
103
106
109
110
111
118
120
121
122
123 return self
124
127
129 prefix = self.getBuildbotURL()
130 return prefix + "builders/%s/builds/%d" % (
131 urllib.quote(builder_name, safe=''),
132 build_number)
133
135 prefix = self.getBuildbotURL()
136 if not prefix:
137 return None
138 if interfaces.IStatus.providedBy(thing):
139 return prefix
140 if interfaces.ISchedulerStatus.providedBy(thing):
141 pass
142 if interfaces.IBuilderStatus.providedBy(thing):
143 bldr = thing
144 return prefix + "builders/%s" % (
145 urllib.quote(bldr.getName(), safe=''),
146 )
147 if interfaces.IBuildStatus.providedBy(thing):
148 build = thing
149 bldr = build.getBuilder()
150 return self.getURLForBuild(bldr.getName(), build.getNumber())
151
152 if interfaces.IBuildStepStatus.providedBy(thing):
153 step = thing
154 build = step.getBuild()
155 bldr = build.getBuilder()
156 return prefix + "builders/%s/builds/%d/steps/%s" % (
157 urllib.quote(bldr.getName(), safe=''),
158 build.getNumber(),
159 urllib.quote(step.getName(), safe=''))
160
161
162
163
164
165 if interfaces.IStatusEvent.providedBy(thing):
166
167 if isinstance(thing, changes.Change):
168 change = thing
169 return "%schanges/%d" % (prefix, change.number)
170
171 if interfaces.IStatusLog.providedBy(thing):
172 loog = thing
173 step = loog.getStep()
174 build = step.getBuild()
175 bldr = build.getBuilder()
176
177 logs = step.getLogs()
178 for i in range(len(logs)):
179 if loog is logs[i]:
180 break
181 else:
182 return None
183 return prefix + "builders/%s/builds/%d/steps/%s/logs/%s" % (
184 urllib.quote(bldr.getName(), safe=''),
185 build.getNumber(),
186 urllib.quote(step.getName(), safe=''),
187 urllib.quote(loog.getName(), safe=''))
188
190 return list(self.master.change_svc)
191
199 d.addCallback(chdict2change)
200 return d
201
204
216
218 """
219 @rtype: L{BuilderStatus}
220 """
221 return self.botmaster.builders[name].builder_status
222
225
228
234 d.addCallback(make_status_objects)
235 return d
236
237 - def generateFinishedBuilds(self, builders=[], branches=[],
238 num_builds=None, finished_before=None,
239 max_search=200):
240
241 def want_builder(bn):
242 if builders:
243 return bn in builders
244 return True
245 builder_names = [bn
246 for bn in self.getBuilderNames()
247 if want_builder(bn)]
248
249
250
251
252 sources = []
253 for bn in builder_names:
254 b = self.getBuilder(bn)
255 g = b.generateFinishedBuilds(branches,
256 finished_before=finished_before,
257 max_search=max_search)
258 sources.append(g)
259
260
261 next_build = [None] * len(sources)
262
263 def refill():
264 for i,g in enumerate(sources):
265 if next_build[i]:
266
267 continue
268 if not g:
269
270 continue
271 try:
272 next_build[i] = g.next()
273 except StopIteration:
274 next_build[i] = None
275 sources[i] = None
276
277 got = 0
278 while True:
279 refill()
280
281 candidates = [(i, b, b.getTimes()[1])
282 for i,b in enumerate(next_build)
283 if b is not None]
284 candidates.sort(lambda x,y: cmp(x[2], y[2]))
285 if not candidates:
286 return
287
288
289 i, build, finshed_time = candidates[-1]
290 next_build[i] = None
291 got += 1
292 yield build
293 if num_builds is not None:
294 if got >= num_builds:
295 return
296
303
304
305
306
311
313 """
314 @rtype: L{BuilderStatus}
315 """
316 filename = os.path.join(self.basedir, basedir, "builder")
317 log.msg("trying to load status pickle from %s" % filename)
318 builder_status = None
319 try:
320 with open(filename, "rb") as f:
321 builder_status = load(f)
322 builder_status.master = self.master
323
324
325
326
327
328
329 versioneds = styles.versionedsToUpgrade
330 styles.doUpgrade()
331 if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]:
332 log.msg("re-writing upgraded builder pickle")
333 builder_status.saveYourself()
334
335 except IOError:
336 log.msg("no saved status pickle, creating a new one")
337 except:
338 log.msg("error while loading status pickle, creating a new one")
339 log.msg("error follows:")
340 log.err()
341 if not builder_status:
342 builder_status = builder.BuilderStatus(name, category, self.master)
343 builder_status.addPointEvent(["builder", "created"])
344 log.msg("added builder %s in category %s" % (name, category))
345
346
347 builder_status.category = category
348 builder_status.master = self.master
349 builder_status.basedir = os.path.join(self.basedir, basedir)
350 builder_status.name = name
351 builder_status.status = self
352
353 if not os.path.isdir(builder_status.basedir):
354 os.makedirs(builder_status.basedir)
355 builder_status.determineNextBuildNumber()
356
357 builder_status.setBigState("offline")
358
359 for t in self.watchers:
360 self.announceNewBuilder(t, name, builder_status)
361
362 return builder_status
363
368
373
378
383
385 result = {}
386
387 result['title'] = self.getTitle()
388 result['titleURL'] = self.getTitleURL()
389 result['buildbotURL'] = self.getBuildbotURL()
390
391
392 return result
393
395 if brid in self._buildreq_observers:
396 for o in self._buildreq_observers[brid]:
397 eventually(o, build_status)
398
400 self._buildreq_observers.add(brid, observer)
401
403 self._buildreq_observers.discard(brid, observer)
404
406 d = defer.Deferred()
407 self._buildset_finished_waiters.add(bsid, d)
408 self._maybeBuildsetFinished(bsid)
409 return d
410
422 d.addCallback(do_notifies)
423 d.addErrback(log.err, 'while notifying for buildset finishes')
424
426
427 self._builder_observers.add(buildername, watcher)
428
430 self._builder_observers.discard(buildername, watcher)
431
440 d.addCallback(do_notifies)
441 d.addErrback(log.err, 'while notifying buildsetSubmitted')
442
444 self._maybeBuildsetFinished(bsid)
445
447 buildername = notif['buildername']
448 if buildername in self._builder_observers:
449 brs = buildrequest.BuildRequestStatus(buildername,
450 notif['brid'], self)
451 for observer in self._builder_observers[buildername]:
452 if hasattr(observer, 'requestSubmitted'):
453 eventually(observer.requestSubmitted, brs)
454