#! /usr/bin/perl -w
################################################################################
# Copyright 2005-2009 MERETHIS
# Centreon is developped by : Julien Mathis and Romain Le Merlus under
# GPL Licence 2.0.
# 
# 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.
# 
# 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, see <http://www.gnu.org/licenses>.
# 
# Linking this program statically or dynamically with other modules is making a 
# combined work based on this program. Thus, the terms and conditions of the GNU 
# General Public License cover the whole combination.
# 
# As a special exception, the copyright holders of this program give MERETHIS 
# permission to link this program with independent modules to produce an executable, 
# regardless of the license terms of these independent modules, and to copy and 
# distribute the resulting executable under terms of MERETHIS choice, provided that 
# MERETHIS also meet, for each linked independent module, the terms  and conditions 
# of the license of that module. An independent module is a module which is not 
# derived from this program. If you modify this program, you may extend this 
# exception to your version of the program, but you are not obliged to do so. If you
# do not wish to do so, delete this exception statement from your version.
# 
# For more information : contact@centreon.com
# 
# SVN : $URL
# SVN : $Id :
#
####################################################################################
#
# Script init
#

use strict;
use POSIX qw(mkfifo);
use DBI;

use File::Copy;

use vars qw($debug $LOG %status $generalcounter $stop $method);
use vars qw($mysql_user $mysql_passwd $mysql_host $mysql_database_oreon $mysql_database_ods);
use vars qw($con $ssh $scp $installedPath);

if (POSIX::getuid() == 0 ) { 
    print  STDERR "You must not execute centcore with root user \n"; exit 1;
}

my $echo = "/bin/echo";

my $installedPath = "/usr/share/centreon";
my $LOG = "/var/log/centreon/centcore.log";
my $PID = "/var/run/centreon/centcore.pid";
my $cmdFile = "/var/lib/centreon/centcore.cmd";

$ssh = "/usr/bin/ssh";
$scp = "/usr/bin/scp";

my $stop = 1;
my $debug = 0;
my $cfg;

# Include Configuration Data
require "/etc/centreon/conf.pm";

sub catch_zap {
	$stop = 0;
	writeLogFile("Receiving order to stop...\n");
}

sub writeLogFile($){
	open (LOG, ">> ".$LOG) || print "can't write $LOG: $!";
	print LOG time()." - ".$_[0];
	close LOG or warn $!;
}

my $timeBetween2SyncPerf = 60;

# Starting ODS Engine
writeLogFile("Starting ODS engine...\n");
writeLogFile("PID : ".$$."\n");

# checking if pid file exists.
if (-x $PID){
	writeLogFile("centcore already running. can't launch again....\n");
	exit(2);
}

sub killChild(){
	;#print "Kill : $$ -> OK\n";
}

# Writing PID
open (PID, ">> ".$PID) || print "can't write PID : $!";
print PID $$ ;
close PID or warn $!;

# Set signals
$SIG{'INT'}  	= \&catch_zap;
$SIG{'CHLD'} 	= \&killChild;

# Declare functions

sub parseRequest($);
sub GetAllNagiosServerPerfData();
sub moveCmdFile($);

# Add the handles for our programs into the readset.
# In other words, we're keeping track of these handles.

my $timeSyncPerf = 0;
my $timeNagiosLogs = 0;

my $difTime = 0;

while ($stop) {  
    # Select Wait
    if (moveCmdFile($cmdFile) && open(FILE, "< $cmdFile"."_read")){
		while (<FILE>){
		    parseRequest($_);
		}
    }
    close(FILE);
    if (defined($timeSyncPerf) && $timeSyncPerf) {
		$difTime = time() - $timeSyncPerf;
    }
    if ((defined($difTime) && $timeBetween2SyncPerf <= $difTime) || $timeSyncPerf == 0){
		# Get PerfData on Nagios Poller
		GetAllNagiosServerPerfData();		
		$timeSyncPerf = time();
    }
    sleep(1);
}

sub moveCmdFile($){
    my $CMDFILE = $_[0];
    if (move($CMDFILE, $CMDFILE."_read")){
		return(1);
    }
}

sub removeTmpCmdFile($){
    my $CMDFILE = $_[0];
    if (unlink($CMDFILE."_read")){
		return(1);
    } else {
		writeLogFile("Can't remove temporary command file.\n");
		return 0;
    }
}

