#!/usr/bin/perl -w #-d
#
# sar/iostat graphing tool based on rrdtool
# (c) 2004 B. Cornec HP <bruno.cornec@hp.com>
# Licensed under the GPL or Artistic License
#
# Original Charter: Monitor CPU/Load/Net_eth0|2 (io/s)/Disk (io/s) 
# 1 mesure par 20 seconde
# So the script has been developped first with that context in mind
# trying to be generic enough to be expandable later on
# More work needs to be done, some code factorized, ...
#
#
use strict;		# Always :-)
use RRDs;		# for data management and graphing
use Data::Dumper;	# for debug
use HTML::AsSubs;	# for HTML generation
use Storable;		# for data exchange
use Date::Manip;	# for timestamp
use Config::Auto;	# for config file
use sario2rrd qw(from_epoch);
                        # local common functions

# Avoid localisation problems in sar
$ENV{LANG}="C";

#
# Begin of configuration options
#
my $dir = "sar2rrd"; 	# Place under the html dir of user apache
			# Under that directory you should have one
			# directory per machine and in it all the
			# files resulting form the sar and iostat
			# commands (saxx and ioxx). Look at the 
			# cron file and related script

my ($l,$p,$uid,$gid,$q,$c,$gc,$apache,$empty) = getpwnam("apache") or die "apache not in passwd file";
my $base = "$apache/html/$dir";
my $config = Config::Auto::parse("$base/$dir.conf");
my @machines = @{$config->{machines}};
my @shots = @{$config->{shots}};
my $lgshot = $config->{lgshot};

my $debug = 0;
foreach my $a (@ARGV) {
	$debug++ if ($a =~ /-v/);
	$| = 1;		# Flush STDOUT
}
my $m;
my %t;
my %attrio = %{ retrieve("$base/$config->{svgio}") };
my %attrsar = %{ retrieve("$base/$config->{svgsar}") };

my $h = "$base/dgi.html";
open (MAIN, "> $h") || die "Unable to create $h : $!";
my @hm = (h1("sar2rrd - sar/iostats monitoring via rrdtool"),
	p("List of systems to monitor:"));
my @index;
my @tmp1;
my @tmp2;

print Dumper($config) if ($debug > 1);

