]> git.ipfire.org Git - ipfire.org.git/commitdiff
Checked in new build.ipfire.org.
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 30 Sep 2008 15:57:52 +0000 (17:57 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 30 Sep 2008 15:57:52 +0000 (17:57 +0200)
14 files changed:
build/build.py [deleted file]
build/builder.py [new file with mode: 0644]
build/config.py [new file with mode: 0644]
build/constants.py [new file with mode: 0644]
build/distcc.py [deleted file]
build/hosts [deleted file]
build/images/compiling.png [deleted file]
build/images/error.png [deleted file]
build/images/idle.png [deleted file]
build/images/unknown.png [deleted file]
build/index.py [new file with mode: 0644]
build/probe.c [deleted file]
build/rpc.py [new file with mode: 0644]
build/tmp/empty.txt [deleted file]

diff --git a/build/build.py b/build/build.py
deleted file mode 100644 (file)
index 0cade55..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-#!/usr/bin/python
-
-import os
-import time
-import cgi
-
-from stat import ST_MTIME
-from rhpl.simpleconfig import SimpleConfigFile
-
-DB_DIR = "db"
-
-def format_time(seconds, use_hours=1):
-       if seconds is None or seconds < 0:
-               if use_hours: return '--:--:--'
-               else:         return '--:--'
-       else:
-               seconds = int(seconds)
-               minutes = seconds / 60
-               seconds = seconds % 60
-               if use_hours:
-                       hours = minutes / 60
-                       minutes = minutes % 60
-                       return '%02i:%02i:%02i' % (hours, minutes, seconds)
-               else:
-                       return '%02i:%02i' % (minutes, seconds)
-
-def format_number(number, SI=0, space=' '):
-       """Turn numbers into human-readable metric-like numbers"""
-       symbols = ['',  # (none)
-                  'k', # kilo
-                  'M', # mega
-                  'G', # giga
-                  'T', # tera
-                  'P', # peta
-                  'E', # exa
-                  'Z', # zetta
-                  'Y'] # yotta
-    
-       if SI: step = 1000.0
-       else: step = 1024.0
-
-       thresh = 999
-       depth = 0
-       max_depth = len(symbols) - 1
-    
-       # we want numbers between 0 and thresh, but don't exceed the length
-       # of our list.  In that event, the formatting will be screwed up,
-       # but it'll still show the right number.
-       while number > thresh and depth < max_depth:
-               depth  = depth + 1
-               number = number / step
-
-       if type(number) == type(1) or type(number) == type(1L):
-               # it's an int or a long, which means it didn't get divided,
-               # which means it's already short enough
-               format = '%i%s%s'
-       elif number < 9.95:
-               # must use 9.95 for proper sizing.  For example, 9.99 will be
-               # rounded to 10.0 with the .1f format string (which is too long)
-               format = '%.1f%s%s'
-       else:
-               format = '%.0f%s%s'
-        
-       return(format % (float(number or 0), space, symbols[depth]))
-
-stage2desc = {
-       "unknown" : "Dunno what the host is doing at the moment...",
-       "compiling" : "The host is really hard working at the moment...",
-       "error" : "Oops! The host had an error...",
-       "idle" : "The host is idle at the moment...",
-}
-
-sys2desc = {
-       "CPU_NAME" : "CPU model",
-       "CPU_MIPS" : "Bogomips",
-       "CPU_MHZ"  : "CPU MHz",
-       "CPU_CNT"  : "CPU cores",
-       "MEM_SIZE" : "Memory size",
-} 
-
-class Site:
-       def __init__(self):
-               print "Content-type: text/html"
-               print   
-       
-       def __call__(self):
-               print '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-               <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
-               <head>
-                       <title>IPFire - Builder</title>
-                       <style type="text/css">
-                               body { font-family: Verdana; font-size: 9pt; background-color:#f0f0f0; }
-                               a:link { color: black; text-decoration: none; }
-                               a:visited { color: black; text-decoration: none; }
-                               table { font-family: Verdana; font-size: 8pt; border: 1px solid; }
-                               td.header { background-color: #a0a0a0; text-align: left; color: white; 
-                                               font-size: 11pt; }
-                               td.date { text-align: center; }
-                               font.installed { color: green; }
-                               font.deleted { color: red; }
-                               font.update { color: blue; }
-                               font.error { color: red; }
-                               td.log { background: pink; }
-                               td.update { background: darkgrey; }
-                               /* td.distcc { background: darkgrey; } */
-                               td.online { background: green; color: white; text-align: center; }
-                               td.offline { background: red; color: white; text-align: center; }
-                       </style>
-                       <meta http-equiv="refresh" content="90; URL=%s" />
-               </head>
-               <body>
-                       <h1>IPFire Builder</h1>
-                       <p>This site is for monitoring the build machines...</p>
-                       <p>Made: %s</p>''' % (os.environ['SCRIPT_NAME'], time.ctime())
-
-               self.content()
-
-               print "\t\t</body>\n</html>"
-       
-       def content(self):
-               for builder in builders:
-                       builder()
-
-
-class Builder:
-       def __init__(self, uuid=None):
-               self.uuid = uuid
-               self.db = os.path.join(DB_DIR, self.uuid)
-               
-               if not os.path.isdir(self.db):
-                       os.mkdir(self.db)
-               
-               self.fn = {
-                       'state' : os.path.join(self.db, "state"),
-                       'distcc' : os.path.join(self.db, "distcc"),
-                       'hostname' : os.path.join(self.db, "hostname"),
-                       'build_durations' : os.path.join(self.db, "build_durations"),
-                       'log' : os.path.join(self.db, "log"),
-                       'profile' : os.path.join(self.db, "profile"),
-               }
-               
-               self.sys = SimpleConfigFile()
-               self.sys.read(self.fn['profile'])
-               
-               self.state = self._state()
-       
-       def _state(self, state="unknown"):
-               """State says what the host is doing at the moment.
-                       This can be:
-                        - unknown      -       Didn't talk with host for more than two hours.
-                        - compiling    -       Host is working
-                        - error        -       Host had an error
-                        - idle         -       Host is idle
-                        - hidden       -       Host was idle or unknown for more than 12 hours"""
-               
-               if not state == "unknown":
-                       f = open(self.fn['state'], "w")
-                       f.write("%s\n" % state)
-                       f.close()
-
-               if not os.access(self.fn['state'], os.R_OK):
-                       return state
-               
-               six_h_ago = int(time.time()) - (3600 * 6)
-               twelve_h_ago = int(time.time()) - (3600 * 12)
-               mtime = os.stat(self.fn['state'])[ST_MTIME]
-               
-               if mtime > six_h_ago:
-                       try:
-                               f = open(self.fn['state'])
-                               state = f.readline().rstrip("\n")
-                               f.close()
-                       except:
-                               pass
-               elif mtime > twelve_h_ago:
-                       state = "hidden"
-
-               return state
-       
-       def _build_durations(self, duration=None):
-               """This returns a 4x-tupel:
-                       First value is best build duration.
-                       Second value is average build duration.
-                       Third value is worst build duration.
-                       Fourth value is the whole build duration."""
-               
-               ## set duration
-               if duration:
-                       f = open(self.fn['build_durations'], "a")
-                       f.write("%s\n" % int(duration))
-                       f.close()
-                       return
-               
-               ## get duration
-               durations = []
-               all_build_duration = 0
-               try:
-                       f = open(self.fn['build_durations'])
-               except IOError:
-                       return (None, None, None, None)
-               else:
-                       while True:
-                               duration = f.readline().rstrip("\n")
-                               if not duration:
-                                       break # EOF
-                               durations.append(int(duration))
-                       f.close()
-                       durations.sort()
-                       for duration in durations:
-                               if duration < 3600: continue
-                               all_build_duration += duration
-                       
-                       avg = all_build_duration / len(durations)
-                       
-                       return (durations[0], avg, durations[-1], all_build_duration)
-       
-       def _log(self, log=[]):
-               
-               if log:
-                       f = open(self.fn['log'], "w")
-                       f.write("%s\n" % log)
-                       f.close()
-                       return
-               
-               try:
-                       f = open(self.fn['log'])
-                       log = f.readlines()
-                       f.close()
-               except:
-                       pass
-               
-               return log
-       
-       def _last_update(self):
-               if not os.access(self.fn['state'], os.R_OK):
-                       return
-
-               return os.stat(self.fn['state'])[ST_MTIME]
-       
-       def _profile_get(self, what=None):
-               data = self.sys.get(what)
-               if data and what.endswith("_SIZE"):
-                       data = format_number(int(data))
-               return data or None
-       
-       def _profile_set(self, what):
-               self.sys.set(what)
-               self.sys.write(self.fn['profile'])
-
-       def __repr__(self):
-               return "<Builder %s>" % self.uuid
-       
-       def __call__(self):
-               if self.state == "hidden":
-                       return
-               
-               self.hostname = self._profile_get("HOSTNAME")
-               self.distcc = self._profile_get("DISTCC")
-               self.build_durations = self._build_durations()
-               self.last_update = self._last_update()
-
-               print "<table width='66%'>"
-               
-               ## give hostname or uuid
-               print "\t<tr>"
-               print "\t\t<td class='header' colspan='3' width='100%'>",
-               if self.hostname:
-                       print self.hostname,
-               else:
-                       print self.uuid,
-               print "</td>"
-               print "\t</tr>"
-               
-               ## give state
-               print "\t<tr>"
-               print "\t\t<td class='state' colspan='2' width='80%'><b>",
-               print stage2desc[self.state],
-               print "</b></td>"
-               print "\t\t<td class='state' rowspan='8' width='20%'>",
-               print "<img alt='%s' width='128px' height='128px' src='/images/%s.png' />" % (self.state, self.state,),
-               print "</td>"
-               print "\t</tr>"
-               
-               ## give sys info
-               for key in ["CPU_NAME", "CPU_MHZ", "CPU_CNT", "CPU_MIPS", "MEM_SIZE"]:
-                       print "\t<tr>"
-                       print "\t\t<td class='sys' width='60%'><b>",
-                       print sys2desc[key]
-                       print "</b></td>"
-                       print "\t\t<td class='durations' width='40%'>",
-                       print self._profile_get(key) or "N/A"
-                       print "</td>"
-                       print "\t</tr>"
-               
-               ## give durations
-               (min, avg, max, all) = self.build_durations
-               print "\t<tr>"
-               print "\t\t<td class='durations' width='60%'>",
-               print "<b>Build durations</b>",
-               print "</td>"
-               print "\t\t<td class='durations' width='40%'>",
-               if avg:
-                       print "<b>Average:</b> %s h<br />" % format_time(avg),
-               if min:
-                       print "<b>Minimum:</b> %s h<br />" % format_time(min),
-               if max:
-                       print "<b>Maximum:</b> %s h<br />" % format_time(max),
-               if all:
-                       print "<b>As a whole:</b> %s h" % format_time(all),
-               
-               if not avg and not min and not max and not all:
-                       print "N/A",
-               
-               print "</td>"
-               print "\t</tr>"
-               
-               ## give distcc
-               print "\t<tr>"
-               print "\t\t<td class='distcc' width='60%'>",
-               print "<b>Distcc capable</b>",
-               print "</td>"
-               print "\t\t<td class='distcc' width='40%'>",
-               if self.distcc == None or self.distcc == "0":
-                       print "No",
-               else:
-                       print "Yes (port: %s)" \
-                               % (self.distcc),
-               print "</td>"
-               print "\t</tr>"
-               
-               ## give log
-               if self.state == "error":
-                       print "\t<tr>"
-                       print "\t\t<td class='log' colspan='3' width='100%'>",
-                       for line in self._log():
-                               print "%s<br/>" % (line,)
-                       print "</td>"
-                       print "\t</tr>"
-               
-               ## give lastupdate
-               if self.last_update:
-                       print "\t<tr>"
-                       print "\t\t<td class='update' colspan='3' width='100%'>",
-                       print "Last update:",
-                       print time.strftime("%Y-%b-%d %I:%M %p", time.localtime(self.last_update)),
-                       print " - ",
-                       print format_time(int(time.time() - self.last_update)),
-                       print "ago </td>"
-                       print "\t</tr>"
-               
-               print "</table>"
-               
-               print "<br />"
-
-form = cgi.FieldStorage()
-action  = form.getfirst('action')
-
-if action in [ "compiling", "error", "idle", "set" ]:
-       builder = Builder(form.getfirst('uuid'))
-       if not action == "set":
-               builder._state(action)
-       if action == "set":
-               key = form.getfirst('key')
-               val = form.getfirst('val')
-               if key == "duration":
-                       builder._build_durations(val)
-               else:
-                       builder._profile_set((key, val))
-       elif action == "error":
-               log = form.getfirst('log')
-               builder._log(log)
-else:
-       builders = []
-       for uuid in os.listdir(DB_DIR):
-               if not os.path.isdir(os.path.join(DB_DIR, uuid)): continue
-               builders.append(Builder(uuid))
-       
-       site = Site()
-       site()
diff --git a/build/builder.py b/build/builder.py
new file mode 100644 (file)
index 0000000..4ed3feb
--- /dev/null
@@ -0,0 +1,201 @@
+#!/usr/bin/python
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2008  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import os
+import sys
+import time
+import socket
+from pysqlite2 import dbapi2 as sqlite
+
+sys.path.append(".")
+
+from constants import config
+
+class Database:
+       def __init__(self, path):
+               self.db = sqlite.connect(os.path.join(path, config["db_name"]))
+               c = self.cursor()
+               c.executescript("""
+                       create table if not exists config(key, value, date);
+                       create table if not exists durations(duration);
+               """)
+               c.close()
+       
+       def __call__(self):
+               return self.cursor()
+       
+       def __del__(self):
+               self.commit()
+               self.db.close()
+
+       def cursor(self):
+               return self.db.cursor()
+       
+       def commit(self):
+               self.db.commit()
+
+class DatabaseConfig:
+       def __init__(self, db, key):
+               self.db = db
+               self.key = key
+               self.data = None
+               self.date = None
+
+       def get(self):
+               if not self.data:
+                       c = self.db.cursor()
+                       c.execute("SELECT value FROM %(table)s WHERE key = '%(key)s'" \
+                                               % { "table" : "config",
+                                                       "key"   : self.key, })
+                       try:
+                               self.data = c.fetchone()[0]
+                       except TypeError:
+                               self.data = None
+                       c.close()
+               return self.data
+       
+       __call__ = get
+       
+       def time(self):
+               if not self.date:
+                       c = self.db.cursor()
+                       c.execute("SELECT date FROM %(table)s WHERE key = '%(key)s'" \
+                                               % { "table" : "config",
+                                                       "key"   : self.key, })
+                       try:
+                               self.date = float("%s" % c.fetchone()[0])
+                       except TypeError:
+                               self.date = None
+                       c.close()
+               return self.date or float(0)
+
+       def set(self, value):
+               #value = (value,)
+               c = self.db.cursor()
+               if not self.get():
+                       sql = "INSERT INTO %(table)s(key, value, date) VALUES('%(key)s', '%(value)s', '%(date)s')" \
+                                               % { "table" : "config",
+                                                       "key"   : self.key,
+                                                       "value" : value,
+                                                       "date"  : time.time(), }
+                       
+               else:
+                       sql = "UPDATE %(table)s SET value='%(value)s', date='%(date)s' WHERE key='%(key)s'" \
+                                               % { "table" : "config",
+                                                       "key"   : self.key,
+                                                       "value" : value,
+                                                       "date"  : time.time(), }
+               c.execute(sql)
+               c.close()
+               self.data = value
+               self.db.commit()
+
+class DurationsConfig:
+       def __init__(self, db):
+               self.db = db
+       
+       def get(self, sort=0):
+               c = self.db.cursor()
+               c.execute("SELECT duration FROM durations")
+               ret = c.fetchall()
+               c.close()
+               if sort: ret.sort()
+               return ret
+       
+       def set(self, value):
+               #value = (value,)
+               c = self.db.cursor()
+               c.execute("INSERT INTO %(table)s(duration) VALUES('%(value)s')" \
+                                       % { "table" : "durations",
+                                               "value" : value, })
+               c.close()
+               self.db.commit()
+
+       def get_avg(self):
+               sum = 0
+               durations = self.get()
+               if not len(durations):
+                       return None
+               for value in durations:
+                       sum += int("%s" % value)
+               avg = sum / len(durations)
+               return avg
+       
+       def get_eta(self, timestamp):
+               avg = self.get_avg()
+               if not avg:
+                       return "N/A"
+               eta = int(timestamp) + avg
+               return time.ctime(eta)
+
+class DistccConfig(DatabaseConfig):
+       def __init__(self, db, key, hostname):
+               DatabaseConfig.__init__(self, db, key)
+               self.hostname = hostname
+       
+       def __str__(self):
+               if not self.hostname:
+                       return ""
+               return "%s:%s/4,lzo" % \
+                       (socket.gethostbyname(self.hostname), self.get(),)
+
+       def ping(self):
+               if not self.hostname:
+                       return False
+               return not os.system("ping -c1 -w1 %s &>/dev/null" % self.hostname)
+
+       def version(self):
+               return os.popen("distcc --version").readlines()
+
+class Builder:
+       def __init__(self, config, uuid):
+               self.uuid = uuid
+               self.config = config
+               self.path = os.path.join(self.config['path']['db'], self.uuid)
+               
+               if not os.access(self.path, os.R_OK):
+                       try:
+                               os.mkdir(self.path)
+                       except:
+                               pass
+
+               self.db = Database(self.path)
+               
+               self.hostname = DatabaseConfig(self.db, "hostname")
+               self.state    = DatabaseConfig(self.db, "state")
+               self.package  = DatabaseConfig(self.db, "package")
+               
+               self.duration = DurationsConfig(self.db)
+               self.distcc   = DistccConfig(self.db, "distcc", self.hostname.get())
+
+       def set(self, key, value):
+               eval("self.%s.set(\"%s\")" % (key, value,))
+
+       def get(self, key):
+               return eval("self.%s.get()" % (key,))
+
+def getAllBuilders():
+       builders = []
+       for uuid in os.listdir(config["path"]["db"]):
+               if uuid == "empty.txt": continue
+               builder = Builder(config, uuid)
+               builders.append(builder)
+       return builders
diff --git a/build/config.py b/build/config.py
new file mode 100644 (file)
index 0000000..74064ef
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+import os
+import time
+
+config = {
+       "title"       : "IPFire - Builder",
+       "nightly_url" : "ftp://ftp.ipfire.org/pub/nightly-builds",
+       "path"        : { "db" : "db", },
+       "script"      : os.environ['SCRIPT_NAME'],
+       "time"        : time.ctime(),
+       "db_name"     : "builder.db",
+}
diff --git a/build/constants.py b/build/constants.py
new file mode 100644 (file)
index 0000000..49060a9
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2008  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import os
+import time
+
+config = {
+       "title"       : "IPFire - Builder",
+       "nightly_url" : ("ftp://ftp.ipfire.org/pub/nightly-builds/", "http://www.rowie.at/ipfire/builds/",),
+       "path"        : { "db" : "db", },
+       "script"      : os.environ['SCRIPT_NAME'],
+       "db_name"     : "builder.db",
+}
+
+statedesc = {
+       None : "",
+       "unknown" : "Dunno what the host is doing at the moment...",
+       "compiling" : "The host is really hard working at the moment...",
+       "error" : "Oops! The host had an error...",
+       "idle" : "The host is idle at the moment...",
+}
+
+ping2class = {
+       True  : "online",
+       False : "offline",
+}
+
+state2style = {
+       None        : "",
+       "compiling" : "background: #8C8; border: 1px solid #0e0;",
+       "error"     : "background: #c33; border: 1px solid #e00;",
+       "idle"      : "height: 60px; background: #ddd; border: 1px solid #eee;",
+}
diff --git a/build/distcc.py b/build/distcc.py
deleted file mode 100644 (file)
index 5373e5a..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python
-
-import cgitb, os, time, cgi, re, random, socket, DNS
-cgitb.enable()
-
-def print_http_header():
-       print "Content-type: text/html"
-       print
-
-def print_header():
-       print_http_header()     
-       print '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-       <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
-       <head>
-               <title>IPFire - DistccWatch</title>
-               <style type="text/css">
-                       body { font-family: Verdana; font-size: 9pt; background-color:#f0f0f0; }
-                       a:link { color: black; text-decoration: none; }
-                       a:visited { color: black; text-decoration: none; }
-                       table { font-family: Verdana; font-size: 8pt; border: 1px solid; }
-                       td.header { background-color: #a0a0a0; text-align: center; color: white; }
-                       td.date { text-align: center; }
-                       font.installed { color: green; }
-                       font.deleted { color: red; }
-                       font.update { color: blue; }
-                       font.error { color: red; }
-                       td.online { background: green; color: white; text-align: center; }
-                       td.offline { background: red; color: white; text-align: center; }
-               </style>
-               <meta http-equiv="refresh" content="60; URL=%s" />
-       </head>
-       <body>
-               <h1>IPFire DistccWatch</h1>
-               <p>Made: %s</p>''' % (os.environ['SCRIPT_NAME'], time.ctime())
-               
-def print_footer():
-       print "\t</body>\n</html>"
-               
-def print_dcc_info():
-       print "<pre>",
-       print os.popen("distcc --version").read(),
-       print "</pre>"
-
-def read_hosts():
-       f = open("hosts")
-       hosts = []
-       while True:
-               line = f.readline()
-               if len(line) == 0:
-                       hosts.sort()
-                       return hosts
-                       break #EOF
-               
-               if not line.startswith("#"):
-                       hosts.append(line.rstrip("\n"))
-
-def process_hosts(hosts=""):
-       if not hosts:
-               print "You need to specify the hosts you want to check in the config file."
-               return
-               
-       print '''<table width='66%'>
-       <tr>
-                       <td class='header' width='68%'>Host</td>
-                       <td class='header' width='16%'>State</td>
-                       <td class='header' width='16%'>Probe</td>
-       </tr>'''
-       
-       for hostname in hosts:
-       
-               state = "DOWN"
-               time = "&nbsp;"
-               command = "HOME=tmp DISTCC_HOSTS=\"%s\" DISTCC_VERBOSE=1 distcc probe.c -S -o /dev/null 2>&1" % hostname
-               state_pattern = re.compile("on %s completed ok" % hostname)
-               time_pattern = re.compile("elapsed compilation time ")
-
-               for line in os.popen(command).readlines():
-                       state_result = re.search(state_pattern, line)
-                       time_result = re.search(time_pattern, line)
-                       if not state_result == None:
-                               state = "UP"
-                       if not time_result == None:
-                               if state == "UP":
-                                       time = time_result.string[-10:]
-                       
-               print "<tr><td><pre>%s</pre></td><td>%s</td><td>%s</td></tr>" % (hostname, state, time)
-       
-       print "</table>"
-
-def mixup_hosts(hosts=""):
-       string = ""
-       while True:
-               if len(hosts) == 0:
-                       break
-                       
-               rand = random.randint(0, len(hosts)-1)
-               host, options = re.split(re.compile(':'),hosts[rand])
-               string += socket.gethostbyname(host) + ":" + options + " "
-               hosts.pop(rand)
-               
-       print string
-       
-form = cgi.FieldStorage()
-action  = form.getfirst('action')
-
-if action == "raw":
-       print_http_header()
-       
-       hosts = read_hosts()
-       
-       mixup_hosts(hosts)
-
-else:
-
-       print_header()
-       print_dcc_info()
-       
-       hosts = read_hosts()
-       
-       process_hosts(hosts)
-       
-       print_footer()
diff --git a/build/hosts b/build/hosts
deleted file mode 100644 (file)
index 5f25c81..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#mirror1.ipfire.org:3632,lzo
-#mirror2.ipfire.org:3632,lzo
-#mirror3.ipfire.org:3632,lzo
-compiler02.ipfire.org:3630/10,lzo
-compiler02.ipfire.org:3631/10,lzo
diff --git a/build/images/compiling.png b/build/images/compiling.png
deleted file mode 100644 (file)
index 903a27e..0000000
Binary files a/build/images/compiling.png and /dev/null differ
diff --git a/build/images/error.png b/build/images/error.png
deleted file mode 100644 (file)
index 9d67d8a..0000000
Binary files a/build/images/error.png and /dev/null differ
diff --git a/build/images/idle.png b/build/images/idle.png
deleted file mode 100644 (file)
index 8df47a5..0000000
Binary files a/build/images/idle.png and /dev/null differ
diff --git a/build/images/unknown.png b/build/images/unknown.png
deleted file mode 100644 (file)
index 61400e2..0000000
Binary files a/build/images/unknown.png and /dev/null differ
diff --git a/build/index.py b/build/index.py
new file mode 100644 (file)
index 0000000..9ef8c43
--- /dev/null
@@ -0,0 +1,233 @@
+#!/usr/bin/python
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2008  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import os
+import sys
+import time
+
+sys.path.append(".")
+
+from builder import Builder, getAllBuilders
+from constants import *
+
+def format_time(seconds, use_hours=1):
+       if seconds is None or seconds < 0:
+               if use_hours: return '--:--:--'
+               else:         return '--:--'
+       else:
+               seconds = int(seconds)
+               minutes = seconds / 60
+               seconds = seconds % 60
+               if use_hours:
+                       hours = minutes / 60
+                       minutes = minutes % 60
+                       return '%02i:%02i:%02i' % (hours, minutes, seconds)
+               else:
+                       return '%02i:%02i' % (minutes, seconds)
+
+class Site:
+       def __init__(self, config):
+               self.builders = None
+               self.config = config
+               print "Content-type: text/html"
+               print
+       
+       def __call__(self, builders=None):
+               self.builders = builders
+               print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+               <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+               <head>
+                       <title>%(title)s</title>
+                       <style type="text/css">
+                               * {
+                                       margin: auto;
+                                       padding: 0;
+                                       text-decoration: none;
+                                       outline: none;
+                               }
+                               body {
+                                       font-family: Verdana;
+                                       font-size: 90%%;
+                                       background-color:#f9f9f9;
+                               }
+                               h1 {
+                                       text-decoration: underline;
+                               }
+                               #header {
+                                       width: 800px;
+                                       height: 100px;
+                                       text-align: center;
+                                       background: #E0E0E0;
+                                       border: 1px solid #999;
+                                       padding-top: 10px;
+                               }
+                               #content {
+                                       padding-top: 10px;
+                                       width: 800px;
+                               }
+                               div.box {
+                                       padding: 5px;
+                                       margin: 10px 0 10px 0;
+                                       height: 80px;
+                                       border: 1px solid;
+                               }
+                               div.infobox {
+                                       float: right;
+                                       width: 240px;
+                               }
+                               p {
+                                       margin: 2px;
+                               }
+                               p.boxheader {
+                                       font-weight: bold;
+                               }
+                               p.online {
+                                       color: green;
+                               }
+                               p.offline {
+                                       color: red;
+                               }
+                               p.package {
+                                       font: bold;
+                                       font-size: 150%%;
+                               }
+                               img.right {
+                                       float: right;
+                               }
+                               p.desc {
+                                       text-decoration: bold;
+                               }
+                               a:link {
+                                       color: black; text-decoration: none;
+                               }
+                               a:visited {
+                                       color: black; text-decoration: none;
+                               }
+                       </style>
+                       <meta http-equiv="refresh" content="90; URL=%(script)s" />
+               </head>
+               <body>
+                       <div id="header">
+                               <h1>IPFire Builder</h1>""" % self.config
+               if self.builders:
+                       print """\
+                               <p>
+                                       """,
+                       for builder in self.builders:
+                               print builder,
+                       print """
+                               </p>"""
+               for i in self.config["nightly_url"]:
+                       print """\
+                               <p><a href="%s" target="_blank">%s</a></p>""" % (i, i,)
+               print """\
+                       </div>"""
+
+               self.content()
+
+               print "\t\t</body>\n</html>"
+
+       def content(self):
+               if self.builders:
+                       count = 0
+                       print """\
+                       <div id="content">"""
+                       for builder in self.builders:
+                               builder(count)
+                               count += 1
+                       print """\
+                       </div>"""
+
+class Box:
+       def __init__(self, builder):
+               self.builder =  builder
+       
+       def __call__(self, count):
+               print """\
+                               <a name="%s"></a>
+                               <div class="box" style="%s">"""\
+                               % (self.builder.hostname(), state2style[self.builder.state()],)
+               print """\
+                                       <div class="infobox">"""
+               self.distccinfo()
+               self.package()
+               self.time()
+               print """\
+                                       </div>"""
+               self.header()
+               self.stateinfo()
+               self.durations()
+               print """\
+                               </div>"""
+       
+       def __str__(self):
+               return """<a href="#%(hostname)s">%(hostname)s</a>""" % { "hostname" : self.builder.hostname(), }
+
+       def header(self):
+               print """\
+                                       <p class="boxheader">
+                                               %(hostname)s <span>[%(uuid)s]</span>
+                                       </p>
+                                       <!-- <img class="right" src="/images/%(state)s.png" /> -->""" \
+                               % { "hostname" : self.builder.hostname(),
+                                       "state"    : self.builder.state(),
+                                       "uuid"     : self.builder.uuid, }
+       
+       def package(self):
+               if self.builder.state() in [ "compiling", "error", ]:
+                       print """\
+                                               <p class="package">%s</p>"""\
+                               % self.builder.package()
+       
+       def time(self):
+               print """\
+                                               <p>%s</p>""" \
+                               % time.ctime(float(self.builder.state.time()))
+       
+       def stateinfo(self):
+               if self.builder.state() in [ "compiling", "error", "idle", ]:
+                       print """\
+                                       <p class="desc">%s</p>""" \
+                                % statedesc[self.builder.state()]
+       
+       def durations(self):
+               print """\
+                                       <p>Average Build Duration: %s</p>""" \
+                               % format_time(self.builder.duration.get_avg())
+               if self.builder.state() == "compiling":
+                       print """\
+                                       <p>ETA: %s</p>""" \
+                               % self.builder.duration.get_eta(self.builder.state.time())
+       
+       def distccinfo(self):
+               state = self.builder.distcc.ping()
+               print """\
+                                               <p class="%s">Distcc: %s</p>""" \
+                               % (ping2class[state], self.builder.distcc.get(),)
+
+site = Site(config)
+
+boxes = []
+for builder in getAllBuilders():
+       boxes.append(Box(builder))
+
+site(boxes)
diff --git a/build/probe.c b/build/probe.c
deleted file mode 100644 (file)
index dbec910..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-int main () {
-       return 0;
-}
diff --git a/build/rpc.py b/build/rpc.py
new file mode 100644 (file)
index 0000000..bfcf44d
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2008  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import os
+import sys
+import cgi
+import time
+import random
+
+sys.path.append(".")
+
+from builder import Builder, getAllBuilders
+from constants import config
+
+class Response:
+       def __init__(self, config):
+               self.config = config
+               
+               self.code = "200"
+               self.mesg = "OK"
+       
+       def __call__(self, exit=0):
+               print "Status: %s" % self.code
+               print "Content-type: text/plain"
+               print
+               print "%s" % self.mesg
+               if exit:
+                       os._exit(0)
+       
+       def set_code(self, code):
+               self.code = code
+       
+       def set_mesg(self, mesg):
+               self.mesg = mesg
+
+response = Response(config)
+
+data = cgi.FieldStorage()
+
+action  = data.getvalue('action')
+if action == "set":
+       uuid = data.getfirst("uuid")
+       if not uuid:
+               response.set_code("406")
+               response.set_mesg("UUID is not valid!")
+               response(1)
+       
+       builder = Builder(config, uuid)
+       
+       key = None
+       for key in [ "distcc", "duration", "hostname", "state", "package", ]:
+               for value in data.getlist(key):
+                       builder.set(key, value)
+elif action == "get":
+       for key in [ "distcc", ]:
+               if key == "distcc":
+                       for value in data.getlist(key):
+                               if value == "raw":
+                                       builders = []
+                                       for builder in getAllBuilders():
+                                               builders.append("%s" % builder.distcc)
+                                       string = ""
+                                       while True:
+                                               if not builders: break
+                                               rand = random.randint(0, len(builders)-1)
+                                               string += "%s\n" % builders[rand]
+                                               builders.pop(rand)
+                                       response.set_mesg(string)
+                                       
+else:
+       response.set_code("501")
+       response.set_mesg("Don't know what to do with command \"%s\"" % action)
+       response(1)
+
+response()
diff --git a/build/tmp/empty.txt b/build/tmp/empty.txt
deleted file mode 100644 (file)
index e69de29..0000000