]>
Commit | Line | Data |
---|---|---|
dfff8bd5 MM |
1 | # vi: encoding=utf-8 ts=8 sts=4 sw=4 et |
2 | ||
57b6e61d MM |
3 | import email |
4 | import string | |
5 | import time | |
6 | import os | |
7 | import StringIO | |
cc94eb63 | 8 | import sys |
91f92271 | 9 | import fnmatch |
57b6e61d MM |
10 | |
11 | import gpg | |
12 | import request | |
13 | import log | |
14 | import path | |
c8782384 | 15 | import util |
6b44a683 | 16 | import wrap |
bdc3292c | 17 | import status |
57b6e61d MM |
18 | from acl import acl |
19 | from lock import lock | |
20 | from bqueue import B_Queue | |
b5a39692 | 21 | from config import config, init_conf |
57b6e61d MM |
22 | |
23 | def check_double_id(id): | |
dfff8bd5 | 24 | id_nl = id + "\n" |
e6376553 | 25 | |
dfff8bd5 MM |
26 | ids = open(path.processed_ids_file) |
27 | for i in ids.xreadlines(): | |
28 | if i == id_nl: | |
29 | # FIXME: security email here? | |
30 | log.alert("request %s already processed" % id) | |
31 | return 1 | |
32 | ids.close() | |
e6376553 | 33 | |
dfff8bd5 MM |
34 | ids = open(path.processed_ids_file, "a") |
35 | ids.write(id_nl) | |
36 | ids.close() | |
57b6e61d | 37 | |
dfff8bd5 | 38 | return 0 |
57b6e61d | 39 | |
34738db3 | 40 | def handle_group(r, user): |
e1389e9c | 41 | lockf = None |
dfff8bd5 MM |
42 | def fail_mail(msg): |
43 | if len(r.batches) >= 1: | |
44 | spec = r.batches[0].spec | |
45 | else: | |
46 | spec = "None.spec" | |
47 | log.error("%s: %s" % (spec, msg)) | |
48 | m = user.message_to() | |
49 | m.set_headers(subject = "building %s failed" % spec) | |
50 | m.write_line(msg) | |
51 | m.send() | |
e6376553 | 52 | |
e1389e9c | 53 | lockf = lock("request") |
dfff8bd5 | 54 | if check_double_id(r.id): |
e1389e9c | 55 | lockf.close() |
dfff8bd5 | 56 | return |
91f92271 | 57 | |
dfff8bd5 | 58 | for batch in r.batches: |
897f56ee | 59 | |
dfff8bd5 MM |
60 | if not user.can_do("src", config.builder, batch.branch): |
61 | fail_mail("user %s is not allowed to src:%s:%s" \ | |
62 | % (user.get_login(), config.builder, batch.branch)) | |
e1389e9c | 63 | lockf.close() |
dfff8bd5 | 64 | return |
d2c1ec3f | 65 | |
e936beda MM |
66 | if 'test-build' in r.flags and 'upgrade' in r.flags: |
67 | fail_mail("it's forbidden to upgrade from a test build") | |
e1389e9c | 68 | lockf.close() |
e936beda MM |
69 | return |
70 | ||
dfff8bd5 MM |
71 | if "upgrade" in r.flags and not user.can_do("upgrade", config.builder, batch.branch): |
72 | fail_mail("user %s is not allowed to upgrade:%s:%s" \ | |
73 | % (user.get_login(), config.builder, batch.branch)) | |
e1389e9c | 74 | lockf.close() |
dfff8bd5 | 75 | return |
d2c1ec3f | 76 | |
07db6665 | 77 | # src builder handles only special commands |
a72a1c1c | 78 | if batch.is_command() and (batch.command in ["git pull"] or batch.command[:5] == "skip:" or config.builder in batch.builders): |
07db6665 AM |
79 | batch.expand_builders(config.binary_builders + [config.src_builder]) |
80 | else: | |
81 | batch.expand_builders(config.binary_builders) | |
82 | ||
dfff8bd5 MM |
83 | if not batch.is_command() and config.builder in batch.builders: |
84 | batch.builders.remove(config.builder) | |
07db6665 | 85 | |
dfff8bd5 MM |
86 | for bld in batch.builders: |
87 | batch.builders_status[bld] = '?' | |
1432ffd5 | 88 | batch.builders_status_time[bld] = time.time() |
dfff8bd5 MM |
89 | if bld not in config.binary_builders and bld != config.builder: |
90 | fail_mail("I (src rpm builder '%s') do not handle binary builder '%s', only '%s'" % \ | |
9e8a7e70 | 91 | (config.builder, bld, string.join(config.binary_builders))) |
e1389e9c | 92 | lockf.close() |
dfff8bd5 MM |
93 | return |
94 | if batch.is_command(): | |
e242bc52 AM |
95 | if "no-chroot" in batch.command_flags: |
96 | if not user.can_do("command-no-chroot", bld): | |
97 | fail_mail("user %s is not allowed to command-no-chroot:%s" \ | |
98 | % (user.get_login(), bld)) | |
99 | lockf.close() | |
100 | return | |
dfff8bd5 MM |
101 | if not user.can_do("command", bld): |
102 | fail_mail("user %s is not allowed to command:%s" \ | |
103 | % (user.get_login(), bld)) | |
e1389e9c | 104 | lockf.close() |
dfff8bd5 MM |
105 | return |
106 | elif not user.can_do("binary", bld, batch.branch): | |
107 | pkg = batch.spec | |
108 | if pkg.endswith(".spec"): | |
109 | pkg = pkg[:-5] | |
110 | if not user.can_do("binary-" + pkg, bld, batch.branch): | |
111 | fail_mail("user %s is not allowed to binary-%s:%s:%s" \ | |
112 | % (user.get_login(), pkg, bld, batch.branch)) | |
e1389e9c | 113 | lockf.close() |
dfff8bd5 | 114 | return |
e5e1ca0e KK |
115 | if not "test-build" in r.flags and not user.can_do("ready", bld, batch.branch): |
116 | fail_mail("user %s is not allowed to send ready builds (ready:%s:%s)" \ | |
117 | % (user.get_login(), bld, batch.branch)) | |
118 | lockf.close() | |
119 | return | |
e6376553 | 120 | |
dfff8bd5 MM |
121 | r.priority = user.check_priority(r.priority,config.builder) |
122 | r.requester = user.get_login() | |
123 | r.requester_email = user.mail_to() | |
124 | r.time = time.time() | |
125 | log.notice("queued %s from %s" % (r.id, user.get_login())) | |
126 | q = B_Queue(path.queue_file) | |
127 | q.lock(0) | |
128 | q.read() | |
129 | q.add(r) | |
130 | q.write() | |
131 | q.unlock() | |
e1389e9c | 132 | lockf.close() |
57b6e61d | 133 | |
59ce7cd6 | 134 | def handle_notification(r, user): |
dfff8bd5 MM |
135 | if not user.can_do("notify", r.builder): |
136 | log.alert("user %s is not allowed to notify:%s" % (user.login, r.builder)) | |
137 | q = B_Queue(path.req_queue_file) | |
138 | q.lock(0) | |
139 | q.read() | |
140 | not_fin = filter(lambda (r): not r.is_done(), q.requests) | |
141 | r.apply_to(q) | |
142 | for r in not_fin: | |
143 | if r.is_done(): | |
9be34149 | 144 | util.clean_tmp(path.srpms_dir + '/' + r.id) |
dfff8bd5 MM |
145 | now = time.time() |
146 | def leave_it(r): | |
147 | # for ,,done'' set timeout to 4d | |
148 | if r.is_done() and r.time + 4 * 24 * 60 * 60 < now: | |
149 | return False | |
150 | # and for not ,,done'' set it to 20d | |
151 | if r.time + 20 * 24 * 60 * 60 < now: | |
9be34149 | 152 | util.clean_tmp(path.srpms_dir + '/' + r.id) |
dfff8bd5 MM |
153 | return False |
154 | return True | |
155 | q.requests = filter(leave_it, q.requests) | |
156 | q.write() | |
8d15cbfe AM |
157 | q.dump(path.queue_stats_file) |
158 | q.dump_html(path.queue_html_stats_file) | |
89ad1c79 | 159 | q.write_signed(path.req_queue_signed_file) |
dfff8bd5 | 160 | q.unlock() |
59ce7cd6 | 161 | |
f02c1e4d AM |
162 | def handle_request(req, filename = None): |
163 | if req == '': | |
c1ad9456 ER |
164 | log.alert('Empty body received. Filename: %s' % filename) |
165 | return False | |
166 | ||
8736fafd | 167 | keys = gpg.get_keys(req) |
f02c1e4d | 168 | (em, body) = gpg.verify_sig(req) |
8736fafd | 169 | if not em: |
030fb437 | 170 | log.alert("Invalid signature, missing/untrusted key. Keys in gpg batch: '%s'" % keys) |
8736fafd | 171 | return False |
dfff8bd5 MM |
172 | user = acl.user_by_email(em) |
173 | if user == None: | |
174 | # FIXME: security email here | |
8736fafd | 175 | log.alert("'%s' not in acl. Keys in gpg batch: '%s'" % (em, keys)) |
f6eb7039 | 176 | return False |
b5e0afc4 | 177 | |
dfff8bd5 | 178 | acl.set_current_user(user) |
db286098 | 179 | status.push("request from %s" % user.login) |
dfff8bd5 MM |
180 | r = request.parse_request(body) |
181 | if r.kind == 'group': | |
182 | handle_group(r, user) | |
183 | elif r.kind == 'notification': | |
184 | handle_notification(r, user) | |
185 | else: | |
186 | msg = "%s: don't know how to handle requests of this kind '%s'" \ | |
187 | % (user.get_login(), r.kind) | |
188 | log.alert(msg) | |
189 | m = user.message_to() | |
190 | m.set_headers(subject = "unknown request") | |
191 | m.write_line(msg) | |
192 | m.send() | |
193 | status.pop() | |
f6eb7039 | 194 | return True |
cc94eb63 | 195 | |
f02c1e4d | 196 | def handle_request_main(req, filename = None): |
e3e3d74f | 197 | acl.try_reload() |
dfff8bd5 MM |
198 | init_conf("src") |
199 | status.push("handling email request") | |
f02c1e4d | 200 | ret = handle_request(req, filename = filename) |
dfff8bd5 | 201 | status.pop() |
63319e0a AM |
202 | return ret |
203 | ||
204 | def main(): | |
f02c1e4d | 205 | sys.exit(not handle_request_main(sys.stdin.read())) |
1f62bccc | 206 | |
e8ee9db8 | 207 | if __name__ == '__main__': |
dfff8bd5 | 208 | wrap.wrap(main) |