Imported Upstream version 0.6.24+dfsg1

This commit is contained in:
Mario Fetka
2017-05-20 15:26:21 +02:00
commit 32a360eca6
705 changed files with 87250 additions and 0 deletions

52
scripts/Makefile.in Normal file
View File

@@ -0,0 +1,52 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
LIBEXECDIR=@libexecdir@
CGIDIR=@sbindir@
INIT_DIR=@init_dir@
INIT_OPTS=-o root -g root
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
PERFDATADIR=@PERFDATA_DIR@
CP=@CP@
all html:
clean:
distclean: clean
-rm -f process_perfdata.pl check_pnp_rrds.pl net2pnp.pl rc.npcd rc.pnp_gearman_worker rrd_convert.pl
-rm -f Makefile
devclean: distclean
install-init:
$(INSTALL) -m 755 $(INIT_OPTS) -d $(DESTDIR)$(INIT_DIR)
$(INSTALL) -m 755 $(INIT_OPTS) rc.npcd $(DESTDIR)$(INIT_DIR)/npcd
$(INSTALL) -m 755 $(INIT_OPTS) rc.pnp_gearman_worker $(DESTDIR)$(INIT_DIR)/pnp_gearman_worker
install-processperfdata:
$(INSTALL) -m 755 $(INSTALL_OPTS) process_perfdata.pl $(DESTDIR)$(LIBEXECDIR)
install-plugins:
$(INSTALL) -m 755 $(INSTALL_OPTS) check_pnp_rrds.pl $(DESTDIR)$(LIBEXECDIR)
install-rrdconvert:
$(INSTALL) -m 755 $(INSTALL_OPTS) rrd_convert.pl $(DESTDIR)$(LIBEXECDIR)
install-rrdmodify:
$(INSTALL) -m 755 $(INSTALL_OPTS) rrd_modify.pl $(DESTDIR)$(LIBEXECDIR)
install:
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATADIR)
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBEXECDIR)
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)/stats
$(MAKE) install-processperfdata
$(MAKE) install-plugins
$(MAKE) install-rrdconvert
$(MAKE) install-rrdmodify

View File

