From 19a8d9a0dcb2a61debd9fc9bb26936a248b9004e Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Tue, 17 Jun 2008 17:28:32 +0200 Subject: [PATCH] Imported other web components. --- build/build.py | 379 +++++++++++++++++++++++++++++++++++++ build/distcc.py | 123 ++++++++++++ build/hosts | 5 + build/images/compiling.png | Bin 0 -> 16973 bytes build/images/error.png | Bin 0 -> 10719 bytes build/images/idle.png | Bin 0 -> 14583 bytes build/images/unknown.png | Bin 0 -> 17167 bytes build/probe.c | 3 + download/getfile.py | 56 ++++++ download/mirrorlist | 6 + pakfire/counter.py | 49 +++++ pakfire/show.py | 217 +++++++++++++++++++++ 12 files changed, 838 insertions(+) create mode 100644 build/build.py create mode 100644 build/distcc.py create mode 100644 build/hosts create mode 100644 build/images/compiling.png create mode 100644 build/images/error.png create mode 100644 build/images/idle.png create mode 100644 build/images/unknown.png create mode 100644 build/probe.c create mode 100644 download/getfile.py create mode 100644 download/mirrorlist create mode 100644 pakfire/counter.py create mode 100644 pakfire/show.py diff --git a/build/build.py b/build/build.py new file mode 100644 index 00000000..edaf98cf --- /dev/null +++ b/build/build.py @@ -0,0 +1,379 @@ +#!/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", + "MEM_SIZE" : "Memory size", +} + +class Site: + def __init__(self): + print "Content-type: text/html" + print + + def __call__(self): + print ''' + + + IPFire - Builder + + + + +

IPFire Builder

+

This site is for monitoring the build machines...

+

Made: %s

''' % (os.environ['SCRIPT_NAME'], time.ctime()) + + self.content() + + print "\t\t\n" + + 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 "" % 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 "" + + ## give hostname or uuid + print "\t" + print "\t\t" + print "\t" + + ## give state + print "\t" + print "\t\t" + print "\t\t" + print "\t" + + ## give sys info + for key in [ "CPU_NAME", "CPU_MHZ", "CPU_MIPS", "MEM_SIZE", ]: + print "\t" + print "\t\t" + print "\t\t" + print "\t" + + ## give durations + (min, avg, max, all) = self.build_durations + print "\t" + print "\t\t" + print "\t\t" + print "\t" + + ## give distcc + print "\t" + print "\t\t" + print "\t\t" + print "\t" + + ## give log + if self.state == "error": + print "\t" + print "\t\t" + print "\t" + + ## give lastupdate + if self.last_update: + print "\t" + print "\t\t" + print "\t" + + print "
", + if self.hostname: + print self.hostname, + else: + print self.uuid, + print "
", + print stage2desc[self.state], + print "", + print "%s" % (self.state, self.state,), + print "
", + print sys2desc[key] + print "", + print self._profile_get(key) or "N/A" + print "
", + print "Build durations", + print "", + if avg: + print "Average: %s h
" % format_time(avg), + if min: + print "Minimum: %s h
" % format_time(min), + if max: + print "Maximum: %s h
" % format_time(max), + if all: + print "As a whole: %s h" % format_time(all), + + if not avg and not min and not max and not all: + print "N/A", + + print "
", + print "Distcc capable", + print "", + if self.distcc == None or self.distcc == "0": + print "No", + else: + print "Yes (port: %s)" \ + % (self.distcc), + print "
", + for line in self._log(): + print "%s
" % (line,) + print "
", + 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
" + + print "
" + +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/distcc.py b/build/distcc.py new file mode 100644 index 00000000..5373e5ab --- /dev/null +++ b/build/distcc.py @@ -0,0 +1,123 @@ +#!/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 ''' + + + IPFire - DistccWatch + + + + +

IPFire DistccWatch

+

Made: %s

