#!/usr/bin/perl 
# 
# clear_downtime_matching
# 
# cli to remove scheduled downtime 
#
# $Header: /opt/home/doke/work/nagios/RCS/cancel_downtime_matching,v 1.1 2014/08/14 23:08:25 doke Exp $


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, $noop, $pattern, %hosts, %services_by_host );

$pattern = undef;
$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', 
    -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,
    'n' => \$noop,
    'v+' => \$verbose,
    'h' => \$help,
    );
&usage( 0 ) if ( $help );
&usage( 1 ) if ( ! $pattern );

read_statusfile( $pattern );
cancel_downtime_hosts();
cancel_downtime_services();

exit 0;



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


sub read_statusfile { 
    my( $pattern ) = @_;
    my( $in_hostdowntime, $in_servicedowntime, $host, $service, $downtime_id, $current_state, 
	$entry_time, $start_time, $end_time, $author, $comment ); 

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

    $in_hostdowntime = 0;
    $in_servicedowntime = 0;
    $host = '';
    $service = '';
    $downtime_id = 0;
    $current_state = 0;
    $entry_time = 0;
    $start_time = 0;
    $end_time = 0;
    $author = '';
    $comment = '';
    while ( <fH> ) { 
	if ( $in_servicedowntime || $in_hostdowntime ) { 

	    if ( m/^\s*host_name=(.*)/ ) { 
		$host = $1;
		}
	    elsif ( m/^\s*service_description=(.+)/ ) { 
		$service = $1;
		}
	    elsif ( m/^\s*downtime_id=(\d+)/ ) { 
		$downtime_id = $1;
		}
	    elsif ( m/^\s*current_state=(\d+)/ ) { 
		$current_state = $1;
		}
	    elsif ( m/^\s*entry_time=(\d+)/ ) { 
		$entry_time = $1;
		}
	    elsif ( m/^\s*start_time=(\d+)/ ) { 
		$start_time = $1;
		}
	    elsif ( m/^\s*end_time=(\d+)/ ) { 
		$end_time = $1;
		}
	    elsif ( m/^\s*author=(.+)/ ) { 
		$author = $1;
		}
	    elsif ( m/^\s*comment=(.+)/ ) { 
		$comment = $1;
		}

	    # { make vi happy 
	    elsif ( m/^\s*}\s*$/ ) { 
		if ( $in_servicedowntime ) {   
		    if ( $host && $service && $downtime_id
			    && ( $host =~ m/$pattern/i 
				|| $service =~ m/$pattern/i
				|| "$host/$service" =~ m/$pattern/i ) ) { 
			$verbose && print "found downtime for $host/$service\n";
			$services_by_host{ $host }{ $service }{ 'downtime_id' } = $downtime_id;
			$services_by_host{ $host }{ $service }{ 'current_state' } = $current_state;
			$services_by_host{ $host }{ $service }{ 'entry_time' } = $entry_time;
			$services_by_host{ $host }{ $service }{ 'start_time' } = $start_time;
			$services_by_host{ $host }{ $service }{ 'end_time' } = $end_time;
			$services_by_host{ $host }{ $service }{ 'author' } = $author;
			$services_by_host{ $host }{ $service }{ 'comment' } = $comment;
			}
		    $in_servicedowntime = 0;
		    $host = '';
		    $service = '';
		    $downtime_id = 0;
		    $current_state = 0;
		    $entry_time = 0;
		    $start_time = 0;
		    $end_time = 0;
		    $author = '';
		    $comment = '';
		    }
		elsif ( $in_hostdowntime ) {   
		    if ( $host && $downtime_id 
			    && $host =~ m/$pattern/i  ) {
			$verbose && print "found downtime for $host\n";
			$hosts{ $host }{ 'downtime_id' } = $downtime_id;
			$hosts{ $host }{ 'current_state' } = $current_state;
			$hosts{ $host }{ 'entry_time' } = $entry_time;
			$hosts{ $host }{ 'start_time' } = $start_time;
			$hosts{ $host }{ 'end_time' } = $end_time;
			$hosts{ $host }{ 'author' } = $author;
			$hosts{ $host }{ 'comment' } = $comment;
			}
		    $in_hostdowntime = 0;
		    $host = '';
		    $downtime_id = 0;
		    $current_state = 0;
		    $entry_time = 0;
		    $start_time = 0;
		    $end_time = 0;
		    $author = '';
		    $comment = '';
		    }
		}
	    }
	elsif ( m/^servicedowntime\s*{/ ) {    # } make vi happy
	    $in_servicedowntime = 1;
	    $host = '';
	    $service = '';
	    $downtime_id = 0;
	    $current_state = 0;
	    $entry_time = 0;
	    $start_time = 0;
	    $end_time = 0;
	    $author = '';
	    $comment = '';
	    }
	elsif ( m/^hostdowntime\s*{/ ) {    # } make vi happy
	    $in_hostdowntime = 1;
	    $host = '';
	    $downtime_id = 0;
	    $current_state = 0;
	    $entry_time = 0;
	    $start_time = 0;
	    $end_time = 0;
	    $author = '';
	    $comment = '';
	    }

	}
    close fH;
    }



sub cancel_downtime_hosts { 
    my( $now, $host, $downtime_id, $nagios_cmd );

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

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

    # append results to nagios command file
    if ( ! open( cH, ">$cmdfile" ) ) { 
	die "can't write-open cmdfile $cmdfile: $!\n"; 
	}
    $now = time;
    foreach $host ( sort keys %hosts ) { 
	printf "%-20s  %-25s  %-25s  %-20s  %s\n", 
	    $host,
	    scalar( localtime( $hosts{ $host }{ 'start_time' } ) ),
	    scalar( localtime( $hosts{ $host }{ 'end_time' } ) ),
	    $hosts{ $host }{ 'author' },
	    $hosts{ $host }{ 'comment' };

	$downtime_id = $hosts{ $host }{ 'downtime_id' };
	$nagios_cmd = sprintf "[%lu] DEL_HOST_DOWNTIME;%u\n",
	    $now, $downtime_id;

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




sub cancel_downtime_services { 
    my( $now, $host, $service, $downtime_id, $nagios_cmd );

    $verbose && print "canceling downtime for services\n";

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

    # append results to nagios command file
    if ( ! open( cH, ">$cmdfile" ) ) { 
	die "can't write-open cmdfile $cmdfile: $!\n"; 
	}
    $now = time;
    foreach $host ( sort keys %services_by_host ) { 
	foreach $service ( sort keys %{$services_by_host{ $host }} ) { 
	    printf "%-30s  %-25s  %-25s  %-20s  %s\n", 
		"$host/$service",
		scalar( localtime( $services_by_host{ $host }{ $service }{ 'start_time' } ) ),
		scalar( localtime( $services_by_host{ $host }{ $service }{ 'end_time' } ) ),
		$services_by_host{ $host }{ $service }{ 'author' },
		$services_by_host{ $host }{ $service }{ 'comment' };

	    $downtime_id = $services_by_host{ $host }{ $service }{ 'downtime_id' };
	    $nagios_cmd = sprintf "[%lu] DEL_SVC_DOWNTIME;%u\n",
		$now, $downtime_id;

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