foreach $m (@machines) {
	#
	# The graphs/HTML generation
	#
	push @index,li(a({href=>"$m/dgi.html"}, "$m"));
	my $hm = "$base/$m/dgi.html";
	open (MACHINE, "> $hm") || die "Unable to create $hm : $!";
	my @hhm = (h1("sar2rrd - Monitoring $m"));
	my $img="$base/$m/img";
	print "Graphing rrd base for $m under $img\n" if ($debug > 0);
	my $cpt = 1;
	foreach my $t (@shots) {
		@tmp1 = ();
		@tmp2 = ();
		my $ht = "$base/$m/tir-$cpt.html";
		open (TIR, "> $ht") || die "Unable to create $ht : $!";
		my @hht = (h1("sar2rrd - Monitoring $m - Shot $cpt"));
		my $sdt = UnixDate($t,"%s");
		my $edt = $sdt + $lgshot;
		my $sdtiso = from_epoch($sdt);
		my $edtiso = from_epoch($edt);
		printf "Shot #$cpt - Machine $m (Between $sdt/$sdtiso et $edt/$edtiso)\n" if ($debug > 0);
		print "Generating " if ($debug > 0);
		mkdir "$img",0755 if (not (-d "$img"));
		unlink <$img/*-tir$cpt.png>;
		print "mem-tir$cpt.png " if ($debug > 0);
		RRDs::graph("$img/mem-tir$cpt.png","-s $sdt","-e $edt","-v KiloBytes","-aPNG","-t Memory Report - $m","DEF:s1=$base/$m/$config->{rrdsar}:memoryfree:AVERAGE","AREA:s1#00ee22:Free Memory");
		my $rrderror = RRDs::error;
    		die "Problem while generating graph: $rrderror\n" if ($rrderror);
		print "load-tir$cpt.png " if ($debug > 0);
		RRDs::graph("$img/load-tir$cpt.png","-s $sdt","-e $edt","-S",$config->{step},"-aPNG","-t","Load Report - $m","DEF:s1=$base/$m/$config->{rrdsar}:load1:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:load5:AVERAGE","DEF:s3=$base/$m/$config->{rrdsar}:runq:AVERAGE","LINE2:s1#00b6e4:Load 1m","LINE2:s2#00ee22:Load 5m","LINE2:s3#ff0000:Run Queue");
		$rrderror = RRDs::error;
    		die "Problem while generating graph: $rrderror\n" if ($rrderror);
		push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/mem-tir$cpt.png"}));
		push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/load-tir$cpt.png"}));
		push @tmp1,HTML::AsSubs::tr(@tmp1);

		my $col = 0;
		foreach my $i (@{$attrsar{$m}{measures}},@{$attrio{$m}{measures}}) {
			if ($i =~ /^eth/) {
				$i =~ s/-[inout]+//;
				next if (-f "$img/$i-tir$cpt.png");
				print "$i-tir$cpt.png " if ($debug > 0);
				RRDs::graph("$img/$i-tir$cpt.png","-s",$sdt,"-e",$edt,"-v packets/s","-S",$config->{step},"-aPNG","-t","Network Report $i - $m","DEF:s1=$base/$m/$config->{rrdsar}:$i-in:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:$i-out:AVERAGE","LINE2:s1#ff0000:$i (in)","LINE2:s2#00ee22:$i (out)");
				push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i-tir$cpt.png"}));
				$col++;
				if ($col == 2) {
					push @tmp1,HTML::AsSubs::tr(@tmp2);
					@tmp2 = ();
					$col = 0;
				}
					
			}
			if (($i =~ /^sd/) || ($i =~ /^hd/) || ($i =~ /^cciss/)) {
				$i =~ s/-[inout]+//;
				next if (-f "$img/$i-tir$cpt.png");
				print "$i-tir$cpt.png " if ($debug > 0);
				RRDs::graph("$img/$i-tir$cpt.png","-s",$sdt,"-e",$edt,"-v Op/s","-S",$config->{step},"-aPNG","-t","Disk Report $i - $m","DEF:s1=$base/$m/$config->{rrdio}:$i-in:AVERAGE","DEF:s2=$base/$m/$config->{rrdio}:$i-out:AVERAGE","LINE2:s1#ff0000:$i (in)","LINE2:s2#00ee22:$i (out)");
				push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i-tir$cpt.png"}));
				$col++;
				if ($col == 2) {
					push @tmp1,HTML::AsSubs::tr(@tmp2);
					@tmp2 = ();
					$col = 0;
				}
			}
			if (($i =~ /^cpu/) || ($i =~ /^all/)) {
				$i =~ s/-[a-z]+//;
				next if (-f "$img/$i-tir$cpt.png");
				print "$i-tir$cpt.png " if ($debug > 0);
				RRDs::graph("$img/$i-tir$cpt.png","-s",$sdt,"-e",$edt,"-S",$config->{step},"-aPNG","-t","CPU Report $i - $m","DEF:s1=$base/$m/$config->{rrdsar}:$i-idle:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:$i-nice:AVERAGE","DEF:s3=$base/$m/$config->{rrdsar}:$i-system:AVERAGE","DEF:s4=$base/$m/$config->{rrdsar}:$i-user:AVERAGE","AREA:s1#00b6e4:$i (idle)","STACK:s2#00ee22:$i (nice)","STACK:s3#ff0000:$i (system)","STACK:s4#000000:$i (user)");
				push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i-tir$cpt.png"}));
				$col++;
				if ($col == 2) {
					push @tmp1,HTML::AsSubs::tr(@tmp2);
					@tmp2 = ();
					$col = 0;
				}
			}
		}
		$rrderror = RRDs::error;
    		die "Problem while generating graph: $rrderror\n" if ($rrderror);
		print "\n" if ($debug > 0);
		push @hht,table(@tmp1);
		my $hht = body(@hht);
		print TIR $hht->as_HTML;
		close(TIR);
		push @hhm,li(a({href=>"tir-$cpt.html"}, "Tir $cpt"));
		$cpt++;
	}
	my $hhm = body(@hhm);
	print MACHINE $hhm->as_HTML;
	close(MACHINE);
}
push @hm,ul(@index);
my $hm = body(@hm);
print MAIN $hm->as_HTML;
close MAIN;
print "Point your browser to $config->{http}/$dir/dgi.html\n" if ($debug > 0);

#
# Second pass
#
$h = "$base/dgi-tirs.html";
open (MAIN, "> $h") || die "Unable to create $h : $!";
@hm = (h1("sar2rrd - sar/iostats monitoring via rrdtool"),
	p("List of shots:"));
@index = ();
my $cpt = 1;
my %attrs; 
foreach $m (@machines) {
	foreach my $attr (@{$attrsar{$m}{measures}},@{$attrio{$m}{measures}}) {
		next if ($attr =~ /^load/);
		next if ($attr =~ /^runq/);
		$attr = "mem" if ($attr =~ /^memory/);
		$attr = "load" if ($attr =~ /^plist/);
		$attrs{$attr}++;
	}
}

foreach my $t (@shots) {
	#
	# The graphs/HTML generation
	#
	push @index,li(a({href=>"dgi-tir-$cpt.html"}, "Tir $cpt"));
	my $hm = "$base/dgi-tir-$cpt.html";
	open (SHOT, "> $hm") || die "Unable to create $hm : $!";
	my @hhm = (h1("sar2rrd - Monitoring Shots"));
	print "Graphing rrd base for Shot $cpt\n" if ($debug > 0);
	foreach my $i (sort keys %attrs) {
		@tmp1 = ();
		@tmp2 = ();
		my $ht = "$base/attr-$cpt-$i.html";
		open (ATTR, "> $ht") || die "Unable to create $ht : $!";
		my @hht = (h1("sar2rrd - Monitoring $i - Tir $cpt"));
		my $col = 0;
		foreach $m (@machines) {
			my $img="$base/$m/img";
			#push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/load-tir$cpt.png"}));
			#push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/load-tir$cpt.png"}));
			#push @tmp1,HTML::AsSubs::tr(@tmp1);

			push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i-tir$cpt.png"}));
			$col++;
			if ($col == 2) {
				push @tmp1,HTML::AsSubs::tr(@tmp2);
				@tmp2 = ();
				$col = 0;
			}
		}
		push @hht,table(@tmp1);
		my $hht = body(@hht);
		print ATTR $hht->as_HTML;
		close(ATTR);
		push @hhm,li(a({href=>"attr-$cpt-$i.html"}, "$i"));
	}
	my $hhm = body(@hhm);
	print SHOT $hhm->as_HTML;
	close(SHOT);
	$cpt++;
}
push @hm,ul(@index);
$hm = body(@hm);
print MAIN $hm->as_HTML;
close MAIN;
print "Point your browser to $config->{http}/$dir/dgi-tirs.html\n" if ($debug > 0);
