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