#!/usr/bin/perl 


my $statusfile = "/usr/local/nagios/var/status.dat";  
my $cmdfile = "/usr/local/nagios/var/rw/nagios.cmd";

use strict;   
use warnings;   
use Getopt::Long;

my( $verbose, $help, $ephemeral, $noop, $pattern, $do_pending, $downtime,
    $comment, %hosts, %services_by_host, %services_by_service );

$pattern = undef;
$do_pending = 0;
$downtime = 1;  # hours
$comment = 'downtime';
$ephemeral = 0;
$noop = 0;
$verbose = 0;
$help = 0;

sub usage { 
    my( $rc ) = @_;
    print "Usage: $0 [-nvh] { -p <pattern> | -P } [-c <comment>]
    -p pattern   search for hosts or services matching perl regular expression
		 examples: 'copland', 'sw-ne37-.*', 'mahler.*prtdiag', 
    -P           schedule downtime for all pending services and hosts
    -t f         schedule f hours of downtime (floating point)
    -c comment   apply this comment
    -e           ephemeral comment, will disappear after next nagios reload
    -n           no-operation, don't actually do it, but show matches
    -v           verbose
    -h           this help
\n";
    exit $rc;
    }


Getopt::Long::Configure ("bundling");
GetOptions(
    'p=s' => \$pattern,
    'P' => \$do_pending,
    't=f' => \$downtime,
    'c=s' => \$comment,
    'e' => \$ephemeral,
    'n' => \$noop,
    'v+' => \$verbose,
    'h' => \$help,
    );
&usage( 0 ) if ( $help );
&usage( 1 ) if ( ! $pattern && ! $do_pending );

read_statusfile( $pattern, $do_pending );
downtime_hosts(  $downtime, $comment );
downtime_services( $downtime, $comment );

exit 0;



##########################


