]>
Commit | Line | Data |
---|---|---|
dfff8bd5 MM |
1 | # vi: encoding=utf-8 ts=8 sts=4 sw=4 et |
2 | ||
3ea4b156 MM |
3 | import sys |
4 | import os | |
5 | import atexit | |
6 | import time | |
deda9a51 | 7 | import string |
3ea4b156 MM |
8 | import urllib |
9 | ||
10 | from config import config, init_conf | |
11 | from bqueue import B_Queue | |
3ea4b156 MM |
12 | import lock |
13 | import util | |
3f446d8f | 14 | import loop |
3ea4b156 MM |
15 | import path |
16 | import status | |
17 | import log | |
18 | import chroot | |
19 | import ftp | |
e2cad913 | 20 | import buildlogs |
59ce7cd6 | 21 | import notify |
17f23d66 MM |
22 | import build |
23 | import report | |
deda9a51 MM |
24 | import upgrade |
25 | import install_br | |
3ea4b156 | 26 | |
53989cf3 MM |
27 | # *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK* |
28 | import socket | |
29 | ||
30 | socket.myorigsocket=socket.socket | |
31 | ||
32 | def mysocket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0): | |
dfff8bd5 MM |
33 | s=socket.myorigsocket(family, type, proto) |
34 | s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) | |
35 | return s | |
53989cf3 MM |
36 | |
37 | socket.socket=mysocket | |
38 | # *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK* | |
39 | ||
3ea4b156 MM |
40 | # this code is duplicated in srpm_builder, but we |
41 | # might want to handle some cases differently here | |
42 | def pick_request(q): | |
dfff8bd5 MM |
43 | def mycmp(r1, r2): |
44 | if r1.kind != 'group' or r2.kind != 'group': | |
45 | raise "non-group requests" | |
46 | pri_diff = cmp(r1.priority, r2.priority) | |
47 | if pri_diff == 0: | |
48 | return cmp(r1.time, r2.time) | |
49 | else: | |
50 | return pri_diff | |
51 | q.requests.sort(mycmp) | |
52 | ret = q.requests[0] | |
53 | return ret | |
3ea4b156 | 54 | |
17f23d66 | 55 | def fetch_src(r, b): |
dfff8bd5 MM |
56 | src_url = config.control_url + "/srpms/" + r.id + "/" + b.src_rpm |
57 | b.log_line("fetching %s" % src_url) | |
58 | start = time.time() | |
59 | good=False | |
60 | while not good: | |
61 | try: | |
62 | good=True | |
63 | f = urllib.urlopen(src_url) | |
64 | except IOError, error: | |
65 | if error[1][0] == 60 or error[1][0] == 110 or error[1][0] == -3 or error[1][0] == 111 or error[1][0] == 61: | |
66 | good=False | |
67 | b.log_line("unable to connect... trying again") | |
68 | else: | |
69 | f = urllib.urlopen(src_url) # So we get the exception logged :) | |
70 | ||
71 | o = chroot.popen("cat > %s" % b.src_rpm, mode = "w") | |
72 | bytes = util.sendfile(f, o) | |
73 | f.close() | |
74 | o.close() | |
75 | t = time.time() - start | |
76 | if t == 0: | |
77 | b.log_line("fetched %d bytes" % bytes) | |
78 | else: | |
79 | b.log_line("fetched %d bytes, %.1f K/s" % (bytes, bytes / 1024.0 / t)) | |
3ea4b156 | 80 | |
17f23d66 | 81 | def build_rpm(r, b): |
dfff8bd5 MM |
82 | status.push("building %s" % b.spec) |
83 | b.log_line("request from: %s" % r.requester) | |
84 | b.log_line("started at: %s" % time.asctime()) | |
85 | fetch_src(r, b) | |
86 | b.log_line("installing srpm: %s" % b.src_rpm) | |
87 | res = chroot.run("rpm -U %s" % b.src_rpm, logfile = b.logfile) | |
88 | chroot.run("rm -f %s" % b.src_rpm, logfile = b.logfile) | |
89 | b.files = [] | |
90 | tmpdir = "/tmp/B." + b.b_id[0:6] | |
91 | if res: | |
92 | b.log_line("error: installing src rpm failed") | |
93 | res = 1 | |
deda9a51 | 94 | else: |
dfff8bd5 MM |
95 | chroot.run("install -m 700 -d %s" % tmpdir) |
96 | rpmbuild_opt = "%s --target %s-pld-linux" % (b.bconds_string(), config.arch) | |
97 | cmd = "cd rpm/SPECS; TMPDIR=%s nice -n %s rpmbuild -bb %s %s" % \ | |
98 | (tmpdir, config.nice, rpmbuild_opt, b.spec) | |
99 | if ("no-install-br" not in r.flags) and install_br.install_br(r, b): | |
100 | res = 1 | |
101 | else: | |
102 | b.log_line("building RPM using: %s" % cmd) | |
103 | res = chroot.run(cmd, logfile = b.logfile) | |
104 | files = util.collect_files(b.logfile) | |
105 | if len(files) > 0: | |
106 | r.chroot_files.extend(files) | |
107 | else: | |
108 | b.log_line("error: No files produced.") | |
109 | res = 1 # FIXME: is it error? | |
110 | b.files = files | |
111 | chroot.run("rm -rf %s; cd rpm/SPECS; rpmbuild --nodeps --nobuild " \ | |
112 | "--clean --rmspec --rmsource %s" % \ | |
113 | (tmpdir, b.spec), logfile = b.logfile) | |
114 | chroot.run("rm -rf $HOME/rpm/BUILD/*") | |
115 | ||
116 | def ll(l): | |
117 | util.append_to(b.logfile, l) | |
deda9a51 | 118 | |
dfff8bd5 MM |
119 | if b.files != []: |
120 | chroot.run("cp -f %s /spools/ready/; poldek --nodiff --mkidxz " \ | |
121 | "-s /spools/ready/" % \ | |
122 | string.join(b.files), logfile = b.logfile, user = "root") | |
123 | ll("Begin-PLD-Builder-Info") | |
124 | if "upgrade" in r.flags: | |
125 | upgrade.upgrade_from_batch(r, b) | |
126 | else: | |
127 | ll("not upgrading") | |
128 | ll("End-PLD-Builder-Info") | |
deda9a51 | 129 | |
1051562e | 130 | for f in b.files: |
dfff8bd5 MM |
131 | local = r.tmp_dir + os.path.basename(f) |
132 | chroot.run("cat %s; rm -f %s" % (f, f), logfile = local) | |
133 | ftp.add(local) | |
1051562e | 134 | |
dfff8bd5 MM |
135 | def uploadinfo(b): |
136 | c="file:SRPMS:%s\n" % b.src_rpm | |
137 | for f in b.files: | |
138 | c=c + "file:ARCH:%s\n" % os.path.basename(f) | |
139 | c=c + "END\n" | |
140 | return c | |
3ea4b156 | 141 | |
dfff8bd5 MM |
142 | if b.files != []: |
143 | fname = r.tmp_dir + b.src_rpm + ".uploadinfo" | |
144 | f = open(fname, "w") | |
145 | f.write(uploadinfo(b)) | |
146 | f.close() | |
147 | ftp.add(fname, "uploadinfo") | |
148 | ||
149 | status.pop() | |
150 | ||
151 | return res | |
3ea4b156 | 152 | |
17f23d66 | 153 | def handle_request(r): |
dfff8bd5 MM |
154 | ftp.init(r) |
155 | buildlogs.init(r) | |
156 | build.build_all(r, build_rpm) | |
157 | report.send_report(r, is_src = False) | |
158 | ftp.flush() | |
159 | notify.send() | |
3ea4b156 MM |
160 | |
161 | def check_load(): | |
dfff8bd5 MM |
162 | do_exit = 0 |
163 | try: | |
164 | f = open("/proc/loadavg") | |
165 | if float(string.split(f.readline())[2]) > config.max_load: | |
166 | do_exit = 1 | |
167 | except: | |
168 | pass | |
169 | if do_exit: | |
170 | sys.exit(0) | |
3ea4b156 | 171 | |
e8ee9db8 | 172 | def main_for(builder): |
dfff8bd5 MM |
173 | init_conf(builder) |
174 | # allow only one build in given builder at once | |
175 | if not lock.lock("building-rpm-for-%s" % config.builder, non_block = 1): | |
176 | return | |
177 | # don't kill server | |
178 | check_load() | |
179 | # not more then job_slots builds at once | |
180 | locked = 0 | |
181 | for slot in range(config.job_slots): | |
182 | if lock.lock("building-rpm-slot-%d" % slot, non_block = 1): | |
183 | locked = 1 | |
184 | break | |
185 | if not locked: | |
186 | return | |
187 | ||
188 | status.push("picking request for %s" % config.builder) | |
189 | q = B_Queue(path.queue_file + "-" + config.builder) | |
190 | q.lock(0) | |
191 | q.read() | |
192 | if q.requests == []: | |
193 | q.unlock() | |
194 | return | |
195 | req = pick_request(q) | |
7b16924c | 196 | q.unlock() |
dfff8bd5 MM |
197 | status.pop() |
198 | ||
199 | # record fact that we got lock for this builder, load balancer | |
200 | # will use it for fair-queuing | |
201 | l = lock.lock("got-lock") | |
202 | f = open(path.got_lock_file, "a") | |
203 | f.write(config.builder + "\n") | |
204 | f.close() | |
205 | l.close() | |
206 | ||
207 | msg = "handling request %s (%d) for %s from %s" \ | |
208 | % (req.id, req.no, config.builder, req.requester) | |
209 | log.notice(msg) | |
210 | status.push(msg) | |
211 | handle_request(req) | |
212 | status.pop() | |
213 | ||
214 | def otherreqs(r): | |
215 | if r.no==req.no: | |
216 | return False | |
217 | else: | |
218 | return True | |
219 | ||
220 | q = B_Queue(path.queue_file + "-" + config.builder) | |
221 | q.lock(0) | |
222 | q.read() | |
223 | previouslen=len(q.requests) | |
224 | q.requests=filter(otherreqs, q.requests) | |
225 | if len(q.requests)<previouslen: | |
226 | q.write() | |
227 | q.unlock() | |
228 | ||
e8ee9db8 | 229 | def main(): |
dfff8bd5 MM |
230 | if len(sys.argv) < 2: |
231 | raise "fatal: need to have builder name as first arg" | |
232 | return main_for(sys.argv[1]) | |
233 | ||
e8ee9db8 | 234 | if __name__ == '__main__': |
dfff8bd5 | 235 | loop.run_loop(main) |