]>
Commit | Line | Data |
---|---|---|
3ea4b156 MM |
1 | import sys |
2 | import os | |
3 | import atexit | |
4 | import time | |
5 | import urllib | |
6 | ||
7 | from config import config, init_conf | |
8 | from bqueue import B_Queue | |
9 | from acl import acl | |
10 | import lock | |
11 | import util | |
3f446d8f | 12 | import loop |
3ea4b156 MM |
13 | import path |
14 | import status | |
15 | import log | |
16 | import chroot | |
17 | import ftp | |
18 | import buildlogs | |
59ce7cd6 | 19 | import notify |
3ea4b156 MM |
20 | |
21 | # this code is duplicated in srpm_builder, but we | |
22 | # might want to handle some cases differently here | |
23 | def pick_request(q): | |
24 | def mycmp(r1, r2): | |
25 | if r1.kind != 'group' or r2.kind != 'group': | |
26 | raise "non-group requests" | |
27 | pri_diff = cmp(r1.priority, r2.priority) | |
28 | if pri_diff == 0: | |
29 | return cmp(r1.time, r2.time) | |
30 | else: | |
31 | return pri_diff | |
32 | q.requests.sort(mycmp) | |
33 | ret = q.requests[0] | |
34 | q.requests = q.requests[1:] | |
35 | return ret | |
36 | ||
37 | def handle_request(r): | |
38 | def log_line(l): | |
39 | log.notice(l) | |
40 | util.append_to(spec_log, l) | |
41 | ||
42 | def fetch_src(b): | |
43 | src_url = config.control_url + "/srpms/" + r.id + "/" + b.src_rpm | |
44 | log_line("fetching %s" % src_url) | |
45 | start = time.time() | |
46 | f = urllib.urlopen(src_url) | |
47 | o = chroot.popen("cat > %s" % b.src_rpm, mode = "w") | |
48 | bytes = util.sendfile(f, o) | |
49 | f.close() | |
50 | o.close() | |
51 | t = time.time() - start | |
52 | if t == 0: | |
53 | log_line("fetched %d bytes" % bytes) | |
54 | else: | |
55 | log_line("fetched %d bytes, %.1f K/s" % (bytes, bytes / 1024.0 / t)) | |
56 | ||
30dbf6a3 | 57 | def build_rpm(r, b): |
3ea4b156 | 58 | global spec_log |
30dbf6a3 | 59 | spec_log = b.logfile |
3ea4b156 | 60 | status.push("building %s" % b.spec) |
30dbf6a3 MM |
61 | log_line("request from: %s" % r.requester) |
62 | log_line("started at: %s" % time.asctime()) | |
3ea4b156 | 63 | fetch_src(b) |
30dbf6a3 | 64 | log_line("installing srpm: %s" % b.src_rpm) |
1489d009 MM |
65 | res = chroot.run("rpm -U %s" % b.src_rpm, logfile = b.logfile) |
66 | chroot.run("rm -f %s" % b.src_rpm, logfile = b.logfile) | |
3ea4b156 MM |
67 | if res: |
68 | log_line("error: installing src rpm failed") | |
30dbf6a3 | 69 | res = 1 |
3ea4b156 | 70 | else: |
f50e2253 MM |
71 | cmd = "install -m 700 -d $HOME/%s; cd rpm/SPECS; " \ |
72 | "TMPDIR=$HOME/%s rpmbuild -bb %s" % \ | |
73 | (b.b_id, b.b_id, b.spec) | |
30dbf6a3 MM |
74 | log_line("building RPM using: %s" % cmd) |
75 | res = chroot.run(cmd, logfile = b.logfile) | |
76 | files = util.collect_files(b.logfile) | |
3ea4b156 | 77 | if len(files) > 0: |
30dbf6a3 | 78 | r.chroot_files.extend(files) |
3ea4b156 MM |
79 | else: |
80 | # FIXME: is it error? | |
81 | log_line("error: No files produced.") | |
82 | res = 1 | |
30dbf6a3 | 83 | b.files = files |
f50e2253 MM |
84 | chroot.run("rm -rf $HOME/%s; cd rpm/SPECS; rpmbuild --nodeps --nobuild " \ |
85 | "--clean --rmspec --rmsource %s" % \ | |
1489d009 | 86 | (b.b_id, b.spec), logfile = b.logfile) |
30dbf6a3 | 87 | buildlogs.add(logfile = b.logfile, failed = res) |
3ea4b156 MM |
88 | status.pop() |
89 | return res | |
90 | ||
30dbf6a3 | 91 | r.build_all(build_rpm) |
3ea4b156 | 92 | |
0638381b | 93 | ftp.init(r) |
30dbf6a3 MM |
94 | for b in r.batches: |
95 | if not b.build_failed: | |
96 | for f in b.files: | |
97 | local = r.tmp_dir + os.path.basename(f) | |
98 | chroot.run("cat %s; rm -f %s" % (f, f), logfile = local) | |
99 | ftp.add(local) | |
100 | ||
101 | r.clean_files() | |
102 | r.send_report() | |
3ea4b156 MM |
103 | buildlogs.flush() |
104 | ftp.flush() | |
59ce7cd6 | 105 | notify.send() |
3ea4b156 MM |
106 | |
107 | def check_load(): | |
3f446d8f | 108 | do_exit = 0 |
3ea4b156 MM |
109 | try: |
110 | f = open("/proc/loadavg") | |
111 | if float(string.split(f.readline())[2]) > config.max_load: | |
3f446d8f | 112 | do_exit = 1 |
3ea4b156 MM |
113 | except: |
114 | pass | |
3f446d8f MM |
115 | if do_exit: |
116 | sys.exit(0) | |
3ea4b156 | 117 | |
e8ee9db8 MM |
118 | def main_for(builder): |
119 | init_conf(builder) | |
3ea4b156 MM |
120 | # allow only one build in given builder at once |
121 | if not lock.lock("building-rpm-for-%s" % config.builder, non_block = 1): | |
122 | return | |
123 | # don't kill server | |
124 | check_load() | |
125 | # not more then job_slots builds at once | |
126 | locked = 0 | |
127 | for slot in range(config.job_slots): | |
128 | if lock.lock("building-rpm-slot-%d" % slot, non_block = 1): | |
129 | locked = 1 | |
130 | break | |
131 | if not locked: | |
132 | return | |
133 | ||
134 | status.push("picking request for %s" % config.builder) | |
135 | q = B_Queue(path.queue_file + "-" + config.builder) | |
136 | q.lock(0) | |
137 | q.read() | |
138 | if q.requests == []: | |
139 | return | |
140 | r = pick_request(q) | |
141 | q.write() | |
142 | q.unlock() | |
143 | status.pop() | |
144 | ||
145 | # record fact that we got lock for this builder, load balancer | |
146 | # will use it for fair-queuing | |
147 | l = lock.lock("got-lock") | |
148 | f = open(path.got_lock_file, "a") | |
149 | f.write(config.builder + "\n") | |
150 | f.close() | |
151 | l.close() | |
152 | ||
153 | msg = "handling request %s (%d) for %s from %s" \ | |
154 | % (r.id, r.no, config.builder, r.requester) | |
155 | log.notice(msg) | |
156 | status.push(msg) | |
157 | handle_request(r) | |
158 | status.pop() | |
159 | ||
e8ee9db8 MM |
160 | def main(): |
161 | if len(sys.argv) < 2: | |
162 | raise "fatal: need to have builder name as first arg" | |
163 | return main_for(sys.argv[1]) | |
164 | ||
165 | if __name__ == '__main__': | |
3f446d8f | 166 | loop.run_loop(main) |