@@ -0,0 +1,298 @@
#!@PERL@
# nagios: -epn
## check_pnp_rrds - PNP4Nagios.
## Copyright (c) 2006-2009 Joerg Linge (http://www.pnp4nagios.org)
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
use File::Find;
use File::Basename;
use warnings;
use strict;
use Getopt::Long;
my $read_input;
if (eval {require "Term/ReadKey.pm"}) {
import Term::ReadKey;
$read_input = \&read_key;
} else {
$read_input = \&read_stdin;
}
Getopt::Long::Configure('bundling');
my ( $opt_V, $opt_h, $opt_b );
my $opt_a = 7;
my $opt_dxml = 0;
my $opt_drrd = 0;
my $opt_w = 1;
my $opt_c = 10;
my $opt_t = 10;
my $opt_p = "@PERFDATA_DIR@";
my $opt_ncmd = "/usr/local/nagios/var/rw/nagios.cmd";
my $opt_phost = "";
my $opt_pservice = "";
my $opt_ignore;
my $VERSION = "@PKG_VERSION@";
my $PROGNAME = basename($0);
my $PASV = 0;
my $USER = getpwuid($<);
sub print_help () ;
sub print_usage () ;
GetOptions(
"V" => \$opt_V,
"version" => \$opt_V,
"h" => \$opt_h,
"help" => \$opt_h,
"t=i" => \$opt_t,
"timeout=i" => \$opt_t,
"w=i" => \$opt_w,
"warning=i" => \$opt_w,
"c=i" => \$opt_c,
"critical=i" => \$opt_c,
"fileage=i" => \$opt_a,
"a=i" => \$opt_a,
"deletexml" => \$opt_dxml,
"deleterrd" => \$opt_drrd,
"p=s" => \$opt_p,
"rrdpath=s" => \$opt_p,
"passiv-hostname=s" => \$opt_phost,
"passiv-servicedesc=s" => \$opt_pservice,
"nagios-cmd=s" => \$opt_ncmd,
"ignore-hosts=s" => \$opt_ignore,
) or print_help();
print_help() if ($opt_h);
my $RRD_ERRORS = 0;
my $RRD_ERR = "";
my $RRD_AGE = "";
my $XML_COUNT_AGE = 0;
my $XML_COUNT = 0;
my $RRD_COUNT = 0;
my $RC = 0;
my $OUT = "OK: ";
my $PERF = "";
$SIG{'ALRM'} = sub {
print "UNKNOWN: Timeout after $opt_t sec.\n";
exit 3;
};
alarm($opt_t);
$PASV = 1 if($opt_phost && $opt_pservice && $opt_ncmd);
if($PASV == 1 && !-e $opt_ncmd){
print "\n\nUNKNOWN: $opt_ncmd does not exist\n\n";
print_usage();
exit 3;
}
if($PASV == 1 && !-w $opt_ncmd){
print "\n\nUNKNOWN: $opt_ncmd is not writable by \"$USER\" \n\n";
print_usage();
exit 3;
}
if ( -r $opt_p ) {
find { no_chdir => 1,
wanted => \&inspect_files,
} => $opt_p
}
else {
print "UNKNOWN: $opt_p not readable\n";
exit 3;
}
sub inspect_files {
my $file = $File::Find::name;
return unless m/\.xml$/;
return unless -f $file;
my $found = -1;
my $TXT = "invalid xml file";
my $host;
my $service;
my $dir = $File::Find::dir;
if ( $file =~ /\.xml/ ) {
$service = basename($file);
$host = dirname($file);
$host = basename($host);
if ( defined $opt_ignore && $host =~ $opt_ignore ) {
return;
}
$XML_COUNT++;
open F, $file or print "couldn't open $file\n" && return;
while (<F>) {
if (m/<RC>(.*)<\/RC>/) {
$found = $1;
}
if ( $found != 0 && m/<TXT>(.*)<\/TXT>/ ) {
$TXT = $1;
last;
}
}
close F;
my $mtime = ( stat($file) )[9];
my $fileage = ( ( time() - $mtime ) / 86400 );
if ( $fileage >= ( $opt_a ) ) {
if ($opt_dxml) {
print $host . " / " . $service . " is ".$fileage." days old. Delete? (y/n/q) ";
my $ret1 = &$read_input;
# my $ret1 = <>;
if ($ret1 =~ /y/i) {
if (! unlink($file)) {
print " ...Deletion of $file failed!";
} else {
print " ...Deleted file $file.";
}
} elsif ($ret1 =~ /q/i) {
exit;
}
print "\n";
if ($opt_drrd) {
my $rrd = $file;
$rrd =~ s/\.[^.]+$//;
$rrd .= ".rrd";
if (-e $rrd) {
print " Delete " . basename($rrd) . "? (y/n/q) ";
my $ret2 = &$read_input;
if ($ret2 =~ /y/i) {
unlink($rrd) ? print " $rrd deleted." : print " Deletion of $rrd failed.";
} elsif ($ret2 =~/q/i) {
exit;
}
}
}
print "\n\n";
} else {
$XML_COUNT_AGE++;
$RRD_AGE .= sprintf(".../%s/%s is %d days old.\n",$host,$service,$fileage);
}
}
$RRD_ERRORS++ if $found != "0";
$RRD_ERR .= ".../$host/$service $TXT\n" if $found != 0;
}
else {
return;
}
}
sub PROCESS_SERVICE_CHECK_RESULT {
my $RC = shift;
my $OUT = shift;
my $time = time();
my $CommandLine = "[$time] PROCESS_SERVICE_CHECK_RESULT;$opt_phost;$opt_pservice;$RC;$OUT";
print "PROCESS_SERVICE_CHECK_RESULT\n";
print $OUT;
open(CommandFile, ">>$opt_ncmd");
print CommandFile $CommandLine;
close CommandFile;
}
if ( $XML_COUNT == 0 ) {
print "UNKNOWN: No XML files found in $opt_p\n";
exit 3;
}
if ( $RRD_ERRORS >= $opt_w || $XML_COUNT_AGE >= $opt_w ) {
$RC = 1;
$OUT = "WARNING: ";
}
if ( $RRD_ERRORS >= $opt_c || $XML_COUNT_AGE >= $opt_c ) {
$RC = 2;
$OUT = "CRITICAL: ";
}
$OUT .= "$XML_COUNT XML Files checked. $RRD_ERRORS RRD Errors found. $XML_COUNT_AGE old XML Files found";
$PERF = " | total=$XML_COUNT errors=$RRD_ERRORS;$opt_w;$opt_c;0;$XML_COUNT old=$XML_COUNT_AGE;$opt_w;$opt_c;0;$XML_COUNT\n";
$OUT .= $PERF . $RRD_ERR . $RRD_AGE;
if($PASV == 0){
print $OUT;
exit $RC;
}else{
PROCESS_SERVICE_CHECK_RESULT($RC,$OUT);
}
sub print_help (){
print "Copyright (c) 2008 Joerg Linge, Pitchfork\@pnp4nagios.org\n\n";
print "\n";
print "$PROGNAME $VERSION\n";
print "$PROGNAME is used to find old or unusable RRD Files\n";
print "\n";
print_usage();
print "\n";
print "\n";
print_support();
exit 3;
}
sub print_usage () {
print "USAGE: $PROGNAME [OPTIONS]\n";
print " -w,--warning\n";
print " Default: $opt_w\n";
print " -c,--critical\n";
print " Default: $opt_c\n";
print " -a,--fileage Max XML File Age.\n";
print " Default: $opt_a Days\n";
print " -p,--rrdpath Path to your RRD and XML Files.\n";
print " Default: $opt_p\n";
print " -t,--timeout Max Plugin Runtime.\n";
print " Default: $opt_t Seconds\n";
print " --ignore-hosts \n";
print " Regular expression to ignore a set of hosts";
print "\n\n";
print " --deletexml\n";
print " delete old XML files (interactive). \n";
print " --deleterrd\n";
print " delete old RRD files (interactive, only if --deletexml). \n";
print "\n\n";
print " --passiv-hostname=\n";
print " Nagios Hostname\n";
print " --passiv-servicedesc=\n";
print " Nagios Servicedesc\n";
print " --nagios-cmd=\n";
print " External Command File (nagios.cmd)\n";
}
sub print_support {
print "SUPPORT: http://www.pnp4nagios.org/pnp/\n";
print "\n\n";
}
sub read_stdin {
my $rk;
$rk = <>;
return $rk;
}
sub read_key {
my $rk;
ReadMode('cbreak');
$rk = ReadKey(0);
ReadMode('normal');
return $rk;
}
# vim: set ai tabstop=4 shiftwidth=4

