]> git.pld-linux.org Git - projects/pld-builder.new.git/blame - PLD_Builder/rpm_builder.py
- call it 0.4 for the sake of new cvs structure
[projects/pld-builder.new.git] / PLD_Builder / rpm_builder.py
CommitLineData
dfff8bd5
MM
1# vi: encoding=utf-8 ts=8 sts=4 sw=4 et
2
3ea4b156
MM
3import sys
4import os
5import atexit
6import time
deda9a51 7import string
3ea4b156
MM
8import urllib
9
10from config import config, init_conf
11from bqueue import B_Queue
3ea4b156
MM
12import lock
13import util
3f446d8f 14import loop
3ea4b156
MM
15import path
16import status
17import log
18import chroot
19import ftp
e2cad913 20import buildlogs
59ce7cd6 21import notify
17f23d66
MM
22import build
23import report
73bdb36b 24import install
3ea4b156 25
53989cf3
MM
26# *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*
27import socket
28
29socket.myorigsocket=socket.socket
30
31def mysocket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
dfff8bd5
MM
32 s=socket.myorigsocket(family, type, proto)
33 s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
34 return s
53989cf3
MM
35
36socket.socket=mysocket
37# *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*
38
3ea4b156
MM
39# this code is duplicated in srpm_builder, but we
40# might want to handle some cases differently here
41def pick_request(q):
dfff8bd5
MM
42 def mycmp(r1, r2):
43 if r1.kind != 'group' or r2.kind != 'group':
939af6d7 44 raise Exception, "non-group requests"
dfff8bd5
MM
45 pri_diff = cmp(r1.priority, r2.priority)
46 if pri_diff == 0:
47 return cmp(r1.time, r2.time)
48 else:
bbed4c4d 49 return pri_diff
dfff8bd5
MM
50 q.requests.sort(mycmp)
51 ret = q.requests[0]
52 return ret
3ea4b156 53
17f23d66 54def fetch_src(r, b):
dfff8bd5
MM
55 src_url = config.control_url + "/srpms/" + r.id + "/" + b.src_rpm
56 b.log_line("fetching %s" % src_url)
57 start = time.time()
58 good=False
59 while not good:
60 try:
61 good=True
62 f = urllib.urlopen(src_url)
63 except IOError, error:
64 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:
65 good=False
66 b.log_line("unable to connect... trying again")
67 else:
68 f = urllib.urlopen(src_url) # So we get the exception logged :)
69
70 o = chroot.popen("cat > %s" % b.src_rpm, mode = "w")
9e89ce60
AM
71
72 try:
73 bytes = util.sendfile(f, o)
74 except IOError, e:
00a1db68 75 b.log_line("error: unable to write to `%s': %s" % (b.src_rpm, e))
9e89ce60
AM
76 raise
77
dfff8bd5
MM
78 f.close()
79 o.close()
80 t = time.time() - start
81 if t == 0:
82 b.log_line("fetched %d bytes" % bytes)
83 else:
84 b.log_line("fetched %d bytes, %.1f K/s" % (bytes, bytes / 1024.0 / t))
3ea4b156 85
84c6175b
MM
86def prepare_env():
87 chroot.run("test ! -f /proc/uptime && mount /proc", 'root')
9b2ab0b4
AM
88 chroot.run("test ! -e /dev/full && mknod /dev/full c 1 7 && chmod 666 /dev/full", 'root')
89 chroot.run("test ! -e /dev/null && mknod /dev/null c 1 3 && chmod 666 /dev/null", 'root')
90 chroot.run("test ! -e /dev/random && mknod /dev/random c 1 8 && chmod 644 /dev/random", 'root')
91 chroot.run("test ! -e /dev/urandom && mknod /dev/urandom c 1 9 && chmod 644 /dev/urandom", 'root')
92 chroot.run("test ! -e /dev/zero && mknod /dev/zero c 1 5 && chmod 666 /dev/zero", 'root')
62aff600 93 # try to limit network access for builder account
52a64a7d 94 chroot.run("/bin/setfacl -m u:builder:--- /etc/resolv.conf", 'root')
84c6175b 95
17f23d66 96def build_rpm(r, b):
dfff8bd5
MM
97 status.push("building %s" % b.spec)
98 b.log_line("request from: %s" % r.requester)
99 b.log_line("started at: %s" % time.asctime())
100 fetch_src(r, b)
101 b.log_line("installing srpm: %s" % b.src_rpm)
102 res = chroot.run("rpm -U %s" % b.src_rpm, logfile = b.logfile)
103 chroot.run("rm -f %s" % b.src_rpm, logfile = b.logfile)
104 b.files = []
105 tmpdir = "/tmp/B." + b.b_id[0:6]
106 if res:
107 b.log_line("error: installing src rpm failed")
511ece79 108 res = "FAIL_SRPM_INSTALL"
deda9a51 109 else:
84c6175b 110 prepare_env()
dfff8bd5 111 chroot.run("install -m 700 -d %s" % tmpdir)
be264f26
ER
112
113 b.default_target(config.arch)
2e5736d2 114 rpmbuild_opt = "%s %s %s" % (b.target_string(), b.kernel_string(), b.bconds_string())
81c135f6
ER
115 # check for build arch before filling BR
116 cmd = "cd rpm/SPECS; TMPDIR=%s nice -n %s rpmbuild -bp --short-circuit --nodeps --define 'prep exit 0' %s %s" % \
117 (tmpdir, config.nice, rpmbuild_opt, b.spec)
118 res = chroot.run(cmd, logfile = b.logfile)
4f2d26fb 119 if res:
511ece79 120 res = "UNSUPP"
a957e64f 121 b.log_line("error: build arch check (%s) failed" % cmd)
81c135f6
ER
122
123 if not res:
feb26777 124 if ("no-install-br" not in r.flags) and not install.uninstall_self_conflict(b):
511ece79 125 res = "FAIL_DEPS_UNINSTALL"
feb26777 126 if ("no-install-br" not in r.flags) and not install.install_br(r, b):
511ece79 127 res = "FAIL_DEPS_INSTALL"
73bdb36b 128 if not res:
a1b28a50 129 max_jobs = max(min(int(os.sysconf('SC_NPROCESSORS_ONLN') * 1.5), config.max_jobs), 1)
85303822 130 if r.max_jobs > 0:
a1b28a50 131 max_jobs = max(min(config.max_jobs, r.max_jobs), 1)
b3c8d962 132 cmd = "cd rpm/SPECS; TMPDIR=%s nice -n %s rpmbuild -bb --define '_smp_mflags -j%d' %s %s" % \
85303822 133 (tmpdir, config.nice, max_jobs, rpmbuild_opt, b.spec)
81c135f6 134 b.log_line("building RPM using: %s" % cmd)
efb3621d 135 begin_time = time.time()
81c135f6 136 res = chroot.run(cmd, logfile = b.logfile)
efb3621d 137 end_time = time.time()
200299dd 138 b.log_line("ended at: %s, done in %s" % (time.asctime(), time.strftime("%Hh %Mm %Ss", time.gmtime(end_time - begin_time))))
4f2d26fb
AM
139 if res:
140 res = "FAIL"
81c135f6
ER
141 files = util.collect_files(b.logfile)
142 if len(files) > 0:
143 r.chroot_files.extend(files)
144 else:
145 b.log_line("error: No files produced.")
2b9e7381
AM
146 last_section = util.find_last_section(b.logfile)
147 if last_section == None:
148 res = "FAIL"
149 else:
150 res = "FAIL_%s" % last_section.upper()
81c135f6
ER
151 b.files = files
152
dfff8bd5
MM
153 chroot.run("rm -rf %s; cd rpm/SPECS; rpmbuild --nodeps --nobuild " \
154 "--clean --rmspec --rmsource %s" % \
155 (tmpdir, b.spec), logfile = b.logfile)
156 chroot.run("rm -rf $HOME/rpm/BUILD/*")
157
158 def ll(l):
159 util.append_to(b.logfile, l)
deda9a51 160
dfff8bd5 161 if b.files != []:
fd499dc1 162 rpm_cache_dir = config.rpm_cache_dir
e936beda 163 if "test-build" not in r.flags:
fd499dc1
ER
164 # XXX missing error check!
165 b.log_line("copy rpm files to cache_dir=%s" % rpm_cache_dir)
166 res = chroot.run(
167 "cp -f %s %s && poldek --mo=nodiff --mkidxz -s %s/" % \
168 (string.join(b.files), rpm_cache_dir, rpm_cache_dir),
169 logfile = b.logfile, user = "root"
170 )
e936beda 171 else:
fd499dc1 172 ll("test-build: not copying to " + rpm_cache_dir)
dfff8bd5
MM
173 ll("Begin-PLD-Builder-Info")
174 if "upgrade" in r.flags:
73bdb36b 175 b.upgraded = install.upgrade_from_batch(r, b)
dfff8bd5
MM
176 else:
177 ll("not upgrading")
178 ll("End-PLD-Builder-Info")
deda9a51 179
1051562e 180 for f in b.files:
dfff8bd5 181 local = r.tmp_dir + os.path.basename(f)
3e689257 182 chroot.cp(f, outfile = local, rm = True)
dfff8bd5 183 ftp.add(local)
1051562e 184
dfff8bd5
MM
185 def uploadinfo(b):
186 c="file:SRPMS:%s\n" % b.src_rpm
187 for f in b.files:
188 c=c + "file:ARCH:%s\n" % os.path.basename(f)
189 c=c + "END\n"
190 return c
3ea4b156 191
71a06b82 192 if config.gen_upinfo and b.files != [] and 'test-build' not in r.flags:
dfff8bd5
MM
193 fname = r.tmp_dir + b.src_rpm + ".uploadinfo"
194 f = open(fname, "w")
195 f.write(uploadinfo(b))
196 f.close()
197 ftp.add(fname, "uploadinfo")
198
199 status.pop()
200
201 return res
3ea4b156 202
17f23d66 203def handle_request(r):
dfff8bd5
MM
204 ftp.init(r)
205 buildlogs.init(r)
206 build.build_all(r, build_rpm)
207 report.send_report(r, is_src = False)
208 ftp.flush()
63319e0a 209 notify.send(r)
3ea4b156
MM
210
211def check_load():
dfff8bd5
MM
212 do_exit = 0
213 try:
214 f = open("/proc/loadavg")
215 if float(string.split(f.readline())[2]) > config.max_load:
216 do_exit = 1
217 except:
218 pass
219 if do_exit:
220 sys.exit(0)
3ea4b156 221
e8ee9db8 222def main_for(builder):
b8ec18af
AM
223 msg = ""
224
dfff8bd5 225 init_conf(builder)
dfff8bd5 226
dfff8bd5
MM
227 q = B_Queue(path.queue_file + "-" + config.builder)
228 q.lock(0)
229 q.read()
230 if q.requests == []:
231 q.unlock()
232 return
233 req = pick_request(q)
7b16924c 234 q.unlock()
dfff8bd5 235
91112237
AM
236 # high priority tasks have priority < 0, normal tasks >= 0
237 if req.priority >= 0:
b8ec18af
AM
238
239 # allow only one build in given builder at once
240 if not lock.lock("building-rpm-for-%s" % config.builder, non_block = 1):
241 return
242 # don't kill server
243 check_load()
244 # not more then job_slots builds at once
245 locked = 0
246 for slot in range(config.job_slots):
247 if lock.lock("building-rpm-slot-%d" % slot, non_block = 1):
248 locked = 1
249 break
250 if not locked:
251 return
252
253 # record fact that we got lock for this builder, load balancer
254 # will use it for fair-queuing
255 l = lock.lock("got-lock")
256 f = open(path.got_lock_file, "a")
257 f.write(config.builder + "\n")
258 f.close()
259 l.close()
260 else:
261 msg = "HIGH PRIORITY: "
dfff8bd5 262
b8ec18af
AM
263 msg += "handling request %s (%d) for %s from %s, priority %s" \
264 % (req.id, req.no, config.builder, req.requester, req.priority)
dfff8bd5
MM
265 log.notice(msg)
266 status.push(msg)
267 handle_request(req)
268 status.pop()
269
270 def otherreqs(r):
271 if r.no==req.no:
272 return False
273 else:
274 return True
275
276 q = B_Queue(path.queue_file + "-" + config.builder)
277 q.lock(0)
278 q.read()
279 previouslen=len(q.requests)
280 q.requests=filter(otherreqs, q.requests)
281 if len(q.requests)<previouslen:
282 q.write()
283 q.unlock()
284
e8ee9db8 285def main():
dfff8bd5 286 if len(sys.argv) < 2:
939af6d7 287 raise Exception, "fatal: need to have builder name as first arg"
dfff8bd5
MM
288 return main_for(sys.argv[1])
289
e8ee9db8 290if __name__ == '__main__':
dfff8bd5 291 loop.run_loop(main)
This page took 0.114602 seconds and 4 git commands to generate.