]> git.pld-linux.org Git - projects/pld-builder.new.git/blame - PLD_Builder/rpm_builder.py
- tz without dst fix
[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
10764658 8import urllib2
3ea4b156
MM
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
5c91097f 54def check_skip_build(r, b):
6ce49c66 55 src_url = config.control_url + "/srpms/" + r.id + "/skipme"
79141e52 56 good = False
9143deab 57 b.log_line("checking if we should skip the build")
6ce49c66
AM
58 while not good:
59 try:
aa90a502
AM
60 headers = { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' }
61 req = urllib2.Request(url=src_url, headers=headers)
62 f = urllib2.urlopen(req)
29526c54 63 good = True
f1d6a788 64 except urllib2.HTTPError, error:
f1d6a788 65 return False
10764658
AM
66 except urllib2.URLError, error:
67 # see errno.h
b8660ef8 68 if error.errno in [-3, 60, 61, 110, 111]:
6ce49c66
AM
69 b.log_line("unable to connect... trying again")
70 continue
71 else:
72 return False
7ff08f87 73 return True
29526c54 74 f.close()
6ce49c66
AM
75 return False
76
17f23d66 77def fetch_src(r, b):
dfff8bd5
MM
78 src_url = config.control_url + "/srpms/" + r.id + "/" + b.src_rpm
79 b.log_line("fetching %s" % src_url)
80 start = time.time()
29526c54 81 good = False
dfff8bd5
MM
82 while not good:
83 try:
aa90a502
AM
84 headers = { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' }
85 req = urllib2.Request(url=src_url, headers=headers)
86 f = urllib2.urlopen(req)
29526c54 87 good = True
f1d6a788
AM
88 except urllib2.HTTPError, error:
89 # fail in a way where cron job will retry
90 msg = "unable to fetch file, http code: %d" % error.code
91 b.log_line(msg)
2a7e772f
AM
92 queue_time = time.time() - r.time
93 # 6 hours
02bb30ae 94 if error.code != 404 or (queue_time >= 0 and queue_time < (6 * 60 * 60)):
2a7e772f
AM
95 raise IOError, msg
96 else:
ec3ee349 97 msg = "in queue for more than 6 hours, download failing"
2a7e772f
AM
98 b.log_line(msg)
99 return False
10764658
AM
100 except urllib2.URLError, error:
101 # see errno.h
b8660ef8 102 if error.errno in [-3, 60, 61, 110, 111]:
dfff8bd5 103 b.log_line("unable to connect... trying again")
e0226a74 104 continue
dfff8bd5 105 else:
85d03545 106 raise
dfff8bd5
MM
107
108 o = chroot.popen("cat > %s" % b.src_rpm, mode = "w")
9e89ce60
AM
109
110 try:
111 bytes = util.sendfile(f, o)
112 except IOError, e:
00a1db68 113 b.log_line("error: unable to write to `%s': %s" % (b.src_rpm, e))
9e89ce60
AM
114 raise
115
dfff8bd5
MM
116 f.close()
117 o.close()
118 t = time.time() - start
119 if t == 0:
120 b.log_line("fetched %d bytes" % bytes)
121 else:
122 b.log_line("fetched %d bytes, %.1f K/s" % (bytes, bytes / 1024.0 / t))
3ea4b156 123
84c6175b 124def prepare_env():
3cf6c853 125 chroot.run("""
efb9c5f7 126 test ! -f /proc/uptime && mount /proc 2>/dev/null
3cf6c853
ER
127 test ! -c /dev/full && rm -f /dev/full && mknod -m 666 /dev/full c 1 7
128 test ! -c /dev/null && rm -f /dev/null && mknod -m 666 /dev/null c 1 3
129 test ! -c /dev/random && rm -f /dev/random && mknod -m 644 /dev/random c 1 8
130 test ! -c /dev/urandom && rm -f /dev/urandom && mknod -m 644 /dev/urandom c 1 9
131 test ! -c /dev/zero && rm -f /dev/zero && mknod -m 666 /dev/zero c 1 5
132
133 # make neccessary files readable for builder user
134 # TODO: see if they really aren't readable for builder
135 for db in Packages Name Basenames Providename Pubkeys; do
136 db=/var/lib/rpm/$db
137 test -f $db && chmod a+r $db
138 done
139
140 # try to limit network access for builder account
141 /bin/setfacl -m u:builder:--- /etc/resolv.conf
142 """, 'root')
84c6175b 143
17f23d66 144def build_rpm(r, b):
dfff8bd5
MM
145 status.push("building %s" % b.spec)
146 b.log_line("request from: %s" % r.requester)
6ce49c66 147
5c91097f 148 if check_skip_build(r, b):
6ce49c66
AM
149 b.log_line("build skipped due to src builder request")
150 res = "SKIP_REQUESTED"
151 return res
152
dfff8bd5
MM
153 b.log_line("started at: %s" % time.asctime())
154 fetch_src(r, b)
155 b.log_line("installing srpm: %s" % b.src_rpm)
156 res = chroot.run("rpm -U %s" % b.src_rpm, logfile = b.logfile)
157 chroot.run("rm -f %s" % b.src_rpm, logfile = b.logfile)
158 b.files = []
159 tmpdir = "/tmp/B." + b.b_id[0:6]
160 if res:
161 b.log_line("error: installing src rpm failed")
511ece79 162 res = "FAIL_SRPM_INSTALL"
deda9a51 163 else:
84c6175b 164 prepare_env()
dfff8bd5 165 chroot.run("install -m 700 -d %s" % tmpdir)
be264f26
ER
166
167 b.default_target(config.arch)
2e5736d2 168 rpmbuild_opt = "%s %s %s" % (b.target_string(), b.kernel_string(), b.bconds_string())
81c135f6 169 # check for build arch before filling BR
0dded0a1 170 cmd = "cd rpm/SPECS; TMPDIR=%s exec nice -n %s rpmbuild -bp --short-circuit --nodeps --define 'prep exit 0' %s %s" % \
81c135f6
ER
171 (tmpdir, config.nice, rpmbuild_opt, b.spec)
172 res = chroot.run(cmd, logfile = b.logfile)
4f2d26fb 173 if res:
511ece79 174 res = "UNSUPP"
a957e64f 175 b.log_line("error: build arch check (%s) failed" % cmd)
81c135f6
ER
176
177 if not res:
feb26777 178 if ("no-install-br" not in r.flags) and not install.uninstall_self_conflict(b):
511ece79 179 res = "FAIL_DEPS_UNINSTALL"
feb26777 180 if ("no-install-br" not in r.flags) and not install.install_br(r, b):
511ece79 181 res = "FAIL_DEPS_INSTALL"
73bdb36b 182 if not res:
a1b28a50 183 max_jobs = max(min(int(os.sysconf('SC_NPROCESSORS_ONLN') * 1.5), config.max_jobs), 1)
85303822 184 if r.max_jobs > 0:
a1b28a50 185 max_jobs = max(min(config.max_jobs, r.max_jobs), 1)
0dded0a1 186 cmd = "echo build-id: %s; cd rpm/SPECS; TMPDIR=%s exec nice -n %s rpmbuild -bb --define '_smp_mflags -j%d' %s %s" % \
0e8fbf23 187 (r.id, tmpdir, config.nice, max_jobs, rpmbuild_opt, b.spec)
81c135f6 188 b.log_line("building RPM using: %s" % cmd)
efb3621d 189 begin_time = time.time()
81c135f6 190 res = chroot.run(cmd, logfile = b.logfile)
efb3621d 191 end_time = time.time()
8d0b8338 192 b.log_line("ended at: %s, done in %s" % (time.asctime(), time.strftime("%ddays %Hh %Mm %Ss", time.gmtime(end_time - begin_time))))
4f2d26fb
AM
193 if res:
194 res = "FAIL"
81c135f6
ER
195 files = util.collect_files(b.logfile)
196 if len(files) > 0:
197 r.chroot_files.extend(files)
198 else:
199 b.log_line("error: No files produced.")
2b9e7381
AM
200 last_section = util.find_last_section(b.logfile)
201 if last_section == None:
202 res = "FAIL"
203 else:
204 res = "FAIL_%s" % last_section.upper()
81c135f6
ER
205 b.files = files
206
dfff8bd5
MM
207 chroot.run("rm -rf %s; cd rpm/SPECS; rpmbuild --nodeps --nobuild " \
208 "--clean --rmspec --rmsource %s" % \
209 (tmpdir, b.spec), logfile = b.logfile)
4e9e9dee 210 chroot.run("chmod -R u+rwX rpm/BUILD/*; rm -rf rpm/BUILD/*", logfile = b.logfile)
dfff8bd5
MM
211
212 def ll(l):
213 util.append_to(b.logfile, l)
deda9a51 214
dfff8bd5 215 if b.files != []:
fd499dc1 216 rpm_cache_dir = config.rpm_cache_dir
e936beda 217 if "test-build" not in r.flags:
adc1235e 218 # NOTE: copying to cache dir doesn't mean that build failed, so ignore result
90d9480e 219 b.log_line("copy rpm files to cache_dir: %s" % rpm_cache_dir)
adc1235e 220 chroot.run(
fd499dc1
ER
221 "cp -f %s %s && poldek --mo=nodiff --mkidxz -s %s/" % \
222 (string.join(b.files), rpm_cache_dir, rpm_cache_dir),
223 logfile = b.logfile, user = "root"
224 )
e936beda 225 else:
fd499dc1 226 ll("test-build: not copying to " + rpm_cache_dir)
dfff8bd5
MM
227 ll("Begin-PLD-Builder-Info")
228 if "upgrade" in r.flags:
73bdb36b 229 b.upgraded = install.upgrade_from_batch(r, b)
dfff8bd5
MM
230 else:
231 ll("not upgrading")
232 ll("End-PLD-Builder-Info")
deda9a51 233
1051562e 234 for f in b.files:
dfff8bd5 235 local = r.tmp_dir + os.path.basename(f)
3e689257 236 chroot.cp(f, outfile = local, rm = True)
dfff8bd5 237 ftp.add(local)
1051562e 238
dfff8bd5
MM
239 def uploadinfo(b):
240 c="file:SRPMS:%s\n" % b.src_rpm
241 for f in b.files:
242 c=c + "file:ARCH:%s\n" % os.path.basename(f)
243 c=c + "END\n"
244 return c
3ea4b156 245
71a06b82 246 if config.gen_upinfo and b.files != [] and 'test-build' not in r.flags:
dfff8bd5
MM
247 fname = r.tmp_dir + b.src_rpm + ".uploadinfo"
248 f = open(fname, "w")
249 f.write(uploadinfo(b))
250 f.close()
251 ftp.add(fname, "uploadinfo")
252
253 status.pop()
254
255 return res
3ea4b156 256
17f23d66 257def handle_request(r):
dfff8bd5
MM
258 ftp.init(r)
259 buildlogs.init(r)
260 build.build_all(r, build_rpm)
261 report.send_report(r, is_src = False)
262 ftp.flush()
63319e0a 263 notify.send(r)
3ea4b156
MM
264
265def check_load():
dfff8bd5
MM
266 do_exit = 0
267 try:
268 f = open("/proc/loadavg")
269 if float(string.split(f.readline())[2]) > config.max_load:
270 do_exit = 1
271 except:
272 pass
273 if do_exit:
274 sys.exit(0)
3ea4b156 275
e8ee9db8 276def main_for(builder):
b8ec18af
AM
277 msg = ""
278
dfff8bd5 279 init_conf(builder)
dfff8bd5 280
dfff8bd5
MM
281 q = B_Queue(path.queue_file + "-" + config.builder)
282 q.lock(0)
283 q.read()
284 if q.requests == []:
285 q.unlock()
286 return
287 req = pick_request(q)
7b16924c 288 q.unlock()
dfff8bd5 289
91112237
AM
290 # high priority tasks have priority < 0, normal tasks >= 0
291 if req.priority >= 0:
b8ec18af
AM
292
293 # allow only one build in given builder at once
294 if not lock.lock("building-rpm-for-%s" % config.builder, non_block = 1):
295 return
296 # don't kill server
297 check_load()
298 # not more then job_slots builds at once
299 locked = 0
300 for slot in range(config.job_slots):
301 if lock.lock("building-rpm-slot-%d" % slot, non_block = 1):
302 locked = 1
303 break
304 if not locked:
305 return
306
307 # record fact that we got lock for this builder, load balancer
308 # will use it for fair-queuing
309 l = lock.lock("got-lock")
310 f = open(path.got_lock_file, "a")
311 f.write(config.builder + "\n")
312 f.close()
313 l.close()
314 else:
315 msg = "HIGH PRIORITY: "
dfff8bd5 316
b8ec18af
AM
317 msg += "handling request %s (%d) for %s from %s, priority %s" \
318 % (req.id, req.no, config.builder, req.requester, req.priority)
dfff8bd5
MM
319 log.notice(msg)
320 status.push(msg)
321 handle_request(req)
322 status.pop()
323
324 def otherreqs(r):
325 if r.no==req.no:
326 return False
327 else:
328 return True
329
330 q = B_Queue(path.queue_file + "-" + config.builder)
331 q.lock(0)
332 q.read()
333 previouslen=len(q.requests)
334 q.requests=filter(otherreqs, q.requests)
335 if len(q.requests)<previouslen:
336 q.write()
337 q.unlock()
338
e8ee9db8 339def main():
dfff8bd5 340 if len(sys.argv) < 2:
939af6d7 341 raise Exception, "fatal: need to have builder name as first arg"
dfff8bd5
MM
342 return main_for(sys.argv[1])
343
e8ee9db8 344if __name__ == '__main__':
dfff8bd5 345 loop.run_loop(main)
This page took 0.112367 seconds and 4 git commands to generate.