File diff suppressed because it is too large Load Diff

162
scripts/rc.npcd.in Normal file
View File

@@ -0,0 +1,162 @@
#!@SHELL@
#
### BEGIN INIT INFO
# Provides: npcd
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: @PKG_NAME@ NPCD Daemon Version @PKG_VERSION@
# Description: Nagios Performance Data C Daemon
### END INIT INFO
# chkconfig: 345 99 01
#
# File : npcd
#
servicename=@npcd_name@
prefix=@prefix@
exec_prefix=${prefix}
NpcdBin=@bindir@/@npcd_name@
NpcdCfgFile=@sysconfdir@/npcd.cfg
NpcdVarDir=@localstatedir@
NpcdRunFile=/var/run/npcd.pid
NpcdLockDir=/var/lock/subsys
NpcdLockFile=@npcd_name@
NpcdUser=@nagios_user@
NpcdGroup=@nagios_grp@
status_npcd (){
pid_npcd
if ps -p $NpcdPID > /dev/null 2>&1; then
return 0
else
if test -f $NpcdLockDir/$NpcdLockFile; then
return 2
else
return 1
fi
fi
return 1
}
printstatus_npcd(){
if status_npcd $1 $2; then
echo "$servicename (pid $NpcdPID) is running..."
exit 0
elif test $? -eq 2; then
echo "$servicename is not running but subsystem locked"
exit 2
else
echo "$servicename is not running"
exit 1
fi
}
killproc_npcd (){
kill $2 $NpcdPID
}
pid_npcd (){
if test ! -f $NpcdRunFile; then
return 1
fi
NpcdPID=`head -n 1 $NpcdRunFile`
return 0
}
# Source function library
# Solaris doesn't have an rc.d directory, so do a test first
if [ -f /etc/rc.d/init.d/functions ]; then
. /etc/rc.d/init.d/functions
elif [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
fi
# Check that npcd exists.
if [ ! -f $NpcdBin ]; then
echo "Executable file $NpcdBin not found. Exiting."
exit 1
fi
# Check that npcd.cfg exists.
if [ ! -f $NpcdCfgFile ]; then
echo "Configuration file $NpcdCfgFile not found. Exiting."
exit 1
fi
# See how we were called.
case "$1" in
start)
status_npcd
if [ $? -eq 0 ]; then
echo "$servicename already started..."
exit 1
fi
echo -n "Starting $servicename:"
touch $NpcdRunFile
chown $NpcdUser:$NpcdGroup $NpcdRunFile
$NpcdBin -d -f $NpcdCfgFile
if [ -d $NpcdLockDir ]; then touch $NpcdLockDir/$NpcdLockFile; fi
echo " done."
exit 0
;;
stop)
status_npcd
if ! [ $? -eq 0 ]; then
echo "$servicename was not running... could not stop"
exit 1
fi
echo -n "Stopping $servicename: "
pid_npcd
killproc_npcd npcd
# now we have to wait for npcd to exit and remove its
# own NpcdRunFile, otherwise a following "start" could
# happen, and then the exiting npcd will remove the
# new NpcdRunFile, allowing multiple npcd daemons
# to (sooner or later) run - John Sellens
#echo -n 'Waiting for npcd to exit .'
for i in 1 2 3 4 5 6 7 8 9 10 ; do
if status_npcd > /dev/null; then
echo -n '.'
sleep 1
else
break
fi
done
if status_npcd > /dev/null; then
echo ''
echo 'Warning - $servicename did not exit in a timely manner'
else
echo 'done.'
fi
rm -f $NpcdLockDir/$NpcdLockFile
;;
status)
printstatus_npcd
;;
reload)
$0 restart
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $servicename {start|stop|restart|status}"
exit 1
;;
esac
# End of this script

View File