sub GetAllNagiosServerPerfData(){
    CheckMySQLConnexion();
    my $sth2 = $con->prepare("SELECT `id` FROM `nagios_server` WHERE `localhost` = '0' AND `ns_activate` = '1'");
    if (!$sth2->execute()) {
		writeLogFile("Error when getting server properties : ".$sth2->errstr."\n");
    }
    while (my $data = $sth2->fetchrow_hashref()){
		GetPerfData($data->{'id'});
		GetLogFile($data->{'id'});
    }
    $sth2->finish();
    $con->disconnect();
    return;
}

# -------------------
#      Functions 
# -------------------
#
# Functions

sub getNagiosConfigurationField($$){
    CheckMySQLConnexion();
    my $sth2 = $con->prepare("SELECT ".$_[1]." FROM `cfg_nagios` WHERE `nagios_server_id` = '".$_[0]."'");
    if (!$sth2->execute()) {
		writeLogFile("Error when getting server properties : ".$sth2->errstr."\n");
    }
    my $data = $sth2->fetchrow_hashref();
    return $data->{$_[1]};
}

sub getLocalOptionsField($){
    CheckMySQLConnexion();
    my $sth2 = $con->prepare("SELECT ".$_[0]." FROM `general_opt` LIMIT 1");
    if (!$sth2->execute()) {
		writeLogFile("Error when getting general options properties : ".$sth2->errstr."\n");
    }
    my $data = $sth2->fetchrow_hashref();
    return $data->{$_[0]};
}

sub getLocalServerID(){
    CheckMySQLConnexion();
    my $sth2 = $con->prepare("SELECT id FROM `nagios_server` WHERE `localhost` = '1'");
    if (!$sth2->execute()) {
		writeLogFile("Error when getting server properties : ".$sth2->errstr."\n");
    }
    return $sth2->fetchrow_hashref();
}

sub getServerConfig($){
    CheckMySQLConnexion();
    my $sth2 = $con->prepare("SELECT * FROM `nagios_server` WHERE `id` = '".$_[0]."' AND ns_activate = '1'");
    if (!$sth2->execute()) {
		writeLogFile("Error when getting server properties : ".$sth2->errstr."\n");
    }
    return $sth2->fetchrow_hashref();
}

sub CheckMySQLConnexion(){
    while ((!defined($con) || !$con->ping)){
		if (!defined($con)) {
		    $con = DBI->connect("DBI:mysql:database=".$mysql_database_oreon.";host=".$mysql_host, $mysql_user, $mysql_passwd, {'RaiseError' => 0, 'PrintError' => 0, 'AutoCommit' => 1});
		    if (!defined($con)) {
			writeLogFile("Error when connecting to database : " . $DBI::errstr . "\n");
			sleep(2);
		    }
		} else {
		    sleep(2);
		    undef($con);
		    $con = DBI->connect("DBI:mysql:database=".$mysql_database_oreon.";host=".$mysql_host, $mysql_user, $mysql_passwd, {'RaiseError' => 0, 'PrintError' => 0, 'AutoCommit' => 1});
		}
    }
}

#
# Send an external command on a remote server.
# Param : id_remote_server, external command
#

sub sendExternalCommand($$){
    # Init Parameters
    my $id = $_[0];
    my $cmd = $_[1];

    # Get command file 
    my $command_file = getNagiosConfigurationField($id, "command_file");

    # Get server informations
    my $server_info = getServerConfig($id);

    # check if ip address is defined
    if (defined($server_info->{'ns_ip_address'})){
		my $cmd = "$ssh -q ".$server_info->{'ns_ip_address'}." 'echo \"".$cmd."\" >> ".$command_file."'\n";
		my $stdout = `$cmd`;
		writeLogFile("External command : ".$server_info->{'ns_ip_address'}." ($id) : \"".$cmd."\"\n");
		if (defined($stdout) && $stdout){
		    writeLogFile("Result : $stdout\n");
		}
		# Free
		undef($stdout);
    } else {
		writeLogFile("Ip address not defined for poller $id \n");
    }
    # Free
    undef($id);
    undef($cmd);
    undef($server_info);
    undef($command_file);
}

#
# Get PerfdataFile
#

sub getNagiosInformation($){

}

