#!/usr/local/bin/perl
# $Id$
# License: OSI Artistic License
# Author: (c) 2010 Matthew Wall
## no critic (InputOutput::RequireCheckedSyscalls)
## no critic (RegularExpressions)
## no critic (ProhibitPackageVars)
# The configuration file and ngshared.pm must be in this directory:
use lib '/usr/local/etc/nagios/nagiosgraph';
use POSIX;
use English qw(-no_match_vars);
use strict;
use warnings;
emitheader();
#checkstyles();
checkmodules();
checkng();
dumpenv();
dumpinc();
dumpngconfig();
dumpfiles();
dumpdirs();
emitfooter();
exit 0;
sub emitheader {
print <<"EOB";
Content-Type: text/html
nagiosgraph: configuration
EOB
print "nagiosgraph configuration on $ENV{SERVER_NAME}
\n";
my $ts = strftime '%d %b %Y %H:%M:%S %Z', localtime time;
print "$ts
\n";
return;
}
sub emitfooter {
print '' . "\n";
return;
}
sub checkstyles {
print "a
b
c
\n";
print "a
b
c
\n";
print "a
b
c
\n";
print "a
b
c
\n";
return;
}
sub dumpenv {
print "Environment
\n";
print "\n";
print "
\n";
foreach my $i (sort keys %ENV) {
print "$i=$ENV{$i}\n";
}
print "
\n";
return;
}
sub dumpinc {
print "Include Paths
\n";
print "\n";
print "
\n";
for my $i (@INC) {
print $i . "\n";
}
print "
\n";
print "
\n";
return;
}
sub printrow {
my ($style, $func, $msg, $errmsg) = @_;
$errmsg ||= q();
print " | $func: | $msg | $errmsg |
\n";
return;
}
sub checkmodule {
my ($func, $optional) = @_;
my $statusstr = 'not installed';
my $status = $optional ? 'warning' : 'critical';
my $rval = eval "{ require $func; }"; ## no critic (ProhibitStringyEval)
if (defined $rval && $rval == 1) {
$statusstr = $func->VERSION;
$status = 'ok';
}
printrow($status, $func, $statusstr);
return;
}
sub checkmodules {
print 'PERL modules
' . "\n";
print '' . "\n";
print '
' . "\n";
print " | required |
\n";
checkmodule('Carp');
checkmodule('CGI');
checkmodule('Data::Dumper');
checkmodule('Digest::MD5');
checkmodule('File::Basename');
checkmodule('File::Find');
checkmodule('MIME::Base64');
checkmodule('POSIX');
checkmodule('RRDs');
checkmodule('Time::HiRes');
print " | optional |
\n";
checkmodule('GD', 1);
checkmodule('Nagios::Config', 1);
print '
' . "\n";
print '
' . "\n";
return;
}
sub checkngshared {
my ($failures) = @_;
my $func = 'ngshared.pm';
my $status = 'ok';
my $style = 'ok';
my $errmsg = q();
my $rval = eval { require ngshared; };
if (! defined $rval || $rval != 1) {
$status = 'fail';
$style = 'critical';
$errmsg = 'cannot load ngshared.pm
' .
'not found in any of these locations:
' . "\n";
for my $ii (@INC) {
$errmsg .= $ii . '
' . "\n";
}
push @{$failures}, $errmsg;
}
printrow($style, $func, $status, $errmsg);
return;
}
sub checkngversion {
my ($failures) = @_;
my $func = 'version';
my $status = 'ok';
my $style = 'ok';
my $errmsg = q();
if ($ngshared::VERSION) {
$status = $ngshared::VERSION;
} else {
$status = 'fail';
$style = 'critical';
$errmsg = 'cannot initialize/import ngshared.pm';
}
if ($status eq 'fail') {
push @{$failures}, $errmsg;
}
printrow($style, $func, $status, $errmsg);
return;
}
sub checkngconf {
my ($failures) = @_;
my $func = 'nagiosgraph.conf';
my $status = 'ok';
my $style = 'ok';
my $errmsg = q();
$errmsg = ngshared::readconfig('showconfig', 'cgilogfile');
if ($errmsg ne q()) {
$status = 'fail';
$style = 'critical';
$errmsg = 'cannot read nagiosgraph configuration file:
' . $errmsg;
}
if ($status eq 'fail') {
push @{$failures}, $errmsg;
}
printrow($style, $func, $status, $errmsg);
return;
}
sub checkmaprules {
my ($failures) = @_;
my $func = 'map file';
my $status = 'ok';
my $errmsg = q();
if ($ngshared::Config{mapfile}) {
$errmsg = ngshared::getrules($ngshared::Config{mapfile});
if ($errmsg ne q()) {
$status = 'fail';
}
} else {
$status = 'fail';
$errmsg = 'map file is not defined';
}
my $style = $status eq 'ok' ? 'ok' : 'critical';
if ($status eq 'fail') {
push @{$failures}, $errmsg;
}
printrow($style, $func, $status, $errmsg);
return;
}
# verifty that we have a functional nagiosgraph installation.
sub checkng {
my $rval;
my $status;
my @failures;
print 'nagiosgraph
' . "\n";
print '' . "\n";
checkngshared(\@failures);
checkngversion(\@failures);
if (scalar @failures) {
print '
' . "\n";
emitfooter();
exit 1;
}
checkngconf(\@failures);
checkdir('rrddir', 'RRD directory', \@failures);
checkfile('logfile', 'log file', \@failures);
checkfile('cgilogfile', 'CGI log file', \@failures, 1);
# TODO: check for read/write access by nagios user
checkmaprules(\@failures);
print '' . "\n";
if (scalar @failures) {
emitfooter();
exit 1;
}
return;
}
sub dumpngconfig {
my $cfgname = $ngshared::CFGNAME;
my $blah = $ngshared::CFGNAME; # keep perl from whining at us
my %vars = %ngshared::Config;
print 'base configuration
';
print '';
print '
' . $INC[0] . q(/) . $cfgname . '
' . "\n";
print "
\n";
foreach my $n (sort keys %vars) {
print $n . q(=);
if (ref($vars{$n}) eq 'ARRAY') {
print "\n";
for my $ii (@{$vars{$n}}) {
print q( ) . $ii . "\n";
}
} elsif (ref($vars{$n}) eq 'HASH') {
print "\n";
my %hash = %{$vars{$n}};
for my $ii (sort keys %hash) {
print q( ) . $ii . q(=) . $hash{$ii} . "\n";
}
} else {
print $vars{$n} . "\n";
}
}
print "
\n";
print '
';
return;
}
sub dumpfiles {
dumpfile('mapfile','map rules');
dumpfile('labelfile','labels');
dumpfile('hostdb','host settings');
dumpfile('servdb','service settings');
dumpfile('groupdb','group settings');
dumpfile('datasetdb','data sources');
dumpfile('rrdoptsfile','RRD options');
return;
}
sub dumpdirs {
dumpdir($INC[0],'contents of config directory');
dumpdir($ngshared::Config{'rrddir'},'contents of RRD directory');
return;
}
sub dumpfile {
my ($key, $desc) = @_;
my %vars = %ngshared::Config;
print '' . $desc . '
';
print '';
if ($vars{$key}) {
my $fn = ngshared::getcfgfn($vars{$key});
print '
' . $fn . '
';
print '
';
if (open my $FH, '<', $fn) {
while (<$FH>) {
my $line = $_;
next if $line =~ /^\s*\#/;
print $line;
}
close $FH or print "close failed for $fn: $OS_ERROR";
} else {
print "cannot read $fn: $OS_ERROR";
}
print '
';
} else {
print '
' . $key . ' is not defined';
}
print '
';
return;
}
# FIXME: do the recursive listing in pure perl
sub dumpdir {
my ($dir, $desc) = @_;
print '' . $desc . '
';
print '';
print '
' . "\n";
print `ls -lRa $dir`; ## no critic (InputOutput::ProhibitBacktickOperators)
print "\n" . '
' . "\n";
print '
';
return;
}
sub checkdir {
my ($key, $desc, $failures) = @_;
my $status = 'ok';
my $errmsg = q();
if ($ngshared::Config{$key}) {
my $dir = ngshared::getcfgfn($ngshared::Config{$key});
if (-d $dir) {
if (! -r $dir) {
$status = 'fail';
$errmsg = 'www user cannot read directory';
}
} else {
$status = 'fail';
$errmsg = 'directory does not exist';
}
} else {
$status = 'fail';
$errmsg = 'directory is not defined';
}
my $style = $status eq 'ok' ? 'ok' : 'critical';
if ($status eq 'fail') {
push @{$failures}, $errmsg;
}
printrow($style, $desc, $status, $errmsg);
return;
}
sub checkfile {
my ($key, $desc, $failures, $optional) = @_;
my $status = 'ok';
my $errmsg = q();
if ($ngshared::Config{$key}) {
my $fn = ngshared::getcfgfn($ngshared::Config{$key});
if (-f $fn) {
if (! -r $fn) {
$status = 'fail';
$errmsg = 'www user cannot read file';
}
} else {
$status = 'fail';
$errmsg = 'file does not exist';
}
} else {
$status = 'fail';
$errmsg = 'file is not defined';
}
my $style = $status eq 'ok' ? 'ok' : 'warning';
if ($status eq 'fail' && ! $optional) {
push @{$failures}, $errmsg;
$style = 'critical';
}
printrow($style, $desc, $status, $errmsg);
return;
}
__END__
=head1 NAME
showconfig.cgi - Show nagiosgraph configuration
=head1 DESCRIPTION
This is a CGI script that is designed to be run on a web server. It displays
the nagiosgraph configuration.
=head1 USAGE
B
=head1 REQUIRED ARGUMENTS
None.
=head1 OPTIONS
None.
=head1 EXIT STATUS
=head1 DIAGNOSTICS
=head1 CONFIGURATION
This script refers to the nagiosgraph library B and the
nagiosgraph configuration file B.
=head1 DEPENDENCIES
None.
=head1 INSTALLATION
Copy B and B to a
configuration directory such as /etc/nagiosgraph.
Copy this file to a CGI script directory on a web server and ensure that
it is executable by the web server. Modify the B