OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Wrapper that does auto-retry and stats logging for command invocation. | 7 """Wrapper that does auto-retry and stats logging for command invocation. |
8 | 8 |
9 Various command line tools in use: gsutil, curl have spurious failure. | 9 Various command line tools in use: gsutil, curl have spurious failure. |
10 This wrapper will track stats to an AppEngine based service to | 10 This wrapper will track stats to an AppEngine based service to |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 Arguments: | 29 Arguments: |
30 options: parsed options | 30 options: parsed options |
31 command_id: unique id for this command (shared by all retries) | 31 command_id: unique id for this command (shared by all retries) |
32 attempt: which try numbered from 0 | 32 attempt: which try numbered from 0 |
33 cmd: command run | 33 cmd: command run |
34 returncode: return code from running command | 34 returncode: return code from running command |
35 stdout: text of stdout | 35 stdout: text of stdout |
36 stderr: text of stderr | 36 stderr: text of stderr |
37 runtime: command runtime in seconds | 37 runtime: command runtime in seconds |
| 38 Returns: |
| 39 True/False indicating if the current result should be accepted without |
| 40 further retry. |
38 """ | 41 """ |
39 uname = platform.uname() | 42 uname = platform.uname() |
40 params = urllib.urlencode({ | 43 params = urllib.urlencode({ |
41 'attempt': str(attempt), | 44 'attempt': str(attempt), |
42 'cwd': os.getcwd(), | 45 'cwd': os.getcwd(), |
43 'command_id': command_id, | 46 'command_id': command_id, |
44 'command': cmd, | 47 'command': cmd, |
45 'returncode': str(returncode), | 48 'returncode': str(returncode), |
46 'stdout': stdout[:400], | 49 'stdout': stdout[:400], |
47 'stderr': stderr[:400], | 50 'stderr': stderr[:400], |
48 'runtime': str(runtime), | 51 'runtime': str(runtime), |
49 'retries': str(options.retries), | 52 'retries': str(options.retries), |
50 'uname_sysname': uname[0], | 53 'uname_sysname': uname[0], |
51 'uname_nodename': uname[1], | 54 'uname_nodename': uname[1], |
52 'uname_release': uname[2], | 55 'uname_release': uname[2], |
53 'uname_version': uname[3], | 56 'uname_version': uname[3], |
54 'uname_machine': uname[4], | 57 'uname_machine': uname[4], |
55 'uname_processor': uname[5], | 58 'uname_processor': uname[5], |
56 }) | 59 }) |
57 f = urllib.urlopen(options.logurl, params) | 60 f = urllib.urlopen(options.logurl, params) |
58 f.read() | 61 ret = f.read() |
59 f.close() | 62 f.close() |
| 63 return int(ret) != 0 |
60 | 64 |
61 | 65 |
62 def main(argv): | 66 def main(argv): |
63 parser = optparse.OptionParser() | 67 parser = optparse.OptionParser() |
64 parser.add_option('-r', '--retries', dest='retries', | 68 parser.add_option('-r', '--retries', dest='retries', |
65 type='int', default=10, | 69 type='int', default=10, |
66 help='number of times to retry on failure') | 70 help='number of times to retry on failure') |
67 parser.add_option('-u', '--logurl', dest='logurl', | 71 parser.add_option('-u', '--logurl', dest='logurl', |
68 default='https://command-wrapper.appspot.com/log', | 72 default='https://command-wrapper.appspot.com/log', |
69 help='URL to log invocations/failures to') | 73 help='URL to log invocations/failures to') |
70 (options, args) = parser.parse_args(args=argv[1:]) | 74 (options, args) = parser.parse_args(args=argv[1:]) |
71 | 75 |
72 command_id = uuid.uuid1() | 76 command_id = uuid.uuid1() |
73 cmd = ' '.join(args) | 77 cmd = ' '.join(args) |
74 for r in range(options.retries): | 78 for r in range(options.retries): |
75 tm = time.time() | 79 tm = time.time() |
76 p = subprocess.Popen(cmd, shell=True, | 80 p = subprocess.Popen(cmd, shell=True, |
77 stdout=subprocess.PIPE, | 81 stdout=subprocess.PIPE, |
78 stderr=subprocess.PIPE) | 82 stderr=subprocess.PIPE) |
79 (p_stdout, p_stderr) = p.communicate() | 83 (p_stdout, p_stderr) = p.communicate() |
80 sys.stdout.write(p_stdout) | 84 sys.stdout.write(p_stdout) |
81 sys.stderr.write(p_stderr) | 85 sys.stderr.write(p_stderr) |
82 runtime = time.time() - tm | 86 runtime = time.time() - tm |
83 LogCommand(options, command_id, r, cmd, | 87 accept = LogCommand(options, command_id, r, cmd, |
84 p.returncode, p_stdout, p_stderr, runtime) | 88 p.returncode, p_stdout, p_stderr, runtime) |
| 89 if accept: |
| 90 return p.returncode |
85 if p.returncode == 0: | 91 if p.returncode == 0: |
86 return 0 | 92 return 0 |
87 print 'Command %s failed with retcode %d, try %d.' % ( | 93 print 'Command %s failed with retcode %d, try %d.' % ( |
88 ' '.join(args), p.returncode, r + 1) | 94 ' '.join(args), p.returncode, r + 1) |
89 print 'Command %s failed %d retries, giving up.' % ( | 95 print 'Command %s failed %d retries, giving up.' % ( |
90 ' '.join(args), options.retries) | 96 ' '.join(args), options.retries) |
91 | 97 |
92 return p.returncode | 98 return p.returncode |
93 | 99 |
94 | 100 |
95 if __name__ == '__main__': | 101 if __name__ == '__main__': |
96 sys.exit(main(sys.argv)) | 102 sys.exit(main(sys.argv)) |
OLD | NEW |