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