]> git.pld-linux.org Git - projects/pld-builder.new.git/commitdiff
- preparing for real operation testing
authorMichal Moskal <michal@moskal.me>
Thu, 12 Jun 2003 14:04:21 +0000 (14:04 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
- but not tested at all yet :-)

Changed files:
    PLD_Builder/bqueue.py -> 1.4
    PLD_Builder/buildlogs.py -> 1.7
    PLD_Builder/config.py -> 1.10
    PLD_Builder/file_sender.py -> 1.3
    PLD_Builder/gpg.py -> 1.6
    PLD_Builder/log.py -> 1.4
    PLD_Builder/mailer.py -> 1.4
    PLD_Builder/notify.py -> 1.1
    PLD_Builder/path.py -> 1.8
    PLD_Builder/request.py -> 1.8
    PLD_Builder/request_handler.py -> 1.10
    PLD_Builder/rpm_builder.py -> 1.4
    PLD_Builder/srpm_builder.py -> 1.10
    config/acl.conf -> 1.3
    config/builder.conf -> 1.7
    doc/TODO -> 1.8

16 files changed:
PLD_Builder/bqueue.py
PLD_Builder/buildlogs.py
PLD_Builder/config.py
PLD_Builder/file_sender.py
PLD_Builder/gpg.py
PLD_Builder/log.py
PLD_Builder/mailer.py
PLD_Builder/notify.py [new file with mode: 0644]
PLD_Builder/path.py
PLD_Builder/request.py
PLD_Builder/request_handler.py
PLD_Builder/rpm_builder.py
PLD_Builder/srpm_builder.py
config/acl.conf
config/builder.conf
doc/TODO

index 062a5b9dbe7fe67c40714d12f30d0b7bd1027115..99f099ca246ab79e92a72f8b76f0b75f7a056db4 100644 (file)
@@ -15,6 +15,10 @@ class B_Queue:
     self.name = filename
     self.requests = []
     self.fd = None
+
+  def dump(self, f):
+    for r in self.requests:
+      r.dump(f)
   
   # read possibly compressed, signed queue
   def read_signed(self):
index f5c4dd214f341eea639b5f219f28e2a3bc6d7515..ede545559e7a5fe785a157dd1eef1117dc9be6a9 100644 (file)
@@ -19,21 +19,23 @@ class Buildlogs_Queue:
     id = util.uuid()
     os.system("bzip2 --best --force < %s > %s" \
                 % (logfile, path.buildlogs_queue_dir + id))
+
+    if l['failed']: s = "FAIL"
+    else: s = "OK"
+    f = open(path.buildlogs_queue_dir + id + ".info", "w")
+    f.write("Status: %s\nEND\n" % s)
+    f.close()
+
     self.queue.append({'name': name, 'id': id, 'failed': failed})
 
   def flush(self):
     def desc(l):