@@ -0,0 +1,113 @@
#!@SHELL@
### BEGIN INIT INFO
# Provides: pnp_gearman_worker
# Required-Start: $all
# Required-Stop: $all
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop the pnp4nagios gearman worker
### END INIT INFO
DAEMON="@libexecdir@/process_perfdata.pl"
CFG="@sysconfdir@/process_perfdata.cfg"
NAME=pnp_gearman_worker
PIDFILE=@localstatedir@/${NAME}.pid
LOCKFILE=/var/lock/subsys/${NAME}
USER=@nagios_user@
USERID=`id -u`
CMD="$DAEMON --pidfile=$PIDFILE --config=$CFG --gearman --daemon"
function get_status() {
pid=`cat $PIDFILE 2>/dev/null`
if [ "$pid" != "" ]; then
ps -p $pid > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "$NAME is running with pid $pid"
return 0;
fi
fi
echo "$NAME is not running"
return 1;
}
function kill_procs() {
pid=`cat $PIDFILE 2>/dev/null`
if [ -z $pid ]; then
echo ". Not running."
else
# do a kill if still now down
ps -p $pid > /dev/null 2>&1 && kill $pid
for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5; do
echo -n "."
ps -p $pid > /dev/null 2>&1 && sleep 1;
done
ps -p $pid > /dev/null 2>&1;
if [ $? -ne 0 ]; then
rm -f $PIDFILE
if [ "$USERID" -eq 0 ]; then
rm -f $LOCKFILE
fi
echo "done"
exit 0;
else
echo "failed"
exit 1;
fi
fi
}
case "$1" in
start)
echo -n "Starting $NAME "
get_status > /dev/null;
if [ $? = 0 ]; then
echo "failed"
echo "$NAME already running"
exit 0;
fi
if [ "$USERID" -eq 0 ]; then
su -s $SHELL - $USER -c "$CMD"
else
$CMD
fi
if [ $? -eq 0 ]; then
if [ "$USERID" -eq 0 ]; then
touch $LOCKFILE
fi
echo "done"
exit 0;
else
echo "failed"
exit 1;
fi
;;
stop)
echo -n "Stopping $NAME"
pid=`cat $PIDFILE 2>/dev/null`
if [ -z $pid ]; then
echo ". Not running."
else
# kill if still running
ps -p $pid > /dev/null 2>&1 && kill_procs;
fi
;;
status)
get_status;
exit $?;
;;
restart)
$0 stop && sleep 1 && $0 start
exit $?
;;
*)
echo "Usage: $NAME {start|stop|status|restart}"
exit 1
;;
esac
exit 0

555
scripts/rrd_convert.pl.in Normal file
View File

