#!/opt/perl5.6.0/bin/perl -wT ############################################################################### #### index.cgi #### $Id: index.cgi,v 1.18 2004/01/30 04:54:56 ssklar Exp ssklar $ ############################################################################### use strict; use CGI ':standard'; use CGI::Carp 'fatalsToBrowser'; use lib '/main/systory/rrdtool-perl56/lib/perl'; use RRDs; ############################################################################### my $basedir = "/main/systory"; my $groupdir = "$basedir/group"; my $datadir = "$basedir/host"; ############################################################################### my %stats = ( cpu => "CPU", load => "LOAD", swap => "SWAP" ); my %spans = ( day => "1d", twodays => "2d", week => "7d", twoweeks => "14d", month => "30d", sixmonths => "180d", year => "365d" ); my %spans_pretty = ( '1d' => "last day", '2d' => "last two days", '7d' => "last week", '14d' => "last two weeks", '30d' => "last month", '180d' => "last six months", '365d' => "last year" ); ############################################################################### ## main my ($group, @hosts, @stats, @spans, @notes); &determine_hosts; &determine_stats; &determine_spans; &print_page_top; if (defined (param('graph')) || defined (param('g'))) { &generate_graphs } else { &generate_index }; if (scalar(@notes) > 0) { print "
"; print @notes; print "

"; }; &print_page_bottom; exit 0; ## END main ############################################################################### sub note { ## formats an message for proper presentation in the webpage and ## pushes it onto the @notes array. my $message = join (" ", @_); push (@notes, $message . "
\n"); }; ## END sub note ############################################################################### sub print_page_top { my $title = "systory"; if ($group) { $title .= " | group: $group" } elsif (scalar (@hosts) >= 1) { $title .= " | host: $hosts[0]" }; if (defined (param('graph')) || defined (param('g'))) { if (scalar (@stats) == 1) { $title .= " | stat: $stats[0]" } elsif (scalar (@stats) > 1) { $title .= " | stats: multiple" }; if (scalar (@spans) == 1) { $title .= " | span: $spans_pretty{$spans[0]}" } elsif (scalar (@spans) > 1) { $title .= " | spans: multiple" }; }; if ( defined (param('print'))) { print header ( -type => "text/html", -expires => "+10m" ); print ' '; print "$title"; print ' '; print '
'; print '
'; return } else { opendir (GROUPDIR, $groupdir) || die "Fatal: can't open groupdir $groupdir: $!"; my @groups = sort (grep { -f "$groupdir/$_" && /^\w+/ } readdir (GROUPDIR)); closedir GROUPDIR; print header ( -type => "text/html", -expires => "+10m" ); print ' '; print "$title"; print ' '; print '
'; print ' END my $hostindex = "0"; my $rowcolor; foreach (@hosts) { open(SUMMARY, "$datadir/$_/summary") || do { note "no summary found for host $_" ; next }; my $age = sprintf ("%d", time() - (sub { $_[9] } -> (stat SUMMARY))); $age = ($age > 86399) ? "" . sprintf ("%d", $age / 86400) . " d" : ($age > 3549) ? "" . sprintf ("%d", $age / 3600) . " h" : ($age > 601) ? "" . sprintf ("%d", $age / 600) . " m" : ($age > 300) ? "" . sprintf ("%d", $age ) . " s" : $age . " s"; my ($host, $os, $model, $proc_info, $ram, $uptime) = split (/\|/, ()); $hostindex++; if ($hostindex % 2) { $rowcolor = "#FFFFFF" } else { $rowcolor = "#EFEEED" }; print "\n"; print ''; print "\n"; close SUMMARY; }; print "\n"; print "
'; print '

systory

'; print '

Click on a host name from the table on the right to view all statistics for all time spans or Check one or more hosts and/or one or more groups, one or more statistics, and one or more time spans.

'; #### here goes the form elements print '
'; print ''; #### the "group" selection menu ... print '
group:
'; print ''; #### the "stat" selection menu ... print '
stat:
'; print ''; #### the "span" selection menu ... print '
span:
'; print ''; #### the graph size selection ... print '
graph size:
'; print ' small
'; print ' medium
'; print ' large
'; #### the printer-friendly checkbox ... print '
printer friendly
(no selection form)
'; #### the "submit" button ... print '




'; #print "

param dump:

