[Buildbot-commits] buildbot/buildbot buildslave.py, 1.6, 1.7 interfaces.py, 1.62, 1.63 master.py, 1.109, 1.110

Brian Warner warner at users.sourceforge.net
Sun Aug 12 23:17:14 UTC 2007


Update of /cvsroot/buildbot/buildbot/buildbot
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv27314/buildbot

Modified Files:
	buildslave.py interfaces.py master.py 
Log Message:
[project @ make BuildSlaves live as Service children of the BotMaster]

Original author: warner at lothar.com
Date: 2007-08-12 23:14:33+00:00

Index: buildslave.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/buildslave.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- buildslave.py	12 Aug 2007 22:22:46 -0000	1.6
+++ buildslave.py	12 Aug 2007 23:17:12 -0000	1.7
@@ -1,12 +1,15 @@
 
 import time
+from zope.interface import implements
 from twisted.python import log
 from twisted.internet import defer, reactor
+from twisted.application import service
 
 from buildbot.pbutil import NewCredPerspective
 from buildbot.status.builder import SlaveStatus
+from buildbot.interfaces import IBuildSlave
 
-class BuildSlave(NewCredPerspective):
+class BuildSlave(NewCredPerspective, service.MultiService):
     """This is the master-side representative for a remote buildbot slave.
     There is exactly one for each slave described in the config file (the
     c['slaves'] list). When buildbots connect in (.attach), they get a
@@ -17,6 +20,8 @@
     running builds.  I am instantiated by the configuration file, and can be
     subclassed to add extra functionality."""
 
+    implements(IBuildSlave)
+
     def __init__(self, name, password, max_builds=None):
         """
         @param name: botname this machine will supply when it connects
@@ -26,7 +31,7 @@
                            be run concurrently on this buildslave (the
                            default is None for no limit)
         """
-
+        service.MultiService.__init__(self)
         self.slavename = name
         self.password = password
         self.botmaster = None # no buildmaster yet

Index: interfaces.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/interfaces.py,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- interfaces.py	12 Aug 2007 22:22:51 -0000	1.62
+++ interfaces.py	12 Aug 2007 23:17:12 -0000	1.63
@@ -1035,3 +1035,6 @@
     def logChunk(build, step, log, channel, text):
         pass
 
+class IBuildSlave(Interface):
+    # this is a marker interface for the BuildSlave class
+    pass

Index: master.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/master.py,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -d -r1.109 -r1.110
--- master.py	7 Aug 2007 19:21:39 -0000	1.109
+++ master.py	12 Aug 2007 23:17:12 -0000	1.110
@@ -30,7 +30,7 @@
 
 ########################################
     
-class BotMaster(service.Service):
+class BotMaster(service.MultiService):
 
     """This is the master-side service which manages remote buildbot slaves.
     It provides them with BuildSlaves, and distributes file change
@@ -40,6 +40,7 @@
     debug = 0
 
     def __init__(self):
+        service.MultiService.__init__(self)
         self.builders = {}
         self.builderNames = []
         # builders maps Builder names to instances of bb.p.builder.Builder,
@@ -96,14 +97,58 @@
                 return d
         return defer.succeed(None)
 
+    def loadConfig_Slaves(self, new_slaves):
+        old_slaves = [c for c in list(self)
+                      if interfaces.IBuildSlave.providedBy(c)]
 
-    def addSlave(self, slave):
-        slave.setBotmaster(self)
-        self.slaves[slave.slavename] = slave
+        # identify added/removed slaves. For each slave we construct a tuple
+        # of (name, password, class), and we consider the slave to be already
+        # present if the tuples match. (we include the class to make sure
+        # that BuildSlave(name,pw) is different than
+        # SubclassOfBuildSlave(name,pw) ). If the password or class has
+        # changed, we will remove the old version of the slave and replace it
+        # with a new one. If anything else has changed, we just update the
+        # old BuildSlave instance in place. If the name has changed, of
+        # course, it looks exactly the same as deleting one slave and adding
+        # an unrelated one.
+        old_t = {}
+        for s in old_slaves:
+            old_t[(s.slavename, s.password, s.__class__)] = s
+        new_t = {}
+        for s in new_slaves:
+            new_t[(s.slavename, s.password, s.__class__)] = s
+        removed = [old_t[t]
+                   for t in old_t
+                   if t not in new_t]
+        added = [new_t[t]
+                 for t in new_t
+                 if t not in old_t]
+        remaining_t = [t
+                       for t in new_t
+                       if t in old_t]
+        # removeSlave will hang up on the old bot
+        dl = []
+        for s in removed:
+            dl.append(self.removeSlave(s))
+        d = defer.DeferredList(dl, fireOnOneErrback=True)
+        def _add(res):
+            for s in added:
+                self.addSlave(s)
+            for t in remaining_t:
+                old_t[t].update(new_t[t])
+        d.addCallback(_add)
+        return d
 
-    def removeSlave(self, slavename):
-        d = self.slaves[slavename].disconnect()
-        del self.slaves[slavename]
+    def addSlave(self, s):
+        s.setServiceParent(self)
+        s.setBotmaster(self)
+        self.slaves[s.slavename] = s
+
+    def removeSlave(self, s):
+        # TODO: technically, disownServiceParent could return a Deferred
+        s.disownServiceParent()
+        d = self.slaves[s.slavename].disconnect()
+        del self.slaves[s.slavename]
         return d
 
     def slaveLost(self, bot):
@@ -326,7 +371,6 @@
 
         self.statusTargets = []
 
-        self.slaves = []
         # this ChangeMaster is a dummy, only used by tests. In the real
         # buildmaster, where the BuildMaster instance is activated
         # (startService is called) by twistd, this attribute is overwritten.
@@ -684,43 +728,8 @@
         for s in new_slaves:
             self.checker.addUser(s.slavename, s.password)
         self.checker.addUser("change", "changepw")
-
-        # identify new/old slaves. For each slave we construct a tuple of
-        # (name, password, class), and we consider the slave to be already
-        # present if the tuples match. (we include the class to make sure
-        # that BuildSlave(name,pw) is different than
-        # SubclassOfBuildSlave(name,pw) ). If the password or class has
-        # changed, we will remove the old version of the slave and replace it
-        # with a new one. If anything else has changed, we just update the
-        # old BuildSlave instance in place. If the name has changed, of
-        # course, it looks exactly the same as deleting one slave and adding
-        # an unrelated one.
-        old_t = {}
-        for s in self.slaves:
-            old_t[(s.slavename, s.password, s.__class__)] = s
-        new_t = {}
-        for s in new_slaves:
-            new_t[(s.slavename, s.password, s.__class__)] = s
-        removed = [old_t[t]
-                   for t in old_t
-                   if t not in new_t]
-        added = [new_t[t]
-                 for t in new_t
-                 if t not in old_t]
-        remaining_t = [t
-                       for t in new_t
-                       if t in old_t]
-        # removeSlave will hang up on the old bot
-        dl = [self.botmaster.removeSlave(s.slavename) for s in removed]
-        d = defer.DeferredList(dl, fireOnOneErrback=True)
-        def _add(res):
-            for s in added:
-                self.botmaster.addSlave(s)
-            for t in remaining_t:
-                old_t[t].update(new_t[t])
-            self.slaves = new_slaves
-        d.addCallback(_add)
-        return d
+        # let the BotMaster take care of the rest
+        return self.botmaster.loadConfig_Slaves(new_slaves)
 
     def loadConfig_Sources(self, sources):
         if not sources:





More information about the Commits mailing list