Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(534)

Side by Side Diff: command_wrapper/bin/command_wrapper.py

Issue 3085016: Adding timeout for log server access + more safety with bad response.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/tools/
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 help track down the cause of failures, as well as add retry logic. 11 help track down the cause of failures, as well as add retry logic.
12 """ 12 """
13 13
14 14
15 import optparse 15 import optparse
16 import os 16 import os
17 import platform 17 import platform
18 import socket
18 import subprocess 19 import subprocess
19 import sys 20 import sys
21 import threading
20 import time 22 import time
21 import urllib 23 import urllib
22 import uuid 24 import uuid
23 25
24 26
27 LOG_TIMEOUT = 10
28
29
25 def LogCommand(options, command_id, 30 def LogCommand(options, command_id,
26 attempt, cmd, returncode, stdout, stderr, runtime): 31 attempt, cmd, returncode, stdout, stderr, runtime):
27 """Log a command invocation and result to a central location. 32 """Log a command invocation and result to a central location.
28 33
29 Arguments: 34 Arguments:
30 options: parsed options 35 options: parsed options
31 command_id: unique id for this command (shared by all retries) 36 command_id: unique id for this command (shared by all retries)
32 attempt: which try numbered from 0 37 attempt: which try numbered from 0
33 cmd: command run 38 cmd: command run
34 returncode: return code from running command 39 returncode: return code from running command
(...skipping 18 matching lines...) Expand all
53 'uname_sysname': uname[0], 58 'uname_sysname': uname[0],
54 'uname_nodename': uname[1], 59 'uname_nodename': uname[1],
55 'uname_release': uname[2], 60 'uname_release': uname[2],
56 'uname_version': uname[3], 61 'uname_version': uname[3],
57 'uname_machine': uname[4], 62 'uname_machine': uname[4],
58 'uname_processor': uname[5], 63 'uname_processor': uname[5],
59 }) 64 })
60 f = urllib.urlopen(options.logurl, params) 65 f = urllib.urlopen(options.logurl, params)
61 ret = f.read() 66 ret = f.read()
62 f.close() 67 f.close()
63 return int(ret) != 0 68 try:
69 return int(ret) != 0
70 except ValueError:
71 return 0
72
73
74 def RunWithTimeout(timeout, func, *args, **kwargs):
75 result = None
76 def CallFunc():
77 result = func(*args, **kwargs)
78 th = threading.Thread(target=CallFunc)
79 th.start()
80 th.join(timeout)
81 return result
64 82
65 83
66 def main(argv): 84 def main(argv):
67 parser = optparse.OptionParser() 85 parser = optparse.OptionParser()
68 parser.add_option('-r', '--retries', dest='retries', 86 parser.add_option('-r', '--retries', dest='retries',
69 type='int', default=10, 87 type='int', default=10,
70 help='number of times to retry on failure') 88 help='number of times to retry on failure')
71 parser.add_option('-u', '--logurl', dest='logurl', 89 parser.add_option('-u', '--logurl', dest='logurl',
72 default='https://command-wrapper.appspot.com/log', 90 default='https://command-wrapper.appspot.com/log',
73 help='URL to log invocations/failures to') 91 help='URL to log invocations/failures to')
74 (options, args) = parser.parse_args(args=argv[1:]) 92 (options, args) = parser.parse_args(args=argv[1:])
75 93
94 # Limit tcp connnection timeouts to 10 seconds.
95 socket.setdefaulttimeout(10)
96
76 command_id = uuid.uuid1() 97 command_id = uuid.uuid1()
77 cmd = ' '.join(args) 98 cmd = ' '.join(args)
99
100 # Log that we're even starting.
101 RunWithTimeout(LOG_TIMEOUT, LogCommand,
102 options, command_id, -1, cmd, -1, '', '', 0)
103
104 # Try up to a certain number of times.
78 for r in range(options.retries): 105 for r in range(options.retries):
79 tm = time.time() 106 tm = time.time()
80 p = subprocess.Popen(cmd, shell=True, 107 p = subprocess.Popen(cmd, shell=True,
81 stdout=subprocess.PIPE, 108 stdout=subprocess.PIPE,
82 stderr=subprocess.PIPE) 109 stderr=subprocess.PIPE)
83 (p_stdout, p_stderr) = p.communicate() 110 (p_stdout, p_stderr) = p.communicate()
84 sys.stdout.write(p_stdout) 111 sys.stdout.write(p_stdout)
85 sys.stderr.write(p_stderr) 112 sys.stderr.write(p_stderr)
86 runtime = time.time() - tm 113 runtime = time.time() - tm
87 accept = LogCommand(options, command_id, r, cmd, 114 accept = RunWithTimeout(LOG_TIMEOUT, LogCommand,
88 p.returncode, p_stdout, p_stderr, runtime) 115 options, command_id, r, cmd,
116 p.returncode, p_stdout, p_stderr, runtime)
89 if accept: 117 if accept:
90 return p.returncode 118 return p.returncode
91 if p.returncode == 0: 119 if p.returncode == 0:
92 return 0 120 return 0
93 print 'Command %s failed with retcode %d, try %d.' % ( 121 print 'Command %s failed with retcode %d, try %d.' % (
94 ' '.join(args), p.returncode, r + 1) 122 ' '.join(args), p.returncode, r + 1)
95 print 'Command %s failed %d retries, giving up.' % ( 123 print 'Command %s failed %d retries, giving up.' % (
96 ' '.join(args), options.retries) 124 ' '.join(args), options.retries)
97 125
98 return p.returncode 126 return p.returncode
99 127
100 128
101 if __name__ == '__main__': 129 if __name__ == '__main__':
102 sys.exit(main(sys.argv)) 130 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698