sub read_statusfile { 
    my( $pattern, $do_pending ) = @_;
    my( $in_host, $in_service, $host, $service, $current_state, $state_type, $last_check, $next_check, $has_been_checked ); 

    open( fH, $statusfile ) || die "can't read-open $statusfile: $!\n";

    while ( <fH> ) { 
	if ( m/^service(status)?\s*{/ ) {    # } make vi happy
	    $in_service = 1;
	    $host = undef;
	    $service = undef;
	    $current_state = 0;
	    $state_type = 0;
	    $last_check = 0;
	    $next_check = 0;
	    $has_been_checked = 0;
	    }
	elsif ( m/^host(status)?\s*{/ ) {    # } make vi happy
	    $in_host = 1;
	    $host = undef;
	    $current_state = 0;
	    $state_type = 0;
	    $last_check = 0;
	    $next_check = 0;
	    $has_been_checked = 0;
	    }
	elsif ( m/^\s*host_name=(.*)/ ) { 
	    $host = $1;
	    }
	elsif ( m/^\s*service_description=(.*)/ ) { 
	    $service = $1;
	    }
	elsif ( m/^\s*current_state=(\d+)/ ) { 
	    $current_state = $1;
	    }
	elsif ( m/^\s*state_type=(\d+)/ ) { 
	    $state_type = $1;
	    }
	elsif ( m/^\s*last_check=(\d+)/ ) { 
	    $last_check = $1;
	    }
	elsif ( m/^\s*next_check=(\d+)/ ) { 
	    $next_check = $1;
	    }
	elsif ( m/^\s*has_been_checked=(\d+)/ ) { 
	    $has_been_checked = $1;
	    }
	# { make vi happy 
	elsif ( m/^\s*}\s*$/ ) { 
	    if ( $in_service ) {   
		if ( ! $do_pending && $host && $service 
			&& ( $host =~ m/$pattern/i 
			    || $service =~ m/$pattern/i
			    || "$host/$service" =~ m/$pattern/i ) ) { 
		    $verbose && print "found match $host/$service\n";
		    $services_by_host{ $host }{ $service } = 1;
		    #$services_by_service{ $service }{ $host } = 1;
		    }
		elsif ( $do_pending && $host && $service && $last_check == 0 
			&& $has_been_checked == 0 ) {
		    $verbose && print "found pending $host/$service\n";
		    $services_by_host{ $host }{ $service } = 1;
		    #$services_by_service{ $service }{ $host } = 1;
		    }
		$in_service = 0;
		$host = undef;
		$service = undef;
		$current_state = 0;
		$state_type = 0;
		$last_check = 0;
		$next_check = 0;
		$has_been_checked = 0;
		}
	    elsif ( $in_host ) {   
		if ( ! $do_pending && $host 
			&& $host =~ m/$pattern/i  ) {
		    $verbose && print "found match $host\n";
		    $hosts{ $host } = 1;
		    }
		elsif ( $do_pending && $host && $last_check == 0 
			&& $has_been_checked == 0 ) {
		    $verbose && print "found pending $host\n";
		    $hosts{ $host } = 1;
		    }
		$in_host = 0;
		$host = undef;
		$current_state = 0;
		$state_type = 0;
		$last_check = 0;
		$next_check = 0;
		$has_been_checked = 0;
		}
	    }
	}
    close fH;
    }



sub downtime_hosts { 
    my( $downtime, $comment ) = @_;
    my( $now, $author, $host, $nagios_cmd );

    $verbose && print "downtiming hosts\n";

    if ( scalar( keys %hosts ) < 1 ) { 
	$verbose && print "no hosts to downtime\n";
	return;
	}

    # append results to nagios command file
    if ( ! open( cH, ">$cmdfile" ) ) { 
	die "can't write-open cmdfile $cmdfile: $!\n"; 
	}
    $now = time;
    $author = getlogin || getpwuid( $< ) || 'unknown';
    foreach $host ( sort keys %hosts ) { 
	print "$host\n";

	#snprintf(command_buffer,sizeof(command_buffer)-1,"[%lu] SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;%s;%lu;%lu;%d;%lu;%lu;%s;%s\n",current_time,host_name,start_time,end_time,(fixed==TRUE)?1:0,triggered_by,duration,comment_author,comment_data);
	#$nagios_cmd = sprintf "[%lu] SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;%s;%u;%u;%d;%u;%u;%s;%s\n",
	    #$now, $host, $now, $now + $downtime * 3600, 0, 0, $downtime * 3600, $author, $comment;

	#snprintf(command_buffer,sizeof(command_buffer)-1,"[%lu] SCHEDULE_HOST_DOWNTIME;%s;%lu;%lu;%d;%lu;%lu;%s;%s\n",current_time,host_name,start_time,end_time,(fixed==TRUE)?1:0,triggered_by,duration,comment_author,comment_data)
	$nagios_cmd = sprintf "[%lu] SCHEDULE_HOST_DOWNTIME;%s;%u;%u;%d;%u;%u;%s;%s\n",
	    $now, $host, $now, $now + $downtime * 3600, 1, 0, $downtime * 3600, $author, $comment;

	$verbose && print "nagios_cmd = $nagios_cmd";
	if ( ! $noop ) { 
	    print cH $nagios_cmd;
	    }
	}
    close cH;
    }




sub downtime_services { 
    my( $downtime, $comment ) = @_;
    my( $now, $author, $host, $service, $nagios_cmd );

    $verbose && print "downtiming service problems\n";

    if ( scalar( keys %services_by_host ) < 1 ) { 
	$verbose && print "no services to downtime\n";
	return;
	}

    # append results to nagios command file
    if ( ! open( cH, ">$cmdfile" ) ) { 
	die "can't write-open cmdfile $cmdfile: $!\n"; 
	}
    $now = time;
    $author = getlogin || getpwuid( $< ) || 'unknown';
    foreach $host ( sort keys %services_by_host ) { 
	foreach $service ( sort keys %{$services_by_host{ $host }} ) { 

	    print "$host/$service\n";

	    #snprintf(command_buffer,sizeof(command_buffer)-1,"[%lu] SCHEDULE_SVC_DOWNTIME;%s;%s;%lu;%lu;%d;%lu;%lu;%s;%s\n",current_time,host_name,service_desc,start_time,end_time,(fixed==TRUE)?1:0,triggered_by,duration,comment_author,comment_data);
	    $nagios_cmd = sprintf "[%lu] SCHEDULE_SVC_DOWNTIME;%s;%s;%u;%u;%d;%u;%u;%s;%s\n",
		$now, $host, $service, $now, $now + $downtime * 3600, 0, 0, $downtime * 3600, $author, $comment;

	    $verbose && print "nagios_cmd = $nagios_cmd";
	    if ( ! $noop ) { 
		print cH $nagios_cmd;
		}
	    }
	}
    close cH;
    }