-      if l['failed']: s = "FAIL"
-      elif self.some_failed: s = "OKOF" # OK but Others Failed
-      else: s = "OK"
       return """Target: %s/%s
 Builder: %s
-Status: %s
-Store-desc: yes
 Time: %d
 Requester: %s
 END
-""" % (config.buildlogs_url, l['name'], config.builder, s, time.time(), acl.current_user)
+""" % (config.buildlogs_url, l['name'], config.builder, time.time(), acl.current_user)
     
     for l in self.queue:
       f = open(path.buildlogs_queue_dir + l['id'] + ".desc", "w")
index 09634f123b23910afa07cc4717198ecd1bd42be4..cf6f7ea5e0bbb20d7038cc7a4dbb64ad23f3abd2 100644 (file)
@@ -23,13 +23,18 @@ class Builder_Conf:
       else:
         log.panic("cannot find %s::%s" % (builder, o))
         
+    if builder == "src":
+      self.builder = get("src_builder", builder)
+    else
+      self.builder = builder
+
     p.readfp(open(path.builder_conf))
     self.builders = string.split(get("builders"))
     self.control_url = get("control_url")
     self.queue_signed_by = get("queue_signed_by")
+    self.notify_email = get("notify_email")
     self.admin_email = get("admin_email")
     self.email = self.admin_email
-    self.builder = builder
 
     if builder == "all":
       return
@@ -54,4 +59,5 @@ def init_conf(builder):
   log.builder = builder
   if builder == "": builder = "all"
   config.read(builder)
+  log.builder = config.builder
   status.pop()
index cb00e615260f9d97e774974276c044d96b6a5148..941ee5b73110f1363d003a7712dcd63389b74709 100644 (file)
@@ -115,8 +115,8 @@ def flush_queue(dir):
     if send_file(d['_file'], d['Target']):
       error = d
       break
-    if d.has_key('Store-desc') and d['Store-desc'] == "yes":
-      if send_file(d['_desc'], d['Target'] + ".desc"):
+    if os.access(d['_file'] + ".info", os.F_OK):
+      if send_file(d['_file'] + ".info", d['Target'] + ".info"):
         error = d
         break
     os.unlink(d['_file'])
index 120643318547575b8ce88e27b9a63bad12bafbe2..864c3460f0fb136bebbbaa95abb694f196bad4d6 100644 (file)
@@ -29,7 +29,7 @@ def verify_sig(buf):
   return (emails, body)
 
 def sign(buf):
-  (gpg_out, gpg_in, gpg_err) = popen2.popen3("gpg --clearsign --default-key builder")
+  (gpg_out, gpg_in, gpg_err) = popen2.popen3("gpg --clearsign")
   util.sendfile(buf, gpg_in)
   gpg_in.close()
   body = StringIO.StringIO()
index c82eaa6ef6bba2e44457d61d9c8997c6636879ce..b57acbfc0c906bf7e4e12ab88bbb4b99e6afb2f6 100644 (file)
@@ -1,9 +1,14 @@
 import sys
+import time
+
+import path
 
 builder = ""
 
 def log(s):
-  sys.stderr.write("LOG[%s]: %s\n" % (builder, s))
+  f = open(path.log_file, "a")
+  f.stderr.write("%s [%s]: %s\n" % (time.asctime(), builder, s))
+  f.close()
   
 def alert(s):
   log("alert: %s" % s) 
index 80a8b09b9dced25ee1c102b547248a025779dfcd..8167711635c7c84ce04bbc050a2ddd53632ae719 100644 (file)
@@ -64,5 +64,6 @@ class Message:
     util.sendfile(self.body, f)
 
   def send(self):
-    # FIXME
-    self.write_to(sys.stdout)
+    f = os.popen("/usr/sbin/sendmail -t")
+    self.write_to(f)
+    f.close()
diff --git a/PLD_Builder/notify.py b/PLD_Builder/notify.py
new file mode 100644 (file)
index 0000000..e6ab481
--- /dev/null
@@ -0,0 +1,32 @@
+import StringIO
+
+import mailer
+import gpg
+
+class Notifier:
+  def __init__(self, g):
+    self.xml = StringIO.StringIO()
+    self.xml.write("<notification group-id='%s' builder='%s'>\n" % \
+                        (g.id, config.builder))
+  
+  def send():
+    self.xml.write("</notification>\n")
+    msg = mailer.Message()
+    msg.set_headers(to = config.notify_email, subject = "status notification")
+    msg.write(gpg.sign(self.xml))
+    msg.send()
+    self.xml = None
+  
+  def add_batch(b, s):
+    self.xml.write("  <batch id='%s' status='%s'>\n" % (b.b_id, s))
+  
+n = None
+
+def begin(group):
+  n = Notifier(group)
+
+def add_batch(batch, status):
+  n.add_batch(batch, status)
+
+def send():
+  n.send()
index c8282fe356e1db92837c0d678ce2216324e795c6..f105d3dedc59e92e6b7b5123d18a97fc6385e50a 100644 (file)
@@ -17,8 +17,10 @@ buildlogs_queue_dir = spool_dir + "buildlogs/"
 ftp_queue_dir = spool_dir + "ftp/"
 last_req_no_file = spool_dir + "last_req_no"
 got_lock_file = spool_dir + "got_lock"
+log_file = spool_dir + "log"
 
 # www/
 srpms_dir = www_dir + "srpms/"
 req_queue_signed_file = www_dir + "queue.gz"
 max_req_no_file = www_dir + "max_req_no"
+queue_state_file = www_dir + "queue.txt"
index 9a144723a93b1b9607db618b3ae31a05fd2b847e..5a6aa19d433b00502ba16b4303216fe43b497a1a 100644 (file)
@@ -10,6 +10,7 @@ import path
 import util
 import chroot
 from acl import acl
+import notify
 
 __all__ = ['parse_request', 'parse_requests']
   
@@ -72,12 +73,12 @@ class Group:
           raise "xml: dependency not found in group"
       b.depends_on = deps
 
-  def dump(self):
-    print "group: %s @%d" % (self.id, self.priority)
-    print "  from: %s" % self.requester
-    print "  time: %s" % time.asctime(time.localtime(self.time))
+  def dump(self, f):
+    f.write("group: %d (id=%s pri=%d)\n" % (self.no, self.id, self.priority))
+    f.write("  from: %s\n" % self.requester)
+    f.write("  time: %s\n" % time.asctime(time.localtime(self.time)))
     for b in self.batches:
-      b.dump()
+      b.dump(f)
 
   def write_to(self, f):
     f.write("""
@@ -91,6 +92,8 @@ class Group:
     f.write("       </group>\n\n")
 
   def build_all(r, build_fnc):
+    notify.begin(r)
+
     tmp = path.spool_dir + util.uuid() + "/"
     r.tmp_dir = tmp
     os.mkdir(tmp)
