#!/usr/bin/perl -w

use strict;
use POSIX qw(strftime);
use RRDs;
use Color::Rgb;
use CGI qw/:all/;


=head1 NAME

ExtPerfGraph.pl -- lets you choose special time periods for a single graph.

=head1 VERSION

Version 1.1

=head1 SYNOPSIS

Call from the web.

=head1 DESCRIPTION

This is a quick hack(!) to create pictures for certain graphs.

Another addition is used to give you a CSV file of all values in the given time
from the logonALL-days.rrd database.

The major B<disatvantages>:

=over 4

=item 1

It always overwrites the same file, which is fetched by the browser. Two people
using this at the same time won't become very happy.

=item 2

It uses the output of C<rrdtool info> to actually find out what variable names
there are in the database. Not very clean, but I could not really think of
anything better.

=back

=head1 CONFIGURATION

This script contains hard coded paths.

=head1 AUTHOR

(c) 2003 Hannes Schulz <mail@hannes-schulz.de>

=cut


my $imgdir = "/usr/local/nagios/share/images/rw";
my $rrds  = "/usr/local/nagios_indep/var/rrds";
my @hosts = map {m|/([^/]+)/?$| } <$rrds/*>;

my $host = param('host');
my $serv = param('serv');
my $sday = param('sday');
my $days = param('days');

my $rgb = new Color::Rgb(rgb_txt => '/usr/X11R6/lib/X11/rgb.txt');
my @colors = (
    $rgb->hex('red','#'),
    $rgb->hex('blue','#'),
    $rgb->hex('green','#'),
    $rgb->hex('orange','#'),
    $rgb->hex('dark red','#'),
    $rgb->hex('dark green','#'),
    $rgb->hex('dark blue','#')
);
undef $rgb;


logonstats(param('s'),param('e')) if(param('logonstats'));

choosehost() unless($host);

my @services = map { m!/([^/]+)\.rrd!i; $1; } glob("$rrds/$host/*.rrd");

chooseservice() unless($serv);

chooseperiod() unless($days and $sday);

sendpic();


sub choosehost{

	print header(),start_html('Extended Performance Graphs'),
      h1('Extended Performance Graphs'),
	  p('Please choose host:'),
	  start_form,
		scrolling_list(-size=>1, -name => 'host', -Values => [ reverse sort @hosts ]),p,
		submit,
	  end_form,
	  end_html;
	exit 0

}

sub chooseservice{

	print header(),start_html('Extended Performance Graphs'),
      h1('Extended Performance Graphs'),
	  p("Please choose a service for host $host:"),
	  start_form,
		hidden(-name => "host", -value => "$host"),
		scrolling_list(-name   => 'serv', -size => 1,
                   -Values     => [ sort @services ]),p,
		submit,
	  end_form,
	  end_html;
	exit 0

}

sub chooseperiod{

	my (undef,undef,undef,$mday,$mon,$year,undef,undef,undef) = localtime();
	$mon++;
	$year += 1900;
	my $endday = 7;

	print header(),start_html('Extended Performance Graphs'),
      h1('Extended Performance Graphs'),
	  p("Please choose a time period for service $serv on host $host:"),
	  start_form(-method=>"GET"),
		hidden(-name => "host", -value => "$host"),
		hidden(-name => "serv", -value => "$serv"),
		"Starting day (DD-MM-YYYY): ",
		textfield(-name   => 'sday', -value => "$mday-$mon-$year"),br(),
		"How many days from there: ",
		textfield(-name   => 'days', -value => "$endday"),br(),
		submit("Finish"),
	  end_form,
	  end_html;
	exit 0

}

sub sendpic{

	my($d,$m,$y) = split /-/,$sday;

	my $start = POSIX::mktime(1,1,0,$d,$m-1,$y-1900);
	my $end   = POSIX::mktime(0,0,0,$d+$days,$m-1,$y-1900);

	my $file  = "$rrds/$host/$serv.rrd";

    my $grid;
    $grid =  "WEEK:1:MONTH:1:MONTH:1:2592000:%b" if($days>40);
    $grid =  "WEEK:1:MONTH:1:WEEK:1:60480:%V"   if($days<=40);
    $grid =  "DAY:1:WEEK:1:DAY:1:86400:%a"      if($days<=20);
    $grid =  "HOUR:2:DAY:1:HOUR:2:0:%H"         if($days<=3);
    $grid =  "HOUR:2:DAY:1:HOUR:2:0:%H:00"      if($days<2);

	my @vars = getvarnames($host,$serv);

	my $url = script_name();
	print header(),start_html(
        -title => 'Extended Performance Graphs',
		-meta => {"http-equiv" => "cache-control", content => "no-cache"},
		-meta => {"http-equiv" => "pragma", content => "no-cache"}
      ),
	  h1('Extended Performance Graphs'),
	  p('Your selected graph:');

    my @cmd =(
     "$imgdir/tmp.png",                           # Destination
     "--x-grid", $grid,                           
     "--start", $start,                           
     "--end", $end,                               
     "--imgformat", "PNG",
     "--title", "$host: $serv" 
    );

    my $i = 0;
    my $e = "";
	
    foreach(@vars){
        $e = $_;
        $e =~ y|_|/| if($serv eq "fs-disk-nrpep");
        push @cmd, "DEF:$_=$file:$_:AVERAGE";
        push @cmd, "LINE2:$_$colors[$i]:$e";
        $i++;
    }
    
    RRDs::graph(@cmd);
    my $ERR=RRDs::error;

	if($ERR){ print p("ERROR while graphing: $ERR\n".join(", ",@cmd))}
	else{
		print '<img src="/nagios/images/rw/tmp.png"/><br/>'; 
	}

	print p(qq{<a href="$url?h=$host&f=$serv&s=$start&e=$end&logonstats=1">Get CSV statistics</a> for this});
	print p('Please check the graph if it is ok. If not, reloading the page might help!'),
      end_html();

}

sub getvarnames{

	my ($host,$serv) = @_;

	open(RT,"rrdtool info $rrds/$host/$serv.rrd |") or do{
		print header(),start_html,p("Could not open RR-Database: $!"),end_html;
		exit 0;
	};

	my %ds = ();
	while(<RT>){$ds{$1} = 1 if (/^ds\[(.*?)\]/)}
	return keys(%ds)
}

sub logonstats{
	my $start = int(shift()/3600)*3600;
	my $end   = int(shift()/3600)*3600;
	my $h = param('h');  $h =~ s/[^\w_\-]//g;
	my $f = param('f');  $f =~ s/[^\w_\-]//g;

	my @head = getvarnames($h,$f);
	my $out   = "All time/date values are CET!\n\n;;".join(";",@head)."\n";

	my ($t,@val);
	my $str = `/usr/bin/rrdtool fetch $rrds/$h/$f.rrd  AVERAGE -r 3600 -s $start -e $end 2>&1`;
	if ($str =~ "ERROR"){ return $str };
	foreach(split /\n/, $str){
			($t,@val) = split/:?\s+/;
			next unless($t and scalar @val);
			chomp @val;
			next if($f eq "logonALL-day" and ((localtime $t)[1] != 0 or (localtime $t)[2] != 0 ));
			$out .= strftime("%H:%M;%d-%m-%Y",(localtime $t)) . ";" 
                 .  join(";",map{sprintf("%i",$_)}@val)
                 .  "\n";
	}

	print header(-type=>"application/excel\nContent-Disposition: inline; filename=stats$t.csv"),$out;
	exit();
}
