#! /usr/bin/perl -w
################################################################################
# Copyright 2004-2011 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$
#
####################################################################################

use strict;
use DBI;
use Getopt::Long;
use vars qw($centreon_config);

########################################
# GLOBAL VARIABLES COMMON TO ALL PLUGINS
########################################

my $PROGNAME = $0;
my $VERSION = "2.5";
my $MODIF_DATE = "07-22-2013";

my %ERRORS = ( "OK" => 0, "WARNING" => 1, "CRITICAL" => 2, "UNKNOWN" => 3);
my %DSTYPE = ( "0" => "g", "1" => "c", "2" => "d", "3" => "a");

require "/DBA/centreon-data/centreon/etc/conf.pm";
my $dbh  = DBI->connect("DBI:mysql:database=$centreon_config->{centreon_db};host=$centreon_config->{db_host}","$centreon_config->{db_user}", "$centreon_config->{db_passwd}",{'RaiseError' => 1});
my $db_centstorage  = DBI->connect("DBI:mysql:database=$centreon_config->{centstorage_db};host=$centreon_config->{db_host}","$centreon_config->{db_user}", "$centreon_config->{db_passwd}",{'RaiseError' => 1});

my $row;
my $ndo_prefix;
my $db_broker;
my $DBRESULT;

sub get_db_layer();
my $db_layer = get_db_layer();

if ($db_layer eq "ndo") {
    $DBRESULT = $dbh->prepare("SELECT * FROM `cfg_ndo2db`");
    if (!$DBRESULT->execute) {
        die "Error:" . $dbh->errstr . "\n";
    }
    $row = $DBRESULT->fetchrow_hashref();
    if (defined($row)) {
        $db_broker = DBI->connect("DBI:mysql:database=".$row->{'db_name'}.";host=".$row->{'db_host'}.":".$row->{'db_port'}, $row->{'db_user'}, $row->{'db_pass'}, {'RaiseError' => 1});
        $ndo_prefix = $row->{'db_prefix'};
    } else {
        print "Could not find broker connection info!\n";
        exit $ERRORS{'UNKNOWN'};
    }
}

my @metric_value_tab;
my $warning;
my $critical;
my $calculation;
my $regexp;
my $metric_select;
my $display;

###############
# HELP FUNCTION
###############
sub print_help() {
    print "Usage: ".$PROGNAME."\n";
    print "   -i (--id)   Hostname to query (required)\n";    
    print "   -l (--legacy) Compatible with Centreon perfdata syntax prior to v2.4\n";
    print "   -V (--version)    Plugin version\n";
    print "   -h (--help)       usage help\n";
}

############################
# GETTING PARAMETERS OPTIONS
############################

my %OPTION = ( "help" => undef, "version" => undef, "id" => undef);          

Getopt::Long::Configure('bundling');
GetOptions
    ("h|help"      => \$OPTION{'help'},
     "l|legacy"    => \$OPTION{'legacy'},
     "V|version"   => \$OPTION{'version'},
     "i|id=s"      => \$OPTION{'id'});

if (defined($OPTION{'version'})) {
    print $PROGNAME." : ".$VERSION." last modification : ".$MODIF_DATE."\n";
    exit $ERRORS{'UNKNOWN'};
}

if (defined($OPTION{'help'})) {
    print_help();
    exit $ERRORS{'UNKNOWN'};
}

if (!defined($OPTION{'id'})) {
        print_help;
        exit $ERRORS{'UNKNOWN'};
}

