1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from twisted.web import html
18 import urllib, time
19 from twisted.python import log
20 from twisted.internet import defer
21 from buildbot import interfaces
22 from buildbot.status.web.base import HtmlResource, BuildLineMixin, \
23 path_to_build, path_to_slave, path_to_builder, path_to_change, \
24 path_to_root, ICurrentBox, build_get_class, \
25 map_branches, path_to_authzfail, ActionResource
26 from buildbot.schedulers.forcesched import ForceScheduler, InheritBuildParameter
27 from buildbot.status.web.build import BuildsResource, StatusResourceBuild
28 from buildbot import util
31
32 - def __init__(self, status, selectedOrAll):
33 self.status = status
34 self.selectedOrAll = selectedOrAll
35 self.action = "forceAllBuilds"
36
37 @defer.deferredGenerator
62
64
65 - def __init__(self, status, selectedOrAll):
66 self.status = status
67 self.selectedOrAll = selectedOrAll
68 self.action = "stopAllBuilds"
69
70 @defer.deferredGenerator
100
102
104 self.builder_status = builder_status
105 self.action = "pingBuilder"
106
107 @defer.deferredGenerator
124
126
128 self.builder_status = builder_status
129 self.action = "forceBuild"
130
131 @defer.deferredGenerator
163
164 -def buildForceContext(cxt, req, master, buildername=None):
165 force_schedulers = {}
166 default_props = {}
167 for sch in master.allSchedulers():
168 if isinstance(sch, ForceScheduler) and (buildername is None or(buildername in sch.builderNames)):
169 force_schedulers[sch.name] = sch
170 for p in sch.all_fields:
171 pname = "%s.%s"%(sch.name, p.name)
172 default = p.default
173 if isinstance(p, InheritBuildParameter):
174
175
176 p.choices = p.compatible_builds(master.status, buildername)
177 if p.choices:
178 default = p.choices[0]
179 default = req.args.get(pname, [default])[0]
180 if p.type=="bool":
181 default_props[pname] = default and "checked" or ""
182 else:
183
184 if type(default)==unicode:
185 default = html.escape(default.encode('ascii','ignore'))
186 default_props[pname] = default
187 cxt['force_schedulers'] = force_schedulers
188 cxt['default_props'] = default_props
189
192 addSlash = True
193
197
198 - def getPageTitle(self, request):
199 return "Buildbot: %s" % self.builder_status.getName()
200
226
227 @defer.deferredGenerator
228 - def content(self, req, cxt):
229 b = self.builder_status
230
231 cxt['name'] = b.getName()
232 req.setHeader('Cache-Control', 'no-cache')
233 slaves = b.getSlaves()
234 connected_slaves = [s for s in slaves if s.isConnected()]
235
236 cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()]
237
238 cxt['pending'] = []
239 wfd = defer.waitForDeferred(
240 b.getPendingBuildRequestStatuses())
241 yield wfd
242 statuses = wfd.getResult()
243 for pb in statuses:
244 changes = []
245
246 wfd = defer.waitForDeferred(
247 pb.getSourceStamp())
248 yield wfd
249 source = wfd.getResult()
250
251 wfd = defer.waitForDeferred(
252 pb.getSubmitTime())
253 yield wfd
254 submitTime = wfd.getResult()
255
256 wfd = defer.waitForDeferred(
257 pb.getBsid())
258 yield wfd
259 bsid = wfd.getResult()
260
261 wfd = defer.waitForDeferred(
262 pb.master.db.buildsets.getBuildsetProperties(bsid))
263 yield wfd
264 properties = wfd.getResult()
265
266 if source.changes:
267 for c in source.changes:
268 changes.append({ 'url' : path_to_change(req, c),
269 'who' : c.who,
270 'revision' : c.revision,
271 'repo' : c.repository })
272
273 cxt['pending'].append({
274 'when': time.strftime("%b %d %H:%M:%S",
275 time.localtime(submitTime)),
276 'delay': util.formatInterval(util.now() - submitTime),
277 'id': pb.brid,
278 'changes' : changes,
279 'num_changes' : len(changes),
280 'properties' : properties,
281 })
282
283 numbuilds = int(req.args.get('numbuilds', ['5'])[0])
284 recent = cxt['recent'] = []
285 for build in b.generateFinishedBuilds(num_builds=int(numbuilds)):
286 recent.append(self.get_line_values(req, build, False))
287
288 sl = cxt['slaves'] = []
289 connected_slaves = 0
290 for slave in slaves:
291 s = {}
292 sl.append(s)
293 s['link'] = path_to_slave(req, slave)
294 s['name'] = slave.getName()
295 c = s['connected'] = slave.isConnected()
296 if c:
297 s['admin'] = unicode(slave.getAdmin() or '', 'utf-8')
298 connected_slaves += 1
299 cxt['connected_slaves'] = connected_slaves
300
301 cxt['authz'] = self.getAuthz(req)
302 cxt['builder_url'] = path_to_builder(req, b)
303 buildForceContext(cxt, req, self.getBuildmaster(req), b.getName())
304 template = req.site.buildbot_service.templates.get_template("builder.html")
305 yield template.render(**cxt)
306
307 - def ping(self, req):
309
323
325
329
330 @defer.deferredGenerator
369
371
372 @defer.deferredGenerator
374 try:
375 request_change = req.args.get("change", [None])[0]
376 request_change = int(request_change)
377 except:
378 request_change = None
379
380 authz = self.getAuthz(req)
381 if request_change:
382 c = interfaces.IControl(self.getBuildmaster(req))
383 builder_control = c.getBuilder(builder_status.getName())
384
385 wfd = defer.waitForDeferred(
386 builder_control.getPendingBuildRequestControls())
387 yield wfd
388 brcontrols = wfd.getResult()
389
390 build_controls = dict((x.brid, x) for x in brcontrols)
391
392 wfd = defer.waitForDeferred(
393 builder_status.getPendingBuildRequestStatuses())
394 yield wfd
395 build_req_statuses = wfd.getResult()
396
397 for build_req in build_req_statuses:
398 wfd = defer.waitForDeferred(
399 build_req.getSourceStamp())
400 yield wfd
401 ss = wfd.getResult()
402
403 if not ss.changes:
404 continue
405
406 for change in ss.changes:
407 if change.number == request_change:
408 control = build_controls[build_req.brid]
409 log.msg("Cancelling %s" % control)
410 d = authz.actionAllowed('stopChange', req, control)
411 wfd = defer.waitForDeferred(d)
412 yield wfd
413 res = wfd.getResult()
414 if (auth_ok or res):
415 control.cancel()
416 else:
417 yield False
418 return
419
420 yield True
421
424
428
429 @defer.deferredGenerator
441
444
448
449 @defer.deferredGenerator
470
494
515
518 pageTitle = "Builders"
519 addSlash = True
520
521 @defer.deferredGenerator
522 - def content(self, req, cxt):
523 status = self.getStatus(req)
524
525 builders = req.args.get("builder", status.getBuilderNames())
526 branches = [b for b in req.args.get("branch", []) if b]
527
528
529 brstatus_ds = []
530 brcounts = {}
531 def keep_count(statuses, builderName):
532 brcounts[builderName] = len(statuses)
533 for builderName in builders:
534 builder_status = status.getBuilder(builderName)
535 d = builder_status.getPendingBuildRequestStatuses()
536 d.addCallback(keep_count, builderName)
537 brstatus_ds.append(d)
538 wfd = defer.waitForDeferred(
539 defer.gatherResults(brstatus_ds))
540 yield wfd
541 wfd.getResult()
542
543 cxt['branches'] = branches
544 bs = cxt['builders'] = []
545
546 building = 0
547 online = 0
548 base_builders_url = path_to_root(req) + "builders/"
549 for bn in builders:
550 bld = { 'link': base_builders_url + urllib.quote(bn, safe=''),
551 'name': bn }
552 bs.append(bld)
553
554 builder = status.getBuilder(bn)
555 builds = list(builder.generateFinishedBuilds(map_branches(branches),
556 num_builds=1))
557 if builds:
558 b = builds[0]
559 bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber())
560 label = b.getProperty("got_revision")
561 if not label or len(str(label)) > 20:
562 label = "#%d" % b.getNumber()
563
564 bld['build_label'] = label
565 bld['build_text'] = " ".join(b.getText())
566 bld['build_css_class'] = build_get_class(b)
567
568 current_box = ICurrentBox(builder).getBox(status, brcounts)
569 bld['current_box'] = current_box.td()
570
571 builder_status = builder.getState()[0]
572 if builder_status == "building":
573 building += 1
574 online += 1
575 elif builder_status != "offline":
576 online += 1
577
578 cxt['authz'] = self.getAuthz(req)
579 cxt['num_building'] = building
580 cxt['num_online'] = online
581 buildForceContext(cxt, req, self.getBuildmaster(req))
582 template = req.site.buildbot_service.templates.get_template("builders.html")
583 yield template.render(**cxt)
584
596