]>
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 MM |
24 | id_nl = id + "\n" |
25 | ||
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() | |
33 | ||
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): |
dfff8bd5 MM |
41 | def fail_mail(msg): |
42 | if len(r.batches) >= 1: | |
43 | spec = r.batches[0].spec | |
44 | else: | |
45 | spec = "None.spec" | |
46 | log.error("%s: %s" % (spec, msg)) | |
47 | m = user.message_to() | |
48 | m.set_headers(subject = "building %s failed" % spec) | |
49 | m.write_line(msg) | |
50 | m.send() | |
57b6e61d | 51 | |
dfff8bd5 MM |
52 | lock("request") |
53 | if check_double_id(r.id): | |
54 | return | |
55 | ||
91f92271 | 56 | |
dfff8bd5 MM |
57 | for batch in r.batches: |
58 | if not user.can_do("src", config.builder, batch.branch): | |
59 | fail_mail("user %s is not allowed to src:%s:%s" \ | |
60 | % (user.get_login(), config.builder, batch.branch)) | |
61 | return | |
d2c1ec3f | 62 | |
e936beda MM |
63 | if 'test-build' in r.flags and 'upgrade' in r.flags: |
64 | fail_mail("it's forbidden to upgrade from a test build") | |
65 | return | |
66 | ||
dfff8bd5 MM |
67 | if "upgrade" in r.flags and not user.can_do("upgrade", config.builder, batch.branch): |
68 | fail_mail("user %s is not allowed to upgrade:%s:%s" \ | |
69 | % (user.get_login(), config.builder, batch.branch)) | |
70 | return | |
d2c1ec3f | 71 | |
dfff8bd5 MM |
72 | batch.expand_builders(config.binary_builders) |
73 | if not batch.is_command() and config.builder in batch.builders: | |
74 | batch.builders.remove(config.builder) | |
75 | for bld in batch.builders: | |
76 | batch.builders_status[bld] = '?' | |
77 | if bld not in config.binary_builders and bld != config.builder: | |
78 | fail_mail("I (src rpm builder '%s') do not handle binary builder '%s', only '%s'" % \ | |
9e8a7e70 | 79 | (config.builder, bld, string.join(config.binary_builders))) |
dfff8bd5 MM |
80 | return |
81 | if batch.is_command(): | |
82 | if not user.can_do("command", bld): | |
83 | fail_mail("user %s is not allowed to command:%s" \ | |
84 | % (user.get_login(), bld)) | |
85 | return | |
86 | elif not user.can_do("binary", bld, batch.branch): | |
87 | pkg = batch.spec | |
88 | if pkg.endswith(".spec"): | |
89 | pkg = pkg[:-5] | |
90 | if not user.can_do("binary-" + pkg, bld, batch.branch): | |
91 | fail_mail("user %s is not allowed to binary-%s:%s:%s" \ | |
92 | % (user.get_login(), pkg, bld, batch.branch)) | |
93 | return | |
94 | ||
95 | r.priority = user.check_priority(r.priority,config.builder) | |
96 | r.requester = user.get_login() | |
97 | r.requester_email = user.mail_to() | |
98 | r.time = time.time() | |
99 | log.notice("queued %s from %s" % (r.id, user.get_login())) | |
100 | q = B_Queue(path.queue_file) | |
101 | q.lock(0) | |
102 | q.read() | |
103 | q.add(r) | |
104 | q.write() | |
105 | q.unlock() | |
57b6e61d | 106 | |
59ce7cd6 | 107 | def handle_notification(r, user): |
dfff8bd5 MM |
108 | if not user.can_do("notify", r.builder): |
109 | log.alert("user %s is not allowed to notify:%s" % (user.login, r.builder)) | |
110 | q = B_Queue(path.req_queue_file) | |
111 | q.lock(0) | |
112 | q.read() | |
113 | not_fin = filter(lambda (r): not r.is_done(), q.requests) | |
114 | r.apply_to(q) | |
115 | for r in not_fin: | |
116 | if r.is_done(): | |
117 | util.clean_tmp(path.srpms_dir + r.id) | |
118 | now = time.time() | |
119 | def leave_it(r): | |
120 | # for ,,done'' set timeout to 4d | |
121 | if r.is_done() and r.time + 4 * 24 * 60 * 60 < now: | |
122 | return False | |
123 | # and for not ,,done'' set it to 20d | |
124 | if r.time + 20 * 24 * 60 * 60 < now: | |
125 | util.clean_tmp(path.srpms_dir + r.id) | |
126 | return False | |
127 | return True | |
128 | q.requests = filter(leave_it, q.requests) | |
129 | q.write() | |
130 | q.dump(open(path.queue_stats_file, "w")) | |
131 | q.dump_html(open(path.queue_html_stats_file, "w")) | |
132 | os.chmod(path.queue_html_stats_file, 0644) | |
133 | os.chmod(path.queue_stats_file, 0644) | |
134 | q.unlock() | |
59ce7cd6 | 135 | |
57b6e61d | 136 | def handle_request(f): |
dfff8bd5 MM |
137 | sio = StringIO.StringIO() |
138 | util.sendfile(f, sio) | |
139 | sio.seek(0) | |
140 | (em, body) = gpg.verify_sig(sio) | |
141 | user = acl.user_by_email(em) | |
142 | if user == None: | |
143 | # FIXME: security email here | |
144 | log.alert("invalid signature, or not in acl %s" % em) | |
f6eb7039 | 145 | return False |
dfff8bd5 MM |
146 | acl.set_current_user(user) |
147 | status.push("email from %s" % user.login) | |
148 | r = request.parse_request(body) | |
149 | if r.kind == 'group': | |
150 | handle_group(r, user) | |
151 | elif r.kind == 'notification': | |
152 | handle_notification(r, user) | |
153 | else: | |
154 | msg = "%s: don't know how to handle requests of this kind '%s'" \ | |
155 | % (user.get_login(), r.kind) | |
156 | log.alert(msg) | |
157 | m = user.message_to() | |
158 | m.set_headers(subject = "unknown request") | |
159 | m.write_line(msg) | |
160 | m.send() | |
161 | status.pop() | |
f6eb7039 | 162 | return True |
cc94eb63 | 163 | |
63319e0a | 164 | def handle_request_main(stream): |
dfff8bd5 MM |
165 | init_conf("src") |
166 | status.push("handling email request") | |
63319e0a | 167 | ret = handle_request(stream) |
dfff8bd5 | 168 | status.pop() |
63319e0a AM |
169 | return ret |
170 | ||
171 | def main(): | |
172 | sys.exit(not handle_request_main(sys.stdin)) | |
1f62bccc | 173 | |
e8ee9db8 | 174 | if __name__ == '__main__': |
dfff8bd5 | 175 | wrap.wrap(main) |