diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py index 23d8a25be1a4c076912749f244d236d68e4ebd3a..171130a0193447708e6fa2bd53baf4eaac51a34f 100644 --- a/lib/utils/__init__.py +++ b/lib/utils/__init__.py @@ -1769,56 +1769,3 @@ class FieldSet(object): """ return [val for val in items if not self.Matches(val)] - - -class RunningTimeout(object): - """Class to calculate remaining timeout when doing several operations. - - """ - __slots__ = [ - "_allow_negative", - "_start_time", - "_time_fn", - "_timeout", - ] - - def __init__(self, timeout, allow_negative, _time_fn=time.time): - """Initializes this class. - - @type timeout: float - @param timeout: Timeout duration - @type allow_negative: bool - @param allow_negative: Whether to return values below zero - @param _time_fn: Time function for unittests - - """ - object.__init__(self) - - if timeout is not None and timeout < 0.0: - raise ValueError("Timeout must not be negative") - - self._timeout = timeout - self._allow_negative = allow_negative - self._time_fn = _time_fn - - self._start_time = None - - def Remaining(self): - """Returns the remaining timeout. - - """ - if self._timeout is None: - return None - - # Get start time on first calculation - if self._start_time is None: - self._start_time = self._time_fn() - - # Calculate remaining time - remaining_timeout = self._start_time + self._timeout - self._time_fn() - - if not self._allow_negative: - # Ensure timeout is always >= 0 - return max(0.0, remaining_timeout) - - return remaining_timeout diff --git a/lib/utils/algo.py b/lib/utils/algo.py index 9546904c3c488ced1214f8248a82e25a9d8dac58..3cccaa88d9630c969e6c83134eb72e4c903d0d62 100644 --- a/lib/utils/algo.py +++ b/lib/utils/algo.py @@ -23,6 +23,7 @@ """ import re +import time _SORTER_RE = re.compile("^%s(.*)$" % (8 * "(\D+|\d+)?")) @@ -111,3 +112,56 @@ def NiceSort(values, key=None): keyfunc = lambda value: _NiceSortKey(key(value)) return sorted(values, key=keyfunc) + + +class RunningTimeout(object): + """Class to calculate remaining timeout when doing several operations. + + """ + __slots__ = [ + "_allow_negative", + "_start_time", + "_time_fn", + "_timeout", + ] + + def __init__(self, timeout, allow_negative, _time_fn=time.time): + """Initializes this class. + + @type timeout: float + @param timeout: Timeout duration + @type allow_negative: bool + @param allow_negative: Whether to return values below zero + @param _time_fn: Time function for unittests + + """ + object.__init__(self) + + if timeout is not None and timeout < 0.0: + raise ValueError("Timeout must not be negative") + + self._timeout = timeout + self._allow_negative = allow_negative + self._time_fn = _time_fn + + self._start_time = None + + def Remaining(self): + """Returns the remaining timeout. + + """ + if self._timeout is None: + return None + + # Get start time on first calculation + if self._start_time is None: + self._start_time = self._time_fn() + + # Calculate remaining time + remaining_timeout = self._start_time + self._timeout - self._time_fn() + + if not self._allow_negative: + # Ensure timeout is always >= 0 + return max(0.0, remaining_timeout) + + return remaining_timeout diff --git a/test/ganeti.utils.algo_unittest.py b/test/ganeti.utils.algo_unittest.py index d9834bbfabfa43deda980ae7d41269e42c8fad39..a0685a85979346e4ee78581adf24423f0b638166 100755 --- a/test/ganeti.utils.algo_unittest.py +++ b/test/ganeti.utils.algo_unittest.py @@ -219,5 +219,41 @@ class TestNiceSort(unittest.TestCase): msg="Key function was not called once per value") +class TimeMock: + def __init__(self, values): + self.values = values + + def __call__(self): + return self.values.pop(0) + + +class TestRunningTimeout(unittest.TestCase): + def setUp(self): + self.time_fn = TimeMock([0.0, 0.3, 4.6, 6.5]) + + def testRemainingFloat(self): + timeout = algo.RunningTimeout(5.0, True, _time_fn=self.time_fn) + self.assertAlmostEqual(timeout.Remaining(), 4.7) + self.assertAlmostEqual(timeout.Remaining(), 0.4) + self.assertAlmostEqual(timeout.Remaining(), -1.5) + + def testRemaining(self): + self.time_fn = TimeMock([0, 2, 4, 5, 6]) + timeout = algo.RunningTimeout(5, True, _time_fn=self.time_fn) + self.assertEqual(timeout.Remaining(), 3) + self.assertEqual(timeout.Remaining(), 1) + self.assertEqual(timeout.Remaining(), 0) + self.assertEqual(timeout.Remaining(), -1) + + def testRemainingNonNegative(self): + timeout = algo.RunningTimeout(5.0, False, _time_fn=self.time_fn) + self.assertAlmostEqual(timeout.Remaining(), 4.7) + self.assertAlmostEqual(timeout.Remaining(), 0.4) + self.assertEqual(timeout.Remaining(), 0.0) + + def testNegativeTimeout(self): + self.assertRaises(ValueError, algo.RunningTimeout, -1.0, True) + + if __name__ == "__main__": testutils.GanetiTestProgram() diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py index ea136f3b5fc207ad3758b6a8507642acc15be43d..84a3130a6f39f030b484f468dcee0f5b901f219f 100755 --- a/test/ganeti.utils_unittest.py +++ b/test/ganeti.utils_unittest.py @@ -845,42 +845,6 @@ class TestFindMatch(unittest.TestCase): self.assert_(utils.FindMatch(data, "Hello World") is None) -class TimeMock: - def __init__(self, values): - self.values = values - - def __call__(self): - return self.values.pop(0) - - -class TestRunningTimeout(unittest.TestCase): - def setUp(self): - self.time_fn = TimeMock([0.0, 0.3, 4.6, 6.5]) - - def testRemainingFloat(self): - timeout = utils.RunningTimeout(5.0, True, _time_fn=self.time_fn) - self.assertAlmostEqual(timeout.Remaining(), 4.7) - self.assertAlmostEqual(timeout.Remaining(), 0.4) - self.assertAlmostEqual(timeout.Remaining(), -1.5) - - def testRemaining(self): - self.time_fn = TimeMock([0, 2, 4, 5, 6]) - timeout = utils.RunningTimeout(5, True, _time_fn=self.time_fn) - self.assertEqual(timeout.Remaining(), 3) - self.assertEqual(timeout.Remaining(), 1) - self.assertEqual(timeout.Remaining(), 0) - self.assertEqual(timeout.Remaining(), -1) - - def testRemainingNonNegative(self): - timeout = utils.RunningTimeout(5.0, False, _time_fn=self.time_fn) - self.assertAlmostEqual(timeout.Remaining(), 4.7) - self.assertAlmostEqual(timeout.Remaining(), 0.4) - self.assertEqual(timeout.Remaining(), 0.0) - - def testNegativeTimeout(self): - self.assertRaises(ValueError, utils.RunningTimeout, -1.0, True) - - class TestTryConvert(unittest.TestCase): def test(self): for src, fn, result in [