''' Generate reports from the database ''' import time import sys import pandokia.text_table as text_table import pandokia.common try: from io import StringIO except ImportError: from StringIO import StringIO # maybe the output is html 3.2 - in any case, it is way simpler than # more recent standards. # this will be reset by the cgi main program if we are in a real cgi cginame = 'arf.cgi' # def info_callback_status( db, run, tablename, host, cmd ) : c = db.cursor() c.execute("SELECT status FROM sm_status WHERE run = ? AND host = ? AND tablename = ? AND cmd = ?",( run, host, tablename, cmd ) ) status, = c.fetchone() return { 'text' : status } # ok_status = ( '0', 'N', 'S' ) simple_status = ( 'N', 'P', 'S', 'W' ) def info_callback_gui( db, run, tablename, host, cmd ) : c = db.cursor() c.execute("SELECT status, start_time, end_time, logs FROM sm_status WHERE run = ? AND host = ? AND tablename = ? AND cmd = ?",( run, host, tablename, cmd ) ) x = c.fetchone() if x is None : return '' status, start_time, end_time, logs_exist = x if start_time is None : start_time = '' if end_time is None : end_time = '' # t_result = '%s %s %s'%(status, start_time, end_time ) t_result = status if status not in ok_status : d_status = '%s'%status else : d_status = status if status in simple_status : link = '%s'%d_status else : link = "%s" %(cginame, run, host, tablename, cmd, d_status ) if not status in simple_status : try : st = pandokia.common.parse_time(start_time) st = '%d:%02d'%(st.hour,st.minute) except ValueError : st = '?' try : et = pandokia.common.parse_time(end_time ) et = '%d:%02d'%(et.hour,et.minute) except ValueError : et = '?' link = link + " : " + st + " - " + et # h_result = '%s %s %s %s'%(link, d_status, start_time, end_time) if logs_exist: link += "
%s" %(cginame, run, host, tablename, cmd, 'logs' ) h_result = link return { 'text' : t_result, 'html' : h_result } # def info_callback_debug_table_cell( db, run, tablename, cmd, host ) : return { 'text' : '%s %s %s %s' % ( run, host, tablename, cmd ) } # def get_table_list( db, run_name ) : c = db.cursor() c.execute("select max(depth) as d, tablename from sm_status where run = ? group by tablename order by d asc",(run_name,)) table_list = [ x for x in c ] # table_list contains ( depth, tablename ) return table_list # a single table in the report - covers commands tablename/* def get_table( db, run_name, tablename, info_callback, showdepth=0 ) : t = text_table.text_table() t.set_html_table_attributes('border=1') t.define_column('-',html=' ',showname='-') # the command name in column 0 if showdepth : t.define_column('depth') c = db.cursor() c.execute("select distinct host from sm_status where tablename = ? and run = ? order by host asc",(tablename, run_name)) for host, in c : t.define_column(host) c.execute("select cmd, max(depth) as d from sm_status where tablename = ? and run = ? group by cmd order by d asc",(tablename, run_name)) row = -1 cmd_to_row = { } for cmd, depth in c : row = row + 1 cmd_to_row[cmd] = row cmd_html = ' %s'%(tablename, cmd, cmd) t.set_value(row, 0, cmd, html=cmd_html) if showdepth : t.set_value(row, 'depth', depth) c.execute("""select cmd, host, status, start_time, end_time, notes from sm_status where tablename = ? and run = ? order by cmd asc """, ( tablename, run_name ) ) t.sm_host_failures = { } # list of failures on this host row = 0 for x in c : cmd, host, status, start_time, end_time, notes = x try : if ( status in ( 'E', 'P' ) ) or ( int(status) != 0 ) : t.sm_host_failures[host] = t.sm_host_failures.get(host,[]) + [ ( tablename, cmd ) ] except ValueError : pass row = cmd_to_row[cmd] info = info_callback( db, run_name, tablename, host, cmd ) if 'html' in info : t.set_value( row, host, text=info['text'], html=info['html'] ) else : t.set_value( row, host, text=info['text']) t.pad() return t # class raw_report(object): def __init__( self, db, run_name, info_callback ) : table_list = get_table_list(db, run_name) self.table_header = [ ] self.table_body = [ ] self.host_failures = { } for depth, tablename in table_list : self.table_header.append( tablename ) t = get_table( db, run_name, tablename, info_callback, showdepth=1 ) self.table_body.append( t ) for x in t.sm_host_failures : self.host_failures[x] = self.host_failures.get(x,[]) + t.sm_host_failures[x] def report_text( db, run_name, info_callback = info_callback_status ) : raw = raw_report( db, run_name, info_callback ) s = StringIO() table_list = get_table_list(db, run_name) if len(raw.host_failures) > 0 : s.write('hosts with failures:\n') t = text_table.text_table() for x in sorted(raw.host_failures) : t.set_value(0,x,raw.host_failures[x]) s.write(t.get_track_wiki(headings=True)) for header, body in zip( raw.table_header, raw.table_body ) : s.write("------\n") s.write(header) s.write('\n') s.write( body.get_trac_wiki(headings=True) ) return s.getvalue() # def report_html( db, run_name, info_callback = info_callback_status, hlevel=1 ) : raw = raw_report( db, run_name, info_callback ) s = StringIO() s.write('%s\n'%(hlevel,run_name,hlevel)) hlevel = hlevel + 1 if len(raw.host_failures) > 0 : s.write('hosts with failures\n'%(hlevel,hlevel)) t = text_table.text_table() t.set_html_table_attributes('border=1') for x in sorted(raw.host_failures) : h = '%d
\n'%len(raw.host_failures[x]) for table, cmd in raw.host_failures[x] : name = '%s/%s'%(table,cmd) h = h + '%s
\n'%(name,name) t.set_value(0,x,h, html=h) s.write(t.get_html()) for header, body in zip( raw.table_header, raw.table_body ) : s.write('%s\n'%(hlevel,header,hlevel)) s.write(body.get_html()) return s.getvalue() # def main() : import steuermann.config db = steuermann.config.open_db() print(report_html( db, 'arf2011-08-30 16:52:23.928381' )) if __name__ == '__main__' : main()