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