#!/usr/bin/perl -w
use strict;
use RRDs;

my $rrd = '/var/lib/rrd';
my $img = '/var/www/localhost/htdocs/rrdtool/os';

&ProcessUptime("uptime");
# process data for each specified HDD (add/delete as required)
&ProcessMem("mem");

sub ShowErr
{
	if (my $err = RRDs::error) {
		print "$0: failed to create rrd: $err\n";
	}
}

sub ProcessUptime
{
	my $name = shift;

	my $in = `uptime`;
	my ($l1m, $l5m, $l15m) = ($in =~ /average:\s(\S{4}),\s(\S{4}),\s(\S{4})/);
	foreach($l1m, $l5m, $l15m) {
		$_ *= 100;
	}

	my ($users) = ($in =~ /\s+(\d+)\susers,/);

	open UPTIME, "</proc/uptime";
	$in = <UPTIME>;
	close UPTIME;

	my ($upsecs) = ($in =~ /(\d+)/);
	my $uptime = $upsecs / 86400;

	print "Load Average: $l1m, $l5m, $l15m\n";
	print "users: $users, uptime: $uptime\n";

	if (! -e "$rrd/$name.rrd")
	{
		print "creating rrd database for $name...\n";
		RRDs::create "$rrd/$name.rrd",
			"-s 300",
			"DS:l1m:GAUGE:600:U:U",
			"DS:l5m:GAUGE:600:U:U",
			"DS:l15m:GAUGE:600:U:U",
			"DS:users:GAUGE:600:U:U",
			"DS:uptime:GAUGE:600:U:U",
			"RRA:AVERAGE:0.5:1:576",
			"RRA:AVERAGE:0.5:6:672",
			"RRA:AVERAGE:0.5:24:732",
			"RRA:AVERAGE:0.5:144:1460";
	}
	&ShowErr();

	RRDs::update "$rrd/$name.rrd",
		"-t", "l1m:l5m:l15m:users:uptime",
		"N:$l1m:$l5m:$l15m:$users:$uptime";
	&ShowErr();

	my @intervals = ('day', 'week', 'month', 'year');
	foreach my $time (@intervals) {
	   &CreateUptimeGraph($name, $time);
	}
}

sub ProcessMem
{
	my $name = shift;

	my $in = `free`;
	my ($mtotal, $mshared, $mbuffers, $mcached) = 
		($in =~ /Mem:\s+(\d+)\s+\d+\s+\d+\s+(\d+)\s+(\d+)\s+(\d+)/);
	my ($mused, $mfree) = 
		($in =~ /buffers\/cache:\s+(\d+)\s+(\d+)/);
	my ($stotal, $sused, $sfree) = 
		($in =~ /Swap:\s+(\d+)\s+(\d+)\s+(\d+)/);

	foreach($mtotal, $mshared, $mbuffers, $mcached, $mused, $mfree,
		$stotal, $sused, $sfree) {
		$_ /= 1000;
	}

	print "Mem  | shared $mshared\t buffers $mbuffers\t cached $mcached\n";
	print "     | total $mtotal\tused $mused\tfree $mfree\n";
	print "Swap |       $stotal\t     $sused\t     $sfree\n";

	if (! -e "$rrd/$name.rrd")
	{
		print "creating rrd database for $name...\n";
		RRDs::create "$rrd/$name.rrd",
			"-s 300",
			"DS:mtotal:GAUGE:600:U:U",
			"DS:mshared:GAUGE:600:U:U",
			"DS:mbuffers:GAUGE:600:U:U",
			"DS:mcached:GAUGE:600:U:U",
			"DS:mused:GAUGE:600:U:U",
			"DS:mfree:GAUGE:600:U:U",
			"DS:stotal:GAUGE:600:U:U",
			"DS:sused:GAUGE:600:U:U",
			"DS:sfree:GAUGE:600:U:U",
			"RRA:AVERAGE:0.5:1:576",
			"RRA:AVERAGE:0.5:6:672",
			"RRA:AVERAGE:0.5:24:732",
			"RRA:AVERAGE:0.5:144:1460";
		&ShowErr();
	}

	RRDs::update "$rrd/$name.rrd",
		"-t", "mtotal:mshared:mbuffers:mcached:mused:mfree:stotal:sused:sfree",
		"N:$mtotal:$mshared:$mbuffers:$mcached:$mused:$mfree:$stotal:$sused:$sfree";
	&ShowErr();

	my @intervals = ('day', 'week', 'month', 'year');
	foreach my $time (@intervals) {
	    &CreateMemGraph($name, $time);
	}
}

