1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from twisted.spread import pb
17 from twisted.internet import defer
18 from twisted.python import log
19
20 (ATTACHING,
21 IDLE,
22 PINGING,
23 BUILDING,
24 LATENT,
25 SUBSTANTIATING,
26 ) = range(6)
27
29 """I am the master-side representative for one of the
30 L{buildbot.slave.bot.SlaveBuilder} objects that lives in a remote
31 buildbot. When a remote builder connects, I query it for command versions
32 and then make it available to any Builds that are ready to run. """
33
35 self.ping_watchers = []
36 self.state = None
37 self.remote = None
38 self.slave = None
39 self.builder_name = None
40 self.locks = None
41
43 r = ["<", self.__class__.__name__]
44 if self.builder_name:
45 r.extend([" builder=", repr(self.builder_name)])
46 if self.slave:
47 r.extend([" slave=", repr(self.slave.slavename)])
48 r.append(">")
49 return ''.join(r)
50
54
56 if self.remoteCommands is None:
57
58 return oldversion
59 return self.remoteCommands.get(command)
60
72
75
78
83
84 - def attached(self, slave, remote, commands):
85 """
86 @type slave: L{buildbot.buildslave.BuildSlave}
87 @param slave: the BuildSlave that represents the buildslave as a
88 whole
89 @type remote: L{twisted.spread.pb.RemoteReference}
90 @param remote: a reference to the L{buildbot.slave.bot.SlaveBuilder}
91 @type commands: dict: string -> string, or None
92 @param commands: provides the slave's version of each RemoteCommand
93 """
94 self.state = ATTACHING
95 self.remote = remote
96 self.remoteCommands = commands
97 if self.slave is None:
98 self.slave = slave
99 self.slave.addSlaveBuilder(self)
100 else:
101 assert self.slave == slave
102 log.msg("Buildslave %s attached to %s" % (slave.slavename,
103 self.builder_name))
104 d = defer.succeed(None)
105
106 d.addCallback(lambda _:
107 self.remote.callRemote("setMaster", self))
108
109 d.addCallback(lambda _:
110 self.remote.callRemote("print", "attached"))
111
112 def setIdle(res):
113 self.state = IDLE
114 return self
115 d.addCallback(setIdle)
116
117 return d
118
119 - def prepare(self, builder_status, build):
120 if not self.slave.acquireLocks():
121 return defer.succeed(False)
122 return defer.succeed(True)
123
124 - def ping(self, status=None):
125 """Ping the slave to make sure it is still there. Returns a Deferred
126 that fires with True if it is.
127
128 @param status: if you point this at a BuilderStatus, a 'pinging'
129 event will be pushed.
130 """
131 oldstate = self.state
132 self.state = PINGING
133 newping = not self.ping_watchers
134 d = defer.Deferred()
135 self.ping_watchers.append(d)
136 if newping:
137 if status:
138 event = status.addEvent(["pinging"])
139 d2 = defer.Deferred()
140 d2.addCallback(self._pong_status, event)
141 self.ping_watchers.insert(0, d2)
142
143
144 Ping().ping(self.remote).addCallback(self._pong)
145
146 def reset_state(res):
147 if self.state == PINGING:
148 self.state = oldstate
149 return res
150 d.addCallback(reset_state)
151 return d
152
154 watchers, self.ping_watchers = self.ping_watchers, []
155 for d in watchers:
156 d.callback(res)
157
164
173
174
176 running = False
177
178 - def ping(self, remote):
179 assert not self.running
180 if not remote:
181
182 return defer.succeed(False)
183 self.running = True
184 log.msg("sending ping")
185 self.d = defer.Deferred()
186
187
188 remote.callRemote("print", "ping").addCallbacks(self._pong,
189 self._ping_failed,
190 errbackArgs=(remote,))
191 return self.d
192
194 log.msg("ping finished: success")
195 self.d.callback(True)
196
198 log.msg("ping finished: failure")
199
200
201
202 remote.broker.transport.loseConnection()
203
204
205
206 self.d.callback(False)
207
208
221
231
232 - def prepare(self, builder_status, build):
245 def substantiation_cancelled(res):
246
247 if not res:
248 self.state = LATENT
249 return res
250 d.addCallback(substantiation_cancelled)
251 d.addErrback(substantiation_failed)
252 return d
253
269 def substantiation_failed(res):
270 event.text = ["substantiate", "failed"]
271
272 event.finish()
273 return res
274 d.addCallbacks(substantiated, substantiation_failed)
275 return d
276
280
284
288
289 - def ping(self, status=None):
295