@@ -113,14 +116,17 @@ class Group:
         batch.build_failed = build_fnc(r, batch)
         if batch.build_failed:
           log.notice("building %s FAILED" % batch.spec)
+          notify.add_batch(batch, "FAIL")
         else:
           r.some_ok = 1
           log.notice("building %s OK" % batch.spec)
+          notify.add_batch(batch, "OK")
       else:
         batch.build_failed = 1
         batch.skip_reason = "SKIPED [%s failed]" % failed_dep
         batch.logfile = None
         log.notice("building %s %s" % (batch.spec, batch.skip_reason))
+        notify.add_batch(batch, "SKIP")
 
   def clean_files(r):
     chroot.run("rm -f %s" % string.join(r.chroot_files))
@@ -156,6 +162,13 @@ class Group:
         
     m.send()
 
+  def is_done(self):
+    ok = 1
+    for b in self.batches:
+      if not b.is_done():
+        ok = 0
+    return ok
+
 class Batch:
   def __init__(self, e):
     self.bconds_with = []
@@ -181,19 +194,31 @@ class Batch:
         self.branch = text(c)
       elif c.nodeName == "builder":
         self.builders.append(text(c))
+        self.builders_status[text(c)] = attr(c, "status", "?")
       elif c.nodeName == "with":
         self.bconds_with.append(text(c))
       elif c.nodeName == "without":
         self.bconds_without.append(text(c))
       else:
         raise "xml: evil batch child (%s)" % c.nodeName
-  
-  def dump(self):
-    print "  batch: %s/%s" % (self.src_rpm, self.spec)
-    print "    info: %s" % self.info
-    print "    branch: %s" % self.branch
-    print "    bconds: %s" % self.bconds_string()
-    print "    for: %s" % string.join(self.builders)
+  def is_done(self):
+    ok = 1
+    for b in self.builders:
+      s = self.builders_status[b]
+      if not (s == "OK" or s == "FAIL" or s == "SKIP"):
+        ok = 0
+    return ok
+      
+  def dump(self, f):
+    f.write("  batch: %s/%s\n" % (self.src_rpm, self.spec))
+    f.write("    info: %s\n" % self.info)
+    f.write("    branch: %s\n" % self.branch)
+    f.write("    bconds: %s\n" % self.bconds_string())
+    builders = []
+    for b in self.builders:
+      builders.append("%s:%s" % (b, self.builders_status[b]))
+    f.write("    builders: %s\n" % string.join(builders))
 
   def bconds_string(self):
     r = ""
@@ -218,14 +243,44 @@ class Batch:
     for b in self.bconds_without:
       f.write("           <without>%s</without>\n" % escape(b))
     for b in self.builders:
-      f.write("           <builder>%s</builder>\n" % escape(b))
+      f.write("           <builder status='%s'>%s</builder>\n" % \
+                        (escape(self.builders_status[b]), escape(b)))
     f.write("         </batch>\n")
 
+class Notification:
+  def __init__(self, e):
+    self.batches = []
+    self.kind = 'notification'
+    self.group_id = attr(e, "group-id")
+    self.builder = attr(e, "builder")
+    self.batches = {}
+    for c in e.childNodes:
+      if is_blank(c): continue
+      if c.nodeType != Element.ELEMENT_NODE:
+        raise "xml: evil notification child %d" % c.nodeType
+      if c.nodeName == "batch":
+        id = attr(e, "id")
+        status = attr(e, "status")
+        if status != "OK" and status != "FAIL" and status != "SKIP":
+          raise "xml notification: bad status: %s" % self.status
+        self.batches[id] = status
+      else:
+        raise "xml: evil notification child (%s)" % c.nodeName
+
+  def apply_to(self, q):
+    for r in q.requests:
+      if r.kind == "group":
+        for b in r.batches:
+          if self.batches.has_key(b.b_id):
+            b.builders_status[self.builder] = self.batches[b.b_id]
+
 def build_request(e):
   if e.nodeType != Element.ELEMENT_NODE:
     raise "xml: evil request element"
   if e.nodeName == "group":
     return Group(e)
+  elif e.nodeName == "notification":
+    return Notification(e)
   elif e.nodeName == "command":
     # FIXME
     return Command(e)
index 658de76dc5208b934a927b5fada738c9ced413a6..cc7698a83266a034e5519b4a8db33b3155f5aef8 100644 (file)
@@ -71,6 +71,25 @@ def handle_group(r, user):
   q.write()
   q.unlock()
 
+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():
+      clean_tmp(path.srpms_dir + r.id)
+  now = time.time()
+  def leave_it(r):
+    return not r.is_done() or r.time + 4 * 24 * 60 * 60 > now
+  q.requests = filter(leave_it, q.requests)
+  q.write()
+  q.dump(open(path.queue_stats_file, "w"))
+  q.unlock()
+
 def handle_request(f):
   sio = StringIO.StringIO()
   util.sendfile(f, sio)
