diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py index 2f0d5e20c6..df83f444d4 100644 --- a/tests/unit/test_scheduler.py +++ b/tests/unit/test_scheduler.py @@ -5095,6 +5095,31 @@ For CI problems and help debugging, contact ci@example.org""" self.fake_nodepool.paused = False self.waitUntilSettled() + def test_nodepool_job_removal(self): + "Test that nodes are returned unused after job removal" + + self.fake_nodepool.paused = True + A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A') + A.addApproval('Code-Review', 2) + self.fake_gerrit.addEvent(A.addApproval('Approved', 1)) + self.waitUntilSettled() + + self.commitConfigUpdate('common-config', 'layouts/no-jobs.yaml') + self.sched.reconfigure(self.config) + self.waitUntilSettled() + + self.fake_nodepool.paused = False + self.waitUntilSettled() + + self.assertEqual(A.data['status'], 'MERGED') + self.assertEqual(A.reported, 2) + self.assertHistory([ + dict(name='gate-noop', result='SUCCESS', changes='1,1'), + ]) + for node in self.fake_nodepool.getNodes(): + self.assertFalse(node['_lock']) + self.assertEqual(node['state'], 'ready') + @simple_layout('layouts/multiple-templates.yaml') def test_multiple_project_templates(self): # Test that applying multiple project templates to a project diff --git a/zuul/scheduler.py b/zuul/scheduler.py index ad2fde7f37..abb917ab22 100644 --- a/zuul/scheduler.py +++ b/zuul/scheduler.py @@ -1261,14 +1261,22 @@ class Scheduler(threading.Thread): return if build_set is not build_set.item.current_build_set: - self.log.warning("Build set %s is not current" % (build_set,)) + self.log.warning("Build set %s is not current " + "for node request %s", build_set, request) + if request.fulfilled: + self.nodepool.returnNodeSet(request.nodeset) + return + if request.job.name not in [x.name for x in build_set.item.getJobs()]: + self.log.warning("Item %s does not contain job %s " + "for node request %s", + build_set.item, request.job.name, request) if request.fulfilled: self.nodepool.returnNodeSet(request.nodeset) return pipeline = build_set.item.pipeline if not pipeline: - self.log.warning("Build set %s is not associated with a pipeline" % - (build_set,)) + self.log.warning("Build set %s is not associated with a pipeline " + "for node request %s", build_set, request) if request.fulfilled: self.nodepool.returnNodeSet(request.nodeset) return