|
69 | 69 | -nographic |
70 | 70 | """ |
71 | 71 |
|
| 72 | +def retry(target_exception, tries=4, delay_s=1, backoff=2): |
| 73 | + """Retry calling the decorated function using an exponential backoff. |
| 74 | +
|
| 75 | + http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ |
| 76 | + original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry |
| 77 | +
|
| 78 | + :param target_exception: the exception to check. may be a tuple of |
| 79 | + exceptions to check |
| 80 | + :type target_exception: Exception or tuple |
| 81 | + :param tries: number of times to try (not retry) before giving up |
| 82 | + :type tries: int |
| 83 | + :param delay_s: initial delay between retries in seconds |
| 84 | + :type delay_s: int |
| 85 | + :param backoff: backoff multiplier e.g. value of 2 will double the delay |
| 86 | + each retry |
| 87 | + :type backoff: int |
| 88 | + """ |
| 89 | + import time |
| 90 | + from functools import wraps |
| 91 | + |
| 92 | + def decorated_retry(f): |
| 93 | + @wraps(f) |
| 94 | + def f_retry(*args, **kwargs): |
| 95 | + mtries, mdelay = tries, delay_s |
| 96 | + while mtries > 1: |
| 97 | + try: |
| 98 | + return f(*args, **kwargs) |
| 99 | + except target_exception as e: |
| 100 | + logging.warning("Exception: %s, Retrying in %d seconds...", str(e), mdelay) |
| 101 | + time.sleep(mdelay) |
| 102 | + mtries -= 1 |
| 103 | + mdelay *= backoff |
| 104 | + return f(*args, **kwargs) |
| 105 | + |
| 106 | + return f_retry # true decorator |
| 107 | + |
| 108 | + return decorated_retry |
| 109 | + |
| 110 | + |
| 111 | + |
72 | 112 |
|
73 | 113 | class VMError(RuntimeError): |
74 | 114 | pass |
@@ -177,6 +217,8 @@ def qemu_rsync(ssh_port, local_path, remote_path): |
177 | 217 | def qemu_rsync_to_host(ssh_port, remote_path, local_path): |
178 | 218 | check_call(['rsync', '-e', 'ssh -o StrictHostKeyChecking=no -p{}'.format(ssh_port), '-va', 'qemu@localhost:{}'.format(remote_path), local_path]) |
179 | 219 |
|
| 220 | + |
| 221 | +@retry(subprocess.CalledProcessError) |
180 | 222 | def qemu_provision(ssh_port=QEMU_SSH_PORT): |
181 | 223 | import glob |
182 | 224 | logging.info("Provisioning the VM with artifacts and sources") |
|
0 commit comments