''' % (os.environ['SCRIPT_NAME'], time.ctime()) + +def print_footer(): + print "\t\n" + +def print_dcc_info(): + print "
",
+	print os.popen("distcc --version").read(),
+	print "
" + +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 ''' + + + + + ''' + + for hostname in hosts: + + state = "DOWN" + time = " " + 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 "" % (hostname, state, time) + + print "
HostStateProbe
%s
%s%s
" + +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 new file mode 100644 index 00000000..5f25c816 --- /dev/null +++ b/build/hosts @@ -0,0 +1,5 @@ +#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 new file mode 100644 index 0000000000000000000000000000000000000000..903a27eda6a3017158f4d0181f09437e1dfd6bab GIT binary patch literal 16973 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 literal 0 Hc-jL100001 diff --git a/build/images/error.png b/build/images/error.png new file mode 100644 index 0000000000000000000000000000000000000000..9d67d8a819b4c3d2d392f11a8c2783d23926e8d2 GIT binary patch literal 10719 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 R$*TYW002ovPDHLkV1mRPaJB#d literal 0 Hc-jL100001 diff --git a/build/images/idle.png b/build/images/idle.png new file mode 100644 index 0000000000000000000000000000000000000000..8df47a5be67e24086c160a8fd7987a082981747f GIT binary patch literal 14583 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

;8nQp{KZf#SZ^ylPTW{|OSy~gR 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 literal 0 Hc-jL100001 diff --git a/build/probe.c b/build/probe.c new file mode 100644 index 00000000..dbec9109 --- /dev/null +++ b/build/probe.c @@ -0,0 +1,3 @@ +int main () { + return 0; +} diff --git a/download/getfile.py b/download/getfile.py new file mode 100644 index 00000000..d6c1e641 --- /dev/null +++ b/download/getfile.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +# This is a short script for spread our files... + +import cgi, random, urllib2, sys + +def redirect(url): + print 'Status: 302 Moved Temporarily' + print 'Location:', url + print 'Pragma: no-cache' + print 'Content-Type: text/html' + print + +def notfound(): + print 'Status: 404 Not Found' + print 'Pragma: no-cache' + print + +def selectserver(filename): + servers = [] + f = open("mirrorlist") + while True: + line = f.readline() + if len(line) == 0: + break # EOF + line = line.rstrip('\n') + servers.append(line) + f.close() + + while True: + if len(servers) == 0: + url = "None" + break + rand = random.randint(0, len(servers)-1) + url = "%s/%s" % (servers[rand], cgi.escape(filename)) + try: + req = urllib2.Request(url) + req.add_header('User-Agent', 'IPFire/DownloadScript-1.0') + urllib2.urlopen(req) + except urllib2.HTTPError, e: + servers.pop(rand) + except urllib2.URLError, e: + servers.pop(rand) + else: + break + return url + +form = cgi.FieldStorage() +filename = form.getfirst('file') + +url = selectserver(filename) + +if url == "None": + notfound() +else: + redirect(url) diff --git a/download/mirrorlist b/download/mirrorlist new file mode 100644 index 00000000..88056684 --- /dev/null +++ b/download/mirrorlist @@ -0,0 +1,6 @@ +http://mirror1.ipfire.org +http://www.rowie.at/ipfire +http://ipfire.earl-net.com +http://ipfire.kbarthel.de +http://ipfire.1l0v3u.com +http://hex2.sv-altikon.ch/ipfire diff --git a/pakfire/counter.py b/pakfire/counter.py new file mode 100644 index 00000000..fcaa2be2 --- /dev/null +++ b/pakfire/counter.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +import cgitb, sys, os, time, cgi +cgitb.enable() + +### HTTP-Header +# +print "Content-type: text/html" +print + +form = cgi.FieldStorage() + +uuid = form.getfirst('uuid') +ver = form.getfirst('ver') +ipak = form.getfirst('ipak') +dpak = form.getfirst('dpak') +upak = form.getfirst('upak') +ret = form.getfirst('return') + +if not uuid or not ver: + sys.exit(1) # Exit when the arguments are not set + +if not os.path.exists("version/"+ver): + os.mkdir("version/"+ver) + +zeit = time.time() +string = "%s %d" % (os.environ['REMOTE_ADDR'], zeit) + +if ipak: + string += " installed %s %s" % (ipak, ret) +elif dpak: + string += " deleted %s %s" % (dpak, ret) +elif upak: + string += " upgraded %s %s" % (upak, ret) +else: + string += " update" + +string += "\n" + +f = open("version/"+ver+"/"+uuid, "a") +f.write(string) +f.close() + +for file in os.listdir("version/"+ver): + time_diff = zeit - os.path.getmtime("version/"+ver+"/"+file) + if time_diff > 259200: + os.remove("version/"+ver+"/"+file) + +print "200 OK" diff --git a/pakfire/show.py b/pakfire/show.py new file mode 100644 index 00000000..6a17605f --- /dev/null +++ b/pakfire/show.py @@ -0,0 +1,217 @@ +#!/usr/bin/python + +import cgitb, os, time, socket, cgi, DNS, GeoIP +cgitb.enable() + +#gi = GeoIP.new(GeoIP.GEOIP_STANDARD) +gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE) + +def print_header(): + print ''' + + + IPFire - Distribution + + + + +