sub GetPerfData($){
    # init Values
    my $debug = 0;
    my $id = $_[0];

    # Get Server Infos
    my $server_info = getServerConfig($id);
    my $distantconnexion = $server_info->{'ns_ip_address'};

    my $distantperffile = getNagiosConfigurationField($id, "service_perfdata_file");
    my $distanttmpperffile = $distantperffile."-old";

    my $localbasevardir = "/var/lib/centreon/perfdata/$id";
    # check if directory exist
    mkdir "/var/lib/centreon/perfdata" if (!-d "/var/lib/centreon/perfdata");
    mkdir $localbasevardir if (!-d $localbasevardir);

    my $localhost_id = getLocalServerID(); 
    my $localtmpperffile = "$localbasevardir/service-perfdata";
    my $localperffile = getNagiosConfigurationField($localhost_id->{'id'}, "service_perfdata_file");

    my $origin = $distantconnexion.":".$distanttmpperffile;

    writeLogFile("$ssh -q $distantconnexion ls -l $distantperffile 2>> /dev/null | wc -l\n") if ($debug);
    my $ls = `$ssh -q $distantconnexion ls -l $distantperffile 2>> /dev/null | wc -l`;

    # Check if distant perfdata file 
    if ($ls != 0){
		# Move perfdata file in temp dir
		writeLogFile("$ssh -q $distantconnexion mv $distantperffile $distanttmpperffile\n") if ($debug);
		`$ssh -q $distantconnexion mv $distantperffile $distanttmpperffile`;

		# Get Perfdata file
		writeLogFile("scp -q $origin $localtmpperffile\n") if ($debug);
		`$scp -q $origin $localtmpperffile`;
	
		# Remove old perfdata file 
		# writeLogFile("$ssh -q $distantconnexion rm $distanttmpperffile\n") if ($debug);
		# `$ssh -q $distantconnexion rm $distanttmpperffile`;
	
		# Write data from distant poller on local file for centstorage
		if (-f $localtmpperffile){
		    if ($debug) {
				writeLogFile("cat $localtmpperffile >> $localperffile\n");
		    }
		    `cat $localtmpperffile >> $localperffile`;
		    #`rm -f $localtmpperffile`;
		}
    }
}

sub GetLogFile($){
    # Init values
    my $id = $_[0];

    # Get Server informations
    my $server_info = getServerConfig($id);

    # Check configuration
    my $distantconnexion = $server_info->{'ns_ip_address'};
    if (!defined($distantconnexion)) {
		writeLogFile("IP address not defined for poller $id\n");	
    }

    # Set local directory
    my $localDir = "/var/lib/centreon/log/$id/";

    # Create tmp directory
    mkdir "/var/lib/centreon/log" if (!-d "/var/lib/centreon/log");
    mkdir $localDir if (!-d $localDir);
    if (-d $localDir){

		# Get distant log file path
		my $distantlogfile = getNagiosConfigurationField($id, "log_file");;
		my $locallogfile = $localDir."nagios.log";
	
		# check if we can do the transfert
		if (defined($distantconnexion) && defined($distantlogfile)){
		    # check if log file exists
		    my $ls = `ssh -q $distantconnexion ls -l $distantlogfile 2>> /dev/null | wc -l`;
		    if ($ls){
				# Get log file
				my $ret = `scp -q $distantconnexion:$distantlogfile $locallogfile`;
				writeLogFile("Cannot get log file or log file doesn't exists on poller $id") if ($ret);
		    }
		}
	} else {
		writeLogFile("Unable to create $localDir. Can get nagios log file for poller $id\n");
   	}
}

#
# Send config files to a remote server 
#

