www interface and support libraries for some of monitor's data. Specifically:
authorStephen Soltesz <soltesz@cs.princeton.edu>
Fri, 2 Nov 2007 15:10:25 +0000 (15:10 +0000)
committerStephen Soltesz <soltesz@cs.princeton.edu>
Fri, 2 Nov 2007 15:10:25 +0000 (15:10 +0000)
 - bad nodes
 - bad pcus
 - and actions taken.

www/printbadnodes.py [new file with mode: 0755]
www/printbadpcus.php [new file with mode: 0644]
www/siteactions.cgi [new file with mode: 0755]
www/soltesz.php [new file with mode: 0644]

diff --git a/www/printbadnodes.py b/www/printbadnodes.py
new file mode 100755 (executable)
index 0000000..c8bbfcb
--- /dev/null
@@ -0,0 +1,440 @@
+#!/usr/bin/python
+import soltesz
+from config import config
+from optparse import OptionParser
+import string
+
+import sys
+
+categories = {}
+ssherror = False
+
+def sec2days(sec):
+       if sec == "null":
+               sec = -(60*60*24)
+       sec = int(sec)
+       return sec/(60*60*24)
+
+def array_to_priority_map(array):
+       """ Create a mapping where each entry of array is given a priority equal
+       to its position in the array.  This is useful for subsequent use in the
+       cmpMap() function."""
+       map = {}
+       count = 0
+       for i in array:
+               map[i] = count
+               count += 1
+       return map
+
+def cmpValMap(v1, v2, map):
+       if v1 in map and v2 in map and map[v1] < map[v2]:
+               return 1
+       elif v1 in map and v2 in map and map[v1] > map[v2]:
+               return -1
+       elif v1 in map and v2 in map:
+               return 0
+       else:
+               raise Exception("No index %s or %s in map" % (v1, v2))
+
+def cmpMap(l1, l2, index, map):
+       if index in l1 and index in l2:
+               if map[l1[index]] < map[l2[index]]:
+                       return -1
+               elif map[l1[index]] > map[l2[index]]:
+                       return 1
+               else:
+                       return 0
+       else:
+               return 0
+
+def cmpLoginBase(l1, l2):
+       #print "'" + l1['loginbase'] + "'"  + " < " + "'" + l2['loginbase'] + "'" + "<BR>"
+       if l1['loginbase'] == l2['loginbase']:
+               return 0
+       elif l1['loginbase'] < l2['loginbase']:
+               return -1
+       elif l1['loginbase'] > l2['loginbase']:
+               return 1
+       else:
+               return 0
+
+def cmpState(l1, l2):
+       map = array_to_priority_map([ 'BOOT', 'DEBUG', 'DOWN' ])
+       return cmpMap(l1,l2,'state', map)
+
+def cmpCategoryVal(v1, v2):
+       map = array_to_priority_map([ None, 'ALPHA', 'PROD', 'OLDBOOTCD', 'UNKNOWN', 'ERROR', ])
+       return cmpValMap(v1,v2,map)
+
+def cmpCategory(l1, l2):
+       map = array_to_priority_map([ 'ALPHA', 'PROD', 'OLDBOOTCD', 'UNKNOWN', 'ERROR', ])
+       return cmpMap(l1,l2,'category', map)
+
+def cmpPCU(l1, l2):
+       """ Either PCU or NOPCU"""
+       map = array_to_priority_map([ 'PCU', 'NOPCU', 'UNKNOWN'])
+       return cmpMap(l1, l2, 'pcu', map)
+
+def cmpSSH(l1, l2):
+       """ Either SSH or NOSSH """
+       map = array_to_priority_map([ 'SSH', 'NOSSH'])
+       return cmpMap(l1, l2, 'ssh', map)
+
+def cmpDNS(l1,l2):
+       """ Compare DNS states """
+       map = array_to_priority_map([ 'OK', 'NOHOSTNAME', 'NOENTRY', 'MISMATCH'])
+       return cmpMap(l1, l2, 'dnsmatch', map)
+       
+def cmpPing(l1,l2):
+       """ Either PING or NOPING """
+       map = array_to_priority_map([ 'PING', 'NOPING'])
+       return cmpMap(l1, l2, 'ping', map)
+
+def cmpUname(l1, l2):
+       # Extract the kernel version from kernel -a string
+       l_k1 = l1['kernel'].split()
+       if len(l_k1) > 2:
+               k1 = l_k1[2]
+       else:
+               return 1
+
+       l_k2 = l2['kernel'].split()
+       if len(l_k2) > 2:
+               k2 = l_k2[2]
+       else:
+               return -1
+
+       return cmp(k1, k2)
+
+def cmpDays(l1, l2):
+       if l1['comonstats'][config.comon] == "null":
+               l1['comonstats'][config.comon] = -1
+       if l2['comonstats'][config.comon] == "null":
+               l2['comonstats'][config.comon] = -1
+               
+       if int(l1['comonstats'][config.comon]) > int(l2['comonstats'][config.comon]):
+               return -1
+       elif int(l1['comonstats'][config.comon]) < int(l2['comonstats'][config.comon]):
+               return 1
+       else:
+               return 0
+
+def ssh_error_to_str(str):
+       ssh_error = ""
+       if "Connection timed out" in str:
+               ssh_error = "Timeout" 
+       elif "Connection closed by remote host" in str:
+               ssh_error = "Closed by remote host"
+       elif "Connection refused" in str:
+               ssh_error = "Connection refused"
+       elif "Temporary failure in name resolution" in str:
+               ssh_error = "Could not resolve name"
+       elif "Name or service not known" in str:
+               ssh_error = "Name not known"
+       elif "Too many authentication failures" in str:
+               ssh_error = "Disconnect: root auth failure"
+       elif "Network is unreachable" in str:
+               ssh_error = "Network is unreachable"
+       elif "Connection reset by peer" in str:
+               ssh_error = "Connection reset by peer"
+       elif "WARNING" in str:
+               ssh_error = "WARNING ssh key updated"
+       else:
+               ssh_error = str
+
+       return ssh_error
+
+def fields_to_html(fields, vals):
+       global categories
+       global ssherror
+       colorMap = { 'PING'  : 'darkseagreen',
+                                'NOPING': 'darksalmon',
+                                'SSH': 'darkseagreen',
+                                'NOSSH': 'indianred',
+                                'PCU': 'darkseagreen',
+                                'NOPCU': 'lightgrey',
+                                'OLDBOOTCD': 'crimson',
+                                'DOWN': 'indianred',
+                                'ALPHA': 'gold',
+                                'ERROR': 'crimson',
+                                'PROD': 'darkseagreen',
+                                'DEBUG': 'darksalmon',
+                                'DEBUG': 'darksalmon',
+                                'BOOT': 'lightgreen'}
+       r_str = ""
+       f_prev = ""
+       f_2prev = ""
+       #print 'inside--------------'
+       for f in fields:
+               f = f.strip()
+               #print f
+
+               if f in ['DOWN', 'BOOT', 'DEBUG']:
+                       #key = "%s-%s-%s" % (f,f_prev,f_2prev)
+                       key = "%s-%s" % (f,f_prev)
+                       if key not in categories:
+                               categories[key] = 1
+                       else:
+                               categories[key] += 1
+
+               #print "<pre>%s</pre><br>" % f
+                               
+               if f in colorMap:
+                       bgcolor="bgcolor='%s'" % colorMap[f]
+               else:
+                       bgcolor=""
+
+               if f == 'NOSSH':
+                       if ssherror:
+                               if 'ssherror' in vals:
+                                       str_ssh_error = ssh_error_to_str(vals['ssherror'])
+                               else:
+                                       str_ssh_error = "NO SSHERROR in VALS"
+                               if str_ssh_error != "Timeout":
+                                       r_str += """<td nowrap %s>%s<br><b><font size="-2">%s</font></b></td>""" % \
+                                                               (bgcolor,f,str_ssh_error)
+                               else:
+                                       r_str += "<td %s>%s</td>" % (bgcolor, f)
+                       else:
+                               r_str += "<td %s>%s</td>" % (bgcolor, f)
+               elif f == 'PCU':
+                       if len(vals['plcnode']['pcu_ids']) > 0:
+                               url = "<a href='http://dendrite.cs.princeton.edu/~soltesz/printbadpcus.php#id%s'>PCU</a>" % vals['plcnode']['pcu_ids'][0]
+                               r_str += "<td nowrap %s>%s</td>" % (bgcolor, url)
+               else:
+                       r_str += "<td nowrap %s>%s</td>" % (bgcolor, f)
+               f_2prev = f_prev
+               f_prev  = f
+       
+       return r_str
+
+
+
+def main(sitefilter):
+       db = soltesz.dbLoad(config.dbname)
+
+       ## Field widths used for printing
+       maxFieldLengths = { 'nodename' : -45,
+                                               'ping' : 6, 
+                                               'ssh' : 6, 
+                                               'pcu' : 7, 
+                                               'category' : 9, 
+                                               'state' : 5, 
+                                               'kernel' : 10.65, 
+                                               'comonstats' : 5, 
+                                               'plcsite' : 12,
+                                               'bootcd' : 10.65}
+       ## create format string based on config.fields
+       fields = {}
+       format = ""
+       format_fields = []
+       for f in config.fields.split(','):
+               fields[f] = "%%(%s)s" % f
+               #if f in maxFieldLengths:
+               #       fields[f] = "%%(%s)%ds" % (f, maxFieldLengths[f])
+               #else:
+               #       fields[f] = "%%(%s)%ds" % (f, 10)
+
+               format_fields.append(fields[f])
+       #print fields
+       for f in config.fields.split(','):
+               format += fields[f] + " "
+       #print format
+
+       d_n = db['nodes']
+       l_nodes = d_n.keys()
+
+       # category by site
+       #bysite = {}
+       #for nodename in l_nodes:
+       #       if 'plcsite' in d_n[nodename]['values'] and \
+       #       'login_base' in d_n[nodename]['values']['plcsite']:
+       #               loginbase = d_n[nodename]['values']['plcsite']['login_base']
+       #               if loginbase not in bysite:
+       #                       bysite[loginbase] = []
+       #               d_n[nodename]['values']['nodename'] = nodename
+       #               bysite[loginbase].append(d_n[nodename]['values'])
+
+       # d2 was an array of [{node}, {}, ...]
+       # the bysite is a loginbase dict of [{node}, {node}]
+       d2 = []
+       for nodename in l_nodes: 
+               vals=d_n[nodename]['values'] 
+               v = {}
+               v.update(vals)
+               v['nodename'] = nodename 
+               if  'plcsite' in vals and  \
+                       'status' in vals['plcsite'] and  \
+                       vals['plcsite']['status'] == "SUCCESS":
+
+                       url = "<a href='printbad.cgi?site=%s'>%s</a>" % ( vals['plcsite']['login_base'],
+                                                                                                                        vals['plcsite']['login_base'])
+
+                       site_string = "%s %2s nodes :: %2s of %4s slices" % ( \
+                                                                                                               url,
+                                                                                                               vals['plcsite']['num_nodes'], 
+                                                                                                               vals['plcsite']['num_slices'], 
+                                                                                                               vals['plcsite']['max_slices'])
+                       loginbase = d_n[nodename]['values']['plcsite']['login_base']
+               else:
+                       #print "ERROR: ", nodename, vals, "<br>"
+                       site_string = "<b>UNKNOWN</b>"
+                       loginbase = ""
+
+               v['site_string'] = site_string
+               v['loginbase'] = loginbase
+               if (sitefilter != None and loginbase == sitefilter) or sitefilter == None:
+                       d2.append(v)
+                       
+
+       if sitefilter != None:
+               config.cmpcategory = True
+       else:
+               config.cmploginbase = True
+               
+
+       if config.cmploginbase:
+               d2.sort(cmp=cmpLoginBase)
+       elif config.cmpping:
+               d2.sort(cmp=cmpPing)
+       elif config.cmpdns:
+               d2.sort(cmp=cmpDNS)
+       elif config.cmpssh:
+               d2.sort(cmp=cmpSSH)
+       elif config.cmpcategory:
+               d2.sort(cmp=cmpCategory)
+       elif config.cmpstate:
+               d2.sort(cmp=cmpState)
+       elif config.cmpdays:
+               d2.sort(cmp=cmpDays)
+       elif config.cmpkernel:
+               d2.sort(cmp=cmpUname)
+       else:
+               d2.sort(cmp=cmpCategory)
+       
+
+       #l_loginbase = bysite.keys()
+       #l_loginbase.sort()
+       print "<table width=80% border=1>"
+       prev_sitestring = ""
+       for row in d2:
+
+               site_string = row['site_string']
+               if site_string != prev_sitestring:
+                       print "<tr><td bgcolor=lightblue nowrap>" 
+                       print site_string
+                       print "</td>"
+               else:
+                       print "<tr><td>&nbsp;</td>"
+
+               prev_sitestring = site_string
+
+               vals = row
+               # convert uname values into a single kernel version string
+               if 'kernel' in vals:
+                       kernel = vals['kernel'].split()
+                       if len(kernel) > 0:
+                               if kernel[0] == "Linux":
+                                       vals['kernel'] = kernel[2]
+                               else:
+                                       vals['ssherror'] = vals['kernel']
+                                       vals['kernel'] = ""
+               else:
+                       vals['ssherror'] = ""
+                       vals['kernel'] = ""
+#                      continue
+               if 'model' in vals or 'protocol' in vals or 'portstatus' in vals:
+                       #vals['model'] = string.replace(vals['model']," ", "&nbsp;")
+                       #vals['protocol'] = vals['protocol'].replace(" ", "&nbsp;")
+                       if vals['model'] == None:
+                               vals['model'] = " "
+                       vals['model'] = string.replace(vals['model']," ", "_")
+                       vals['protocol'] = vals['protocol'].replace(" ", "_")
+                       ps = ""
+                       ports = vals['portstatus']
+                       lports = ports.keys()
+                       lports.sort()
+                       for port in lports:
+                               t = ports[port]
+                               if t != "closed":
+                                       ps += "%s:&nbsp;%s<br>" % (port, ports[port])
+                       if ps == "":
+                               ps = "All_closed"
+                               
+                       vals['portstatus'] = ps
+
+               if 'reboot' in vals:
+                       vals['reboot'] = "%s" % vals['reboot']
+                       vals['reboot'] = vals['reboot'].replace(" ", "_")
+
+               try:
+                       str_fields = []
+                       count = 0
+                       for f in format_fields:
+                               str_fields.append(f % vals)
+                               count += 1
+               except:
+                       print >>sys.stderr, vals
+
+               s = fields_to_html(str_fields, vals)
+               print s
+                       
+               print "\n</tr>"
+
+       print "</table>"
+       print "<table>"
+       keys = categories.keys()
+       keys.sort()
+       for cat in keys:
+               print "<tr>"
+               print "<th nowrap align=left>Total %s</th>" % cat
+               print "<td align=left>%s</td>" % categories[cat]
+               print "</tr>"
+       print "</table>"
+
+import cgi
+import cgitb; 
+cgitb.enable()
+import sys
+
+form = cgi.FieldStorage()
+myfilter = None
+
+if form.has_key('site'):
+       myfilter = form.getvalue("site")
+else:
+       myfilter = None
+
+
+if __name__ == '__main__':
+       parser = OptionParser()
+       parser.set_defaults(cmpdays=False, 
+                                               comon="sshstatus", 
+                                               fields="nodename,ping,ssh,pcu,category,state,kernel,bootcd", 
+                                               dbname="findbad", # -070724-1", 
+                                               cmpping=False, 
+                                               cmpdns=False, 
+                                               cmploginbase=False, 
+                                               cmpssh=False, 
+                                               cmpcategory=False,
+                                               cmpstate=False)
+       parser.add_option("", "--fields",       dest="fields", help="")
+       parser.add_option("", "--dbname",       dest="dbname", help="")
+       parser.add_option("", "--days",         dest="cmpdays", action="store_true", help="")
+       parser.add_option("", "--ping",         dest="cmpping", action="store_true", help="")
+       parser.add_option("", "--dns",          dest="cmpdns", action="store_true", help="")
+       parser.add_option("", "--ssh",          dest="cmpssh",  action="store_true", help="")
+       parser.add_option("", "--loginbase",dest="cmploginbase",action="store_true", help="")
+       parser.add_option("", "--category",     dest="cmpcategory", action="store_true", help="")
+       parser.add_option("", "--kernel",       dest="cmpkernel", action="store_true", help="")
+       parser.add_option("", "--state",        dest="cmpstate", action="store_true", help="")
+       parser.add_option("", "--comon",        dest="comon",   help="")
+       config = config(parser)
+       config.parse_args()
+       print "Content-Type: text/html\r\n"
+       print "<html><body>\n"
+       if len(sys.argv) > 1:
+               if sys.argv[1] == "ssherror":
+                       ssherror = True
+       main(myfilter)
+       print "</body></html>\n"
diff --git a/www/printbadpcus.php b/www/printbadpcus.php
new file mode 100644 (file)
index 0000000..fb86fa3
--- /dev/null
@@ -0,0 +1,234 @@
+<?php 
+
+
+function pcu_link($pcu) 
+{ 
+       return "https://www.planet-lab.org/db/sites/pcu.php?id=" . $pcu['pcu_id']; 
+}
+
+function pcu_name($pcu)
+{
+       if ( $pcu['hostname'] != NULL and $pcu['hostname'] != "" ):
+               return $pcu['hostname'];
+       else: 
+               return $pcu['ip'];
+       endif;
+}
+function pcu_entry($pcu)
+{
+       if ( count($pcu['complete_entry']) > 0 ) {
+               return join("<BR>", $pcu['complete_entry']);
+       } else {
+               return "&nbsp;";
+       }
+}
+
+function format_ports($pcu)
+{
+       $str = "";
+       #print print_r(is_array($pcu)) . "<BR>";
+       #print print_r(array_key_exists('portstatus', $pcu)) . "<BR>";
+       if ( is_array($pcu) && array_key_exists('portstatus', $pcu) )
+       {
+               $portstat = $pcu['portstatus'];
+
+               #foreach ( array('22', '23', '80', '443') $portstat as $port => $state)
+               foreach ( array('22', '23', '80', '443') as $port)
+               {
+                       $state = $portstat[$port];
+                       switch ($state)
+                       {
+                               case "open":
+                                       $color = "lightgreen";
+                                       break;
+                               case "filtered":
+                                       $color = "gold";
+                                       break;
+                               case "closed":
+                                       $color = "indianred";
+                                       break;
+                               default:
+                                       $color = "white";
+                                       break;
+                       }
+                       $str .= "<span style='background-color: $color'>$port</span>&nbsp;"; 
+                       #  . ":&nbsp;" . $state . "<br>";
+               }
+       } else {
+       #       print print_r(is_array($pcu)) . "<BR>";
+       #       print print_r(array_key_exists('portstatus', $pcu)) . "<BR>";
+               #echo "<pre>";
+               #print_r($pcu['portstatus']);
+               #echo "</pre>";
+       }
+       if ( $str == "" )
+       {
+               $str = "Closed/Filtered";
+       }
+       return $str;
+}
+function DNS_to_color($dns)
+{
+       switch ($dns)
+       {
+               case "DNS-OK":
+                       return 'lightgreen';
+               case "NOHOSTNAME":
+                       return 'white';
+               case "DNS-MISMATCH":
+                       return 'gold';
+               case "NO-DNS-OR-IP":
+               case "DNS-NOENTRY":
+                       return 'indianred';
+       }
+       return 'white';
+}
+
+function reboot_to_color($reboot)
+{
+       switch ($reboot)
+       {
+               case "0":
+                       return "darkseagreen";
+                       break;
+               case "NetDown":
+                       return "lightgrey";
+                       break;
+               case "Not_Run":
+                       return "lightgrey";
+                       break;
+               case "Unsupported_PCU":
+                       return "indianred";
+                       break;
+               default:
+                       if ( strpos($reboot, "error") >= 0)
+                       {
+                               return "indianred";
+                       } else {
+                               return 'white';
+                       }
+                       break;
+       }
+       return "white";
+}
+
+function get_pcuid($pcu) { return $pcu['pcu_id']; }
+function get_dns($pcu) { return $pcu['dnsmatch']; }
+function get_dryrun($pcu) { return $pcu['reboot']; }
+function get_model($pcu) { return $pcu['model']; }
+function get_category_link($category,$header) 
+{ 
+       return "<a href='printbadpcus.php?category=$category'>$header</a>"; 
+}
+
+include 'soltesz.php';
+$p = new Pickle();
+$findbad = $p->load("findbadpcus");
+$findbadpcus = array_keys($findbad['nodes']);
+
+$pculist = array();
+$c = 0;
+foreach ( $findbadpcus as $pcu_id )
+{
+       if ( is_array($findbad['nodes'][$pcu_id]) ) 
+       {
+               #if ( in_array('values', $findbad['nodes'][$pcu]) )
+               #{
+               #       echo $pcu . " true<BR>";
+               #} else{
+               #       echo $pcu . " false<br>";
+               #}
+               if ( array_key_exists('values', $findbad['nodes'][$pcu_id]) )
+               {
+                       $pculist[] = $findbad['nodes'][$pcu_id]['values'];
+               }
+       }
+}
+$total = count($pculist);
+
+
+## Sort the pculist
+
+#$pcu_ids = array_map('get_pcuid', $pculist);
+#array_multisort($pcu_ids, SORT_ASC, SORT_NUMERIC, $pculist);
+
+#$dns_ids = array_map('get_dns', $pculist);
+#array_multisort($dns_ids, SORT_ASC, SORT_STRING, $pculist);
+
+#$dry_ids = array_map('get_dryrun', $pculist);
+#array_multisort($dry_ids, SORT_ASC, SORT_STRING, $pculist);
+if ( $_GET['category'] ) 
+{
+       $category = $_GET['category'];
+       if ( $category == "node_ids" )
+       {
+               $newfunc = create_function('$pcu', 'return count($pcu[\'' . $category . '\']);');
+       } else {
+               $newfunc = create_function('$pcu', 'return $pcu[\'' . $category . '\'];');
+       }
+       if ( $newfunc != "" )
+       {
+               $fields = array_map($newfunc, $pculist);
+               array_multisort($fields, SORT_ASC, SORT_STRING, $pculist);
+       } else {
+               echo "ERROR create_function == null<BR>";
+       }
+}
+
+if ( $_GET['auth'] )
+{
+       $auth = True;
+} else {
+       $auth = False;
+}
+
+
+//array_multisort($protocols, SORT_ASC, SORT_STRING, $pculist);
+?>
+
+<title>PLC PCU Info</title>
+<html>
+<body>
+
+Total PCUs : <?= $total ?>
+<table border=1>
+               <tr>
+                       <th>Count</th>
+                       <th><?= get_category_link("pcu_id", "PCU ID") ?></th>
+                       <th><?= get_category_link("hostname", "Hostname") ?></th>
+                       <th><?= get_category_link("complete_entry", "Incomplete Fields") ?></th>
+                       <th><?= get_category_link("dnsmatch", "DNS Status") ?></th>
+                       <th><?= get_category_link("portstatus", "Port Status") ?></th>
+                       <th><?= get_category_link("reboot", "Dry Run Results") ?></th>
+                       <th><?= get_category_link("model", "Model") ?></th>
+                       <th><?= get_category_link("node_ids", "Nodes") ?></th>
+                       <?php if ( $auth ): ?>
+                               <th>Username</th>
+                               <th>Password</th>
+                               <th>Notes</th>
+                       <?php endif; ?>
+               </tr>
+<?php $count = 0; ?>
+<?php foreach ( $pculist as $pcu ): ?>
+               <tr>
+                       <td><?= $count ?></td>
+                       <td id='id<?= $pcu['pcu_id'] ?>'><a href='<?= pcu_link($pcu) ?>'><?= $pcu['pcu_id'] ?></a></td>
+                       <td><?= pcu_name($pcu) ?></td>
+                       <td><?= pcu_entry($pcu) ?></td>
+                       <td bgcolor='<?= DNS_to_color($pcu['dnsmatch']) ?>'><?= $pcu['dnsmatch'] ?></td>
+                       <td><?= format_ports($pcu) ?></td>
+                       <td bgcolor='<?= reboot_to_color($pcu['reboot']) ?>'><?= $pcu['reboot'] ?></td>
+                       <td nowrap><?= $pcu['model'] ?></td>
+                       <td><?= count( $pcu['node_ids'] ) ?></td>
+                       <?php if ( $auth ): ?>
+                               <td><?= ( $pcu['username'] ? $pcu['username'] : "&nbsp;" ) ?></td>
+                               <td><?= $pcu['password'] ?></td>
+                               <td><?= $pcu['notes'] ?></td>
+                       <?php endif; ?>
+               </tr>
+<?php $count += 1; ?>
+<?php endforeach; ?>
+</table>
+
+</body>
+</html>
diff --git a/www/siteactions.cgi b/www/siteactions.cgi
new file mode 100755 (executable)
index 0000000..425e468
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+
+# Read in the act_* databases and print out a human readable version
+
+import sys
+import time
+import getopt
+import soltesz
+
+
+def fields_to_html(fields):
+       colorMap = { 'PING'  : 'darkseagreen',
+                                'NOPING': 'darksalmon',
+                                'SSH': 'darkseagreen',
+                                'NOSSH': 'indianred',
+                                'PCU': 'darkseagreen',
+                                'NOPCU': 'lightgrey',
+                                'OLDBOOTCD': 'crimson',
+                                'DOWN': 'indianred',
+                                'ALPHA': 'gold',
+                                'ERROR': 'crimson',
+                                'PROD': 'darkseagreen',
+                                'DEBUG': 'darksalmon',
+                                'DEBUG': 'darksalmon',
+                                'BOOT': 'lightgreen'}
+       r_str = ""
+       for f in fields:
+               if f in colorMap:
+                       bgcolor="bgcolor='%s'" % colorMap[f]
+               else:
+                       bgcolor=""
+               r_str += "<td nowrap %s>%s</td>" % (bgcolor, f)
+       
+       return r_str
+       
+def rtTicketLink(rt_ticket):
+       link = """<a href="https://rt.planet-lab.org/Ticket/Display.html?user=guest&pass=guest&id=%s">RT #%s</a>""" % (rt_ticket, rt_ticket)
+       return link
+
+def main():
+
+       total_sites = 0
+       total_nodes = 0
+       total_restored = 0
+       total_down = 0
+
+       act_all = soltesz.dbLoad("act_all")
+       plcdb_hn2lb = soltesz.dbLoad("plcdb_hn2lb")
+       s_nodenames = ""
+       sickdb = {}
+
+       sorted_keys = act_all.keys()
+       sorted_keys.sort()
+       for nodename in sorted_keys:
+               diag_nodelist = act_all[nodename]
+               if nodename in plcdb_hn2lb:
+                       lb = plcdb_hn2lb[nodename]
+                       if lb not in sickdb:
+                               sickdb[lb] = {}
+                       sickdb[lb][nodename] = diag_nodelist
+
+       sorted_keys = sickdb.keys()
+       sorted_keys.sort()
+       print "<table width=80% border=1>"
+       for loginbase in sorted_keys:
+               nodedict = sickdb[loginbase]
+               sort_nodekeys = nodedict.keys()
+               sort_nodekeys.sort()
+               print "<tr><td bgcolor=lightblue nowrap>",
+               print loginbase,
+               print "</td><td colspan=5>&nbsp;</td>",
+               print "</tr>"
+               total_sites += 1
+               for nodename in sort_nodekeys:
+                       total_nodes += 1
+                       if len(act_all[nodename]) == 0:
+                               #print "<tr><td>%s</td>" % (nodename) 
+                               #print "<td>has no events</td></tr>"
+                               continue
+                       else:
+                               # print just the latest event
+                               event = act_all[nodename][0]
+                               fields = []
+                               fields += [nodename]
+                               if 'time' in event:
+                                       s_time=time.strftime("%Y/%m/%d %H:%M:%S",
+                                                                                       time.gmtime(event['time']))
+                                       fields += [s_time]
+                               if 'ticket_id' in event and event['ticket_id'] != "":
+                                       link = rtTicketLink(event['ticket_id'])
+                                       fields += [link]
+                               else:
+                                       if 'found_rt_ticket' in event and event['found_rt_ticket'] != "":
+                                               link = rtTicketLink(event['found_rt_ticket'])
+                                               fields += [link]
+                                       else:
+                                               fields += ["No Known RT Ticket"]
+
+                               if event['action'] == "close_rt":
+                                       total_restored += 1
+                               else:
+                                       total_down += 1
+
+                               for f in ['category', 'action', 'stage', 'info']:
+                                       if 'stage' in f and 'stage' in event and 'stage' in event['stage']:
+                                               # truncate the stage_ part.
+                                               event['stage'] = event['stage'][6:]
+                                       if f in event:
+                                               if type(event[f]) == type([]):
+                                                       fields += event[f]
+                                               else:
+                                                       fields += [event[f]]
+                                       else:
+                                               fields += ["&nbsp;"]
+
+                               print "<tr>",
+                               print fields_to_html(fields),
+                               print "</tr>"
+
+       print "</table>"
+       print "<table>"
+       print "<tr>"
+       print "<th>Sites</th>"
+       print "<th>Nodes</th>"
+       print "<th>Restored</th>"
+       print "<th>Down</th>"
+       print "</tr>"
+
+       print "<tr>"
+       print "<td>%s</td>" % total_sites
+       print "<td>%s</td>" % total_nodes
+       print "<td>%s</td>" % total_restored
+       print "<td>%s</td>" % total_down
+
+       print "</tr>"
+       print "</table>"
+
+       print s_nodenames
+
+       
+if __name__ == '__main__':
+       print "Content-Type: text/html\r\n"
+       print "<html><body>\n"
+       main()
+       print "</body></html>\n"
diff --git a/www/soltesz.php b/www/soltesz.php
new file mode 100644 (file)
index 0000000..bef3e03
--- /dev/null
@@ -0,0 +1,67 @@
+
+<?php 
+
+// PICKLE_PATH="/home/soltesz/research/planetlab/monitor3/pdb";
+define("PICKLE_PATH", "pdb");
+
+class Pickle
+{
+       public function load($name)
+       {
+               if ( ! $this->exists("production." . $name) )
+               {
+                       print "Exception: No such file %s" . $name . "\n";
+                       return NULL;
+               }
+               $name = "production." . $name;
+               $fname = $this->__file($name);
+               $o = unserialize(file_get_contents($fname));
+
+               return $o;
+       }
+       public function dump($name, $obj)
+       {
+               if ( ! file_exists(PICKLE_PATH) )
+               {
+                       if ( ! mkdir(PICKLE_PATH, 0777, True) )
+                       {
+                               print "Exception: Unable to create directory :" . PICKLE_PATH . "\n";
+                       }
+               }
+               $name = "production." . $name;
+               $fname = $this->__file($name);
+
+               return file_put_contents($fname, serialize($obj));
+       }
+       private function __file($name)
+       {
+               return sprintf("%s/%s.phpserial", PICKLE_PATH, $name);
+       }
+
+       public function exists($name)
+       {
+               return file_exists($this->__file($name));
+       }
+
+       public function remove($name)
+       {
+               return unlink($this->__file($name));
+       }
+
+       public function if_cached_else($cond, $name, $function)
+       {
+               if ( $cond and $this->exists("production.%s" % $name) )
+               {
+                       $o = $this->load($name);
+               } else {
+                       $o = $function();
+                       if ($cond)
+                       {
+                               $this->dump($name, $o); # cache the object using 'name'
+                       }
+               }
+               return o;
+       }
+}
+
+?>