Project

General

Profile

Download (6.34 KB) Statistics
| Branch: | Revision:
00588b29 Hamish Coleman
#!/usr/bin/perl
#
9c83a251 Hamish Coleman
# Generate a machine readable index from mrtg.cfg inputs
00588b29 Hamish Coleman
#

our $VERSION=0.5;

use strict;
use warnings;

use FileHandle;

04a6764e Hamish Coleman
use JSON;

00588b29 Hamish Coleman
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;

use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);
use Sys::Hostname;

use HTML::Entities();

# List of config files to search for
my @config_files = (
'/etc/mrtg.cfg',
'/usr/share/WWW/mrtg/mrtg.cfg',
);

# FIXME - globals
my $warnings;
my $db = {}; # storage for all tests found

7d6cf686 Hamish Coleman
$db->{mrtg}{gifdone} = 0; # Scan for newest graph and save info for later
$db->{mrtg}{global}{postfix}{xsize} = 500;
$db->{mrtg}{global}{postfix}{ysize} = 135;
00588b29 Hamish Coleman
sub config_save_val($$$$) {
04a6764e Hamish Coleman
my ($filename,$name,$var,$val) = @_;
00588b29 Hamish Coleman
my $this_ysize;
my $this_xsize;
my $this_title;

# HACK!
if ( $var eq 'ysize' ) {
$val += 35;
} elsif ( $var eq 'xsize' ) {
$val += 100;
}

# Save any default initializers
04a6764e Hamish Coleman
if ($name eq '_') {
7d6cf686 Hamish Coleman
$db->{mrtg}{global}{postfix}{$var} = $val;
00588b29 Hamish Coleman
return;
}
04a6764e Hamish Coleman
if ($name eq '^') {
7d6cf686 Hamish Coleman
$db->{mrtg}{global}{prefix}{$var} = $val;
00588b29 Hamish Coleman
return;
}

04a6764e Hamish Coleman
# Check for name name collision, and uniqueify
my $unique_name = $name;
00588b29 Hamish Coleman
my $unique_id = 1;
04a6764e Hamish Coleman
while (defined $db->{graph}->{$unique_name}
7d6cf686 Hamish Coleman
&& $db->{graph}->{$unique_name}->{definedby} ne $filename) {
04a6764e Hamish Coleman
$unique_name = $name . '_' . $unique_id;
00588b29 Hamish Coleman
$unique_id++;
}

04a6764e Hamish Coleman
if (!defined $db->{graph}->{$unique_name}) {
# initialize a new name
00588b29 Hamish Coleman
#TODO - instantiate new tests from all of the "_"/"^" defaults

04a6764e Hamish Coleman
push @{$db->{sequence}}, $unique_name;
00588b29 Hamish Coleman
04a6764e Hamish Coleman
$db->{graph}->{$unique_name}->{name} = $name;
7d6cf686 Hamish Coleman
$db->{graph}->{$unique_name}->{definedby} = $filename;
04a6764e Hamish Coleman
$db->{graph}->{$unique_name}->{sequence} = @{$db->{sequence}};
00588b29 Hamish Coleman
7d6cf686 Hamish Coleman
$db->{graph}{$unique_name}{img}{xsize} = $db->{mrtg}{global}{postfix}{xsize};
$db->{graph}{$unique_name}{img}{ysize} = $db->{mrtg}{global}{postfix}{ysize};
00588b29 Hamish Coleman
}
7d6cf686 Hamish Coleman
$db->{mrtg}{target}{$unique_name}{$var} = $val;
00588b29 Hamish Coleman
}