##################################################
##
## Functions
##
##################################################
sub calculate_meta() {
	my $result;
	my $val;
	my $total;
	
	if ($calculation eq "MIN") {
		@metric_value_tab = sort(@metric_value_tab);
		if (defined($metric_value_tab[0])) {
			$result = $metric_value_tab[0];
		} else {
			$result = 0;
		}
	} elsif ($calculation eq "MAX") {
		@metric_value_tab = sort(@metric_value_tab);
		if (defined($metric_value_tab[0])) {
			$result = $metric_value_tab[scalar(@metric_value_tab) - 1];
		} else {
			$result = 0;
		}
	} elsif ($calculation eq "SOM") {
		$result = 0;
		foreach $val (@metric_value_tab) {
			if ($val) {
				$val =~ s/,/./;
				$result += $val;	
			}
		}
	} elsif ($calculation eq "AVE") {
		$result = 0;
		foreach $val (@metric_value_tab) {
			if ($val) {
				$val =~ s/,/./;
				$result = $result + $val;
			}
		}
		$total = scalar(@metric_value_tab);
		if (!$total) {
			$total = 1;
		}
		$result = $result / $total;
	}
	return $result;
} 

##################################################
##
## Get Data Source Type of meta service 
##
##################################################
sub getDataSourceType() {
    my $sql = "SHOW COLUMNS FROM meta_service WHERE Field LIKE 'data_source_type'";
    my $res = $dbh->prepare($sql);
    $res->execute;
    while ($res->fetchrow_hashref()) {
        my $sqlDs = "SELECT data_source_type FROM meta_service WHERE meta_id = ".$OPTION{'id'};
        my $resDs = $dbh->prepare($sqlDs);
        $resDs->execute;
        while ($row = $resDs->fetchrow_hashref()) {
	    if (defined($DSTYPE{$row->{'data_source_type'}})) {
                return $DSTYPE{$row->{'data_source_type'}};
            }
        }
    }
    return $DSTYPE{'0'};
}

##################################################
##
## Retrieve by regexp for Centreon Broker 
##
##################################################
sub retrieve_by_regexp_centreon_broker() {	
	my $row2;
	my $query2 = "SELECT s.perfdata FROM services s WHERE s.description LIKE '".$regexp."'";
	my $DBRES2 = $db_centstorage->prepare($query2);
	if (!$DBRES2->execute) {
		die "Error:" . $DBRES2->errstr . "\n";
	}
	my $i = 0;
	while ($row2 = $DBRES2->fetchrow_hashref()) {
		if (defined($metric_select)) {
			$row2->{'perfdata'} =~ m/$metric_select=([0-9\.]+)/;
			if (defined($1)) {
				$metric_value_tab[$i] = $1;				
				$i++;
			}
		}
		else {
			print "No metric defined!\n";
			exit $ERRORS{'UNKNOWN'};
		}
	}
}

##################################################
##
## Retrieve by regexp for ndo 
##
##################################################
sub retrieve_by_regexp() {	
	my $row2;
	my $query2 = "SELECT ss.perfdata FROM `".$ndo_prefix."servicestatus` ss, `".$ndo_prefix."services` s WHERE ss.service_object_id = s.service_object_id AND s.display_name LIKE '".$regexp."'";
	my $DBRES2 = $db_broker->prepare($query2);
	if (!$DBRES2->execute) {die "Error:" . $DBRES2->errstr . "\n";}
	my $i = 0;
	while ($row2 = $DBRES2->fetchrow_hashref()) {
		if (defined($metric_select)) {
			$row2->{'perfdata'} =~ m/\'?$metric_select\'?=([0-9\.]+)/;
			if (defined($1)) {
				$metric_value_tab[$i] = $1;				
				$i++;
			}
		}
		else {
			print "No metric defined!\n";
			exit $ERRORS{'UNKNOWN'};
		}
	}
}

