Ticket #296: idleScheduler.diff

File idleScheduler.diff, 8.2 kB (added by bhearsum, 6 months ago)

[v3] idle scheduler using buildset scheduler notification

  • a/buildbot/scheduler.py

    old new  
    380380                               self.reason, 
    381381                               properties=self.properties) 
    382382        self.submitBuildSet(bs) 
     383 
     384 
     385 
     386class Idle(BaseUpstreamScheduler): 
     387    compare_attrs = ('name', 'builderNames', 'idleBuildTimer', 'branch', 
     388                     'properties') 
     389 
     390    def __init__(self, name, builderNames, idleBuildTimer, branch=None, 
     391                 properties={}): 
     392        BaseUpstreamScheduler.__init__(self, name, properties, 
     393                                       notifyScheduler=self) 
     394        self.builderNames = builderNames 
     395        self.branch = branch 
     396        self.idleBuildTimer = idleBuildTimer 
     397        self.reason = ("The Idle scheduler name '%s' triggered this build" 
     398                       % name) 
     399        self.runningBuilds = 0 
     400        self.timer = internet.TimerService(self.idleBuildTimer, 
     401                                           self.doPeriodicBuild) 
     402        self.timer.setServiceParent(self) 
     403 
     404    def listBuilderNames(self): 
     405        return self.builderNames 
     406 
     407    def getPendingBuildTimes(self): 
     408        return [] 
     409 
     410    def doPeriodicBuild(self): 
     411        bs = buildset.BuildSet(self.builderNames, 
     412                               SourceStamp(branch=self.branch), 
     413                               self.reason, 
     414                               properties=self.properties) 
     415        self.submitBuildSet(bs) 
     416 
     417    def buildStarted(self, build): 
     418        if build.builder.name in self.builderNames: 
     419            self.runningBuilds += 1 
     420            if self.timer._loop.running: 
     421                self.timer._loop.stop() 
     422 
     423    def buildFinished(self, res, br): 
     424        if br.builder.name in self.builderNames: 
     425            self.runningBuilds -= 1 
     426            if self.runningBuilds == 0: 
     427                self.timer._loop.start(self.idleBuildTimer, now=False) 
    383428 
    384429 
    385430 
  • a/buildbot/test/test_run.py

    old new  
    6767                      'builddir': 'dummy', 'factory': f2}) 
    6868c['builders'].append({'name': 'dummy2', 'slavename': 'bot1', 
    6969                      'builddir': 'dummy2', 'factory': f2}) 
     70""" 
     71 
     72config_idle = config_base + """ 
     73c['slaves'].append(BuildSlave('bot2', 'sekrit')) 
     74 
     75from buildbot.scheduler import Idle, AnyBranchScheduler, Scheduler 
     76 
     77f2 = factory.BuildFactory([s(dummy.Dummy, timeout=2)]) 
     78 
     79c['schedulers'] = [] 
     80idle = Idle('dummy', ['dummy'], 4) 
     81c['schedulers'].append(idle) 
     82c['schedulers'].append(AnyBranchScheduler('dummy2', None, 0, ['dummy'], 
     83                       notifyScheduler=idle)) 
     84 
     85c['builders'] = [{'name': 'dummy', 'slavenames': ['bot1', 'bot2'], 
     86                 'builddir': 'dummy', 'factory': f2}] 
     87""" 
     88 
     89config_idle_2 = config_idle + """ 
     90c['schedulers'] = [] 
     91idle = Idle('idledummy', ['dummy'], 4) 
     92c['schedulers'].append(idle) 
     93c['schedulers'].append(Scheduler('dummy', 'branch1', 0, ['dummy'], 
     94                       notifyScheduler=idle)) 
     95idle2 = Idle('idledummy2', ['dummy2'], 4) 
     96c['schedulers'].append(idle2) 
     97c['schedulers'].append(Scheduler('dummy2', 'branch2', 0, ['dummy2'], 
     98                       notifyScheduler=idle2)) 
     99 
     100c['builders'] = [{'name': 'dummy', 'slavenames': ['bot1'], 
     101                 'builddir': 'dummy', 'factory': f2}, 
     102                 {'name': 'dummy2', 'slavenames': ['bot2'], 
     103                 'builddir': 'dummy2', 'factory': f2}] 
    70104""" 
    71105 
    72106config_2 = config_base + """ 
     
    213247        d.addCallback(_check) 
    214248 
    215249        return d 
     250 
     251 
     252class Idle(RunMixin, unittest.TestCase): 
     253    def setUp(self): 
     254        RunMixin.setUp(self) 
     255 
     256        self.master.loadConfig(config_idle) 
     257        self.master.readConfig = True 
     258        self.master.startService() 
     259 
     260        return self.connectSlave() 
     261 
     262    def isBuilding(self, builder='dummy'): 
     263        b = self.master.botmaster.builders['dummy'] 
     264        return len(b.building) 
     265 
     266    def forceBuild(self, branch=None): 
     267        c = changes.Change("foo", ["blah"], "stuff", branch=branch) 
     268        self.master.change_svc.addChange(c) 
     269 
     270    def testIdleTimerReset(self): 
     271        # idle timer is set to 4, if we wait that long we should have a build 
     272        # going 
     273        self.failUnlessEqual(self.isBuilding(), 1) 
     274        d = defer.Deferred() 
     275        reactor.callLater(2.1, d.callback, None) 
     276        d.addCallback(self._testIdleTimerReset_1) 
     277        return d 
     278 
     279    def _testIdleTimerReset_1(self, res): 
     280        self.failUnlessEqual(self.isBuilding(), 0) 
     281        # now wait until after it is done and force a build 
     282        d = defer.Deferred() 
     283        reactor.callLater(2, d.callback, None) 
     284        d.addCallback(self._testIdleTimerReset_2) 
     285        return d 
     286 
     287    def _testIdleTimerReset_2(self, res): 
     288        self.forceBuild() 
     289        d = defer.Deferred() 
     290        # need extra time here because changes are delayed slightly 
     291        reactor.callLater(4, d.callback, None) 
     292        d.addCallback(self._testIdleTimerReset_3) 
     293        return d 
     294 
     295    def _testIdleTimerReset_3(self, res): 
     296        self.failUnlessEqual(self.isBuilding(), 0) 
     297        d = defer.Deferred() 
     298        reactor.callLater(4, d.callback, None) 
     299        d.addCallback(self._testIdleTimerReset_4) 
     300        return d 
     301 
     302    def _testIdleTimerReset_4(self, res): 
     303        self.failUnlessEqual(self.isBuilding(), 1) 
     304 
     305    def testIdleTimerManyBuilds(self): 
     306        d = self.connectSlave(slavename='bot2') 
     307        d.addCallback(self._testIdleTimerManyBuilds_1) 
     308        return d 
     309 
     310    def _testIdleTimerManyBuilds_1(self, res): 
     311        self.forceBuild() 
     312        self.forceBuild() 
     313        d = defer.Deferred() 
     314        reactor.callLater(1, d.callback, None) 
     315        d.addCallback(self._testIdleTimerManyBuilds_2) 
     316        return d 
     317 
     318    def _testIdleTimerManyBuilds_2(self, res): 
     319        b = self.master.botmaster.builders['dummy'] 
     320        self.failUnlessEqual(self.isBuilding(), 2) 
     321        d = defer.Deferred() 
     322        reactor.callLater(4, d.callback, None) 
     323        d.addCallback(self._testIdleTimerManyBuilds_3) 
     324        return d 
     325 
     326    def _testIdleTimerManyBuilds_3(self, res): 
     327        self.failUnlessEqual(self.isBuilding(), 0) 
     328 
     329class Idle2(RunMixin, unittest.TestCase): 
     330    def setUp(self): 
     331        RunMixin.setUp(self) 
     332 
     333        self.master.loadConfig(config_idle_2) 
     334        self.master.readConfig = True 
     335        self.master.startService() 
     336 
     337        d = self.connectSlave() 
     338        d.addCallback(self._setUp_1) 
     339        return d 
     340 
     341    def _setUp_1(self, res): 
     342        return self.connectSlave(builders=['dummy2'], slavename='bot2') 
     343 
     344    def isBuilding(self, builder='dummy'): 
     345        b = self.master.botmaster.builders['dummy'] 
     346        return len(b.building) 
     347 
     348    def forceBuild(self, branch=None): 
     349        c = changes.Change("foo", ["blah"], "stuff", branch=branch) 
     350        self.master.change_svc.addChange(c) 
     351 
     352    def testTwoBranches(self): 
     353        d = defer.Deferred() 
     354        reactor.callLater(4, d.callback, None) 
     355        d.addCallback(self._testTwoBranches_1) 
     356        return d 
     357 
     358    def _testTwoBranches_1(self, res): 
     359        d1 = defer.Deferred() 
     360        reactor.callLater(2, d1.callback, None) 
     361        d1.addCallback(self._testTwoBranches_branch1_1) 
     362        d2 = defer.Deferred() 
     363        reactor.callLater(2, d2.callback, None) 
     364        d2.addCallback(self._testTwoBranches_branch2_1) 
     365        return defer.DeferredList([d1,d2]) 
     366 
     367    def _testTwoBranches_branch1_1(self, res): 
     368        self.failUnlessEqual(self.isBuilding(), 1) 
     369 
     370        d = defer.Deferred() 
     371        reactor.callLater(6, d.callback, None) 
     372        d.addCallback(self._testTwoBranches_branch1_2) 
     373        return d 
     374 
     375    def _testTwoBranches_branch1_2(self, res): 
     376        self.failUnlessEqual(self.isBuilding(), 1) 
     377 
     378    def _testTwoBranches_branch2_1(self, res): 
     379        self.failUnlessEqual(self.isBuilding('dummy'), 1) 
     380 
     381        d = defer.Deferred() 
     382        reactor.callLater(3, d.callback, None) 
     383        d.addCallback(self._testTwoBranches_branch2_2) 
     384        return d 
     385 
     386    def _testTwoBranches_branch2_2(self, res): 
     387        self.failUnlessEqual(self.isBuilding('dummy'), 0) 
    216388 
    217389 
    218390class Ping(RunMixin, unittest.TestCase):