Sorry for the delay...I ended up almost completely re-writing my perl script. Now it runs every hour via cron as the nagios user and only does a nagios restart if the new hostgroups.cfg is different from the existing hostgroups.cfg (*not* using direct file comparison since timestamps, sort order, etc make comparing the files problematic). Following are code snippets from the actual script so may be missing libraries, subs, variable declarations, etc...
Notes: I only use/modify hostgroups.cfg. You can still make hostgroup assignments in the individual host config files and they will not be affected
by this script. My script does read the host configs and check a few things like notification periods which are compared to an external database, but
I just add those to the info array so I get email and manually make those changes. I might automate those changes later but so far it hasn't been
necessary.
First I import the existing hostgroups.cfg into a hash:
Code: Select all
#!/usr/bin/perl
#####################################################
# nagios-import
#####################################################
use Data::Dumper;
use Clone qw(clone);
use Array::Utils qw(:all);
use strict;
my $hg_current;
my $hg_external;
my $hg_import;
my @info; #array to store info msgs for email notification
my @error; #array to store error msgs for email notification
my $restart_required=0;
get_hostgroups_hash(\$hg_current,"$WorkFile");
#iterate through hash example
#foreach my $key (sort keys %{$hg_current}) {
# print "check key $key\n";
# foreach my $subkey (sort keys %{$hg_current->{$key}}) {
# print "check subkey $subkey\n";
# my $type=ref($hg_current->{$key}{$subkey});
# if ($type eq '') {
# print "VALUE: ".$hg_current->{$key}{$subkey}."\n";
# } elsif ($type eq 'HASH') {
# foreach my $subsubkey (sort keys %{$hg_current->{$key}{$subkey}}) {
# print "subsubkey: $subsubkey\n";
# print "value: ".$hg_current->{$key}{$subkey}{$subsubkey}."\n";
# }
# } else {
# print "REF: $type\n";
# }
# }
#}
Then clone the hash
and build a new hash ($hg_external) based on the external data (source specific so not shown here)
Then merge the two into a third hash for export.
Code: Select all
#check for changes and if found, merge hg_external hosts into hg_import;
foreach my $hostgroup (sort keys %{$hg_external->{'hostgroup'}}) {
my $hosts_import = $hg_import->{'hostgroup'}{$hostgroup}{'hosts'};
my $hosts_external = $hg_external->{'hostgroup'}{$hostgroup}{'hosts'};
my $mask = $hosts_import ^ $hosts_external;
my @s1=split(",",$hosts_import);
my @s2=split(",",$hosts_external);
my $diff=array_diff(@s1,@s2);
#print "$hostgroup: diff=$diff\n";
if ("$diff" == 0) {
#print "$hostgroup : match\n";
} else {
my @removed=array_minus(@s1,@s2);
my @added=array_minus(@s2,@s1);
$restart_required=1; #trigger import file write and nagios restart
if ($diff > 1) {
push(@info,"HOSTGROUP: *$hostgroup* : $diff changes");
} else {
push(@info,"HOSTGROUP: *$hostgroup* : $diff change");
}
my $removed_detail;
foreach my $host (@removed) {
if ($removed_detail eq '') {
$removed_detail.="$host";
} else {
$removed_detail.=",$host";
}
}
my $added_detail;
foreach my $host (@added) {
if ($added_detail eq '') {
$added_detail.="$host";
} else {
$added_detail.=",$host";
}
}
push(@info,"Removed: $removed_detail") if ($removed_detail);
#print "Removed: $removed_detail\n" if ($removed_detail);
push(@info,"Added : $removed_detail") if ($added_detail);
#print "Added : $removed_detail\n" if ($added_detail);
push(@info,"---") if ($diff);
}
#print "merge $hostgroup\n";
#print " using: *".$hg_external->{'hostgroup'}{$hostgroup}{'hosts'}."*\n";
$hg_import->{'hostgroup'}{$hostgroup}{'hosts'} = $hg_external->{'hostgroup'}{$hostgroup}{'hosts'};
$restart_required=1;
}
If changes made, then create the new hostgroups.cfg file in the import directory
Code: Select all
#now create data array for import file hostgroups.cfg.
push (@data,"###############################################################################");
push (@data,"#");
push (@data,"# Hostgroup configuration file");
push (@data,"#");
push (@data,"# Created by: $0");
push (@data,"# Date: $timestamp");
push (@data,"# Nagios 4.x config file");
push (@data,"#");
push (@data,"###############################################################################");
foreach my $hostgroup (sort keys %{$hg_import->{'hostgroup'}}) {
#print "create data for $hostgroup\n";
my $alias=$hg_import->{'hostgroup'}{$hostgroup}{'alias'};
my $members=$hg_import->{'hostgroup'}{$hostgroup}{'hosts'};
my $hostgroup_members=$hg_import->{'hostgroup'}{$hostgroup}{'hostgroup_members'};
#print "alias = $alias\n";
#print "members = $members\n";
#print "hostgroup_members = $hostgroup_members\n";
push (@data,"");
push (@data,"define hostgroup {");
push (@data," hostgroup_name $hostgroup");
push (@data," alias $alias");
push (@data," members $members") if ($members ne '');
push (@data," hostgroup_members $hostgroup_members") if ($hostgroup_members ne '');
push (@data," }");
}
push (@data,"###############################################################################");
push (@data,"#");
push (@data,"# Hostgroups configuration file");
push (@data,"#");
push (@data,"# END OF FILE");
push (@data,"#");
push (@data,"###############################################################################");
Write new hosttroups.cfg and restart nagios (if necessary)
Code: Select all
my $errors=@error;
my $infos = @info;
if (("$errors" == 0) && ($restart_required)) {
#create and write import file
open(IMPORTFILE,">$ImportFile");
foreach my $line (@data) {
print IMPORTFILE "$line\n";
}
close(IMPORTFILE);
#restart nagios
print "restart nagios\n";
my $reconfig=`cd /usr/local/nagiosxi/scripts/;/usr/local/nagiosxi/scripts/reconfigure_nagios.sh`;
push(@info," ");
if ($reconfig=~/Starting nagios\: done\./) {
push(@info,"Nagios restarted with new hostgroups.cfg");
}
} else {
#don't import or restart due to info or err msgs
push(@info,"Import deferred due to error messages");
print "Import deferred due to error messages";
}
print "errors = $errors\n";
if ($errors) {
print "sending errors email\n";
send_error_email();
}
my $infos = @info;
if ($infos) {
print "sending infos email\n";
send_info_email();
}
exit 0;
This is the subroutine that imports the hostgroups.cfg file into a hash.
Code: Select all
sub get_hostgroups_hash($$) {
my $file = $_[1];
my $hostgroup;
my $hostgroup_members;
my $alias;
my $hosts;
open(FILE,"<$file");
while (my $line = <FILE>) {
#print "line: $line\n";
if ($line=~/^define hostgroup/) {
if ($hostgroup ne '') {
#print "storing hostgroup $hostgroup\n";
${($_[0])}->{'hostgroup'}{$hostgroup}{'alias'}=$alias;
${($_[0])}->{'hostgroup'}{$hostgroup}{'hosts'}=$hosts;
${($_[0])}->{'hostgroup'}{$hostgroup}{'hostgroup_members'}=$hostgroup_members if ($hostgroup_members ne '') ;
${($_[0])}->{'alias'}{$alias}=$hostgroup;
}
$hostgroup='';
$hostgroup_members='';
$alias='';
$hosts='';
#print "hostgroup=*$hostgroup* alias=*$alias* hosts=*$hosts*\n";
} elsif ($line=~/hostgroup_name\s+(\S+)/) {
$hostgroup=$1;
#print "Starting hostgroup $hostgroup\n";
} elsif ($line=~/^\s+alias\s+(\S+.*)$/) {
$alias=$1;
#print "alias for hostgroup $hostgroup is $alias\n";
} elsif ($line=~/^\s+members\s+(\S+)/) {
$hosts=$1;
#print "hosts for hostgroup $hostgroup is $hosts\n";
my @members=split(",",$hosts);
$hosts='';
foreach my $host (sort @members) {
#print "Inserting $host into $hostgroup\n";
if ($hosts eq '') {
$hosts=$host;
} else {
$hosts.=",$host";
}
}
} elsif ($line=~/^\s+hostgroup_members\s+(\S+)/) {
$hostgroup_members=$1;
}
}
}