]> TLD Linux GIT Repositories - TLD.git/blobdiff - pld-builder.new/PLD_Builder/request_handler.py
- from https://github.com/pld-linux/pld-builder.new
[TLD.git] / pld-builder.new / PLD_Builder / request_handler.py
diff --git a/pld-builder.new/PLD_Builder/request_handler.py b/pld-builder.new/PLD_Builder/request_handler.py
new file mode 100644 (file)
index 0000000..2c38e83
--- /dev/null
@@ -0,0 +1,203 @@
+# vi: encoding=utf-8 ts=8 sts=4 sw=4 et
+
+import email
+import string
+import time
+import os
+import StringIO
+import sys
+import fnmatch
+
+import gpg
+import request
+import log
+import path
+import util
+import wrap
+import status
+from acl import acl
+from lock import lock
+from bqueue import B_Queue
+from config import config, init_conf
+
+def check_double_id(id):
+    id_nl = id + "\n"
+
+    ids = open(path.processed_ids_file)
+    for i in ids.xreadlines():
+        if i == id_nl:
+            # FIXME: security email here?
+            log.alert("request %s already processed" % id)
+            return 1
+    ids.close()
+
+    ids = open(path.processed_ids_file, "a")
+    ids.write(id_nl)
+    ids.close()
+
+    return 0
+
+def handle_group(r, user):
+    lockf = None
+    def fail_mail(msg):
+        if len(r.batches) >= 1:
+            spec = r.batches[0].spec
+        else:
+            spec = "None.spec"
+        log.error("%s: %s" % (spec, msg))
+        m = user.message_to()
+        m.set_headers(subject = "building %s failed" % spec)
+        m.write_line(msg)
+        m.send()
+
+    lockf = lock("request")
+    if check_double_id(r.id):
+        lockf.close()
+        return
+
+    for batch in r.batches:
+
+        if not user.can_do("src", config.builder, batch.branch):
+            fail_mail("user %s is not allowed to src:%s:%s" \
+                        % (user.get_login(), config.builder, batch.branch))
+            lockf.close()
+            return
+
+        if 'test-build' in r.flags and 'upgrade' in r.flags:
+            fail_mail("it's forbidden to upgrade from a test build")
+            lockf.close()
+            return
+
+        if "upgrade" in r.flags and not user.can_do("upgrade", config.builder, batch.branch):
+            fail_mail("user %s is not allowed to upgrade:%s:%s" \
+                        % (user.get_login(), config.builder, batch.branch))
+            lockf.close()
+            return
+
+        # src builder handles only special commands
+        if batch.is_command() and (batch.command in ["git pull"] or batch.command[:5] == "skip:"  or config.builder in batch.builders):
+            batch.expand_builders(config.binary_builders + [config.src_builder])
+        else:
+            batch.expand_builders(config.binary_builders)
+
+        if not batch.is_command() and config.builder in batch.builders:
+            batch.builders.remove(config.builder)
+
+        for bld in batch.builders:
+            batch.builders_status[bld] = '?'
+            batch.builders_status_time[bld] = time.time()
+            if bld not in config.binary_builders and bld != config.builder:
+                fail_mail("I (src rpm builder '%s') do not handle binary builder '%s', only '%s'" % \
+                        (config.builder, bld, string.join(config.binary_builders)))
+                lockf.close()
+                return
+            if batch.is_command():
+                if "no-chroot" in batch.command_flags:
+                    if not user.can_do("command-no-chroot", bld):
+                        fail_mail("user %s is not allowed to command-no-chroot:%s" \
+                                % (user.get_login(), bld))
+                        lockf.close()
+                        return
+                if not user.can_do("command", bld):
+                    fail_mail("user %s is not allowed to command:%s" \
+                                % (user.get_login(), bld))
+                    lockf.close()
+                    return
+            elif not user.can_do("binary", bld, batch.branch):
+                pkg = batch.spec
+                if pkg.endswith(".spec"):
+                    pkg = pkg[:-5]
+                if not user.can_do("binary-" + pkg, bld, batch.branch):
+                    fail_mail("user %s is not allowed to binary-%s:%s:%s" \
+                                % (user.get_login(), pkg, bld, batch.branch))
+                    lockf.close()
+                    return
+
+    r.priority = user.check_priority(r.priority,config.builder)
+    r.requester = user.get_login()
+    r.requester_email = user.mail_to()
+    r.time = time.time()
+    log.notice("queued %s from %s" % (r.id, user.get_login()))
+    q = B_Queue(path.queue_file)
+    q.lock(0)
+    q.read()
+    q.add(r)
+    q.write()
+    q.unlock()
+    lockf.close()
+
+def handle_notification(r, user):
+    if not user.can_do("notify", r.builder):
+        log.alert("user %s is not allowed to notify:%s" % (user.login, r.builder))
+    q = B_Queue(path.req_queue_file)
+    q.lock(0)
+    q.read()
+    not_fin = filter(lambda (r): not r.is_done(), q.requests)
+    r.apply_to(q)
+    for r in not_fin:
+        if r.is_done():
+            util.clean_tmp(path.srpms_dir + '/' + r.id)
+    now = time.time()
+    def leave_it(r):
+        # for ,,done'' set timeout to 4d
+        if r.is_done() and r.time + 4 * 24 * 60 * 60 < now:
+            return False
+        # and for not ,,done'' set it to 20d
+        if r.time + 20 * 24 * 60 * 60 < now:
+            util.clean_tmp(path.srpms_dir + '/' + r.id)
+            return False
+        return True
+    q.requests = filter(leave_it, q.requests)
+    q.write()
+    q.dump(path.queue_stats_file)
+    q.dump_html(path.queue_html_stats_file)
+    q.write_signed(path.req_queue_signed_file)
+    q.unlock()
+
+def handle_request(req, filename = None):
+    if req == '':
+        log.alert('Empty body received. Filename: %s' % filename)
+        return False
+
+    keys = gpg.get_keys(req)
+    (em, body) = gpg.verify_sig(req)
+    if not em:
+        log.alert("Invalid signature, missing/untrusted key. Keys in gpg batch: '%s'" % keys)
+        return False
+    user = acl.user_by_email(em)
+    if user == None:
+        # FIXME: security email here
+        log.alert("'%s' not in acl. Keys in gpg batch: '%s'" % (em, keys))
+        return False
+
+    acl.set_current_user(user)
+    status.push("request from %s" % user.login)
+    r = request.parse_request(body)
+    if r.kind == 'group':
+        handle_group(r, user)
+    elif r.kind == 'notification':
+        handle_notification(r, user)
+    else:
+        msg = "%s: don't know how to handle requests of this kind '%s'" \
+                        % (user.get_login(), r.kind)
+        log.alert(msg)
+        m = user.message_to()
+        m.set_headers(subject = "unknown request")
+        m.write_line(msg)
+        m.send()
+    status.pop()
+    return True
+
+def handle_request_main(req, filename = None):
+    acl.try_reload()
+    init_conf("src")
+    status.push("handling email request")
+    ret = handle_request(req, filename = filename)
+    status.pop()
+    return ret
+
+def main():
+    sys.exit(not handle_request_main(sys.stdin.read()))
+
+if __name__ == '__main__':
+    wrap.wrap(main)