def attached(self, worker, commands): """This is invoked by the Worker when the self.workername bot registers their builder. @type worker: L{buildbot.worker.Worker} @param worker: the Worker that represents the worker as a whole @type commands: dict: string -> string, or None @param commands: provides the worker's version of each RemoteCommand @rtype: L{twisted.internet.defer.Deferred} @return: a Deferred that fires (with 'self') when the worker-side builder is fully attached and ready to accept commands. """ for w in self.attaching_workers + self.workers: if w.worker == worker: # already attached to them. This is fairly common, since # attached() gets called each time we receive the builder # list from the worker, and we ask for it each time we add or # remove a builder. So if the worker is hosting builders # A,B,C, and the config file changes A, we'll remove A and # re-add it, triggering two builder-list requests, getting # two redundant calls to attached() for B, and another two # for C. # # Therefore, when we see that we're already attached, we can # just ignore it. return defer.succeed(self) wfb = workerforbuilder.WorkerForBuilder() wfb.setBuilder(self) self.attaching_workers.append(wfb) d = wfb.attached(worker, commands) d.addCallback(self._attached) d.addErrback(self._not_attached, worker) return d
def setUp(self): self.setUpTestReactor() self.master = fakemaster.make_master(self, wantData=True, wantMq=True, wantDb=True) self.master.db.insertTestData([ fakedb.Builder(id=80, name='test'), ]) self.builder = builder.Builder('test') self.builder._builderid = 80 self.builder.config_version = 0 self.builder.master = self.master self.builder.botmaster = mock.Mock() self.builder.botmaster.getLockFromLockAccesses = lambda l, c: [] yield self.builder.startService() self.factory = factory.BuildFactory() # will have steps added later new_config = config.MasterConfig() new_config.builders.append( config.BuilderConfig(name='test', workername='testworker', factory=self.factory)) yield self.builder.reconfigServiceWithBuildbotConfig(new_config) self.worker = Worker('worker', 'pass') self.worker.sendBuilderList = lambda: defer.succeed(None) self.worker.parent = mock.Mock() self.worker.master.botmaster = mock.Mock() self.worker.botmaster.maybeStartBuildsForWorker = lambda w: None self.worker.botmaster.getBuildersForWorker = lambda w: [] self.worker.parent = self.master self.worker.startService() self.conn = fakeprotocol.FakeConnection(self.master, self.worker) yield self.worker.attached(self.conn) wfb = self.workerforbuilder = workerforbuilder.WorkerForBuilder() wfb.setBuilder(self.builder) yield wfb.attached(self.worker, {}) # add the buildset/request self.bsid, brids = yield self.master.db.buildsets.addBuildset( sourcestamps=[{}], reason='x', properties={}, builderids=[80], waited_for=False) self.brdict = \ yield self.master.db.buildrequests.getBuildRequest(brids[80]) self.buildrequest = \ yield buildrequest.BuildRequest.fromBrdict(self.master, self.brdict)
def attached(self, worker, commands): """This is invoked by the Worker when the self.workername bot registers their builder. @type worker: L{buildbot.worker.Worker} @param worker: the Worker that represents the worker as a whole @type commands: dict: string -> string, or None @param commands: provides the worker's version of each RemoteCommand @rtype: L{twisted.internet.defer.Deferred} @return: a Deferred that fires (with 'self') when the worker-side builder is fully attached and ready to accept commands. """ for w in self.attaching_workers + self.workers: if w.worker == worker: # already attached to them. This is fairly common, since # attached() gets called each time we receive the builder # list from the worker, and we ask for it each time we add or # remove a builder. So if the worker is hosting builders # A,B,C, and the config file changes A, we'll remove A and # re-add it, triggering two builder-list requests, getting # two redundant calls to attached() for B, and another two # for C. # # Therefore, when we see that we're already attached, we can # just ignore it. return self wfb = workerforbuilder.WorkerForBuilder() wfb.setBuilder(self) self.attaching_workers.append(wfb) try: yield wfb.attached(worker, commands) self.attaching_workers.remove(wfb) self.workers.append(wfb) return self except Exception as e: # pragma: no cover # already log.err'ed by WorkerForBuilder._attachFailure # TODO: remove from self.workers (except that detached() should get # run first, right?) log.err(e, 'worker failed to attach') return None