]> git.pld-linux.org Git - projects/pld-builder.new.git/blob - PLD_Builder/rpm_builder.py
- more statuses supported
[projects/pld-builder.new.git] / PLD_Builder / rpm_builder.py
1 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et
2
3 import sys
4 import os
5 import atexit
6 import time
7 import string
8 import urllib
9
10 from config import config, init_conf
11 from bqueue import B_Queue
12 import lock
13 import util
14 import loop
15 import path
16 import status
17 import log
18 import chroot
19 import ftp
20 import buildlogs
21 import notify
22 import build
23 import report
24 import install
25
26 # *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*
27 import socket
28
29 socket.myorigsocket=socket.socket
30
31 def mysocket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
32     s=socket.myorigsocket(family, type, proto)
33     s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
34     return s
35
36 socket.socket=mysocket
37 # *HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*HACK*
38
39 # this code is duplicated in srpm_builder, but we
40 # might want to handle some cases differently here
41 def pick_request(q):
42     def mycmp(r1, r2):
43         if r1.kind != 'group' or r2.kind != 'group':
44             raise Exception, "non-group requests"
45         pri_diff = cmp(r1.priority, r2.priority)
46         if pri_diff == 0:
47             return cmp(r1.time, r2.time)
48         else:
49             return pri_diff
50     q.requests.sort(mycmp)
51     ret = q.requests[0]
52     return ret
53
54 def fetch_src(r, b):
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")
71
72     try:
73         bytes = util.sendfile(f, o)
74     except IOError, e:
75         b.log_line("error: unable to write to `%s': %s" % (b.src_rpm, e))
76         raise
77
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))
85
86 def prepare_env():
87     chroot.run("test ! -f /proc/uptime && mount /proc", 'root')
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')
93
94 def build_rpm(r, b):
95     status.push("building %s" % b.spec)
96     b.log_line("request from: %s" % r.requester)
97     b.log_line("started at: %s" % time.asctime())
98     fetch_src(r, b)
99     b.log_line("installing srpm: %s" % b.src_rpm)
100     res = chroot.run("rpm -U %s" % b.src_rpm, logfile = b.logfile)
101     chroot.run("rm -f %s" % b.src_rpm, logfile = b.logfile)
102     b.files = []
103     tmpdir = "/tmp/B." + b.b_id[0:6]
104     if res:
105         b.log_line("error: installing src rpm failed")
106         res = "FAIL_SRPM_INSTALL"
107         res = 1
108     else:
109         prepare_env()
110         chroot.run("install -m 700 -d %s" % tmpdir)
111
112         b.default_target(config.arch)
113         rpmbuild_opt = "%s %s %s" % (b.target_string(), b.kernel_string(), b.bconds_string())
114         # check for build arch before filling BR
115         cmd = "cd rpm/SPECS; TMPDIR=%s nice -n %s rpmbuild -bp --short-circuit --nodeps --define 'prep exit 0' %s %s" % \
116             (tmpdir, config.nice, rpmbuild_opt, b.spec)
117         res = chroot.run(cmd, logfile = b.logfile)
118         if res != 0:
119             res = "UNSUPP"
120             b.log_line("error: build arch check (%s) failed" % cmd)
121
122         if not res:
123             if ("no-install-br" not in r.flags) and not install.uninstall_self_conflict(b):
124                 res = "FAIL_DEPS_UNINSTALL"
125             if ("no-install-br" not in r.flags) and not install.install_br(r, b):
126                 res = "FAIL_DEPS_INSTALL"
127             if not res:
128                 cmd = "cd rpm/SPECS; TMPDIR=%s nice -n %s rpmbuild -bb %s %s" % \
129                             (tmpdir, config.nice, rpmbuild_opt, b.spec)
130                 b.log_line("building RPM using: %s" % cmd)
131                 res = chroot.run(cmd, logfile = b.logfile)
132                 files = util.collect_files(b.logfile)
133                 if len(files) > 0:
134                     res = "OK"
135                     r.chroot_files.extend(files)
136                 else:
137                     b.log_line("error: No files produced.")
138                     res = "FAIL_NOFILES"
139                 b.files = files
140
141     chroot.run("rm -rf %s; cd rpm/SPECS; rpmbuild --nodeps --nobuild " \
142                          "--clean --rmspec --rmsource %s" % \
143                          (tmpdir, b.spec), logfile = b.logfile)
144     chroot.run("rm -rf $HOME/rpm/BUILD/*")
145
146     def ll(l):
147         util.append_to(b.logfile, l)
148  
149     if b.files != []:
150         rpm_cache_dir = config.rpm_cache_dir
151         if "test-build" not in r.flags:
152             # XXX missing error check!
153             b.log_line("copy rpm files to cache_dir=%s" % rpm_cache_dir)
154             res = chroot.run(
155                     "cp -f %s %s && poldek --mo=nodiff --mkidxz -s %s/" % \
156                         (string.join(b.files), rpm_cache_dir, rpm_cache_dir),
157                      logfile = b.logfile, user = "root"
158             )
159         else:
160             ll("test-build: not copying to " + rpm_cache_dir)
161         ll("Begin-PLD-Builder-Info")
162         if "upgrade" in r.flags:
163             b.upgraded = install.upgrade_from_batch(r, b)
164         else:
165             ll("not upgrading")
166         ll("End-PLD-Builder-Info")
167
168     for f in b.files:
169         local = r.tmp_dir + os.path.basename(f)
170         chroot.cp(f, outfile = local, rm = True)
171         ftp.add(local)
172
173     def uploadinfo(b):
174         c="file:SRPMS:%s\n" % b.src_rpm
175         for f in b.files:
176             c=c + "file:ARCH:%s\n" % os.path.basename(f)
177         c=c + "END\n"
178         return c
179
180     if config.gen_upinfo and b.files != [] and 'test-build' not in r.flags:
181         fname = r.tmp_dir + b.src_rpm + ".uploadinfo"
182         f = open(fname, "w")
183         f.write(uploadinfo(b))
184         f.close()
185         ftp.add(fname, "uploadinfo")
186
187     status.pop()
188
189     return res
190
191 def handle_request(r):
192     ftp.init(r)
193     buildlogs.init(r)
194     build.build_all(r, build_rpm)
195     report.send_report(r, is_src = False)
196     ftp.flush()
197     notify.send(r)
198
199 def check_load():
200     do_exit = 0
201     try:
202         f = open("/proc/loadavg")
203         if float(string.split(f.readline())[2]) > config.max_load:
204             do_exit = 1
205     except:
206         pass
207     if do_exit:
208         sys.exit(0)
209
210 def main_for(builder):
211     msg = ""
212
213     init_conf(builder)
214
215     q = B_Queue(path.queue_file + "-" + config.builder)
216     q.lock(0)
217     q.read()
218     if q.requests == []:
219         q.unlock()
220         return
221     req = pick_request(q)
222     q.unlock()
223
224     # high priority tasks have priority < 0, normal tasks >= 0
225     if req.priority >= 0:
226
227         # allow only one build in given builder at once
228         if not lock.lock("building-rpm-for-%s" % config.builder, non_block = 1):
229             return
230         # don't kill server
231         check_load()
232         # not more then job_slots builds at once
233         locked = 0
234         for slot in range(config.job_slots):
235             if lock.lock("building-rpm-slot-%d" % slot, non_block = 1):
236                 locked = 1
237                 break
238         if not locked:
239             return
240
241         # record fact that we got lock for this builder, load balancer
242         # will use it for fair-queuing
243         l = lock.lock("got-lock")
244         f = open(path.got_lock_file, "a")
245         f.write(config.builder + "\n")
246         f.close()
247         l.close()
248     else:
249         msg = "HIGH PRIORITY: "
250     
251     msg += "handling request %s (%d) for %s from %s, priority %s" \
252             % (req.id, req.no, config.builder, req.requester, req.priority)
253     log.notice(msg)
254     status.push(msg)
255     handle_request(req)
256     status.pop()
257
258     def otherreqs(r):
259         if r.no==req.no:
260             return False
261         else:
262             return True
263
264     q = B_Queue(path.queue_file + "-" + config.builder)
265     q.lock(0)
266     q.read()
267     previouslen=len(q.requests)
268     q.requests=filter(otherreqs, q.requests)
269     if len(q.requests)<previouslen:
270         q.write()
271     q.unlock()
272     
273 def main():
274     if len(sys.argv) < 2:
275         raise Exception, "fatal: need to have builder name as first arg"
276     return main_for(sys.argv[1])
277     
278 if __name__ == '__main__':
279     loop.run_loop(main)
This page took 0.065709 seconds and 4 git commands to generate.