[Buildbot-commits] [Buildbot] #2506: Add lock for a group of slaves

Buildbot trac trac at buildbot.net
Tue Jun 4 21:06:58 UTC 2013


#2506: Add lock for a group of slaves
------------------------+-----------------------
Reporter:  A1kmm        |      Owner:
    Type:  enhancement  |     Status:  new
Priority:  major        |  Milestone:  undecided
 Version:  master       |   Keywords:  locks
------------------------+-----------------------
 In our buildbot configuration (https://github.com/cellmlapi/cellml-
 build/blob/1fcf9dce/build-master/master.cfg) we have multiple buildslaves
 that share hardware (for example, we have a MSVC10 buildslave that runs
 with an environment set up for MSVC10, and an MSVC11 buildslave set up for
 MSVC11, both of which share the same physical hardware). I expect it is
 very common for people to run multiple buildslaves in VMs or lxc
 containers or similar on the same physical hardware.

 However, buildbot's built in locking support is limited to either having a
 global lock (MasterLock), or having one lock per slave (SlaveLock). This
 makes it hard to limit the number of builds by having a lock shared across
 slaves that run on the same hardware, but not across slaves that run on
 different hardware.

 As a workaround, we put the following in our master.cfg, but ideally
 something like this should be built in to buildbot:

 {{{
 # This code lets us enforce a count across a group of buildslaves.
 class RealSlavegroupLock:
     def __init__(self, lockid):
         self.name = lockid.name
         self.maxCount = lockid.maxCount
         self.maxCountForSlavegroup = lockid.maxCountForSlavegroup
         self.slaveToSlavegroup = lockid.slaveToSlavegroup
         self.description = "<SlavegroupLock(%s, %s, %s, %s)>" %
 (self.name,
 self.maxCount,
 self.maxCountForSlavegroup,
 self.slaveToSlavegroup)
         self.locks = {}
     def __repr__(self):
         return self.description
     def getLock(self, slave):
         if isinstance(slave, SlaveBuilder):
             slavename = slave.slave.slavename
         else:
             slavename = slave.slavename
         # slavegroup defaults to slavename
         slavegroup = self.slaveToSlavegroup.get(slavename, slavename)
         if not self.locks.has_key(slavegroup):
             maxCount = self.maxCountForSlavegroup.get(slavegroup,
                                                       self.maxCount)
             lock = self.locks[slavegroup] = BaseLock(self.name, maxCount)
             desc = "<SlavegroupLock(%s, %s)[%s] %d>" % (self.name,
 maxCount,
                                                         slavegroup,
 id(lock))
             lock.description = desc
             self.locks[slavegroup] = lock
         return self.locks[slavegroup]

 # Note: this only inherits from SlaveLock to get past an assert. Ideally
 the
 # buildbot code would be changed to allow other lock types.
 class SlavegroupLock(SlaveLock):
     """I am a semaphore that limits simultaneous actions on each group of
     buildslaves.

     Builds and BuildSteps can declare that they wish to claim me as they
 run.
     Only a limited number of such builds or steps will be able to run
     simultaneously on any given group of buildslave. By default this
 number is one,
     but my maxCount parameter can be raised to allow two or three or more
     operations to happen across a group of buildslaves at the same time.

     Use this to protect a resource that is shared among all the builds
 taking
     place on a group of slaves that share resources, for example to limit
 CPU
     or memory load on an underpowered machine that runs multiple
 buildslaves.

     Each buildslave can be assigned to a group using the dictionary
     slaveToSlavegroup; buildslaves that do not appear in this dictionary
 are
     placed in the slavegroup with a name equal to the name of the
 buildslave.

     Each group of buildslaves will get an independent copy of this
 semaphore. By
     default each copy will use the same owner count (set with maxCount),
 but
     you can provide maxCountForSlavegroup with a dictionary that maps
     slavegroup to owner count, to allow some slavegroups more parallelism
 than
     others.
     """

     compare_attrs = ['name', 'maxCount', '_maxCountForSlavegroupList',
                      '_slaveToSlavegroupList']
     lockClass = RealSlavegroupLock
     def __init__(self, name, maxCount=1, maxCountForSlavegroup={},
 slaveToSlavegroup={}):
         self.name = name
         self.maxCount = maxCount
         self.maxCountForSlavegroup = maxCountForSlavegroup
         self.slaveToSlavegroup = slaveToSlavegroup
         # for comparison purposes, turn this dictionary into a stably-
 sorted
         # list of tuples
         self._maxCountForSlavegroupList =
 self.maxCountForSlavegroup.items()
         self._maxCountForSlavegroupList.sort()
         self._maxCountForSlavegroupList =
 tuple(self._maxCountForSlavegroupList)
         self._slaveToSlavegroupList = self.slaveToSlavegroup.items()
         self._slaveToSlavegroupList.sort()
         self._slaveToSlavegroupList = tuple(self._slaveToSlavegroupList)
 }}}

-- 
Ticket URL: <http://trac.buildbot.net/ticket/2506>
Buildbot <http://buildbot.net/>
Buildbot: build/test automation


More information about the Commits mailing list