#! /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 :
#
####################################################################################

# Message type 
# 0 -> Service Alerts
# 1 -> Host Alerts
# 2 -> Service notification
# 3 -> Host Notification
# 4 -> All nagios Warning
# 5 -> All logs
# 6 -> Service Current State  
# 7 -> Host Current State
# 8 -> Service Initial State  
# 9 -> Host Initial State

use strict;
use warnings;
use DBI;
use File::stat;
use Getopt::Long;
use POSIX;

use vars qw($mysql_user $mysql_passwd $mysql_host $mysql_database_oreon $mysql_database_ods $opt_h $opt_a $data);

require "/etc/centreon/conf.pm";

## Init Date
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);

# Init MySQL Connexion
my $dbh = DBI->connect("DBI:mysql:database=".$mysql_database_ods.";host=".$mysql_host, $mysql_user, $mysql_passwd, {'RaiseError' => 1});

# Init MySQL Connexion
my $dbhoreon = DBI->connect("DBI:mysql:database=".$mysql_database_oreon.";host=".$mysql_host, $mysql_user, $mysql_passwd, {'RaiseError' => 1});

Getopt::Long::Configure('bundling');
GetOptions("h" => \$opt_h, "help" => \$opt_h,
           "a" => \$opt_a, "archives" => \$opt_a);

if ($opt_h) {
    print " Usage : $0 :\n";
    print "    -a (--archives) load data from log archives to database\n";
    print "    -h (--help) show help\n";
    exit(0);
}

# Get conf Data
my $sth_config = $dbh->prepare("SELECT `archive_log`, `archive_retention`, `nagios_log_file`  FROM `config`");
if (!$sth_config->execute) {die "Error:" . $sth_config->errstr . "\n";}
$data = $sth_config->fetchrow_hashref();
$sth_config->finish();

my $cpt = 0;
my $ctime = 0;
my $last_line_read;

# Parsing nagios.log
sub parseFile ($$) {
    my $instance = $_[1];
    if (!open (FILE, $_[0])){
		print "Cannot open file : $_[0]\n";
		return;
    }
    $cpt = 0;
    #
    # Skip old lines (already read)
    #
    if (!$opt_a) {
		while ($cpt < $last_line_read && <FILE>){
		    $cpt++;
		}
    }
    #
    # Now Read unknown log lines
    #
    while (<FILE>) {
		
		
		if ($_ =~ m/^\[([0-9]*)\]\sSERVICE ALERT\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    $tab[5] =~ s/\\/\\\\/g; 
		    $tab[5] =~ s/\'/\\\'/g;
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `host_name` , `service_description`, `status`, `type`, `retry`, `output`, `instance`) VALUES ('0', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."', '".$tab[3]."','".$tab[4]."','".$tab[5]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sHOST ALERT\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
			if (defined($tab[4]) && $tab[4]) {
			    $tab[4] =~ s/\\/\\\\/g; 
			    $tab[4] =~ s/\'/\\\'/g;
			}
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `host_name` , `status`,  `type`, `retry`, `output`, `instance`) VALUES ('1', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."','".$tab[3]."','".$tab[4]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sSERVICE NOTIFICATION\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    $tab[5] =~ s/\\/\\\\/g; 
		    $tab[5] =~ s/\'/\\\'/g;
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `host_name` , `service_description`, `status`, `notification_cmd`, `notification_contact`, `output`, `instance`) VALUES ('2', '$ctime', '".$tab[1]."', '".$tab[2]."', '".$tab[3]."', '".$tab[4]."','".$tab[0]."','".$tab[5]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sHOST NOTIFICATION\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    $tab[4] =~ s/\\/\\\\/g; 
		    $tab[4] =~ s/\'/\\\'/g;
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `notification_contact`, `host_name` , `status`, `notification_cmd`,  `output`, `instance`) VALUES ('3', '$ctime', '".$tab[0]."','".$tab[1]."', '".$tab[2]."', '".$tab[3]."','".$tab[4]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sCURRENT\sHOST\sSTATE\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    my $rq = "INSERT INTO `log` (`msg_type`, `ctime`, `host_name` , `status`, `type`, `instance`) VALUES ('7', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sCURRENT\sSERVICE\sSTATE\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    my $rq = "INSERT INTO `log` (`msg_type`, `ctime`, `host_name`, `service_description` , `status`, `type`, `instance`) VALUES ('6', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."', '".$tab[3]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sINITIAL\sHOST\sSTATE\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    my $rq = "INSERT INTO `log` (`msg_type`, `ctime`, `host_name` , `status`, `type`, `instance`) VALUES ('9', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sINITIAL\sSERVICE\sSTATE\:\s(.*)$/){
		    my @tab = split(/;/, $2);
		    $ctime = $1;
		    my $rq = "INSERT INTO `log` (`msg_type`, `ctime`, `host_name`, `service_description` , `status`, `type`, `instance`) VALUES ('8', '$ctime', '".$tab[0]."', '".$tab[1]."', '".$tab[2]."', '".$tab[3]."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\sWarning\:\s(.*)$/){
		    my $tab = $2;
		    $ctime = $1;
		    $tab =~ s/\\/\\\\/g; 
		    $tab =~ s/\'/\\\'/g;
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `output`, `instance`) VALUES ('4','$ctime', '".$tab."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	
		} elsif ($_ =~ m/^\[([0-9]*)\]\s(.*)$/) {
		    $ctime = $1;
		    my $tab = $2;
		    $tab =~ s/\\/\\\\/g; 
		    $tab =~ s/\'/\\\'/g;
		    my $rq = "INSERT INTO `log` (`msg_type`,`ctime`, `output`, `instance`) VALUES ('5','$ctime', '".$tab."', '".$instance."')";
		    my $res = $dbh->do($rq);
		    print "SQL INSERT ERROR :" . $rq. "\n" if (!defined($res));	   
		}
		$cpt++;
    }
    close(FILE);
    return $cpt;
}

