From 506be7c5b492e79b36028b636047fa782390685a Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Fri, 7 May 2010 10:09:45 +0200 Subject: [PATCH] utils.Retry: pass up timeout arguments If Retry has to fail with RetryTimeout, it might be useful to pass the Retry argument to RetryTimeout, to help debugging outside the Retry cycle. We also define a RetryTimeout.RaiseInner() helper, to re-raise an exception passed to RetryAgain. All served with a side of unit tests. Signed-off-by: Guido Trotter <ultrotter@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/utils.py | 13 ++++++++--- test/ganeti.utils_unittest.py | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/utils.py b/lib/utils.py index 2864b0024..ce112c914 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -2499,6 +2499,11 @@ class RetryTimeout(Exception): """Retry loop timed out. """ + def RaiseInner(self): + if self.args and isinstance(self.args[0], Exception): + raise self.args[0] + else: + raise RetryTimeout(*self.args) class RetryAgain(Exception): @@ -2612,11 +2617,12 @@ def Retry(fn, delay, timeout, args=None, wait_fn=time.sleep, assert calc_delay is None or callable(calc_delay) while True: + retry_args = [] try: # pylint: disable-msg=W0142 return fn(*args) - except RetryAgain: - pass + except RetryAgain, err: + retry_args = err.args except RetryTimeout: raise errors.ProgrammerError("Nested retry loop detected that didn't" " handle RetryTimeout") @@ -2624,7 +2630,8 @@ def Retry(fn, delay, timeout, args=None, wait_fn=time.sleep, remaining_time = end_time - _time_fn() if remaining_time < 0.0: - raise RetryTimeout() + # pylint: disable-msg=W0142 + raise RetryTimeout(*retry_args) assert remaining_time >= 0.0 diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py index bad5a9a43..55698f59a 100755 --- a/test/ganeti.utils_unittest.py +++ b/test/ganeti.utils_unittest.py @@ -1612,6 +1612,10 @@ class TestRetry(testutils.GanetiTestCase): def _RaiseRetryAgain(): raise utils.RetryAgain() + @staticmethod + def _RaiseRetryAgainWithArg(args): + raise utils.RetryAgain(*args) + def _WrongNestedLoop(self): return utils.Retry(self._RaiseRetryAgain, 0.01, 0.02) @@ -1642,6 +1646,45 @@ class TestRetry(testutils.GanetiTestCase): except utils.RetryTimeout: self.fail("Didn't detect inner loop's exception") + def testTimeoutArgument(self): + retry_arg="my_important_debugging_message" + try: + utils.Retry(self._RaiseRetryAgainWithArg, 0.01, 0.02, args=[[retry_arg]]) + except utils.RetryTimeout, err: + self.failUnlessEqual(err.args, (retry_arg, )) + else: + self.fail("Expected timeout didn't happen") + + def testRaiseInnerWithExc(self): + retry_arg="my_important_debugging_message" + try: + try: + utils.Retry(self._RaiseRetryAgainWithArg, 0.01, 0.02, + args=[[errors.GenericError(retry_arg, retry_arg)]]) + except utils.RetryTimeout, err: + err.RaiseInner() + else: + self.fail("Expected timeout didn't happen") + except errors.GenericError, err: + self.failUnlessEqual(err.args, (retry_arg, retry_arg)) + else: + self.fail("Expected GenericError didn't happen") + + def testRaiseInnerWithMsg(self): + retry_arg="my_important_debugging_message" + try: + try: + utils.Retry(self._RaiseRetryAgainWithArg, 0.01, 0.02, + args=[[retry_arg, retry_arg]]) + except utils.RetryTimeout, err: + err.RaiseInner() + else: + self.fail("Expected timeout didn't happen") + except utils.RetryTimeout, err: + self.failUnlessEqual(err.args, (retry_arg, retry_arg)) + else: + self.fail("Expected RetryTimeout didn't happen") + class TestLineSplitter(unittest.TestCase): def test(self): -- GitLab