\n"; #print CGI::dump(); print '
'; return }; }; ## END print_page_top ############################################################################### sub determine_hosts { if (param('group') =~ /^all$/i) { param(-name => 'host', -value => 'all'); }; unless (param('host') || param('group')) { param(-name => 'host', -value => 'all'); param(-name => 'group', -value => 'all'); $group = "all"; }; if (param('host')) { foreach (param('host')) { if ($_ =~ /^all$/i) { opendir (DATADIR, $datadir) || die "Can't open datadir $datadir: $!"; @hosts = sort (grep { -d "$datadir/$_" && /^\w+/ } readdir (DATADIR)); closedir DATADIR; } elsif (-d "$datadir/$_" && $_ =~ /(^\w.+$)/) { push (@hosts, $1) } else { note ("Invalid host $_ specified."); }; }; } elsif (param('group') && param('group') =~ /(^\w+.*)/) { $group = "$1"; if (-f "$groupdir/$group") { open (GROUPFILE, "$groupdir/$group") || die "Can't read group file $groupdir/$group: $!"; while () { next if /^$/; chomp; if (-d "$datadir/$_") { push (@hosts, $_); } else { note ("No data available for host $_ in group $group."); }; }; close GROUPFILE; } else { note ("Invalid group $group specified."); }; my @hosts_sorted = sort {$::a cmp $::b} @hosts; @hosts = @hosts_sorted; }; }; ## END determine_hosts ############################################################################### sub generate_index { print <
Host
OS
Model
CPUs
RAM (MB)
Uptime
Last Update
" . $host . " $os $model $proc_info $ram $uptime $age
 
\n"; } ## END generate_index ############################################################################### sub determine_stats { unless (param('stat')) { param(-name => 'stat', -value => 'all') }; foreach (param('stat')) { if ($_ =~ /^all$/i) { foreach (keys (%stats)) { push (@stats, $stats{$_}); }; } elsif (exists ($stats{"\L$_"}) && $_ =~ /^(\w+)$/) { push (@stats, $stats{"\L$1"}) } else { note ("Invalid stat $_ specified."); }; }; } ## END determine_stats ############################################################################### sub determine_spans { unless (param('span')) { param(-name => 'span', -value => 'all') }; foreach (param('span')) { if ($_ =~ /^all$/i) { foreach (keys (%spans)) { push (@spans, $spans{$_}); }; } elsif (exists ($spans{"\L$_"}) && $_ =~ /^(\w+)$/) { push (@spans, $spans{"\L$_"}) } else { note ("Invalid span $_ specified."); }; }; my @spans_sorted = sort {$::a <=> $::b} @spans; @spans = @spans_sorted; } ## END determine_spans ############################################################################### sub generate_graphs { print ''; my @graph_common_args = ( "--lazy", "--no-minor", "--lower-limit", "0", "--color", "BACK#FFFFFF", "--color", "CANVAS#FFFFFF", "--color", "MGRID#666666", "--color", "SHADEA#FFFFFF", "--color", "SHADEB#FFFFFF" ); my $gsize; if (param('gsize') =~ /^sm/i) { push (@graph_common_args, "--width", "400", "--height", "100"); $gsize = "small"; } elsif (param('gsize') =~ /^la/i) { push (@graph_common_args, "--width", "800", "--height", "200"); $gsize = "large"; } else { push (@graph_common_args, "--width", "600", "--height", "150"); $gsize = "medium"; }; my @graph_args; foreach my $host (@hosts) { print " \n"; print ""; print ""; foreach my $span (@spans) { print "", @$imgtag); }; print "\n"; }; print '"; print "\n"; }; print "

$host