# Load one or more files
#
sub config_load_file(@) {
while (@_) {
my $filename = shift;

my $fh = new FileHandle $filename,"r";
if (!defined $fh) {
# FIXME globals
$warnings .= "Warning: Could not open $filename $!\n";
return;
}

#TODO - multi-line values
7d6cf686 Hamish Coleman
#TODO - reset the {mrtg}{global} vars
00588b29 Hamish Coleman
while(<$fh>){

# Is this a standard MRTG setting?
if ( $_ =~ /^([^#[][^[]+)\[(.*)\]:\s*(.+)$/ ) {
my $var=lc $1;
04a6764e Hamish Coleman
my $name=lc $2;
00588b29 Hamish Coleman
my $val=$3;

04a6764e Hamish Coleman
config_save_val($filename,$name,$var,$val);
00588b29 Hamish Coleman
7d6cf686 Hamish Coleman
} elsif ( $_ =~ /^([^#[][^[]+):\s*(.+)$/ ) {
# its a global statement
my $var=lc $1;
my $val=$2;

$db->{mrtg}{global}{$var}=$val;
00588b29 Hamish Coleman
}
7d6cf686 Hamish Coleman
00588b29 Hamish Coleman
# TODO - Handle extra statements:
# Include
7d6cf686 Hamish Coleman
# WorkDir - see config_read_filesystem
00588b29 Hamish Coleman
# LogDir
# ##HC Magic for baseurl
}
}
}

04a6764e Hamish Coleman
# Itterate through the loaded name and read their mtime and
00588b29 Hamish Coleman
# any other filesystem details for them.
#
sub config_read_filesystem() {
7d6cf686 Hamish Coleman
# TODO - also check the other directory statements
if ($db->{mrtg}{global}{workdir}) {
chdir $db->{mrtg}{global}{workdir};
}

00588b29 Hamish Coleman
# check and update details for all known tests;
04a6764e Hamish Coleman
for my $i (keys %{$db->{graph}}) {
7d6cf686 Hamish Coleman
my $graph = $db->{graph}->{$i};
my $graphname = $graph->{name};
my $mrtg = $db->{mrtg}{target}{$i};
00588b29 Hamish Coleman
# Default is GIF, unless a PNG file exists
7d6cf686 Hamish Coleman
$mrtg->{_imagetype} = 'gif';
if ( -e "$graphname-day.png" ) {
$mrtg->{_imagetype} = "png";
00588b29 Hamish Coleman
}

7d6cf686 Hamish Coleman
# TODO - determine correct URL prefix
00588b29 Hamish Coleman
# TODO - change the filename based on the displayed period
7d6cf686 Hamish Coleman
my $filename = $graphname . "-day." . $mrtg->{_imagetype};
9afdb02d Hamish Coleman
$graph->{img}{URL}{day} = $filename;

$graph->{img}{URL}{week} = $graphname."-week.".$mrtg->{_imagetype};
$graph->{img}{URL}{month} = $graphname."-month.".$mrtg->{_imagetype};
$graph->{img}{URL}{year} = $graphname."-year.".$mrtg->{_imagetype};
00588b29 Hamish Coleman
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime,$mtime,$ctime,$blksize,$blocks)
= stat($filename);
if (!defined $mtime) {
# if we cannot stat the file, skip it
next;
}

7d6cf686 Hamish Coleman
# TODO - move these to a better function
$graph->{URL} = $graphname . '.html';
$graph->{title} = $mrtg->{title};

$graph->{img}{mtime} = $mtime;
00588b29 Hamish Coleman
# find the newest file
7d6cf686 Hamish Coleman
if ($mtime > $db->{mrtg}{gifdone}) {
$db->{mrtg}{gifdone} = $mtime;
00588b29 Hamish Coleman
}
}
}

sub extract_grouphosttest($) {
my ($name) = @_;

# Do not classify a test with no separators in it
if ($name !~ /,/) {
return undef;
}

my ($group,$host,$test) = split ',', $name;
# TODO cope with missing group/host/test parts.
if (!defined $group || !defined $host || !defined $test) {
return undef;
}
return ($group,$host,$test);
}

04a6764e Hamish Coleman
# Read through the list of name and find common hostname prefixes,
00588b29 Hamish Coleman
# so that we can group these hosts together
# (a hosttype entry)
#
sub maketree_find_hosttypes() {

04a6764e Hamish Coleman
for my $name (keys %{$db->{graph}}) {
00588b29 Hamish Coleman
my ($group,$host,$test) = extract_grouphosttest($name);
if (!defined($group)) {
next;
}
my $hosttype;
# TODO - this needs to have a better way...
# hosttype is the non digit hostname prefix - thus
# "proxy-1" and "proxy-2" would both end up in the
# "proxy-" hosttype
if ($host =~ m/^(.*[^0-9])(\d+)$/) {
$hosttype = $1.'*';
} else {
next;
}

9afdb02d Hamish Coleman
$db->{graph}{$name}{tag}{hosttype} = $hosttype;
00588b29 Hamish Coleman
$db->{hosttype}->{$hosttype}->{$host}++;
}

for my $hosttype (keys %{$db->{hosttype}}) {
if ((keys %{$db->{hosttype}->{$hosttype}})<2) {
delete $db->{hosttype}->{$hosttype};
}
}
}

9afdb02d Hamish Coleman
sub maketags() {
maketree_find_hosttypes();

for my $name (keys %{$db->{graph}}) {
my $graph = $db->{graph}->{$name};
my ($group,$host,$test) = extract_grouphosttest($name);

$graph->{tag}{group}=$group if $group;
$graph->{tag}{host}=$host if $host;
$graph->{tag}{test}=$test if $test;
}
}

9c83a251 Hamish Coleman
my $this_host = hostname;
00588b29 Hamish Coleman
ec551d65 Hamish Coleman
print "Content-Type: text/json; charset=ISO-8859-1\n";
00588b29 Hamish Coleman
9c83a251 Hamish Coleman
config_load_file(@config_files);
config_read_filesystem();
9afdb02d Hamish Coleman
maketags();
00588b29 Hamish Coleman
9c83a251 Hamish Coleman
# Time the next update to occur a little while after the next interval completes
my $interval = 300; # 5 min update interval
my $guardband = 15; # updates occur this many seconds after predicted gif completion
7d6cf686 Hamish Coleman
my $refresh = $interval + $guardband + $db->{mrtg}{gifdone} - time; # predict how long until next update
9c83a251 Hamish Coleman
$refresh = $interval if $refresh <= $guardband;
my $expires = gmtime (time + $interval * 2 + $guardband);
00588b29 Hamish Coleman
ec551d65 Hamish Coleman
$db->{global}{expires} = "$expires GMT";
$db->{global}{refresh} = $refresh;
00588b29 Hamish Coleman
ec551d65 Hamish Coleman
print "\n",JSON->new->utf8(1)->pretty(1)->canonical(1)->encode($db),"\n";
00588b29 Hamish Coleman
if (param('debug')) {
9c83a251 Hamish Coleman
print "\n",Dumper(\$db),"\n";
00588b29 Hamish Coleman
}