IPFire Distribution

+

Made: %s

''' % (os.environ['SCRIPT_NAME'], ver, uuid, time.ctime()) + +def beautify_ip(ip): + try: + hostname = socket.gethostbyaddr(ip) + string = "%s (%s - %s)" % (hostname[0], ip, gi.country_code_by_addr(ip)) + except socket.herror, e: + error = "Couldn't look up name: %s" % e + string = "%s (%s)" % (error, ip) + return string + +def beautify_time(timestamp): + return time.strftime("%d-%m-%Y - %H:%M", time.localtime(float(timestamp))) + +def get_attributes(line): + status = "" + pak = "" + command = "" + args = line.split(" ") + ip = args[0] + timestamp = args[1] + if len(args) > 2: + command = args[2] + if len(args) > 3: + pak = args[3] + if len(args) > 4: + status = args[4] + + return ip, timestamp, command, pak, status + +def showuuid(uuid, ver): + print "

%s

" % (os.environ['SCRIPT_NAME'], dir, uuid, uuid, uuid) + +def summurize_addons(): + addons={} + installed={} + upgraded={} + deleted={} + oldest="9999999999999" + newest="0000000000000" + for dir in os.listdir("version/"): +# print dir+"
" + for uuid in os.listdir("version/"+dir): +# print uuid+"
" + f = open("version/"+dir+"/"+uuid) + while True: + line = f.readline() + if len(line) == 0: + break # EOF + status = "" + pak = "" + command = "" + args = line.split(" ") + if oldest > args[1]: + oldest = args[1] + if newest < args[1]: + newest = args[1] + if len(args) > 2: + command = args[2] +# print command + if len(args) > 3: + pak = args[3] +# print pak + if len(args) > 4: + status = args[4] +# print status+"
" + if (status == "0\n") and (command == "installed") and (dir == "2.1"): + addons[pak] = addons.get(pak,0)+1 + installed[pak] = installed.get(pak,0)+1 + if (status == "0\n") and (command == "deleted") and (dir == "2.1"): + addons[pak] = addons.get(pak,0)-1 + deleted[pak] = deleted.get(pak,0)+1 + if (status == "0\n") and (command == "upgraded") and (dir == "2.1"): + upgraded[pak] = upgraded.get(pak,0)+1 + f.close() + print "Oldest one installed - %s" % beautify_time(oldest) + for x in range(10): + print " " + print "Latest action done - %s" % beautify_time(newest) + print "

" + + for x in range(1,31): + if ( x % 8 ): + print "" % (x,upgraded.get("core-upgrade-" + str(x),0)) + else: + print "" % (x,upgraded.get("core-upgrade-" + str(x),0)) + print "
Core %s - %sCore %s - %s


" + + print "" + for name, nummer in sorted(addons.items()): + print "" + print "
AddonAnzahlInstalliertDeinstalliert
" + print name + print "" + print nummer + print "+" + print installed.get(name, 0) + print "-" + print deleted.get(name, 0) + print "
" + +def showdetails(uuid, ver): + f = open("version/"+dir+"/"+uuid) + print "\n

"+uuid+"

" + print "" + print "" % timestamp + + print string + + print "
IP-addressUpdates" + while True: + line = f.readline() + if len(line) == 0: + break # EOF + + ip, timestamp, command, pak, status = get_attributes(line) + + if command == "update\n": + last_update = timestamp + continue + + string = "
" + string += beautify_ip(ip) + + timestamp = beautify_time(timestamp) + + + if command: + string += " - %s - %s" % (command, command, pak) + if not status == "0\n": + string += " %s" % status + + string += "%s
Last update:%s" % beautify_time(timestamp) + print "
" + f.close() + + +def summary(type): + print "" + print "" + if type == "global": + print "" + + print "" + + + print "
Summary
Versions available:", + print os.listdir("version/"), + print "
Number of total hosts:", + count = 0 + for dir in os.listdir("version/"): + count += len(os.listdir("version/"+dir)) + print count, + print "
" + +### HTTP-Header +# +print "Content-type: text/html" +print + +form = cgi.FieldStorage() + +ver = form.getfirst('ver') +uuid = form.getfirst('uuid') + +if not uuid: + uuid = "" + +print_header() + +summary("global") + +for dir in os.listdir("version/"): + + print "

%s

" % (os.environ['SCRIPT_NAME'], dir, dir) + if ver == dir: + for i in os.listdir("version/"+dir): + if i == uuid: + showdetails(i, dir) + else: + showuuid(i, dir) + +summurize_addons() + +print "" -- 2.39.2