sub CreateUptimeGraph
{
	my ($name, $interval) = @_;

	RRDs::graph "$img/$interval/uptime.png",
		"--lazy",
		"-s -1$interval",
		"-t Uptime",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v days",
		"DEF:uptime=$rrd/$name.rrd:uptime:AVERAGE",
		"LINE2:uptime#00FF00:Uptime",
		"GPRINT:uptime:MIN:  Min\\: %6.2lf",
		"GPRINT:uptime:MAX: Max\\: %6.2lf",
		"GPRINT:uptime:AVERAGE: Avg\\: %6.2lf",
		"GPRINT:uptime:LAST: Current\\: %6.2lf days";
	&ShowErr();

	RRDs::graph "$img/$interval/load.png",
		"--lazy",
		"-s -1$interval",
		"-t Load Average",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v percent",
		"DEF:l1m=$rrd/$name.rrd:l1m:AVERAGE",
		"DEF:l5m=$rrd/$name.rrd:l5m:AVERAGE",
		"DEF:l15m=$rrd/$name.rrd:l15m:AVERAGE",
		"LINE2:l1m#0000FF:1m Average",
		"GPRINT:l1m:MIN:  Min\\: %3.lf",
		"GPRINT:l1m:MAX: Max\\: %3.lf",
		"GPRINT:l1m:AVERAGE: Avg\\: %3.lf",
		"GPRINT:l1m:LAST: Current\\: %3.lf percent\\n",
		"LINE2:l5m#00FF00:5m Average",
		"GPRINT:l5m:MIN:  Min\\: %3.lf",
		"GPRINT:l5m:MAX: Max\\: %3.lf",
		"GPRINT:l5m:AVERAGE: Avg\\: %3.lf",
		"GPRINT:l5m:LAST: Current\\: %3.lf percent\\n",
		"LINE2:l15m#FF0000:15m Average",
		"GPRINT:l15m:MIN:  Min\\: %3.lf",
		"GPRINT:l15m:MAX: Max\\: %3.lf",
		"GPRINT:l15m:AVERAGE: Avg\\: %3.lf",
		"GPRINT:l15m:LAST: Current\\: %3.lf percent";
	&ShowErr();
}

sub CreateMemGraph
{
	my ($name, $interval) = @_;

	RRDs::graph "$img/$interval/mem.png",
		"--lazy",
		"-s -1$interval",
		"-t Memory Use",
		"-h", "240", "-w", "600",
		"-a", "PNG",
		"-b", "1024",
		"-v MB",
		"DEF:mtotal=$rrd/$name.rrd:mtotal:AVERAGE",
#		"DEF:mshared=$rrd/$name.rrd:mshared:AVERAGE",
		"DEF:mbuffers=$rrd/$name.rrd:mbuffers:AVERAGE",
		"DEF:mcached=$rrd/$name.rrd:mcached:AVERAGE",
		"DEF:mused=$rrd/$name.rrd:mused:AVERAGE",
		"DEF:stotal=$rrd/$name.rrd:stotal:AVERAGE",
		"DEF:sused=$rrd/$name.rrd:sused:AVERAGE",
		"CDEF:stotal_neg=stotal,-1,*",
		"CDEF:sused_neg=sused,-1,*",
		"VDEF:mtotal_last=mtotal,LAST",
		"VDEF:stotal_last=stotal_neg,LAST",
		"CDEF:mbufused=mused,mbuffers,+",
		"CDEF:mcachebufused=mbufused,mcached,+",
		"HRULE:mtotal_last#000000",
		"GPRINT:mtotal:LAST: RAM Total\\: %7.3lf MB\\t",
		"GPRINT:stotal:LAST: Swap Total\\: %7.3lf MB\\n",
#		"LINE:mshared#0000FF:RAM Shared",
#		"GPRINT:mshared:MIN:Min\\: %7.3lf",
#		"GPRINT:mshared:MAX: Max\\: %7.3lf",
#		"GPRINT:mshared:AVERAGE: Avg\\: %7.3lf",
#		"GPRINT:mshared:LAST: Current\\: %7.3lf MB\\n",
		"LINE:mcachebufused#FF00FF:RAM Cached",
		"AREA:mcachebufused#CD32CD:",
		"GPRINT:mcached:MIN:Min\\: %7.3lf",
		"GPRINT:mcached:MAX: Max\\: %7.3lf",
		"GPRINT:mcached:AVERAGE: Avg\\: %7.3lf",
		"GPRINT:mcached:LAST: Current\\: %7.3lf MB\\n",
		"LINE:mbufused#0000FF:RAM Buffers",
		"AREA:mbufused#3232CD:",
		"GPRINT:mbuffers:MIN:Min\\: %7.3lf",
		"GPRINT:mbuffers:MAX: Max\\: %7.3lf",
		"GPRINT:mbuffers:AVERAGE: Avg\\: %7.3lf",
		"GPRINT:mbuffers:LAST: Current\\: %7.3lf MB\\n",
		"LINE2:mused#00FF00:RAM Used",
		"AREA:mused#32CD32:",
		"GPRINT:mused:MIN:Min\\: %7.3lf",
		"GPRINT:mused:MAX: Max\\: %7.3lf",
		"GPRINT:mused:AVERAGE: Avg\\: %7.3lf",
		"GPRINT:mused:LAST: Current\\: %7.3lf MB\\n",
		"HRULE:stotal_last#000000",
		"LINE2:sused_neg#FF0000:Swap Used",
		"AREA:sused_neg#CD3232:",
		"GPRINT:sused:MIN:Min\\: %7.3lf",
		"GPRINT:sused:MAX: Max\\: %7.3lf",
		"GPRINT:sused:AVERAGE: Avg\\: %7.3lf",
		"GPRINT:sused:LAST: Current\\: %7.3lf MB\\n";
	&ShowErr();
}

