#!/usr/bin/perl -w if ((@ARGV != 1) && (@ARGV != 2)) { print STDERR "Syntax: ${0} configfile [uid]\n"; exit(1); } use Net::SNMP; use RRDs; use Data::Dumper; $UPSGRAPH::host = ""; $UPSGRAPH::rrdfile = ""; $UPSGRAPH::outdir = ""; $UPSGRAPH::community = "public"; $UPSGRAPH::step = 60; $UPSGRAPH::keep = (370*24*60*60)/$UPSGRAPH::step; @UPSGRAPH::fields = (); $UPSGRAPH::vars = {}; do $ARGV[0] or die "can't read config: $!"; my $host = $UPSGRAPH::host; my $rrdfile = $UPSGRAPH::rrdfile; my $outdir = $UPSGRAPH::outdir; my $community = $UPSGRAPH::community; my $step = $UPSGRAPH::step; my $keep = $UPSGRAPH::keep; my @fields = @UPSGRAPH::fields; my $vars = $UPSGRAPH::vars; sub rrdcreate(@) { my $newrrd = shift; my $field = shift; my $start = shift; my @cmd = ("${newrrd}", "--step=${step}"); if (defined($start)) { push @cmd, "--start=${start}"; } push @cmd, "DS:${field}:GAUGE:600:" . $vars->{$field}->{'min'} . ":" . $vars->{$field}->{'max'} . " "; push @cmd, "RRA:AVERAGE:0.5:1:${keep}"; RRDs::create(@cmd); if (RRDs::error) { print "Error while creating: " . RRDs::error . "\n"; exit 1; } } if ($> == 0) { if (@ARGV != 2) { print STDERR "Running as root, please provide UID as 2th argument!\n"; exit(1); } print "Running as root, switching to ".$ARGV[1]."\n"; $< = $> = $ARGV[1]; } if (-e "${rrdfile}") { print "Reading old ${rrdfile} to preserve data...\n"; my $rrdinfo = RRDs::info("${rrdfile}"); if (RRDs::error) { print "Error while getting info: " . RRDs::error . "\n"; exit 1; } (my $start, my $ostep, my $names, my $data) = RRDs::fetch("${rrdfile}", "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})), "AVERAGE"); if (RRDs::error) { print "Error while fetching data: " . RRDs::error . "\n"; exit 1; } foreach my $field (@$names) { if (! -e "${rrdfile}.${field}") { rrdcreate("${rrdfile}.${field}","${field}",(${start}-${ostep})); } } my $pos = $start; foreach my $line (@$data) { foreach my $field (@$names) { my $val = shift (@$line); next if (!defined($val)); RRDs::update("${rrdfile}.${field}", "${pos}:${val}"); if (RRDs::error) { print "Can't insert data: " . RRDs::error . "\n"; exit 1; } } $pos += $ostep; if ((($pos-$start)/$ostep) == $#$data) { last; } } rename("${rrdfile}", "${rrdfile}.old") or die "Can't rename old file: $!\n"; } foreach my $field (@fields) { if (! -e "${rrdfile}.${field}") { print "Creating ${rrdfile}.${field}...\n"; rrdcreate("${rrdfile}.${field}","${field}"); } my $rrdinfo = RRDs::info("${rrdfile}.${field}"); if (RRDs::error) { print "Error while getting info: " . RRDs::error . "\n"; exit 1; } if ($rrdinfo->{'rra[0].rows'} != $keep) { print "Resizing ${rrdfile}.${field} from " . $rrdinfo->{'rra[0].rows'} . " to ${keep} samples.\n"; (my $start, my $ostep, my $names, my $data) = RRDs::fetch("${rrdfile}.${field}", "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})), "AVERAGE"); if (RRDs::error) { print "Error while fetching data: " . RRDs::error . "\n"; exit 1; } rrdcreate("${rrdfile}.${field}.new", "${field}", (${start}-${ostep})); print "Preserving data since " . localtime($start) . "\n"; my $pos = $start; foreach my $line (@$data) { my $vline = "${pos}"; foreach my $val (@$line) { $val = 'U' if (!defined($val)); $vline .= ":${val}"; } RRDs::update("${rrdfile}.${field}.new", $vline) or die "Can't insert data\n"; if (RRDs::error) { print "Error while updating: " . RRDs::error . "\n"; exit 1; } $pos += $ostep; if ((($pos-$start)/$ostep) == $#$data) { last; } } rename("${rrdfile}.${field}", "${rrdfile}.${field}.old") or die "Can't rename old file: $!\n"; rename("${rrdfile}.${field}.new", "${rrdfile}.${field}") or die "Can't rename new file: $!\n"; $rrdinfo = RRDs::info("${rrdfile}.${field}"); if (RRDs::error) { print "Error while getting info: " . RRDs::error . "\n"; exit 1; } if ($rrdinfo->{'rra[0].rows'} != $keep) { print "Failed!\n"; exit 1; } } } my $child = fork(); die "fork failed!" if (!defined($child)); exit 0 if ($child != 0); while(1) { ($session,$error) = Net::SNMP->session(Hostname => $host, Community => $community); die "session error: $error" unless ($session); $session->translate(0); foreach my $var (@fields) { delete $vars->{$var}->{'value'}; my $result = $session->get_request($vars->{$var}->{'oid'}); next unless (defined $result); $vars->{$var}->{'value'} = $result->{$vars->{$var}->{'oid'}}; if (defined($vars->{$var}->{'factor'})) { $vars->{$var}->{'value'} *= $vars->{$var}->{'factor'}; } } $session->close; foreach my $var (@fields) { if (!(defined($vars->{$var}->{'value'}))) { $vars->{$var}->{'value'} = 'U'; } RRDs::update("${rrdfile}.${var}", "N:" . $vars->{$var}->{'value'}); } if (RRDs::error) { print "Error while updating: " . RRDs::error . "\n"; } open(HTML, ">${outdir}/index.html.new"); print HTML '