top
"; print "
$spans_pretty{$span}
\n"; print "\n"; foreach my $stat (@stats) { print "\n"; @graph_args = @graph_common_args; if ($stat eq 'CPU') { push (@graph_args, "--upper-limit", "100", "--end", "now-5min", "--start", "now-$span", "--title", "$host: CPU Usage ($spans_pretty{$span})", "--vertical-label", "% Busy", "--imginfo", "\"$host", "DEF:A=$datadir/$host/CPU.rrd:user_p:AVERAGE", "DEF:B=$datadir/$host/CPU.rrd:system_p:AVERAGE", "CDEF:C=A,B,+", "CDEF:NODATA=A,UN,INF,UNKN,IF", "AREA:NODATA#EFEEED" ); if ($gsize eq "small") { push (@graph_args, "AREA:A#000066:% User ", "STACK:B#009900:% System ", "LINE1:C#FFFFFF:Total " ); } else { push (@graph_args, "AREA:A#000066:% User ", "GPRINT:A:LAST:\nCur\\: %3.2lf", "GPRINT:A:AVERAGE:Avg\\: %3.2lf", "GPRINT:A:MIN:Min\\: %3.2lf", "GPRINT:A:MAX:Max\\: %3.2lf\\n", "STACK:B#009900:% System ", "GPRINT:B:LAST:Cur\\: %3.2lf", "GPRINT:B:AVERAGE:Avg\\: %3.2lf", "GPRINT:B:MIN:Min\\: %3.2lf", "GPRINT:B:MAX:Max\\: %3.2lf\\n", "LINE1:C#FFFFFF:Total ", "GPRINT:C:LAST:Cur\\: %3.2lf", "GPRINT:C:AVERAGE:Avg\\: %3.2lf", "GPRINT:C:MIN:Min\\: %3.2lf", "GPRINT:C:MAX:Max\\: %3.2lf" ); }; } elsif ($stat eq 'LOAD') { push (@graph_args, "--upper-limit", "10", "--end", "now-5min", "--start", "now-$span", "--title", "$host: Load Average ($spans_pretty{$span})", "--vertical-label", "Load Average", "--imginfo", "\"$host", "DEF:A=$datadir/$host/LOAD.rrd:load_01:AVERAGE", "DEF:B=$datadir/$host/LOAD.rrd:load_05:AVERAGE", "DEF:C=$datadir/$host/LOAD.rrd:load_15:AVERAGE", "CDEF:NODATA=A,UN,INF,UNKN,IF", "AREA:NODATA#EFEEED", ); if ($gsize eq "small") { push (@graph_args, "LINE1:A#000066:1 Minute ", "LINE2:B#009900:5 Minute ", "LINE3:C#FF0000:15 Minute" ); } else { push (@graph_args, "LINE1:A#000066:1 Minute ", "GPRINT:A:LAST:\nCur\\: %3.2lf", "GPRINT:A:AVERAGE:Avg\\: %3.2lf", "GPRINT:A:MIN:Min\\: %3.2lf", "GPRINT:A:MAX:Max\\: %3.2lf\\n", "LINE2:B#009900:5 Minute ", "GPRINT:B:LAST:Cur\\: %3.2lf", "GPRINT:B:AVERAGE:Avg\\: %3.2lf", "GPRINT:B:MIN:Min\\: %3.2lf", "GPRINT:B:MAX:Max\\: %3.2lf\\n", "LINE3:C#FF0000:15 Minute", "GPRINT:C:LAST:Cur\\: %3.2lf", "GPRINT:C:AVERAGE:Avg\\: %3.2lf", "GPRINT:C:MIN:Min\\: %3.2lf", "GPRINT:C:MAX:Max\\: %3.2lf" ); }; } elsif ($stat eq 'SWAP') { push (@graph_args, "--upper-limit", "100", "--end", "now-5min", "--start", "now-$span", "--title", "$host: Paging Usage ($spans_pretty{$span})", "--vertical-label", "% Swap Used", "--imginfo", "\"$host", "DEF:A=$datadir/$host/SWAP.rrd:swap_p:AVERAGE", "CDEF:NODATA=A,UN,INF,UNKN,IF", "AREA:NODATA#EFEEED", ); if ($gsize eq "small") { push (@graph_args, "AREA:A#000066:% Swap Used" ); } else { push (@graph_args, "AREA:A#000066:% Swap Used", "GPRINT:A:LAST:\nCur\\: %3.2lf", "GPRINT:A:AVERAGE:Avg\\: %3.2lf", "GPRINT:A:MIN:Min\\: %3.2lf", "GPRINT:A:MAX:Max\\: %3.2lf" ); }; }; my $filename = "graphs/$host.$stat.$span.$gsize.png"; my ($imgtag, $xsize, $ysize) = RRDs::graph ($filename, @graph_args); my $rrderror = RRDs::error; if ($rrderror) { print "

RRD Error: $rrderror

\n"; } else { printf ("
%s
'; print "\n"; }; print "
"; }; ## END generate_graphs ############################################################################### sub print_page_bottom { print '
'; print ''; print '
'; print '"; print '
'; print "Page generated " . scalar localtime() . ".
Generation time: " . scalar time() - $^T . " seconds.
'; print ''; return }; ## END print_page_bottom ###############################################################################