1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from twisted.spread import pb
18 from twisted.python import components, log as twlog
19 from twisted.internet import reactor
20 from twisted.application import strports
21 from twisted.cred import portal, checkers
22
23 from buildbot import interfaces
24 from zope.interface import Interface, implements
25 from buildbot.status import builder, base
26 from buildbot.changes import changes
27
30
32
33
34 if obj is None:
35 return None
36 return IRemote(obj)
37
38
42
45
48
51
54
60
63
68
73
76
77 components.registerAdapter(RemoteBuildSet,
78 interfaces.IBuildSetStatus, IRemote)
79
80
84
87
90
92 state, builds = self.b.getState()
93 return (state,
94 None,
95 [makeRemote(b) for b in builds])
96
99
102
105
108
111
112 components.registerAdapter(RemoteBuilder,
113 interfaces.IBuilderStatus, IRemote)
114
115
118 self.b = buildreq
119 self.observers = []
120
123
126
128 """The observer's remote_newbuild method will be called (with two
129 arguments: the RemoteBuild object, and our builderName) for each new
130 Build that is created to handle this BuildRequest."""
131 self.observers.append(observer)
132 def send(bs):
133 d = observer.callRemote("newbuild",
134 IRemote(bs), self.b.getBuilderName())
135 d.addErrback(lambda err: None)
136 reactor.callLater(0, self.b.subscribe, send)
137
139
140
141
142
143
144 for o in self.observers:
145 if o == observer:
146 self.observers.remove(o)
147
148 components.registerAdapter(RemoteBuildRequest,
149 interfaces.IBuildRequestStatus, IRemote)
150
153 self.b = build
154 self.observers = []
155
158
161
164
167
170
173
176
179
181
182
183 d = self.b.waitUntilFinished()
184 d.addCallback(lambda res: self)
185 return d
186
189
192
193 - def remote_getText(self):
194 return self.b.getText()
195
198
204
206 """The observer will have remote_stepStarted(buildername, build,
207 stepname, step), remote_stepFinished(buildername, build, stepname,
208 step, results), and maybe remote_buildETAUpdate(buildername, build,
209 eta)) messages sent to it."""
210 self.observers.append(observer)
211 s = BuildSubscriber(observer)
212 self.b.subscribe(s, updateInterval)
213
215
216
217
218 for o in self.observers:
219 if o == observer:
220 self.observers.remove(o)
221
222
223 components.registerAdapter(RemoteBuild,
224 interfaces.IBuildStatus, IRemote)
225
228 self.observer = observer
229
235
242
249
250
287
288 components.registerAdapter(RemoteBuildStep,
289 interfaces.IBuildStepStatus, IRemote)
290
303
304 components.registerAdapter(RemoteSlave,
305 interfaces.ISlaveStatus, IRemote)
306
315
316 components.registerAdapter(RemoteEvent,
317 interfaces.IStatusEvent, IRemote)
318
339
340
341 components.registerAdapter(RemoteLog, builder.LogFile, IRemote)
342
343
354
355 components.registerAdapter(RemoteChange, changes.Change, IRemote)
356
357
359
360 subscribed = None
361 client = None
362
364 self.status = status
365 self.subscribed_to_builders = []
366 self.subscribed_to = []
367
369 d = self.__dict__.copy()
370 d['client'] = None
371 return d
372
376
387
389 """The remote client wishes to subscribe to some set of events.
390 'target' will be sent remote messages when these events happen.
391 'mode' indicates which events are desired: it is a string with one
392 of the following values:
393
394 'builders': builderAdded, builderRemoved
395 'builds': those plus builderChangedState, buildStarted, buildFinished
396 'steps': all those plus buildETAUpdate, stepStarted, stepFinished
397 'logs': all those plus stepETAUpdate, logStarted, logFinished
398 'full': all those plus logChunk (with the log contents)
399
400
401 Messages are defined by buildbot.interfaces.IStatusReceiver .
402 'interval' is used to specify how frequently ETAUpdate messages
403 should be sent.
404
405 Raising or lowering the subscription level will take effect starting
406 with the next build or step."""
407
408 assert mode in ("builders", "builds", "steps", "logs", "full")
409 assert target
410 twlog.msg("PB subscribe(%s)" % mode)
411
412 self.client = target
413 self.subscribed = mode
414 self.interval = interval
415 self.subscribed_to.append(self.status)
416
417
418 reactor.callLater(0, self.status.subscribe, self)
419 return None
420
426
428 """This returns tuples of (buildset, bsid), because that is much more
429 convenient for tryclient."""
430 return [(IRemote(s), s.getID()) for s in self.status.getBuildSets()]
431
434
438
442
444 """Ping method to allow pb clients to validate their connections."""
445 return "pong"
446
447
448
449
451 self.client.callRemote("builderAdded", name, IRemote(builder))
452 if self.subscribed in ("builds", "steps", "logs", "full"):
453 self.subscribed_to_builders.append(name)
454 return self
455 return None
456
458 self.client.callRemote("builderChangedState", name, state, None)
459
460
462 if name in self.subscribed_to_builders:
463 self.subscribed_to_builders.remove(name)
464 self.client.callRemote("builderRemoved", name)
465
469
470
472 self.client.callRemote("buildStarted", name, IRemote(build))
473 if self.subscribed in ("steps", "logs", "full"):
474 self.subscribed_to.append(build)
475 return (self, self.interval)
476 return None
477
484
485
490
501
511
512
518
520
521 rlog = IRemote(log, None)
522 if not rlog:
523 print "hey, couldn't adapt %s to IRemote" % log
524 self.client.callRemote("logStarted",
525 build.getBuilder().getName(), IRemote(build),
526 step.getName(), IRemote(step),
527 log.getName(), IRemote(log, None))
528 if self.subscribed in ("full",):
529 self.subscribed_to.append(log)
530 return self
531 return None
532
540
541
542 - def logChunk(self, build, step, log, channel, text):
548
549
550 -class PBListener(base.StatusReceiverMultiService):
551 """I am a listener for PB-based status clients."""
552
553 compare_attrs = ["port", "cred"]
554 implements(portal.IRealm)
555
556 - def __init__(self, port, user="statusClient", passwd="clientpw"):
557 base.StatusReceiverMultiService.__init__(self)
558 if type(port) is int:
559 port = "tcp:%d" % port
560 self.port = port
561 self.cred = (user, passwd)
562 p = portal.Portal(self)
563 c = checkers.InMemoryUsernamePasswordDatabaseDontUse()
564 c.addUser(user, passwd)
565 p.registerChecker(c)
566 f = pb.PBServerFactory(p)
567 s = strports.service(port, f)
568 s.setServiceParent(self)
569
573
576
583