diff --git a/qa/qa_config.py b/qa/qa_config.py index 664baace9c252ca98ff7392e05f75be67e95bdce..6b74f82b11f159f6979089b88de5bea506f00e30 100644 --- a/qa/qa_config.py +++ b/qa/qa_config.py @@ -553,6 +553,15 @@ def IsTemplateSupported(templ): return GetConfig().IsTemplateSupported(templ) +def _NodeSortKey(node): + """Returns sort key for a node. + + @type node: L{_QaNode} + + """ + return (node.use_count, utils.NiceSortKey(node.primary)) + + def AcquireNode(exclude=None, _cfg=None): """Returns the least used node. @@ -578,17 +587,8 @@ def AcquireNode(exclude=None, _cfg=None): if not nodes: raise qa_error.OutOfNodesError("No nodes left") - # Get node with least number of uses - # TODO: Switch to computing sort key instead of comparing directly - def compare(a, b): - result = cmp(a.use_count, b.use_count) - if result == 0: - result = cmp(a.primary, b.primary) - return result - - nodes.sort(cmp=compare) - - return nodes[0].Use() + # Return node with least number of uses + return sorted(nodes, key=_NodeSortKey)[0].Use() def AcquireManyNodes(num, exclude=None): diff --git a/test/py/qa.qa_config_unittest.py b/test/py/qa.qa_config_unittest.py index ce987f887b3cb3272e0304ef8850dad9bb83d315..f2de71427899b5a5b940cd63ad9e5938ec2055f4 100755 --- a/test/py/qa.qa_config_unittest.py +++ b/test/py/qa.qa_config_unittest.py @@ -349,6 +349,35 @@ class TestQaConfig(unittest.TestCase): self.assertRaises(qa_error.OutOfNodesError, qa_config.AcquireNode, exclude=acquired, _cfg=self.config) + def testAcquireNodeOrder(self): + # Mark all nodes as marked (master excluded) + for node in self.config["nodes"]: + if node != self.config.GetMasterNode(): + node.MarkAdded() + + nodecount = len(self.config["nodes"]) + + for iterations in [0, 1, 3, 100, 127, 7964]: + acquired = [] + + for i in range(iterations): + node = qa_config.AcquireNode(_cfg=self.config) + self.assertTrue(node.use_count > 0) + self.assertEqual(node.use_count, (i / nodecount + 1)) + acquired.append((node.use_count, node.primary, node)) + + # Check if returned nodes were in correct order + key_fn = lambda (a, b, c): (a, utils.NiceSortKey(b), c) + self.assertEqual(acquired, sorted(acquired, key=key_fn)) + + # Release previously acquired nodes + qa_config.ReleaseManyNodes(map(operator.itemgetter(2), acquired)) + + # Check if nodes were actually released + for node in self.config["nodes"]: + self.assertEqual(node.use_count, 0) + self.assertTrue(node.added or node == self.config.GetMasterNode()) + class TestRepresentation(unittest.TestCase): def _Check(self, target, part):