| #!/usr/bin/python |
| # |
| # Copyright 2014 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Wrapper that does auto-retry for gsutil. |
| |
| Pass the path to the real gsutil as the first argument. |
| |
| Deletes ~/.gsutil after failures, which sometimes helps. |
| """ |
| |
| |
| import logging |
| import argparse |
| import os |
| import shutil |
| import subprocess |
| import sys |
| |
| |
| def main(argv): |
| parser = argparse.ArgumentParser() |
| parser.add_argument( |
| 'command', metavar='ARG', nargs='+', |
| help='the gsutil command (including the gsutil path) to run') |
| parser.add_argument('--soft-retries', |
| metavar='N', nargs=1, default=2, type=int, |
| help='number of times to retry') |
| parser.add_argument('--hard-retries', |
| metavar='N', nargs=1, default=2, type=int, |
| help='number of times to retry, with deleting trackers ') |
| args = parser.parse_args() |
| |
| # The -- argument for the wrapped gsutil.py is escaped as ---- as python |
| # 2.7.3 removes all occurrences of --, not only the first. |
| if '----' in args.command: |
| args.command[args.command.index('----')] = '--' |
| |
| cmd = [sys.executable, '-u'] + args.command |
| |
| for hard in range(args.hard_retries): |
| for soft in range(args.soft_retries): |
| retcode = subprocess.call(cmd) |
| |
| if retcode == 0: |
| return 0 |
| |
| logging.warning('Command %s failed with retcode %d, try %d.%d.' % ( |
| ' '.join(cmd), retcode, hard+1, soft+1)) |
| |
| # Failed at least once, try deleting the tracker files |
| try: |
| logging.warning('Trying harder: deleting tracker files') |
| gsutil_dir = os.path.join(os.environ['HOME'], '.gsutil') |
| logging.info('Removing %s' % gsutil_dir) |
| shutil.rmtree(gsutil_dir) |
| except BaseException as e: |
| logging.warning('Deleting tracker files failed: %s' % e) |
| |
| logging.error('Command %s failed %d retries, giving up.' % ( |
| ' '.join(args.command), args.soft_retries*args.hard_retries)) |
| |
| return retcode |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv)) |