##################################################
##
## Retrieve by list for Centreon Broker 
##
##################################################
sub retrieve_by_list_centreon_broker() {
	my $row2;

	my $query3;
	my $DBRES3;
	my $row3;

	my $query4;
	my $DBRES4;
	my $row4;	

	my $query2 = "SELECT host_id, metric_id FROM `meta_service_relation` WHERE meta_id = '".$OPTION{'id'}."'";
	my $DBRES2 = $dbh->prepare($query2);
	if (!$DBRES2->execute) {
        die "Error:" . $DBRES2->errstr . "\n";
	}
	my $i = 0;
	while ($row2 = $DBRES2->fetchrow_hashref()) {
		$query3 = "SELECT host_name, service_description, m.metric_name FROM index_data i, metrics m WHERE i.id = m.index_id AND m.metric_id = '".$row2->{'metric_id'}."' LIMIT 1";
		$DBRES3 = $db_centstorage->prepare($query3);
		if (!$DBRES3->execute) {
			die "Error:" . $DBRES3->errstr . "\n";
		}
		$row3 = $DBRES3->fetchrow_hashref();

		if (defined($row3->{'service_description'})) {
			$query4 = "SELECT s.perfdata FROM services s, hosts h WHERE s.host_id = h.host_id AND h.name = '".$row3->{'host_name'}."' AND s.description = '".$row3->{'service_description'}."' AND s.enabled = '1' AND h.enabled = '1' LIMIT 1"; 
			$DBRES4 = $db_centstorage->prepare($query4);
			if (!$DBRES4->execute) {
				die "Error:" . $DBRES4->errstr . "\n";
			}
			$row4 = $DBRES4->fetchrow_hashref();
            if (defined($OPTION{'legacy'})) {
                while ($row4->{'perfdata'} =~ m/\'?([a-zA-Z0-9\_\-\/\.\:\ ]+)\'?=([0-9\.\,\-]+)/g) {
                    my $value = $2;
                    if (defined($1) && defined($value) && $1 =~ $row3->{'metric_name'}) {
                        $metric_value_tab[$i] = $value;
                        $i++;
                    }
                }
            } else {
                while ($row4->{'perfdata'} =~ m/\'?([a|c|d|g]\[)?([a-zA-Z0-9\_\-\/\.\:\ ]+)(\])?\'?=([0-9\.\,\-]+)/g) {
                    my $value = $4;
                    if (defined($2) && defined($value) && $2 =~ $row3->{'metric_name'}) {
                        $metric_value_tab[$i] = $value;
                        $i++;
                    }
                }
			}
		}
	}
}


##################################################
##
## Retrieve by list for ndo 
##
##################################################
sub retrieve_by_list() {
	my $row2;
		
	my $query3;
	my $DBRES3;
	my $row3;
	
	my $query4;
	my $DBRES4;
	my $row4;	
	
	my $query2 = "SELECT host_id, metric_id FROM `meta_service_relation` WHERE meta_id = '".$OPTION{'id'}."'";
	my $DBRES2 = $dbh->prepare($query2);
	if (!$DBRES2->execute) {
		die "Error:" . $DBRES2->errstr . "\n";
	}
	my $i = 0;
	while ($row2 = $DBRES2->fetchrow_hashref()) {
		$query3 = "SELECT host_name, service_description, m.metric_name FROM index_data i, metrics m WHERE i.id = m.index_id AND m.metric_id = '".$row2->{'metric_id'}."' LIMIT 1";
		$DBRES3 = $db_centstorage->prepare($query3);
		if (!$DBRES3->execute) {
			die "Error:" . $DBRES3->errstr . "\n";
		}
		$row3 = $DBRES3->fetchrow_hashref();
		
		$row3->{'service_description'} =~ s/\#S\#/\//g;
        $row3->{'service_description'} =~ s/\#BS\#/\\/g;
		
		if (defined($row3->{'service_description'})) {
			$query4 = "SELECT ss.perfdata FROM `".$ndo_prefix."servicestatus` ss, `".$ndo_prefix."services` s, `".$ndo_prefix."hosts` h WHERE ss.service_object_id = s.service_object_id AND s.host_object_id = h.host_object_id AND h.display_name = '".$row3->{'host_name'}."' AND s.display_name = '".$row3->{'service_description'}."' LIMIT 1"; 
			$DBRES4 = $db_broker->prepare($query4);
			if (!$DBRES4->execute) {
				die "Error:" . $DBRES4->errstr . "\n";
			}
			$row4 = $DBRES4->fetchrow_hashref();
	
			while ($row4->{'perfdata'} =~ m/\'?([a-zA-Z0-9\_\-\/\.\:\ ]+)\'?=([0-9\.\,\-]+)/g) {
            	my $value = $2;
            	if (defined($1) && defined($value) && $1 =~ $row3->{'metric_name'}) {
                	$metric_value_tab[$i] = $value;
                    $i++;
                }
            }
		}
	}
}

