1010 lines
29 KiB
Perl
1010 lines
29 KiB
Perl
|
#!/usr/bin/perl
|
|||
|
# Copyright (c) 2005-2011 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.
|
|||
|
#
|
|||
|
#
|
|||
|
use strict;
|
|||
|
use warnings;
|
|||
|
use Data::Dumper;
|
|||
|
use Getopt::Long;
|
|||
|
use File::Find;
|
|||
|
use File::Glob;
|
|||
|
use Term::ANSIColor;
|
|||
|
|
|||
|
my $version = 'pnp4nagios-head';
|
|||
|
|
|||
|
# process command line parameters
|
|||
|
use vars qw ( $help $debug $mode $vInfo $PNPCfg $MainCfg $last_check $object);
|
|||
|
my $start_options = $0 . " " . join(" ", @ARGV);
|
|||
|
Getopt::Long::Configure('bundling');
|
|||
|
GetOptions(
|
|||
|
"h|help" => \$help,
|
|||
|
"d|debug" => \$debug,
|
|||
|
"m|mode=s" => \$mode,
|
|||
|
"c|config=s" => \$MainCfg,
|
|||
|
"p|pnpcfg=s" => \$PNPCfg,
|
|||
|
"o|object=s" => \$object,
|
|||
|
);
|
|||
|
|
|||
|
my @modes = ("bulk", "bulk+npcd", "sync", "npcdmod");
|
|||
|
my @products = ("nagios", "icinga");
|
|||
|
my @states = ("OK", "WARN", "CRIT", "UNKN", "INFO", "HINT", "DBG");
|
|||
|
my @colors = ("bold green", "bold yellow", "bold red", "bold blue", "bold blue", "bold yellow", "black on_red");
|
|||
|
my %process_perf_data_stats = ('hosts' => 0, 'services' => 0, 'noperf' => 0, 'noperf_but_enabled' => 0 , 0 => 0, 1 => 0);
|
|||
|
my %stats = ( 0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 =>0 );
|
|||
|
my %sizing = (
|
|||
|
50 => 'sync',
|
|||
|
200 => 'bulk',
|
|||
|
5000 => 'bulk+npcd',
|
|||
|
10000 => 'npcdmod',
|
|||
|
);
|
|||
|
|
|||
|
if ( ! $MainCfg ){
|
|||
|
usage();
|
|||
|
usage_no_config();
|
|||
|
exit;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! $mode ){
|
|||
|
usage();
|
|||
|
usage_no_mode();
|
|||
|
exit;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! $PNPCfg ){
|
|||
|
usage();
|
|||
|
usage_no_pnpcfg();
|
|||
|
exit;
|
|||
|
}
|
|||
|
|
|||
|
if( ! in_array(\@modes, $mode)){
|
|||
|
usage();
|
|||
|
info("'$mode' is not a valid option",2);
|
|||
|
info("Valid modes are [@modes]",2);
|
|||
|
exit;
|
|||
|
}
|
|||
|
|
|||
|
my %statistics = (
|
|||
|
'OK' => 0,
|
|||
|
'WARN' => 0,
|
|||
|
'CRIT' => 0,
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
my %cfg = ();
|
|||
|
my %commands = ();
|
|||
|
my $uid = 0;
|
|||
|
my $gid = 0;
|
|||
|
my $process_perfdata_cfg = 0;
|
|||
|
|
|||
|
#
|
|||
|
# Begin
|
|||
|
#
|
|||
|
|
|||
|
info("========== Starting Environment Checks ============",4);
|
|||
|
info("My version is: ".$version,4);
|
|||
|
info("Start Options: ".$start_options, 4);
|
|||
|
|
|||
|
#
|
|||
|
# Read Main config file
|
|||
|
#
|
|||
|
process_nagios_cfg();
|
|||
|
#
|
|||
|
# get the product name
|
|||
|
#
|
|||
|
my $product = get_product();
|
|||
|
if( $product eq 0 ){
|
|||
|
info("Can´t determine product while reading $MainCfg", 4);
|
|||
|
info_and_exit("$MainCfg does not look like a valid config file", 2);
|
|||
|
}else{
|
|||
|
info("Running product is '$product'", 0);
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Read objects cache file to get more information
|
|||
|
# Needs a running product
|
|||
|
#
|
|||
|
check_config_var('object_cache_file', 'exists', 'break');
|
|||
|
if( -r $cfg{'object_cache_file'} ){
|
|||
|
process_objects_file($cfg{'object_cache_file'});
|
|||
|
}else{
|
|||
|
info_and_exit($cfg{'object_cache_file'}. " is not readable", 2);
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Read resource.cfg
|
|||
|
#
|
|||
|
check_config_var('resource_file', 'exists', 'break');
|
|||
|
if( -r $cfg{'resource_file'} ){
|
|||
|
process_npcd_cfg($cfg{'resource_file'});
|
|||
|
}else{
|
|||
|
info_and_exit($cfg{'resource_file'}. " is not readable", 2);
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Read process_perfdata.cfg
|
|||
|
#
|
|||
|
if ( ! -d $PNPCfg ){
|
|||
|
info_and_exit("Directory $PNPCfg does not exist",2);
|
|||
|
}
|
|||
|
if ( ! -d "$PNPCfg/check_commands" ){
|
|||
|
info("Directory $PNPCfg/check_commands does not exist",2);
|
|||
|
info_and_exit("$PNPCfg does not look like a PNP4Nagios config directory",2);
|
|||
|
}
|
|||
|
my $ppcfg = "$PNPCfg/process_perfdata.cfg";
|
|||
|
process_perfdata_cfg($ppcfg);
|
|||
|
|
|||
|
#
|
|||
|
# Read etc/pnp_release file if exists
|
|||
|
#
|
|||
|
if( -r "$PNPCfg/pnp4nagios_release" ){
|
|||
|
process_pnp4nagios_release("$PNPCfg/pnp4nagios_release");
|
|||
|
info("Found PNP4Nagios version ".get_config_var('PKG_VERSION'), 0);
|
|||
|
info("./configure Options ".get_config_var('CONFIGURE_ARGS'), 0) if get_config_var('CONFIGURE_ARGS');
|
|||
|
}else{
|
|||
|
info("No pnp4nagios_release file found. This might be an older version of PNP4Nagios", 0);
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Start Main config checks
|
|||
|
#
|
|||
|
|
|||
|
if(config_var_exists($product.'_user') ){
|
|||
|
my $user = get_config_var($product.'_user');
|
|||
|
$uid = getpwnam($user);
|
|||
|
info( "Effective User is '$user'", 0);
|
|||
|
if($uid){
|
|||
|
info("User $user exists with ID '$uid'", 0 );
|
|||
|
}else{
|
|||
|
info_and_exit("User $user does not exist", 2 );
|
|||
|
}
|
|||
|
}else{
|
|||
|
info_and_exit("Option '".$product."_user' not found in $MainCfg", 2);
|
|||
|
}
|
|||
|
|
|||
|
if(config_var_exists($product.'_group') ){
|
|||
|
my $group = get_config_var($product.'_group');
|
|||
|
$gid = getgrnam($group);
|
|||
|
info( "Effective group is '$group'", 0);
|
|||
|
if($gid){
|
|||
|
info("Group $group exists with ID '$gid'", 0 );
|
|||
|
}else{
|
|||
|
info_and_exit("Group $group does not exist", 2 );
|
|||
|
}
|
|||
|
}else{
|
|||
|
info_and_exit("Option '".$product."_group' not found in $MainCfg", 2);
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Start sync config checks
|
|||
|
#
|
|||
|
|
|||
|
if($mode eq "sync"){
|
|||
|
info("========== Checking Sync Mode Config ============",4);
|
|||
|
|
|||
|
compare_config_var('process_performance_data', '1');
|
|||
|
compare_config_var('enable_environment_macros', '1');
|
|||
|
|
|||
|
check_config_var('service_perfdata_command', 'exists');
|
|||
|
check_config_var('host_perfdata_command', 'exists');;
|
|||
|
last_info("Needed config options are missing.",5,$last_check);
|
|||
|
|
|||
|
# Options not allowed in sync mode
|
|||
|
check_config_var('service_perfdata_file', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_template', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_mode', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_processing_interval', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_processing_command', 'notexists',);
|
|||
|
check_config_var('host_perfdata_file', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_template', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_mode', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_processing_interval', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_processing_command', 'notexists');
|
|||
|
check_config_var('broker_module', 'notexists');
|
|||
|
last_info("Config options are not allowed in sync mode. http://docs.pnp4nagios.org",5,$last_check);
|
|||
|
|
|||
|
info(ucfirst($product)." config looks good so far",4);
|
|||
|
info("========== Checking config values ============",4);
|
|||
|
my $command_line;
|
|||
|
|
|||
|
$command_line = check_command_definition('service_perfdata_command');
|
|||
|
check_process_perfdata_pl($command_line);
|
|||
|
|
|||
|
$command_line = check_command_definition('host_perfdata_command');
|
|||
|
check_process_perfdata_pl($command_line);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if($mode eq "bulk"){
|
|||
|
info("========== Checking Bulk Mode Config ============",4);
|
|||
|
|
|||
|
compare_config_var('process_performance_data', '1');
|
|||
|
check_config_var('service_perfdata_file', 'exists');
|
|||
|
check_config_var('service_perfdata_file_template', 'exists');
|
|||
|
check_perfdata_file_template(get_config_var('service_perfdata_file_template'));
|
|||
|
check_config_var('service_perfdata_file_mode', 'exists');
|
|||
|
check_config_var('service_perfdata_file_processing_interval', 'exists');
|
|||
|
check_config_var('service_perfdata_file_processing_command', 'exists');
|
|||
|
|
|||
|
check_config_var('host_perfdata_file', 'exists');
|
|||
|
check_config_var('host_perfdata_file_template', 'exists');
|
|||
|
check_perfdata_file_template(get_config_var('host_perfdata_file_template'));
|
|||
|
check_config_var('host_perfdata_file_mode', 'exists');
|
|||
|
check_config_var('host_perfdata_file_processing_interval', 'exists');
|
|||
|
check_config_var('host_perfdata_file_processing_command', 'exists');
|
|||
|
last_info("Needed config options are missing.",5,$last_check);
|
|||
|
|
|||
|
# Options not allowed in bulk mode
|
|||
|
check_config_var('service_perfdata_command', 'notexists');
|
|||
|
check_config_var('host_perfdata_command', 'notexists');
|
|||
|
check_config_var('broker_module', 'notexists');
|
|||
|
last_info("Config options are not allowed in bulk mode",5,$last_check);
|
|||
|
|
|||
|
info(ucfirst($product)." config looks good so far",4);
|
|||
|
info("========== Checking config values ============",4);
|
|||
|
my $command_line;
|
|||
|
|
|||
|
$command_line = check_command_definition('service_perfdata_file_processing_command');
|
|||
|
check_process_perfdata_pl($command_line);
|
|||
|
|
|||
|
$command_line = check_command_definition('host_perfdata_file_processing_command');
|
|||
|
check_process_perfdata_pl($command_line);
|
|||
|
}
|
|||
|
|
|||
|
if($mode eq "bulk+npcd"){
|
|||
|
info("========== Checking Bulk Mode + NPCD Config ============",4);
|
|||
|
|
|||
|
compare_config_var('process_performance_data', '1');
|
|||
|
check_config_var('service_perfdata_file', 'exists');
|
|||
|
check_config_var('service_perfdata_file_template', 'exists');
|
|||
|
check_perfdata_file_template(get_config_var('service_perfdata_file_template'));
|
|||
|
check_config_var('service_perfdata_file_mode', 'exists');
|
|||
|
check_config_var('service_perfdata_file_processing_interval', 'exists');
|
|||
|
check_config_var('service_perfdata_file_processing_command', 'exists');
|
|||
|
|
|||
|
check_config_var('host_perfdata_file', 'exists');
|
|||
|
check_config_var('host_perfdata_file_template', 'exists');
|
|||
|
check_perfdata_file_template(get_config_var('host_perfdata_file_template'));
|
|||
|
check_config_var('host_perfdata_file_mode', 'exists');
|
|||
|
check_config_var('host_perfdata_file_processing_interval', 'exists');
|
|||
|
check_config_var('host_perfdata_file_processing_command', 'exists');
|
|||
|
last_info("Needed config options are missing. http://docs.pnp4nagios.org",5,$last_check);
|
|||
|
|
|||
|
# Options not allowed in bulk mode
|
|||
|
check_config_var('service_perfdata_command', 'notexists');
|
|||
|
check_config_var('host_perfdata_command', 'notexists');
|
|||
|
check_config_var('broker_module', 'notexists');
|
|||
|
last_info("Config options are not allowed in bulk mode with npcd",5,$last_check);
|
|||
|
|
|||
|
info(ucfirst($product)." config looks good so far",4);
|
|||
|
info("========== Checking config values ============",4);
|
|||
|
my $command_line;
|
|||
|
|
|||
|
my $npcd_cfg = check_proc_npcd(get_config_var($product.'_user'));
|
|||
|
|
|||
|
if( -r $npcd_cfg){
|
|||
|
info("$npcd_cfg is used by npcd and readable",0);
|
|||
|
}else{
|
|||
|
info_and_exit("$npcd_cfg is not readable",0);
|
|||
|
}
|
|||
|
# read npcd.cfg into %cfg
|
|||
|
process_npcd_cfg($npcd_cfg);
|
|||
|
|
|||
|
check_config_var('perfdata_spool_dir', 'exists');
|
|||
|
count_spool_files(get_config_var('perfdata_spool_dir'));
|
|||
|
|
|||
|
$command_line = check_command_definition('service_perfdata_file_processing_command');
|
|||
|
$command_line = check_command_definition('host_perfdata_file_processing_command');
|
|||
|
|
|||
|
check_process_perfdata_pl($cfg{'perfdata_file_run_cmd'});
|
|||
|
}
|
|||
|
|
|||
|
if($mode eq "npcdmod"){
|
|||
|
my $val;
|
|||
|
|
|||
|
info("========== Checking npcdmod Mode Config ============",4);
|
|||
|
|
|||
|
compare_config_var('process_performance_data', '1');
|
|||
|
last_info ("Needed config options are missing. http://docs.pnp4nagios.org",5,$last_check);
|
|||
|
|
|||
|
# Options not allowed in sync mode
|
|||
|
check_config_var('service_perfdata_file', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_template', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_mode', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_processing_interval', 'notexists');
|
|||
|
check_config_var('service_perfdata_file_processing_command', 'notexists');
|
|||
|
check_config_var('host_perfdata_file', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_template', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_mode', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_processing_interval', 'notexists');
|
|||
|
check_config_var('host_perfdata_file_processing_command', 'notexists');
|
|||
|
last_info("Config options are not allowed in bulk mode with npcd",5,$last_check);
|
|||
|
|
|||
|
# event_broker_option must have enabled bits 2 and 3 (0b01100)
|
|||
|
check_config_var ('event_broker_options', 'exists');
|
|||
|
$val = get_config_var('event_broker_options') & 0x0c;
|
|||
|
if($val == 12){
|
|||
|
info("event_broker_option bits 2 and 3 enabled ($val)",0);
|
|||
|
}else{
|
|||
|
info_and_exit("event_broker_option bits 2 and/or 3 not enabled",2);
|
|||
|
}
|
|||
|
|
|||
|
check_config_var('broker_module', 'exists', 'break');
|
|||
|
|
|||
|
$val = get_config_var('broker_module');
|
|||
|
# extract npcd.cfg patch from broker_module definition
|
|||
|
my $npcdmod_npcd_cfg;
|
|||
|
$val =~ /npcdmod\.o\s+config_file=(.*)$/;
|
|||
|
if($1){
|
|||
|
$npcdmod_npcd_cfg=$1;
|
|||
|
info("npcdmod.o config file is $npcdmod_npcd_cfg",0);
|
|||
|
if( -r $npcdmod_npcd_cfg){
|
|||
|
info("$npcdmod_npcd_cfg used by npcdmod.o is readable",0);
|
|||
|
}else{
|
|||
|
info_and_exit("$npcdmod_npcd_cfg used by npcdmod.o is not readable",2);
|
|||
|
}
|
|||
|
}else{
|
|||
|
info("broker_module definition looks suspect '$val'",2);
|
|||
|
info_and_exit("Can´t extract path to npcd.cfg from your broker_module definition",2);
|
|||
|
}
|
|||
|
# extract npcd.cfg path from process list
|
|||
|
my $npcd_cfg = check_proc_npcd(get_config_var($product.'_user'));
|
|||
|
if( -r $npcd_cfg){
|
|||
|
info("$npcd_cfg is used by npcd and readable",0);
|
|||
|
}
|
|||
|
if($npcd_cfg eq $npcdmod_npcd_cfg){
|
|||
|
info("npcd and npcdmod.o are using the same config file ($npcd_cfg)",0);
|
|||
|
}else{
|
|||
|
info_and_exit("npcd and npcdmod.o are not using the same config file($npcd_cfg<=>$npcdmod_npcd_cfg)",2);
|
|||
|
}
|
|||
|
|
|||
|
# read npcd.cfg into %cfg
|
|||
|
process_npcd_cfg($npcd_cfg);
|
|||
|
check_config_var('perfdata_spool_dir', 'exists');
|
|||
|
count_spool_files(get_config_var('perfdata_spool_dir'));
|
|||
|
|
|||
|
info(ucfirst($product)." config looks good so far",4);
|
|||
|
info("========== Checking config values ============",4);
|
|||
|
|
|||
|
# read npcd.cfg into %cfg
|
|||
|
process_npcd_cfg($npcd_cfg);
|
|||
|
check_process_perfdata_pl($cfg{'perfdata_file_run_cmd'});
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
info("========== Starting global checks ============",4);
|
|||
|
check_config_var('status_file', 'exists', 'break');
|
|||
|
process_status_file();
|
|||
|
info("==== Starting rrdtool checks ====",4);
|
|||
|
check_rrdtool();
|
|||
|
|
|||
|
info("==== Starting directory checks ====",4);
|
|||
|
check_config_var('RRDPATH', 'exists', 'break');
|
|||
|
check_perfdata_dir(get_config_var('RRDPATH'));
|
|||
|
|
|||
|
if($process_perf_data_stats{1} == 0){
|
|||
|
info("'process_perf_data 1' is not set for any of your hosts/services",2);
|
|||
|
}
|
|||
|
if($process_perf_data_stats{'noperf'} > 0){
|
|||
|
info($process_perf_data_stats{'noperf'}." hosts/services are not providing performance data",1);
|
|||
|
}
|
|||
|
if($process_perf_data_stats{'noperf_but_enabled'} > 0){
|
|||
|
info("'process_perf_data 1' is set for ".$process_perf_data_stats{'noperf_but_enabled'}." hosts/services which are not providing performance data!",1);
|
|||
|
}
|
|||
|
if($process_perf_data_stats{0} > 0){
|
|||
|
info("'process_perf_data 0' is set for ".$process_perf_data_stats{0}." of your hosts/services",1);
|
|||
|
}
|
|||
|
if($process_perf_data_stats{1} > 0){
|
|||
|
info("'process_perf_data 1' is set for ".$process_perf_data_stats{1}." of your hosts/services",0);
|
|||
|
}
|
|||
|
|
|||
|
if ( get_config_var('LOG_LEVEL') gt 0 ){
|
|||
|
info("Logging is enabled in process_perfdata.cfg. This will reduce the overall performance of PNP4Nagios",1)
|
|||
|
}
|
|||
|
|
|||
|
info("==== System sizing ====",4);
|
|||
|
print_sizing();
|
|||
|
|
|||
|
info("==== Check statistics ====",4);
|
|||
|
print_stats();
|
|||
|
exit;
|
|||
|
|
|||
|
#
|
|||
|
# Helper Functions
|
|||
|
#
|
|||
|
|
|||
|
sub config_var_exists {
|
|||
|
my $key = shift;
|
|||
|
if(exists $cfg{$key}){
|
|||
|
return 1;
|
|||
|
}else{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub get_config_var {
|
|||
|
my $key = shift;
|
|||
|
if(exists $cfg{$key}){
|
|||
|
return $cfg{$key};
|
|||
|
}else{
|
|||
|
return undef;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub count_spool_files {
|
|||
|
my $spool_dir = shift;
|
|||
|
my @all_files = glob "$spool_dir/*";
|
|||
|
if($#all_files >= 10){
|
|||
|
info("$#all_files files found in $spool_dir",2);
|
|||
|
info("Something went wrong here!",5);
|
|||
|
}elsif($#all_files >= 3){
|
|||
|
info("$#all_files files found in $spool_dir",1);
|
|||
|
info("Something went wrong here!",5);
|
|||
|
}else{
|
|||
|
info("$#all_files files found in $spool_dir",0);
|
|||
|
}
|
|||
|
}
|
|||
|
sub check_command_definition {
|
|||
|
my $option = shift;
|
|||
|
warn $option;
|
|||
|
my $key = get_config_var($option);
|
|||
|
my $val = $commands{$key};
|
|||
|
if(exists $commands{$key}){
|
|||
|
info("Command $key is defined",0);
|
|||
|
info("'$val'",0);
|
|||
|
}else{
|
|||
|
info_and_exit("Command $key is not defined",2);
|
|||
|
}
|
|||
|
if($mode eq "sync"){
|
|||
|
if ( $option eq "host_perfdata_command"){
|
|||
|
if( $val =~ m/process_perfdata.pl\s+-d\s+HOSTPERFDATA/ ){
|
|||
|
info ( "Command looks good",0 );
|
|||
|
}else{
|
|||
|
info_and_exit ( "Command looks suspect ($val)",2 );
|
|||
|
}
|
|||
|
}else{
|
|||
|
if( $val =~ m/process_perfdata.pl$/ or $val =~ m/process_perfdata.pl\s+-d\s+SERVICEPERFDATA/ ){
|
|||
|
info ( "Command looks good",0 );
|
|||
|
}else{
|
|||
|
info_and_exit ( "Command looks suspect ($val)",2 );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if($mode eq "bulk"){
|
|||
|
if( $val =~ m/process_perfdata.pl\s+--bulk=/){
|
|||
|
info ( "Command looks good",0 );
|
|||
|
}else{
|
|||
|
info_and_exit ( "Command looks suspect ($val)",2 );
|
|||
|
}
|
|||
|
}
|
|||
|
if($mode eq "bulk+npcd"){
|
|||
|
my $dump_file = get_config_var( $option =~m/(.*)_processing_command/ );
|
|||
|
my $perfdata_spool_dir = get_config_var( 'perfdata_spool_dir');
|
|||
|
#print "$dump_file\n";
|
|||
|
my $regex = qr/\/bin\/mv\s+$dump_file\s+$perfdata_spool_dir/;
|
|||
|
if( $val =~ m/$regex/){
|
|||
|
info ( "Command looks good",0 );
|
|||
|
}else{
|
|||
|
info ( "Regex = $regex", 4 );
|
|||
|
info_and_exit ( "Command looks suspect ($val)",2 );
|
|||
|
}
|
|||
|
}
|
|||
|
return $commands{$key};
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
# Max three parameters
|
|||
|
#
|
|||
|
sub check_config_var {
|
|||
|
my $key = shift;
|
|||
|
my $check = shift;
|
|||
|
my $break = shift||0;
|
|||
|
my $var = get_config_var($key);
|
|||
|
if($check eq "exists"){
|
|||
|
if(defined($var)){
|
|||
|
info("$key is defined",0);
|
|||
|
info("$key=$var",0);
|
|||
|
#$last_check = 0;
|
|||
|
}else{
|
|||
|
info("$key is not defined",2);
|
|||
|
$last_check++;
|
|||
|
exit if $break;
|
|||
|
}
|
|||
|
}
|
|||
|
if($check eq "notexists"){
|
|||
|
if( ! defined($var)){
|
|||
|
#info("$key is not defined",0);
|
|||
|
#$last_check = 0;
|
|||
|
}else{
|
|||
|
info("$key is defined ($key=$var)",2);
|
|||
|
info("$key is not allowed in mode '$mode'",2);
|
|||
|
$last_check++;
|
|||
|
exit if $break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub compare_config_var {
|
|||
|
my $key = shift;
|
|||
|
my $compare = shift;
|
|||
|
my $break = shift||0;
|
|||
|
my $var = get_config_var($key);
|
|||
|
if( $var =~ /$compare/){
|
|||
|
info("$key is $var compared with '/$compare/'",0);
|
|||
|
}else{
|
|||
|
info("$key is $var compared with '/$compare/'",2);
|
|||
|
exit if $break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub check_perfdata_file_template {
|
|||
|
$_ = shift;
|
|||
|
if ( not $_ ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( /^DATATYPE::(HOST|SERVICE)PERFDATA/ ){
|
|||
|
info("PERFDATA template looks good",0);
|
|||
|
}else{
|
|||
|
info("PERFDATA template looks suspect",2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub info {
|
|||
|
my $string = shift;
|
|||
|
my $state = shift||0;
|
|||
|
my $break = shift||0;
|
|||
|
|
|||
|
$stats{$state}++;
|
|||
|
return if $state == 6 and not defined $debug;
|
|||
|
$statistics{$states[$state]}++;
|
|||
|
print color $colors[$state];
|
|||
|
printf("[%-4s]", $states[$state]);
|
|||
|
print color 'reset';
|
|||
|
printf(" %s\n", $string);
|
|||
|
}
|
|||
|
|
|||
|
sub last_info {
|
|||
|
my $string = shift;
|
|||
|
my $state = shift;
|
|||
|
my $break = shift||0;
|
|||
|
return if $break == 0;
|
|||
|
info("$string ($break)", $state);
|
|||
|
exit if $break > 0;
|
|||
|
}
|
|||
|
sub info_and_exit {
|
|||
|
my $string = shift;
|
|||
|
my $state = shift;
|
|||
|
info($string, $state);
|
|||
|
exit $state;
|
|||
|
}
|
|||
|
|
|||
|
sub print_stats {
|
|||
|
my $state = 0;
|
|||
|
$state = 1 if $stats{1} > 0;
|
|||
|
$state = 2 if $stats{2} > 0;
|
|||
|
info(sprintf("Warning: %d, Critical: %d",$stats{1}, $stats{2}),$state);
|
|||
|
info("Checks finished...", $state);
|
|||
|
}
|
|||
|
|
|||
|
sub print_sizing {
|
|||
|
my $object_count = ($process_perf_data_stats{'hosts'} + $process_perf_data_stats{'services'});
|
|||
|
my $graph_count = ($process_perf_data_stats{'hosts'} + $process_perf_data_stats{'services'});
|
|||
|
info("$object_count hosts/service objects defined",0);
|
|||
|
foreach my $limit ( sort {$a <=> $b} keys %sizing){
|
|||
|
if($graph_count >= $limit and $sizing{$limit} eq $mode){
|
|||
|
info("Use at least mode '".get_mode_by_size($graph_count)."' to reduce I/O",5);
|
|||
|
last;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub get_mode_by_size {
|
|||
|
my $graph_count = shift;
|
|||
|
foreach my $limit ( sort {$a <=> $b} keys %sizing){
|
|||
|
return $sizing{$limit} if $limit >= $graph_count;
|
|||
|
}
|
|||
|
return 'gearman';
|
|||
|
}
|
|||
|
|
|||
|
sub check_rrdtool {
|
|||
|
check_config_var('RRDTOOL', 'exists', 'break');
|
|||
|
my $rrdtool = get_config_var('RRDTOOL');
|
|||
|
if ( -x $rrdtool ){
|
|||
|
info("$rrdtool is executable",0);
|
|||
|
}else{
|
|||
|
info_and_exit("$rrdtool is not executable",2);
|
|||
|
}
|
|||
|
my @version = `$rrdtool`;
|
|||
|
chomp $version[0];
|
|||
|
info($version[0],0);
|
|||
|
check_config_var('USE_RRDs', 'exists', 'break');
|
|||
|
if(get_config_var('USE_RRDs')){
|
|||
|
unless ( eval "use RRDs;1" ) {
|
|||
|
info("Perl RRDs modules are not loadable",1);
|
|||
|
}else{
|
|||
|
info("Perl RRDs modules are loadable",0);
|
|||
|
}
|
|||
|
}else{
|
|||
|
unless ( eval "use RRDs;1" ) {
|
|||
|
info("Perl RRDs modules are neither loadable nor enabled (USE_RRDs = 0)",1);
|
|||
|
}else{
|
|||
|
info("RRDs modules are loadable but not enabled (USE_RRDs = 0)",1);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub check_proc_npcd {
|
|||
|
my $user = shift;
|
|||
|
my $out = `ps -u $user -o cmd | grep /npcd | grep -v grep`;
|
|||
|
my $rc = $?;
|
|||
|
chomp $out;
|
|||
|
info("Check process: 'ps -u $user -o cmd | grep /npcd | grep -v grep'", 6);
|
|||
|
info("Result: $out", 6);
|
|||
|
info("Returncode: $rc", 6);
|
|||
|
#extract npcd.cfg
|
|||
|
$out =~ /-f\s?(\S+)/;
|
|||
|
my $npcd_cfg = $1;
|
|||
|
if($rc == 0){
|
|||
|
info("npcd daemon is running",0);
|
|||
|
}else{
|
|||
|
info("npcd daemon is not running",2);
|
|||
|
info_and_exit("A running npcd daemon is needed to process data.",4);
|
|||
|
}
|
|||
|
return $npcd_cfg;
|
|||
|
}
|
|||
|
|
|||
|
# process nagios.cfg
|
|||
|
sub process_nagios_cfg {
|
|||
|
info ("Reading $MainCfg", 4);
|
|||
|
open (NFILE, "$MainCfg") || info_and_exit("Failed to open '$MainCfg'. $! ", 2);
|
|||
|
while (<NFILE>) {
|
|||
|
process_main_cfg_line();
|
|||
|
}
|
|||
|
close (NFILE);
|
|||
|
}
|
|||
|
|
|||
|
# process process_perfdata.cfg
|
|||
|
sub process_perfdata_cfg {
|
|||
|
my $cfg_file = shift;
|
|||
|
if ( -r $cfg_file ){
|
|||
|
if ( process_cfg($cfg_file) ){
|
|||
|
$process_perfdata_cfg = 1;
|
|||
|
}else{
|
|||
|
$process_perfdata_cfg = 0;
|
|||
|
}
|
|||
|
}elsif(-e "$PNPCfg/process_perfdata.cfg-sample"){
|
|||
|
info ("$cfg_file does not exist.",1);
|
|||
|
info ("We will try to parse defaults from process_perfdata.pl later on", 1);
|
|||
|
info ("process_perfdata.cfg-sample exists in $PNPCfg", 5);
|
|||
|
info ("It is recommended to rename process_perfdata.cfg-sample to process_perfdata.cfg", 5);
|
|||
|
$process_perfdata_cfg = 0; # we have to parse process_perfdata.pl to get defaults
|
|||
|
}else{
|
|||
|
info ("$cfg_file does not exist.",1);
|
|||
|
info ("We will try to parse defaults from process_perfdata.pl later on", 1);
|
|||
|
info ("It is recommended to place $cfg_file in $PNPCfg", 5);
|
|||
|
info ("A sample file is installed by 'make install-config'", 5);
|
|||
|
$process_perfdata_cfg = 0; # we have to parse process_perfdata.pl to get defaults
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub process_pnp4nagios_release {
|
|||
|
my $cfg_file = shift;
|
|||
|
if ( -r $cfg_file ){
|
|||
|
process_cfg($cfg_file);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub process_cfg {
|
|||
|
my $cfg_file = shift;
|
|||
|
if ( -r $cfg_file ){
|
|||
|
info ("Reading $cfg_file", 4);
|
|||
|
|
|||
|
open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2);
|
|||
|
while (<NFILE>) {
|
|||
|
process_main_cfg_line();
|
|||
|
}
|
|||
|
close (NFILE);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
# process npcd.cfg
|
|||
|
sub process_npcd_cfg {
|
|||
|
my $cfg_file = shift;
|
|||
|
if ( -r $cfg_file ){
|
|||
|
info ("Reading $cfg_file", 4);
|
|||
|
}else{
|
|||
|
info ("$cfg_file does not exist", 4);
|
|||
|
info ("this file is needed to get more information about your system", 5);
|
|||
|
info_and_exit("no further processing possible",2);
|
|||
|
}
|
|||
|
|
|||
|
open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2);
|
|||
|
while (<NFILE>) {
|
|||
|
process_main_cfg_line();
|
|||
|
}
|
|||
|
close (NFILE);
|
|||
|
}
|
|||
|
|
|||
|
# process main config line
|
|||
|
sub process_main_cfg_line {
|
|||
|
chomp;
|
|||
|
return if (/^$/);
|
|||
|
return if (/^#/);
|
|||
|
s/#.*//;
|
|||
|
s/\s*$//;
|
|||
|
if (my ($par, $val) = /([^=]+)\s?=\s?(.*)/){
|
|||
|
$par = trim($par);
|
|||
|
$val = trim($val);;
|
|||
|
if ( (defined($par) && $par eq "") ) {
|
|||
|
info ("oddLine -> $_" ,4);
|
|||
|
return;;
|
|||
|
}
|
|||
|
# skip broker_module lines.
|
|||
|
return if (($par eq "broker_module") and ($val !~ /npcdmod.o/));
|
|||
|
info("'$par' -> '$val'",6);
|
|||
|
$cfg{"$par"} = $val;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub trim {
|
|||
|
my $string = shift;
|
|||
|
$string =~ s/^\s+//;
|
|||
|
$string =~ s/\s+$//;
|
|||
|
return $string;
|
|||
|
}
|
|||
|
|
|||
|
# read object_file
|
|||
|
sub process_objects_file {
|
|||
|
my ($file) = @_;
|
|||
|
my $cmd = "";
|
|||
|
my $line = "";
|
|||
|
info ("Reading $file", 4);
|
|||
|
open (CFILE, "$file") || info_and_exit("Failed to open '$file'. $! ", 2);
|
|||
|
while (<CFILE>) {
|
|||
|
s/#.*//;
|
|||
|
next if (/^$/);
|
|||
|
chomp;
|
|||
|
if (/command_name/) {
|
|||
|
($cmd) = /command_name\s*(.*)/;
|
|||
|
next;
|
|||
|
}
|
|||
|
next unless ( /command_line/);
|
|||
|
($line) = /command_line\s*(.*)/ ;
|
|||
|
$commands{"$cmd"} = "$line";
|
|||
|
next unless (/process_perfdata.pl/);
|
|||
|
my @cmd = split (/\s+/,$line);
|
|||
|
}
|
|||
|
close (CFILE);
|
|||
|
}
|
|||
|
|
|||
|
sub process_status_file {
|
|||
|
my ($file) = get_config_var('status_file');
|
|||
|
my $line = "";
|
|||
|
my $perfdata_found = 0;
|
|||
|
my ($host_query,$service_query) = split(/;/,$object) if ($object);
|
|||
|
$host_query = "" unless (defined $host_query);
|
|||
|
$service_query = "" unless (defined $service_query);
|
|||
|
info("host_query = $host_query",4);
|
|||
|
info("service_query = $service_query",4);
|
|||
|
my $hst = "";
|
|||
|
my $srv = "";
|
|||
|
my $perf = "";
|
|||
|
my $ppd = "";
|
|||
|
info ("Reading $file", 4);
|
|||
|
open (CFILE, "$file") || info_and_exit("Failed to open '$file'. $! ", 2);
|
|||
|
while (<CFILE>) {
|
|||
|
s/#.*//;
|
|||
|
next if (/^$/);
|
|||
|
chomp;
|
|||
|
if(/\shost_name=(.+)/){
|
|||
|
$hst = $1;
|
|||
|
$srv = "";
|
|||
|
}
|
|||
|
if(/\sservice_description=(.+)/){
|
|||
|
$srv = $1;
|
|||
|
}
|
|||
|
if(/\sperformance_data=$/){
|
|||
|
$process_perf_data_stats{'noperf'}++;
|
|||
|
$perfdata_found = 0;
|
|||
|
$perf = " $hst/$srv: [empty perf data]";
|
|||
|
}
|
|||
|
if(/\sperformance_data=(.+)$/){
|
|||
|
$perfdata_found = 1;
|
|||
|
$perf = " $hst/$srv: [$1]";
|
|||
|
}
|
|||
|
# count process_perf_data definitions
|
|||
|
if (/process_performance_data=(\d)$/){
|
|||
|
$ppd=$1;
|
|||
|
$process_perf_data_stats{$1}++ ;
|
|||
|
if ( $perfdata_found == 0 && $1 == 1){
|
|||
|
$process_perf_data_stats{'noperf_but_enabled'}++;
|
|||
|
}
|
|||
|
if ($host_query ne '') {
|
|||
|
$perf = "" if ($hst !~ /$host_query/i);
|
|||
|
if ($service_query ne '') {
|
|||
|
$perf = "" if ($srv !~ /$service_query/i);
|
|||
|
}else{
|
|||
|
$perf = '';
|
|||
|
}
|
|||
|
}else{
|
|||
|
$perf='';
|
|||
|
}
|
|||
|
if ($perf ne ""){
|
|||
|
info ("$perf, ppd=$ppd", 4);
|
|||
|
}
|
|||
|
}
|
|||
|
if(/^hoststatus /){
|
|||
|
$process_perf_data_stats{'hosts'}++;
|
|||
|
}
|
|||
|
if(/^servicestatus /){
|
|||
|
$process_perf_data_stats{'services'}++;
|
|||
|
}
|
|||
|
}
|
|||
|
close (CFILE);
|
|||
|
}
|
|||
|
|
|||
|
sub check_process_perfdata_pl {
|
|||
|
my $command_line = shift;
|
|||
|
my $path = '';
|
|||
|
if( $command_line =~ /\s?([^\s]*)\/process_perfdata.pl\s?/ ){
|
|||
|
$path = $1;
|
|||
|
if ($path =~ /(\$USER\d+\$)/) {
|
|||
|
if (exists $cfg{"$1"}) {
|
|||
|
my $val = $cfg{"$1"};
|
|||
|
$path =~ s/\$USER\d+\$/$val/;
|
|||
|
}
|
|||
|
}
|
|||
|
if( -x "$path/process_perfdata.pl" ){
|
|||
|
info("Script $path/process_perfdata.pl is executable",0);
|
|||
|
}else{
|
|||
|
info_and_exit("Script $path/process_perfdata.pl is not executable",2);
|
|||
|
}
|
|||
|
process_pp_pl ("$path/process_perfdata.pl") if $process_perfdata_cfg == 0;
|
|||
|
}else{
|
|||
|
info_and_exit("Can´t find path to process_perfdata.pl",2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub check_perfdata_spool_dir {
|
|||
|
my $dir = shift;
|
|||
|
if( -d $dir ){
|
|||
|
info("Spool directory '$dir' exists",0);
|
|||
|
}else{
|
|||
|
info_and_exit("Spool directory $dir does not exist",2);
|
|||
|
}
|
|||
|
my @files = <$dir/*>;
|
|||
|
my $count = @files;
|
|||
|
if($count > 1){
|
|||
|
info("$count files in $dir", 1);
|
|||
|
}else{
|
|||
|
info("$dir is empty", 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#
|
|||
|
sub check_perfdata_dir {
|
|||
|
my $dir = shift;
|
|||
|
if( -d $dir ){
|
|||
|
info("Perfdata directory '$dir' exists",0);
|
|||
|
find(\&check_perm, "$dir");
|
|||
|
}else{
|
|||
|
info_and_exit("Perfdata directory $dir does not exist",2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sub check_perm {
|
|||
|
-d ;
|
|||
|
my $f = "$File::Find::name";
|
|||
|
return unless (($f =~ /\/$/) or ($f =~ /rrd$|xml$/));
|
|||
|
check_usrgrp ($f);
|
|||
|
}
|
|||
|
|
|||
|
sub check_usrgrp {
|
|||
|
my $file = shift;
|
|||
|
my $break = shift || 0;
|
|||
|
if ($uid) {
|
|||
|
my $fuid = (stat("$file"))[4];
|
|||
|
my $fname = getpwuid($fuid);
|
|||
|
info ("$file: owner is $fname", 2, $break) if ($fuid != $uid);
|
|||
|
}
|
|||
|
if ($gid) {
|
|||
|
my $fgid = (stat("$file"))[5];
|
|||
|
my $fgroup = getgrgid($fgid);
|
|||
|
info ("$file: group is $fgroup", 2, $break) if ($fgid != $gid);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
# read config inside process_perfdata.pl
|
|||
|
sub process_pp_pl {
|
|||
|
my $cfg_file = shift;
|
|||
|
my $loop = 0;
|
|||
|
info ("Reading $cfg_file", 4);
|
|||
|
open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2);
|
|||
|
while (<NFILE>) {
|
|||
|
chomp;
|
|||
|
last if (/^\s*\);/);
|
|||
|
s/#.*//;
|
|||
|
s/\s*$//;
|
|||
|
s/^\s+//;
|
|||
|
next if (/^$/);
|
|||
|
#$loop++ if (/%conf/);
|
|||
|
#next unless ($loop);
|
|||
|
my ($par, $val) = /([^\s]+)\s+=>\s+([^\s]+)/; # shortest string
|
|||
|
next unless ((defined $par) and (defined $val));
|
|||
|
$val =~ s/['",]//g;
|
|||
|
$cfg{"$par"} = $val;
|
|||
|
}
|
|||
|
close (NFILE);
|
|||
|
}
|
|||
|
|
|||
|
sub get_product {
|
|||
|
for my $product (@products){
|
|||
|
my $string = $product . "_user";
|
|||
|
if ( exists $cfg{$string} ){
|
|||
|
return $product;
|
|||
|
}
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
sub in_array{
|
|||
|
my ($arr,$search_for) = @_;
|
|||
|
my %items = map {$_ => 1} @$arr;
|
|||
|
return (exists($items{$search_for}))?1:0;
|
|||
|
}
|
|||
|
|
|||
|
sub usage{
|
|||
|
print <<EOF;
|
|||
|
|
|||
|
verify_pnp_config -m|--mode=[sync|bulk|bulk+npcd|npcdmod]
|
|||
|
-c|--config=[location of nagios.cfg]
|
|||
|
-p|--pnpcfg=[path to PNP config dir]
|
|||
|
-o|--object="[host][;service]" (optional)
|
|||
|
|
|||
|
This script will check certain settings/entries of your PNP environ-
|
|||
|
ment to assist you in finding problems when you are using PNP.
|
|||
|
It may be used prior and during operation of PNP.
|
|||
|
|
|||
|
Output starts with a letter with the following meaning:
|
|||
|
[INFO] informational message about settings, ...
|
|||
|
[OK ] ok message, will not affect the operation of PNP
|
|||
|
[WARN] warning message, might effect the operation of PNP
|
|||
|
[CRIT] error message: PNP will not work without resolving the problem(s)
|
|||
|
[HINT] hint: it might be worth reading the appropriate documentation
|
|||
|
[DBG ] debugging message, hopefully showing the source of your problem
|
|||
|
|
|||
|
EOF
|
|||
|
}
|
|||
|
|
|||
|
sub usage_no_config{
|
|||
|
info("-c | --config option not given",2);
|
|||
|
info_and_exit("please specify the path to your nagios or icinga.cfg",2);
|
|||
|
}
|
|||
|
|
|||
|
sub usage_no_pnpcfg{
|
|||
|
info("-p | --pnpcfg option not given",2);
|
|||
|
info_and_exit("please specify the path to your PNP config dir",2);
|
|||
|
}
|
|||
|
|
|||
|
sub usage_no_mode{
|
|||
|
info("-m | --mode option not given",2);
|
|||
|
info_and_exit("Valid options are [@modes]",2);
|
|||
|
}
|