#!/usr/bin/env perl 

#
#   Copyright (C) 2010 by G. Montagner <gmontagner@sorint.it> and others
#
#   This script is free software; you can redistribute it and/or modify 
#   it under the same terms as Perl itself, either Perl version 5.8.8 or, 
#   at your option, any later version of Perl 5 you may have available.
#
#   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.
#

use strict;
use warnings;
use DBI;
use Socket;
use POSIX;
use Fcntl qw(:flock);

sub get_timestamp {
	my ($delay) = @_;
	my $time = time();
	$time += $delay if defined($delay);
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
	return sprintf("%.4d-%.2d-%.2d %.2d:%.2d:%.2d", ($year + 1900), ($mon + 1), $mday, $hour, $min, $sec);
}

sub get_lock {
	my $to_lock = shift;
	my $lockfh;
	if (-f $to_lock) {
		open ($lockfh, '+<', $to_lock) or die "Cannot open file $to_lock for R/W"
	} else {
		open ($lockfh, '+>', $to_lock) or die "Cannot open file $to_lock for R/W"
	}
	flock($lockfh, LOCK_EX|LOCK_NB) or return;
	my $previous_default = select($lockfh);
	$|++;
	select($previous_default); 
	return $lockfh;
}

sub release_lock {
	my $to_unlock = shift;
	flock ($to_unlock, LOCK_UN);
	close ($to_unlock);
	return;
}

# Main config
my $host_comm_q = 'select nh.display_name as host, nc.author_name, nc.comment_data 
	from nagios_hosts nh, nagios_comments nc 
	where nc.object_id = nh.host_object_id';
my $svc_comm_q = 'select nh.display_name as host, ns.display_name as service, nc.author_name, nc.comment_data 
	from nagios_hosts nh, nagios_services ns, nagios_comments nc 
	where nc.object_id = ns.service_object_id and ns.host_object_id = nh.host_object_id';

my $lastlog = '/opt/nagios/var/replicate_acks.lock';
my $db_name = 'nagios';
my $db_host = 'localhost';
my $db_port = '3306';
my $db_user = 'nagios';
my $db_pwd = '';
my $target_host = '';
my $target_port = '15667';
my @commands;

# First of all, get lock
my $logfh = get_lock($lastlog);
die "Cannot acquire lock over $lastlog" unless defined($logfh);

# Get last timestamp
my $ts = <$logfh>;
chomp($ts) if defined($ts);

# Write current timestamp to log
seek($logfh, 0, 0);
print $logfh get_timestamp();

# DB conn init
my $dsn = "DBI:mysql:database=$db_name;host=$db_host;port=$db_port";
my $dbh = DBI->connect($dsn, $db_user, $db_pwd);
my $drh = DBI->install_driver("mysql");

# Query host comments
$host_comm_q .= " and nc.comment_time > '$ts'" if defined($ts);
my $sth = $dbh->prepare($host_comm_q);
$sth->execute;

# Parse query and prepare commands
while (my $row = $sth->fetchrow_hashref()) {
	my ($host, $author, $comment) = 
		($row->{'host'}, $row->{'author_name'}, $row->{'comment_data'});
	my $now = time();
	my $str = "[$now]ACKNOWLEDGE_HOST_PROBLEM;$host;1;1;1;$author;$comment\n";
	push (@commands, $str);
}

# Query service comments
$svc_comm_q .= " and nc.comment_time > '$ts'" if defined($ts);
$sth = $dbh->prepare($svc_comm_q);
$sth->execute;

# Parse query and prepare commands
while (my $row = $sth->fetchrow_hashref()) {
	my ($host, $service, $author, $comment) = 
		($row->{'host'}, $row->{'service'}, $row->{'author_name'}, $row->{'comment_data'});
	my $now = time();
	my $str = "[$now] ACKNOWLEDGE_SVC_PROBLEM;$host;$service;1;1;1;$author;$comment\n";
	push (@commands, $str);
}

if ($#commands == -1) {
	close SOCKET;
	release_lock($logfh);
	exit 0;
}

# Connect to target host and throw commands
my $proto = getprotobyname('tcp');
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "Cannot create socket: $!";
my $iaddr = inet_aton($target_host); 
my $paddr = sockaddr_in($target_port, $iaddr);
connect (SOCKET, $paddr) or die "Cannot connect to $target_host:$target_port - $!";

foreach my $command (@commands) {
	print SOCKET "$command";
}

close SOCKET;
release_lock($logfh);

exit 0;