my $retention = $data->{'archive_retention'};

sub parseArchive($$) {
    my ($instance, $localhost) = @_;

    my $archives;
    if ($localhost){
		my $sth = $dbhoreon->prepare("SELECT `log_archive_path` FROM `cfg_nagios` WHERE `nagios_server_id` = '".$_[0]."'");
		if (!$sth->execute()) {
		    die "Error:" . $sth->errstr . "\n";
		}
		$data = $sth->fetchrow_hashref();
		$archives = $data->{'log_archive_path'};
		$sth->finish();
    } else {
		$archives = "/var/lib/centreon/log/$instance/archives/";
    }

    $archives .= "/" if (!($archives =~ /\/$/));

    my @log_files = split /\s/,`ls $archives`;
    my $last_log = time() - ($retention * 24 * 60 * 60);
    foreach (@log_files) {
		$_ =~ /nagios\-([0-9\-]+).log/;
		my @time = split /\-/, $1;
		my $temp = $time[0]."/".$time[1]."/".$time[2];
		$temp = `date -d $temp +%s`;
		if ($temp > $last_log) {
		    if (!(-r $archives.$_)) {
				print "Error : cannot read file $archives$_\n";
		    } else {
				print $archives.$_."\n";
				parseFile($archives.$_, $instance);
		    }
		}
    }
}

