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