]>
Commit | Line | Data |
---|---|---|
4dd00642 MM |
1 | import glob |
2 | import re | |
3 | import string | |
4 | import os | |
5 | import time | |
6 | import shutil | |
7 | ||
4dd00642 MM |
8 | from config import config, init_conf |
9 | import mailer | |
10 | import path | |
0ea52c57 | 11 | import log |
3f446d8f | 12 | import loop |
0ea52c57 | 13 | import status |
3f446d8f | 14 | import lock |
4dd00642 MM |
15 | |
16 | retries_times = [5 * 60, 15 * 60, 60 * 60, 2 * 60 * 60, 5 * 60 * 60] | |
17 | ||
18 | def read_name_val(file): | |
19 | f = open(file) | |
20 | r = {'_file': file[:-5], '_desc': file} | |
21 | rx = re.compile(r"^([^:]+)\s*:(.*)$") | |
22 | for l in f.xreadlines(): | |
23 | if l == "END\n": | |
24 | f.close() | |
25 | return r | |
26 | m = rx.search(l) | |
27 | if m: | |
28 | r[m.group(1)] = string.strip(m.group(2)) | |
0ea52c57 | 29 | else: |
4dd00642 MM |
30 | break |
31 | f.close() | |
32 | return None | |
33 | ||
34 | def scp_file(src, target): | |
35 | global problem | |
36 | f = os.popen("scp -v -B -p %s %s 2>&1 < /dev/null" % (src, target)) | |
37 | problem = f.read() | |
38 | return f.close() | |
39 | ||
40 | def copy_file(src, target): | |
41 | try: | |
42 | shutil.copyfile(src, target) | |
43 | return 0 | |
44 | except: | |
45 | global problem | |
46 | exctype, value = sys.exc_info()[:2] | |
47 | problem = "cannot copy file: %s" % format_exception_only(exctype, value) | |
48 | return 1 | |
49 | ||
6db97676 | 50 | def rsync_file(src, target, host): |
4dd00642 | 51 | global problem |
6db97676 MM |
52 | p = open(path.rsync_password_file, "r") |
53 | password = None | |
54 | for l in p.xreadlines(): | |
55 | l = string.split(l) | |
56 | if len(l) >= 2 and l[0] == host: | |
57 | password = l[1] | |
58 | p.close() | |
59 | rsync = "rsync --verbose --archive" | |
60 | if password != None: | |
61 | p = open(".rsync.pass", "w") | |
62 | os.chmod(".rsync.pass", 0600) | |
63 | p.write("%s\n" % password) | |
64 | p.close() | |
65 | rsync += " --password-file .rsync.pass" | |
66 | f = os.popen("%s %s %s 2>&1 < /dev/null" % (rsync, src, target)) | |
4dd00642 | 67 | problem = f.read() |
6db97676 MM |
68 | res = f.close() |
69 | if password != None: os.unlink(".rsync.pass") | |
4dd00642 MM |
70 | return f.close() |
71 | ||
72 | def send_file(src, target): | |
0ea52c57 | 73 | log.notice("sending %s" % target) |
6db97676 | 74 | m = re.match('rsync://([^/]+)/.*', target) |
0ea52c57 | 75 | if m: |
6db97676 | 76 | return rsync_file(src, target, host = m.group(1)) |
4dd00642 MM |
77 | if target != "" and target[0] == '/': |
78 | return copy_file(src, target) | |
79 | m = re.match('scp://([^@:]+@[^/:]+)(:|)(.*)', target) | |
80 | if m: | |
81 | return scp_file(src, m.group(1) + ":" + m.group(3)) | |
82 | log.alert("unsupported protocol: %s" % target) | |
83 | # pretend everything went OK, so file is removed from queue, | |
84 | # and doesn't cause any additional problems | |
85 | return 0 | |
86 | ||
87 | def maybe_flush_queue(dir): | |
88 | retry_delay = 0 | |
89 | try: | |
90 | f = open(dir + "retry-at") | |
91 | last_retry = int(string.strip(f.readline())) | |
92 | retry_delay = int(string.strip(f.readline())) | |
93 | f.close() | |
94 | if last_retry + retry_delay > time.time(): | |
95 | return | |
96 | os.unlink(dir + "retry-at") | |
97 | except: | |
98 | pass | |
0ea52c57 MM |
99 | |
100 | status.push("flushing %s" % dir) | |
4dd00642 MM |
101 | |
102 | if flush_queue(dir): | |
103 | f = open(dir + "retry-at", "w") | |
0ea52c57 MM |
104 | if retry_delay in retries_times: |
105 | idx = retries_times.index(retry_delay) | |
106 | if idx < len(retries_times) - 1: idx += 1 | |
107 | else: | |
108 | idx = 0 | |
109 | f.write("%d\n%d\n" % (time.time(), retries_times[idx])) | |
4dd00642 MM |
110 | f.close() |
111 | ||
0ea52c57 MM |
112 | status.pop() |
113 | ||
4dd00642 MM |
114 | def flush_queue(dir): |
115 | q = [] | |
6db97676 | 116 | os.chdir(dir) |
4dd00642 MM |
117 | for f in glob.glob(dir + "/*.desc"): |
118 | d = read_name_val(f) | |
119 | if d != None: q.append(d) | |
0ea52c57 MM |
120 | def mycmp(x, y): |
121 | return cmp(x['Time'], y['Time']) | |
122 | q.sort(mycmp) | |
4dd00642 MM |
123 | |
124 | error = None | |
125 | remaining = q | |
126 | for d in q: | |
127 | if send_file(d['_file'], d['Target']): | |
128 | error = d | |
129 | break | |
59ce7cd6 MM |
130 | if os.access(d['_file'] + ".info", os.F_OK): |
131 | if send_file(d['_file'] + ".info", d['Target'] + ".info"): | |
4dd00642 MM |
132 | error = d |
133 | break | |
134 | os.unlink(d['_file']) | |
135 | os.unlink(d['_desc']) | |
136 | remaining = q[1:] | |
137 | ||
138 | if error != None: | |
e2cad913 MM |
139 | emails = {} |
140 | emails[config.admin_email] = 1 | |
4dd00642 MM |
141 | for d in remaining: |
142 | if d.has_key('Requester'): | |
e2cad913 MM |
143 | emails[d['Requester']] = 1 |
144 | e = emails.keys() | |
4dd00642 MM |
145 | m = mailer.Message() |
146 | m.set_headers(to = string.join(e, ", "), | |
147 | subject = "builder queue problem") | |
148 | m.write("there were problems sending files from queue %s:\n" % dir) | |
149 | m.write("problem: %s\n" % problem) | |
150 | m.send() | |
9a8908ac | 151 | log.error("error sending files from %s: %s" % (dir, problem)) |
4dd00642 MM |
152 | return 1 |
153 | ||
154 | return 0 | |
155 | ||
156 | problem = "" | |
157 | ||
158 | def main(): | |
3f446d8f MM |
159 | if lock.lock("sending-files", non_block = 1) == None: |
160 | return | |
4dd00642 MM |
161 | init_conf("") |
162 | maybe_flush_queue(path.buildlogs_queue_dir) | |
163 | maybe_flush_queue(path.ftp_queue_dir) | |
164 | ||
e8ee9db8 | 165 | if __name__ == '__main__': |
3f446d8f | 166 | loop.run_loop(main) |