##################################################
##
## Get Db Layer 
##
##################################################
sub get_db_layer() {
	my $query = "SELECT `value` FROM `options` WHERE `key` = 'broker'";
	my $res = $dbh->prepare($query);
	if (!$res->execute) {
		die "Error:" . $res->errstr . "\n";
	}
	$row = $res->fetchrow_hashref();
	if (!defined($row->{'value'})) {
		return "ndo";
	} else {
		return $row->{'value'};
	}
}


##################################################
##
## MAIN
##
##################################################

##################################################
##
## First query
##
##################################################
my $query = "SELECT meta_display, calcul_type, regexp_str, warning, critical, metric, meta_select_mode FROM `meta_service` WHERE meta_id = '".$OPTION{'id'}."' LIMIT 1";
my $DBRES = $dbh->prepare($query);
if (!$DBRES->execute) {
	die "Error:" . $DBRES->errstr . "\n";
}
$row = $DBRES->fetchrow_hashref();
if (!defined($row->{'calcul_type'})){
	print "Meta Service is not valid\n";
    exit $ERRORS{'CRITICAL'};
}

##################################################
##
## Initialization of Variables
##
##################################################
$warning = $row->{'warning'};
$critical = $row->{'critical'};
$calculation = $row->{'calcul_type'};
$regexp = $row->{'regexp_str'};
$metric_select = $row->{'metric'};
$display = $row->{'meta_display'};

my $selection_mode = $row->{'meta_select_mode'};

if ($selection_mode eq '2') {    
    if ($db_layer eq "broker") {
    	retrieve_by_regexp_centreon_broker();
    } else {
    	retrieve_by_regexp();
    }
} else {
	if ($db_layer eq "broker") {
		retrieve_by_list_centreon_broker();
	} else {
		retrieve_by_list();
	}
}

my $res = calculate_meta();
$res = sprintf("%02.2f", $res);

my $msg = "";
my $meta_status = $ERRORS{'OK'};
if (defined($warning) && defined($critical)) {
	if ($warning <= $critical) {
		if ($res >= $warning) {
			$meta_status = $ERRORS{'WARNING'};
		}
		if ($res >= $critical) {
			$meta_status = $ERRORS{'CRITICAL'};
		}
	} elsif ($warning > $critical) {
		if ($res <= $warning) {
			$meta_status = $ERRORS{'WARNING'};
		}
		if ($res <= $critical) {
			$meta_status = $ERRORS{'CRITICAL'};
		}
	}
}

my $metric = "";
if (defined($metric_select)) {
    $metric = $metric_select;
} else {
    $metric = "value";
}


if (!defined($display) || !$display) {
    if ($calculation eq "AVE") {
	$msg .= "Average - ";
    } elsif ($calculation eq "SOM") {
	$msg .= "Sum - ";
    } elsif ($calculation eq "MIN") {
	$msg .= "Min - ";
    } elsif ($calculation eq "MAX") {
	$msg .= "Max - ";
    }
    $msg .= $metric." : " . $res;
} else {
    $msg = sprintf($display, $res);
}
if (defined($OPTION{'legacy'})) {
    $msg .= "|".$metric."=".$res;
} else {
    $msg .= "|".getDataSourceType()."[".$metric."]=".$res;
}

##############
# PRINT RESULT
##############
print $msg."\n";
exit $meta_status;