sub sendConfigFile($){
    # Init Values
    my $id = $_[0];

    my $cfg_dir = getNagiosConfigurationField($id, "cfg_dir");
    my $server_info = getServerConfig($id);
    my ($md5local, $md5dist, $scpe);

    opendir(DIR, $installedPath."/filesGeneration/nagiosCFG/$id/");
    while (my $file = readdir(DIR)){
		if ($file ne "." && $file ne ".." && $file !~ /\~/ && $file ne "nagiosCFG.DEBUG"){
		    my $origin = $installedPath."/filesGeneration/nagiosCFG/".$id."/$file";
		    my $dest = $server_info->{'ns_ip_address'}.":$cfg_dir$file";
	
		    my $stdout = `scp $origin $dest`;
	
		    # Check sucessfull copy
		    $md5local = `/usr/bin/md5sum $origin`;
		    $md5dist  = `ssh $server_info->{'ns_ip_address'} /usr/bin/md5sum $cfg_dir$file`;
	
		    my @tab_local = split(' ', $md5local);		
		    my @tab_dist = split(' ', $md5dist);		
		    if ($tab_local[0] ne $tab_dist[0]){
				print "Bad Copy !\n";
		    }
		}
    }
    undef($cfg_dir);
}

sub initNagios($$){
    my $id = $_[0];
    my $options = $_[1];
    my $conf = getServerConfig($id);
    my $cmd = "$ssh ".$conf->{'ns_ip_address'}." sudo ".$conf->{'init_script'}." ".$options."\n";
    print "$options : $cmd\n";
    my $stdout = `$cmd`;
    # Logs Actions
    writeLogFile("init Script : 'sudo ".$conf->{'init_script'}." ".$options."' On poller ".$conf->{'ns_ip_address'}." ($id)\n");
    writeLogFile("$stdout\n");
    undef($conf);
    undef($cmd);
    undef($stdout);
}

sub reloadNagios($){
    my $id = $_[0];
    
    my $conf = getServerConfig($id);   
    # 
    # Reload nagios : 
    # /etc/init.d/nagios reload
    #
 
    my $cmd = "ssh ".$conf->{'ns_ip_address'}." sudo ".$conf->{'init_script'}." reload\n";
    my $stdout = `$cmd`;
    writeLogFile("$stdout\n");
    undef($conf);
    undef($cmd);
    undef($stdout);
}

sub stopNagios($){
    my $id = $_[0];
    
    # 
    # Reload nagios : 
    # /etc/init.d/nagios stop
    #
    my $conf = getServerConfig($id);
    my $cmd = "$ssh ".$conf->{'ns_ip_address'}." sudo ".$conf->{'init_script'}." stop\n";
    my $stdout = `$cmd`;
    writeLogFile("$stdout\n");
    undef($conf);
    undef($cmd);
    undef($stdout);
}

sub startNagios($){
    my $id = $_[0];
    
    my $conf = getServerConfig($id);

    # 
    # Reload nagios : 
    # /etc/init.d/nagios start
    #
    my $cmd = "$ssh ".$conf->{'ns_ip_address'}." sudo ".$conf->{'init_script'}." start\n";
    my $stdout = `$cmd`;
    writeLogFile("$stdout\n");
    undef($conf);
    undef($cmd);
    undef($stdout);
}

sub testConfig($){
    my $id = $_[0];

    my $cfg_dir = getNagiosConfigurationField($id, "cfg_dir");
    # $data->{'user'}."@".
    my $data = getServerConfig($id);
    my $distantconnexion = $data->{'ns_ip_address'};
    my $cmd = "$ssh $distantconnexion sudo ".$data->{'nagios_bin'}." -v $cfg_dir/nagios.cfg";
    my $stdout = `$cmd`;
    undef($cmd);
    undef($data);
    undef($distantconnexion);
    writeLogFile("$stdout\n");
    undef($cfg_dir);
}

sub parseRequest($){
    if (!$_[0]){
		return ;
    }
    # 
    # Checks keys for launching commands
    # 
    if ($_[0] =~ /RESTART\:([0-9]*)/){
		initNagios($1, "restart");
    } elsif ($_[0] =~ /RELOAD\:([0-9]*)/){
		initNagios($1, "reload");
    } elsif ($_[0] =~ /START\:([0-9]*)/){
		initNagios($1, "start");
    } elsif ($_[0] =~ /STOP\:([0-9]*)/){
		initNagios($1, "stop");
    } elsif ($_[0] =~ /SENDCFGFILE\:([0-9]*)/){
		sendConfigFile($1);
    } elsif ($_[0] =~ /TEST\:([0-9]*)/){
		testConfig($1);
    } elsif ($_[0] =~ /EXTERNALCMD\:([0-9]*)\:(.*)/){
		sendExternalCommand($1, $2);
    }
}

unlink($PID);
writeLogFile("Centcore stop...\n");
exit();

__END__