sub parseLogFile($$) {
    # Get parameters
    my ($instance, $localhost) = @_;

    my $LOG_FILE;
    if ($localhost){
		my $sth = $dbhoreon->prepare("SELECT `log_file` FROM `cfg_nagios`, `nagios_server` WHERE `nagios_server_id` = '".$_[0]."' AND `nagios_server`.`id` = `cfg_nagios`.`nagios_server_id` AND `nagios_server`.`ns_activate` = 1");
		if (!$sth->execute()) {
			die "Error:" . $sth->errstr . "\n";
		}
		$data = $sth->fetchrow_hashref();
		$LOG_FILE = $data->{'log_file'};
		if (!(-r $LOG_FILE)) {
		    print "Error : cannot open $LOG_FILE\n";
		    exit(0);
		}
		$sth->finish();
    } else {
		$LOG_FILE = "/var/lib/centreon/log/$instance/nagios.log";
    }

    # Decide if we have to read the nagios.log from the begining 

    if ($hour eq 0 && $min eq 0){
		$last_line_read = 0;
		my $rq = "UPDATE `instance` SET `log_flag` = '0'";
		my $res = $dbh->do($rq);
		if (!defined($res)) {die "SQL Error: ".$rq."\n";}
    }

    my $sth_flag = $dbh->prepare("SELECT `log_flag` FROM `instance` WHERE `instance_id` = '".$instance."'");
    if (!$sth_flag->execute) {
    	die "Error:" . $sth_flag->errstr . "\n";
    }
    $data = $sth_flag->fetchrow_hashref();
    $last_line_read = $data->{'log_flag'};
    $last_line_read = 0 if (!defined($last_line_read));
    $sth_flag->finish();

    # Parse -> 

    parseFile($LOG_FILE, $instance);

    ##############################
    # Update statistics and flags
    my $rq = "UPDATE `instance` SET `log_flag` = '".$cpt."' WHERE `instance_id` = '".$instance."'";
    my $res = $dbh->do($rq);
    if (!defined($res)) {
    	die "SQL UPDATE Error:" . $rq . "\n";
    }
    ##############################
}

exit() if (!$data->{'archive_log'});

my $sth2 = $dbhoreon->prepare("SELECT `id`, `name`, `localhost` FROM `nagios_server` WHERE `ns_activate` = 1");
if (!$sth2->execute) {
    die "Error:" . $sth2->errstr . "\n";
} else { 
    while (my $ns_server = $sth2->fetchrow_hashref()){
		my $sth1 = $dbh->prepare("SELECT `instance_name` FROM `instance` WHERE `instance_id` = '".$ns_server->{'id'}."' LIMIT 1");
		if (!$sth1->execute) {
		    die "Error:" . $sth1->errstr . "\n";
		}
		if (!$sth1->rows()){
		    my $sthinsert = $dbh->prepare("INSERT INTO `instance` (`instance_id` , `instance_name` , `log_flag`) VALUES ('".$ns_server->{'id'}."', '".$ns_server->{'name'}."', '0');");
		    if (!$sthinsert->execute) {
				die "Error:" . $sthinsert->errstr . "\n";
		    }
		    $sthinsert->finish();			
		} else {
		    my $sthupdate = $dbh->prepare("UPDATE `instance` SET `instance_name` = '".$ns_server->{'name'}."' WHERE `instance_id` = '".$ns_server->{'id'}."' LIMIT 1");
		    if (!$sthupdate->execute) {
				die "Error:" . $sthupdate->errstr . "\n";
		    }
			$sthupdate->finish();			
		}
		$sth1->finish();
		if ($opt_a) {
			# Empty line counter
		    my $res = $dbh->do("UPDATE `instance` SET `log_flag` = '0'");
		    if (!defined($res)) {die "SQL UPDATE Error : UPDATE `instance` SET `log_flag` = '0'\n";}
	
			$res = $dbh->do("TRUNCATE TABLE `log`");
		    print "SQL INSERT ERROR :TRUNCATE TABLE `log`\n" if (!defined($res));	   
		    parseArchive($ns_server->{'id'}, $ns_server->{'localhost'});
		} else {
		    parseLogFile($ns_server->{'id'}, $ns_server->{'localhost'});
		}
    }
    $sth2->finish();
}

if ($retention ne 0){
    my $last_log = time() - ($retention * 24 * 60 * 60);
  	
  	# Drop Database
    my $res = $dbh->do("DELETE FROM `log` WHERE `ctime` < '$last_log'");
    if (!defined($res)) {die "SQL UPDATE Error : DELETE FROM `log` WHERE `ctime` < '$last_log'\n";}
}
$dbh->disconnect();
$dbhoreon->disconnect();
exit;