@@ -85,6 +104,8 @@ def handle_request(f):
   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)
index 593e1d4eee792ff8f40a6f8367025ac5531aa813..45a14c420f8fdecb06e231dd70b81e19a1de142b 100644 (file)
@@ -15,6 +15,7 @@ import log
 import chroot
 import ftp
 import buildlogs
+import notify
 
 # this code is duplicated in srpm_builder, but we
 # might want to handle some cases differently here
@@ -97,6 +98,7 @@ def handle_request(r):
   r.send_report()
   buildlogs.flush()
   ftp.flush()
+  notify.send()
 
 def check_load():
   try:
index 7c4f25bd2e540c771893b726b676b17ec3002fdc..236af5459abdb6f00af18343a7b05fcdfa161598 100644 (file)
@@ -63,8 +63,9 @@ def store_binary_request(r):
   q.read()
   q.add(r)
   q.write()
-  q.unlock()
+  q.dump(open(path.queue_stats_file, "w"))
   q.write_signed(path.req_queue_signed_file)
+  q.unlock()
   cnt_f.seek(0)
   cnt_f.write("%d\n" % num)
   cnt_f.close()
index 783922f0ce343a4fbacb389ab8e5306106804308..9446ddf1afdc6ba2b180f3455a269d0ea675da10 100644 (file)
@@ -18,7 +18,8 @@
 #   shell wildcards.
 #
 # Actions:
-#   src    -- build src rpm (only makes sense in src:src)
+#   src    -- build src rpm (only makes sense if <which-builder> is src 
+#             builder)
 #   binary -- build binary rpm
 #   notify -- can send notification about build process on given builder.
 #             Used in entries for binary builders.
@@ -43,4 +44,4 @@ privs =
 
 [malekith]
 emails = malekith@roke.freak malekith@pld-linux.org
-privs = src:src binary:*
+privs = src:roke-src binary:roke-*
index 275b8e954cf5f4e3cf8fb7a3066b3dfec88d97af..935bfad3a0f91c1f419c91f21f2fcd97b4e86430 100644 (file)
@@ -1,27 +1,34 @@
 [all]
 # builder email (in From:)
 email = malekith@roke.freak
+admin_email = malekith@roke.freak
+
+# ------ Binary builders config:
 # how much jobs can be run at once
 job_slots = 1
 # maximal load, at which rpm processing can start
 max_load = 10.0
 # where to look for queue.gz and counter
 control_url = http://roke.freak/builder/
-# list of binary builders
-builders = athlon
 # login of user (from acl.conf) that should sign queue
-queue_signed_by = malekith
-#
-admin_email = malekith@roke.freak
+queue_signed_by = src_builder_roke
+# email where to send status notifications
+notify_email = srpms_builder@roke.freak
+
+# ------- Src builder config:
+# list of binary builders
+binary_builders = athlon
+# the only src builder
+src_builder = roke-src
 
-[src]
+[roke-src]
 arch = athlon
 chroot = /adm/chroot-src
-buildlogs_url = scp://malekith@roke.freak/home/services/ftpd/buildlogs/
-ftp_url = scp://malekith@roke.freak/home/services/ftpd/dists/nest/NEW/ready/SRPMS
+buildlogs_url = rsync://bl:foobar123@roke.freak/home/services/ftpd/buildlogs/nest/SRPMS/.new/
+ftp_url = scp://ftpadm@roke.freak/home/services/ftpd/dists/nest/ready/SRPMS
 
-[athlon]
+[roke-athlon]
 arch = athlon
 chroot = /adm/chroot-athlon
-buildlogs_url = scp://malekith@roke.freak/home/services/ftpd/buildlogs/
-ftp_url = scp://malekith@roke.freak/home/services/ftpd/dists/nest/NEW/ready/athlon
+buildlogs_url = rsync://bl:foobar123@roke.freak/home/services/ftpd/buildlogs/nest/athlon/.new/
+ftp_url = scp://ftpadm@roke.freak/home/services/ftpd/dists/nest/ready/athlon
index 76cb2917d98617648e318dbd8599743f82399fcf..5fb9ab837c650f38bec51ed2d1203b02806d6844 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,13 +1,8 @@
-- sending reports from binary to src builder, so it can update its queue and
-  clean srpms that ain't needed anymore
-  
 - store rpms in /spool/ready/ in chroot? (rpm_builder.py)
 
 - deps install/uninstall machinery (hard stuff -- building deps tree already 
   done)
 
-- make mailer.py actually send mail (easy)
-
 - fix make-request.sh to be more user-friendly and configurable
 
 - report time consumed by build
This page took 0.199563 seconds and 4 git commands to generate.