@@ -0,0 +1,555 @@
#!@PERL@
## @PKG_NAME@@PKG_VERSION@ rrd_convert.pl
## Copyright (c) 2006-2010 Joerg Linge (http://www.pnp4nagios.org)
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@PERL_LIB_PATH_CODE@
use strict;
use warnings;
use Getopt::Long;
use Time::HiRes qw(gettimeofday tv_interval);
use File::Find;
use File::Copy;
if( $< == 0 ){
print "dont try this as root \n";
exit 1;
}
#
# Some global Vars
#
my %conf = (
CFG_DIR => "@sysconfdir@/",
RRDPATH => "@PERFDATA_DIR@",
RRDTOOL => "@RRDTOOL@",
LOG_LEVEL => 0,
DRY_RUN => 0,
FORCE => 0,
RRD_BACKUP => 1,
RRD_STORAGE_TYPE => "SINGLE",
TMP_DIR => '/tmp/rrd_convert',
RRD_DAEMON_OPTS => "",
XML_MAX_AGE => 3600,
);
Getopt::Long::Configure('bundling');
my ( $opt_V, $opt_h, $opt_c, $opt_l, $opt_x, $opt_p );
# defaults
$opt_x = 1;
GetOptions(
"V|version" => \$opt_V,
"h|help" => \$opt_h,
"c|check_command=s" => \$opt_c,
"p|cfg_dir=s" => \$opt_p,
"l|list_commands" => \$opt_l,
"x|no_structure_check" => \$opt_x,
"d|dry-run" => \$conf{DRY_RUN},
"t|tmp_dir=s" => \$conf{TMP_DIR},
"force" => \$conf{FORCE},
);
print_help() if $opt_h;
print_help_opt_p() if !$opt_p;
print_help() if !$opt_c and !$opt_l;
print_version() if $opt_V;
if($opt_p){
$conf{CFG_DIR} = $opt_p;
}
parse_config($conf{CFG_DIR}."/process_perfdata.cfg");
if ( $conf{RRD_DAEMON_OPTS} ){
$conf{RRD_DAEMON_OPTS} = "--daemon=".$conf{RRD_DAEMON_OPTS};
}
my @STRUCT;
my %FILEHANDLE;
my @commands; # list of commands
my @worklist; # list of found xml files
my %ds_list;
my %original_ds_list;
my $max_age = time() - $conf{XML_MAX_AGE};
my %stats = (
'rrd_in' => 0,
'rrd_out' => 0,
'old_xml' => 0,
'xml_without_rrd' => 0,
'runtime' => 0,
);
main();
sub main{
check_storage_type();
find(\&wanted_xml_files, $conf{RRDPATH});
summary();
if($opt_l){ # List commands and exit
summary_command_list();
exit;
}
if($#worklist+1 > 0 ){
my $answer = read_choice("Start Converter [n|y]?");
unless ( $answer =~ m/^y$/i ){
print "Exit...\n";
exit;
}
}else{
print "Check Command '".$opt_c."' not found in any XML File\n";
print "\n";
print "\n";
summary_command_list();
exit;
}
check_custom_template();
write_custom_template();
my $t0 = [gettimeofday];
my $i = 0;
foreach my $xmlfile ( @worklist ) {
$i++;
undef %ds_list;
undef %original_ds_list;
my($host,$service) = parse_xml_filename($xmlfile);
my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/;
$rrdfile .= ".rrd";
if(-r $rrdfile){
create_dir($conf{TMP_DIR});
my $dumpfile = sprintf("%s/%s-%s.dump",$conf{TMP_DIR},$host,$service);
print "File ".$i."/".($#worklist+1)."\n";
rrdtool_dump($rrdfile,$dumpfile);
parse_pnp_xml($xmlfile);
build_ds_list($rrdfile);
next if check_ds_list();
open_files($host,$service);
manipulate_rrd_dump($dumpfile);
close_files();
restore_files($host,$service);
backup_rrd_file($rrdfile);
}
}
my $t1 = [gettimeofday];
$stats{runtime} = tv_interval $t0, $t1;
print "DONE\n";
stats();
}
sub build_ds_list{
my $rrdfile = shift;
my @info;
@info = `$conf{'RRDTOOL'} info $rrdfile`;
if( $? > 0 ){
print "ERROR: $conf{'RRDTOOL'} info $rrdfile returns with $?\n";
exit 1;
}
foreach(@info){
if(m/ds\[(\d+)\]\.type/ ) {
$ds_list{$1} = $1;
}
}
my $test = keys %ds_list;
%original_ds_list = %ds_list;
}
sub check_ds_list{
my $rrd_ds_count = keys %ds_list;
my $xml_ds_count = $#STRUCT;
if($rrd_ds_count == $xml_ds_count){
return 0;
}elsif($rrd_ds_count <= $xml_ds_count && $opt_x){
printf("OK: RRD contains '%s' DS but XML contains '%s'. Convert forced by --no_structure_check\n",$rrd_ds_count,$xml_ds_count);
return 0;
}else{
printf ("ERROR: RRD Structure mismatch. DS Count is '%s' but should be '%s'\n",$rrd_ds_count,$xml_ds_count);
return 1;
}
}
sub wanted_xml_files{
if(m/.xml$/){
#printf("File: %s\n",$File::Find::name);
my $xmlfile = $File::Find::name;
my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/;
$rrdfile .= ".rrd";
my $mtime = (stat($xmlfile))[9];
if ( $mtime < $max_age ){
$stats{old_xml}++;
return;
}
open(XML, $xmlfile);
while (<XML>) {
if(/TEMPLATE>(.*)</){
my ($t) = split("!",$1);
push(@commands,$t);
if(( defined $opt_c) and ($t =~ /^$opt_c$/)){
if( -e $rrdfile ){
#print "Found: ".$t." in ".$xmlfile."\n";
push(@worklist,$xmlfile);
}else{
$stats{xml_without_rrd}++;
}
}elsif(( defined $opt_c) and ($opt_c eq 'ALL')){
if( -e $rrdfile ){
# Keyword 'ALL' retunrs all XML Files
push(@worklist,$xmlfile);
}else{
$stats{xml_without_rrd}++;
}
}
}
}
close(XML);
}
}
sub parse_xml_filename{
my $xmlfile = shift;
$_ = $xmlfile;
if( m/([^\/]+)\/([^\/]+)\.xml$/i ){
return ($1, $2);
}
}
sub summary{
my %seen;
my @uniqed = grep !$seen{$_}++, @commands;
print "\n";
printf "%-40s %s\n" ,"Search pattern",$opt_c if( defined ($opt_c) );
printf "%-40s %s\n" ,"XML Files analyzed",$#commands+1;
printf "%-40s %s\n" ,"XML Files found",$#worklist+1;
printf "%-40s %s\n" ,"XML Files without RRD",$stats{'xml_without_rrd'};
printf "%-40s %s\n" ,"Old XML Files ignored",$stats{'old_xml'};
printf "%-40s %s\n" ,"Number of unique check_commands",$#uniqed+1;
if($conf{DRY_RUN} == 1){
printf "%-40s %s\n" ,"Dry run?","[YES]";
printf "%-40s %s\n" ,"Temp Directory",$conf{TMP_DIR};
print "\n\n";
print "This is only a 'dry run'. The new RRD Files are stored in '$conf{TMP_DIR}'\n";
print "\n";
}
}
sub summary_command_list{
my %seen;
my @uniqed = grep !$seen{$_}++, @commands;
printf "\\ List of Check Commands\n";
foreach my $key (sort { $seen{$b} <=> $seen{$a} } keys %seen ) {
printf " |- %-36s %5s\n",$key,$seen{$key};
}
}
sub stats{
print "\n\n \\Statistics:\n";
foreach my $key (sort { $stats{$b} cmp $stats{$a} } keys %stats ) {
printf " |- %-15s %s\n",$key,$stats{$key};
}
}
sub create_dir{
my $dir = shift;
unless ( -d "$dir" ) {
unless ( mkdir "$dir" ) {
print "ERROR: $dir is not writable\n";
exit 1;
}
}
}
sub open_files(){
my $host = shift;
my $service = shift;
foreach my $ds (keys %ds_list){
my $file = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
#print "Open Filehandle ".$file."\n";
open($FILEHANDLE{$ds}, ">", $file);
}
}
sub close_files(){
foreach my $ds (keys %ds_list){
#$ds--;
#print "Close Filehandle ".$STRUCT[$ds]{NAME}."\n";
close($FILEHANDLE{$ds});
}
}
sub write_to_files{
my $data = shift;
foreach my $ds (keys %ds_list){
print { $FILEHANDLE{$ds} } $data;
}
}
sub restore_files(){
my $host = shift;
my $service = shift;
my $err;
$| = 1;
print "Restoring File\n";
foreach my $ds (keys %ds_list){
my $rrdfile = '';
my $restorefile = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
if( $conf{'DRY_RUN'} == 1 ){
$rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME});
create_dir(sprintf("%s/%s", $conf{TMP_DIR},$host ));
}else{
$rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{RRDPATH},$host,$service,$STRUCT[$ds]{NAME});
}
print "$rrdfile\n";
$err = system("$conf{'RRDTOOL'} restore -f '$restorefile' '$rrdfile'");
if($err){
printf("RRDtool Error: %s\n",$err);
exit;
}
unlink($restorefile);
$stats{rrd_out}++;
}
print "... done\n";
$| = 0;
}
sub backup_rrd_file{
my $rrdfile = shift;
if ( $conf{RRD_BACKUP} == 1 ){
move($rrdfile, $rrdfile.".backup");
}
}
sub parse_pnp_xml{
my $xmlfile = shift;
undef @STRUCT;
#print "reading $xmlfile\n";
open(XML, $xmlfile);
my $DATASOURCE = 0;
while (<XML>) {
if(/<DATASOURCE>/){
$DATASOURCE++;
}
if(/<RRD>/){
$DATASOURCE = 0;
}
if(/<([A-Z_]+)>(.*)<\/[A-Z_]+>/ && $DATASOURCE != -1){
$STRUCT[$DATASOURCE]{$1} = $2;
}
}
close(XML);
return @STRUCT;
}
sub rrdtool_dump{
my $rrdfile = shift;
my $dumpfile = shift;
my $err;
print "RRDtool dump to $dumpfile\n";
if ( $conf{RRD_DAEMON_OPTS} ){
$err = system("$conf{'RRDTOOL'} dump $conf{RRD_DAEMON_OPTS} $rrdfile > $dumpfile");
}else{
$err = system("$conf{'RRDTOOL'} dump $rrdfile > $dumpfile");
}
if($err){
printf("RRDtool Error: %s\n",$err);
exit;
}
$stats{rrd_in}++;
return $dumpfile;
}
sub manipulate_rrd_dump{
my $tmpfile = shift;
my $i = 0;
open (XML,$tmpfile);
my @ROW = ();
my $tmpds = 1;
my $inside_ds_block = 0;
print "Manipulating $tmpfile\n";
while (<XML>){
$i++;
unless ( $i % 5000 ){
$| = 1; print "."; $| = 0;
}
my $d = $_;
#
# A Data Row
if(m/<row>/){
m/(.*<row>)/;
my $rowstart = $1;
@ROW = m{<v>([^<].*?)<\/v>}gc;
my $fh = 1;
foreach my $VAL (@ROW){
undef %ds_list;
$ds_list{$fh} = $fh;
write_to_files($rowstart."<v>".$VAL."</v></row>\n");
$fh++;
}
next;
}
if(m/<ds>/){
$inside_ds_block = 1;
undef %ds_list;
$ds_list{$tmpds} = $tmpds;
write_to_files($d);
$tmpds++;
next;
}
if(m/<cdp_prep>/){
write_to_files($d);
$inside_ds_block = 0;
$tmpds = 1;
%ds_list = %original_ds_list;
next;
}
if(m/<\/ds>/){
write_to_files($d);
$inside_ds_block = 0;
# write to all files alter </ds>
%ds_list = %original_ds_list;
next;
}
if(m/<\/database>/){
# write to all files alter </database>
%ds_list = %original_ds_list;
write_to_files($d);
next;
}
if($inside_ds_block == 1){
# rename DS
$d =~ s/<name>(.*)<\/name>/<name> 1 <\/name>/;
}
write_to_files($d);
}
close(XML);
print "... done $i lines\n";
unlink($tmpfile);
}
#
# Parse process_perfdata.cfg
#
sub parse_config {
my $config_file = shift;
my $line = 0;
if( ! -e $config_file ){
print "$config_file not found\n";
exit;
}
if ( -e $config_file ) {
open CFG, '<', "$config_file";
while (<CFG>) {
$line++;
chomp;
s/ //g;
next if /^#/;
next if /^$/;
s/#.*//;
if (/^(.*)=(.*)$/) {
if ( defined $conf{$1} ) {
$conf{$1} = $2;
}
}
}
close CFG;
}
}
#
# Change RRD_STORAGE_TYPE to MULTIPLE
#
sub change_config {
my $cfg_file = $conf{'CFG_DIR'}."/process_perfdata.cfg";
my $error = system("sed -i -e ".'s/\s*RRD_STORAGE_TYPE\s*=\s*SINGLE/RRD_STORAGE_TYPE=MULTIPLE/i'." $cfg_file");
}
sub check_storage_type{
if($conf{'RRD_STORAGE_TYPE'} eq "MULTIPLE"){
print "RRD_STORAGE_TYPE is already set to ".$conf{'RRD_STORAGE_TYPE'}."\n";
}
}
sub check_custom_template {
my $command = $opt_c;
if ( $conf{DRY_RUN} == 1 ){
print "No config check while DRY_RUN = 1\n";
return;
}
if ( $command eq "ALL" ){
return;
}
my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg";
my $storage_type = "MULTIPLE";
if ( -e $config_file && $conf{'FORCE'} == 0 ) {
print "\nConfig for command $command does already exist ($config_file)\n\n";
exit 0;
}
}
sub write_custom_template {
my $command = $opt_c;
if ( $conf{DRY_RUN} == 1 ){
print "No config check while DRY_RUN = 1\n";
return;
}
if ( $opt_c eq "ALL"){
change_config();
return;
}
my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg";
my $storage_type = "MULTIPLE";
open(CFG, ">", $config_file);
print CFG "# Generated by rrd_convert.pl @PKG_VERSION@\n";
print CFG "RRD_STORAGE_TYPE = MULTIPLE\n";
close(CFG);
if ( -s $config_file ) {
print "\nConfig for command $command created ($config_file)\n";
}
}
sub read_choice{
my $question = shift;
print $question.":";
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
sub print_help{
print "Usage: $0 --check_command=<nagios_check_command>\n";
print " --cfg_dir=<path_to_pnp_etc_dir>\n";
print " [ --list_commands ]\n";
print " [ --dry-run ]\n";
print " [ --tmp_dir=<temp directory> ]\n";
print " [ --no_structure_check ]\n";
print "\n";
print "This script is used to switch to RRD_STORAGE_TYPE = MULTIPLE for a given Nagios Check Command\n";
print "More info online http://docs.pnp4nagios.org/pnp-0.6/rrd_convert\n";
exit;
}
sub print_help_opt_p{
print "\n";
print "--cfg_dir not set\n";
print "Please provide the path to your PNP4Nagios config directory\n";
print "\n";
print_help();
}
sub print_version{
print "Version @PKG_VERSION@\n";
exit;
}

282
scripts/rrd_modify.pl.in Normal file
View File

@@ -0,0 +1,282 @@
#!@PERL@ -w
# nagios: -epn
## @PKG_NAME@@PKG_VERSION@
#
# Copyright (c) 2012 PNP4Nagios Developer Team (http://www.pnp4nagios.org)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# There are several Perl modules out there on www.cpan.org which allow adding
# columns to an RRD file, so if this one doesn't fit your needs please have
# a look there.
# Please report any errors nevertheless.
# See http://docs.pnp4nagios.org/pnp-0.6/about#support for details.
use strict;
use warnings;
# you may have to adapt the path to your environment
my $rrdtool = "@RRDTOOL@";
# set to 1 if using PNP4Nagios where data source names are numerical
my $PNP = 1;
### ---------------------------------------- ###
### no user servicable parts below this line ###
my $pgm = "rrd_modify.pl";
my $version = "0.01";
my $legal = "Copyright (c) 2012 PNP4Nagios Developer Team (http://www.pnp4nagios.org)";
my ($rrd,$action,$columns,$type) = @ARGV;
# valid actions
my %action = (insert => 1, delete => 2);
# valid data types
my %type = (GAUGE => 1, COUNTER => 2, DERIVE => 3, ABSOLUTE => 4, COMPUTE => 5);
# xml tags within cdp_prep
my @cdp = ('primary_value','secondary_value','value',
'unknown_datapoints','seasonal','last_seasonal',
'init_flag','intercept','last_intercept',
'slope','last_slope','nan_count','last_nan_count');
my @ds = (); # number of data sources within the rrd file
my $out = 1; # output lines to file
my $sign = "."; # decimal sign (locale dependent)
my %xml = (); # lines within ds structure
# <rrd file> <action> <start column> defined?
if ($#ARGV < 2) {
usage();
exit 1;
}
die "$rrd does not exist\n" unless (-f $rrd);
die "$rrd is not readable\n" unless (-r $rrd);
die "$rrd is not writable\n" unless (-w $rrd);
die "$rrdtool is a directory\n" if (-d $rrdtool);
die "$rrdtool does not exist\n" unless (-f $rrdtool);
die "$rrdtool is not executable\n" unless (-x $rrdtool);
$action = lc($action);
unless (exists($action{$action})) {
print "ERROR: action $action is not valid\n\n";
usage();
exit 1;
}
my ($start,$no) = split(/,/,$columns);
$no = 1 unless (defined $no);
# determine the number of data sources
my $ds = `$rrdtool info $rrd | grep '^ds' | grep 'value' | wc -l`;
# determine the decimal sign
$sign = `$rrdtool info $rrd | grep '^ds' | grep 'value' | tail -1`;
($sign) = $sign =~ /.* \d(.)\d+/;
my $end = ($action eq "insert" ? $ds+$no : $ds);
if (($start < 1) or ($start > $ds + 1)) {
print "ERROR: number ($start) must be within 1..".($ds+1)."\n";
exit 2;
}
# check / set type of data source to be created
if ($action eq "insert") {
if (defined $type) {
$type = uc($type);
unless (exists($type{$type})) {
print "ERROR: type $type is not valid\n\n";
usage();
exit 3;
}
} else {
$type = "GAUGE";
}
}
# names of temporary/output files
my $tmp1 = "$rrd.in";
my $tmp2 = "$rrd.out";
my $cmd = "$rrdtool dump $rrd > $tmp1";
my $erg = system("$cmd");
print "$cmd: RC=$erg\n" if ($erg);
processing ("$rrd");
$cmd = "$rrdtool restore $tmp2 $rrd.chg";
$erg = system("$cmd");
print "$cmd: RC=$erg\n" if ($erg);
unlink "$tmp1";
unlink "$tmp2";
exit;
### some sub routines
sub processing {
open (IFILE, "$tmp1") || die "error during open of $tmp1, RC=$!\n";
open (OFILE, ">$tmp2") || die "error during create of $tmp2, RC=$!\n";
while (<IFILE>) {
my $tmp = $_;
if (/<ds>/) {
$out = 0;
%xml = ();
next;
}
if (/<\/ds>/) {
my %tmp = %xml;
push @ds, \%tmp;
next;
}
if ((m|Round Robin Archives|) or (m|</cdp_prep>|)) {
$out = 1;
if ($action eq "insert") {
my @save = splice(@ds,$start-1);
for (1..$no) {
my %xml = (@save) ? %{$save[0]} : %{$ds[0]};
$xml{name} = $start+$_-1;
# set defaults
if (m|Round Robin Archives|) {
$xml{last_ds} = "U";
$xml{value} = "0${sign}0000000000e+00";
$xml{unknown_sec} = 0;
} else {
$xml{primary_value} = "0${sign}0000000000e+00";
$xml{secondary_value} = "0${sign}0000000000e+00";
$xml{value} = "NaN" if (exists $xml{value});
$xml{unknown_datapoints} = 0 if (exists $xml{unknown_datapoints});
$xml{init_flag} = 1 if (exists $xml{init_flag});
$xml{seasonal} = "NaN" if (exists $xml{seasonal});
$xml{last_seasonal} = "NaN" if (exists $xml{last_seasonal});
$xml{intercept} = "NaN" if (exists $xml{intercept});
$xml{last_intercept} = "NaN" if (exists $xml{last_intercept});
$xml{slope} = "NaN" if (exists $xml{slope});
$xml{last_slope} = "NaN" if (exists $xml{last_slope});
$xml{nan_count} = 1 if (exists $xml{nan_count});
$xml{last_nan_count} = 1 if (exists $xml{last_nan_count});
}
push @ds,\%xml;
}
push @ds,@save;
} else {
my @save = splice(@ds,$start-1,$no);
if ($PNP) { # renumber data source names
for my $idx ($start..$end-$no) {
$ds[$idx-1]->{name} = $idx;
}
}
}
if (m|Round Robin Archives|) {
out_ds1();
} else {
out_ds2();
}
print OFILE $tmp;
@ds = ();
next;
}
if (/<row>/) {
row($_);
next;
}
# value enclosed in XML tags
if (/<(\S+)>\s+(\S+)\s+</) {
$xml{$1} = $2;
}
next unless ($out);
print OFILE $tmp;
}
close (IFILE);
close (OFILE);
}
sub row {
my $in = shift;
my ($line,$r) = $in =~ /(.*<row>)(.*)<\/row>/;
for (1..$start-1) {
if ($r =~ s#^(<v>.*?</v>)##) {
$line .= $1;
}
}
for ($start..$start+$no-1) {
if ($action eq "insert") {
$line .= "<v> NaN </v>";
} else {
$r =~ s#^(<v>.*?</v>)##;
}
}
for ($start+$no..$end) {
if ($r =~ s#^(<v>.*?</v>)##) {
$line .= $1;
}
}
$line .= "</row>\n";
print OFILE $line;
}
sub out_ds1 {
for (0..$#ds) {
print OFILE <<EOD;
\t<ds>
\t\t<name> $ds[$_]->{name} </name>
\t\t<type> $ds[$_]->{type} </type>
\t\t<minimal_heartbeat> $ds[$_]->{minimal_heartbeat} </minimal_heartbeat>
\t\t<min> $ds[$_]->{min} </min>
\t\t<max> $ds[$_]->{max} </max>
\t\t<!-- PDP Status -->
\t\t<last_ds> $ds[$_]->{last_ds} </last_ds>
\t\t<value> $ds[$_]->{value} </value>
\t\t<unknown_sec> $ds[$_]->{unknown_sec} </unknown_sec>
\t</ds>
EOD
}
}
sub out_ds2 {
for my $ds_no (0..$#ds) {
print OFILE "\t\t\t<ds>\n";
for my $tag (0..$#cdp) {
print OFILE "\t\t\t<$cdp[$tag]> $ds[$ds_no]->{$cdp[$tag]} </$cdp[$tag]>\n" if (exists($ds[$ds_no]->{$cdp[$tag]}));
}
print OFILE "\t\t\t</ds>\n";
}
}
sub usage {
print <<EOD;
=== $pgm $version ===
$legal
This script can be used to alter the number of data sources of an RRD file.
Usage:
$pgm RRD_file insert|delete start_ds[,no_of_cols] [type]
Arguments:
RRD_file
the location of the RRD file. It will NOT be overwritten but appended
by ".chg"
insert or delete
the operation to be executed
start_ds
the position at which the operation starts (1..no of data sources+1)
no_of_cols
(an optional) number of columns which will be added/deleted
type
the data type (one of GAUGE, COUNTER)
Defaults to GAUGE if not specified for insert operations
(DERIVE, ABSOLUTE, COMPUTE have not been tested and might result in
errors during creation of a new RRD file)
EOD
}

1009
scripts/verify_pnp_config_v2.pl Executable file

File diff suppressed because it is too large Load Diff