#!/usr/bin/perl

#check_logverify.pl
#
#Description: Verify some problems in OpMon V4.0
#

use strict;
use Getopt::Long;
use POSIX;
use File::Basename;
use Sys::Hostname;
use DBI;

#--------------------------------------------------
# Setting environment
#-------------------------------------------------- 
$ENV{"USER"}="opuser";
$ENV{"HOME"}="/home/opuser";

#--------------------------------------------------
# Global variables
#--------------------------------------------------
our $name = basename($0, ".pl");
our $version = "2.2";
our $path = "/usr/local/opmon/libexec";
our $opt_perfopmonlogerrors = "/usr/local/opmon/var/perfdata.errors";
our $opt_statusopmonlogerrors = "/usr/local/opmon/var/opstatus.errors";
our $opt_statuspriopmonlogerrors = "/usr/local/opmon/var/opstatuspri.errors";
our $opt_perfopmonlog = "/usr/local/opmon/var/perfdata.log";
our $opt_statusopmonlog = "/usr/local/opmon/var/opstatus.log";
our $opt_perfdir = "/usr/local/opmon/var/perfdata"; 
our $opt_statusdir = "/usr/local/opmon/var/opstatus";
our $opt_statuspridir = "/usr/local/opmon/var/opstatuspri";
our $opmonlog = "/usr/local/opmon/var/opmon.log";
our ($opt_help, $opt_verbose, $opt_version);
our $hostname = hostname;

my @metrics = ("perf_insert_errors", "opstatus_errors", "perf_files_found", "status_files_found", "opmon_errors", "opstatuspri_errors");
my @return = ();


# --- Release notes --- #

# --- end notes --- #


					### ---- CORE PROGRAM ---- ###
# -------------------- # -------------------------- # ----------------------- # ---------------------------- # -------- #

sub main {

	# --- Init options --- #
	getoption();
	
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("#--- INIT VERBOSE MODE ---#");}

	# --- Flush return --- #
	my $counter=0;
	my $totalerrors=0;
	
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("Init my vars: counter=$counter : totalerrors=$totalerrors");}

	# --- Zero counter for returns --- #
	for(;$counter<$#metrics+1;$counter++){

		$return[$counter]=0;

	}

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("New counter=$counter");}
	
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("File Perfdata Errors: $opt_perfopmonlogerrors");}
	if($opt_verbose!=0){logger("File Status Errors: $opt_statusopmonlogerrors");}

	# --- My vars --- #
	my $myregex="perl -pe 's/(\\d+)/localtime(\$1)/e'";
	
	my $linkperf="<a href='https://$hostname.opnet.opservices.com.br/opmon/errosperfdata.log'><img width=16 height=16 src='https://opmon.opservices.com.br/opmon/opcfg/logos/opmon35.png' border=0></a>";
	
	my $linkstatus="<a href='https://$hostname.opnet.opservices.com.br/opmon/errosstatus.log'><img width=16 height=16 src='https://opmon.opservices.com.br/opmon/opcfg/logos/opmon35.png' border=0></a>";

	my $flagerrors1=0;
	my $flagerrors2=0;
	my $opstatuspri_errors=0;

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("My REGEX: $myregex : My links out: $linkperf $linkstatus");}

	# --- Verify if file found ---#
	if (-e "$opt_perfopmonlogerrors") {
		# -- Working this archives --- #
		open(FILE,"$opt_perfopmonlogerrors");
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){logger("Perfdata - Return files:");}
		# --- For array --- #
		while(<FILE>){
			# --- VERBOSE MODE --- #
			if($opt_verbose!=0){chomp($_);logger("$_");}
				$flagerrors1++; $totalerrors++;
		}
		close(FILE);
		$return[0]=$totalerrors;
		$flagerrors1++;
		system("$myregex $opt_perfopmonlogerrors > /usr/local/opmon/share/errosperfdata.log");
	}

	# --- Verify if file found ---#
	if (-e "$opt_statusopmonlogerrors"){
		# -- Working this archives --- #
		open(FILE,"$opt_statusopmonlogerrors");
		
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){logger("STATUS - Return files:");}
		
		# --- For array --- #
		while(<FILE>){
		    # --- VERBOSE MODE --- #
		    if($opt_verbose!=0){chomp($_);logger("$_");}
		    $flagerrors2++;
		}
		close(FILE);
		$return[1]=$flagerrors2;
		system("$myregex $opt_statusopmonlogerrors > /usr/local/opmon/share/errosstatus.log");
	}

	# --- Verify if file found ---#
	if (-e "$opt_statuspriopmonlogerrors"){
		# -- Working this archives --- #
		open(FILE,"$opt_statuspriopmonlogerrors");
		
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){logger("STATUS PRI - Return files:");}
		
		# --- For array --- #
		while(<FILE>){
		    # --- VERBOSE MODE --- #
		    if($opt_verbose!=0){chomp($_);logger("$_");}
		    $opstatuspri_errors++;
		}
		close(FILE);
		$return[6]=$opstatuspri_errors;
		system("$myregex $opt_statuspriopmonlogerrors > /usr/local/opmon/share/errosstatus.log");
	}

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("--- --- ---");}

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("My final var results: PERFINSERTERRORS / $totalerrors : STATUSINSERTERROR - $flagerrors2 / OPSTATUSPRI ERRORS $opstatuspri_errors");}

	# --- Verify if file is updated --- #

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("Verify if perflog and statuslog is updated:");}

	my $mytime=time();
	my $resultperf=0;
	my $resultstatus=0;
	my $flagerrors3=0;
	my $modeperf;
	my $modestatus;
	# --- My vars --- #
	if (-e $opt_perfopmonlog) {
		my $modeperf=(stat($opt_perfopmonlog))[8];
		$resultperf=$mytime-$modeperf;
	}
	if (-e $opt_statusopmonlog) {
		my $modestatus=(stat($opt_statusopmonlog))[8];
		$resultstatus=$mytime-$modestatus;
	}
		
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("$opt_perfopmonlog data access: $modeperf Mytime: $mytime --- Result: $resultperf");}
	if($opt_verbose!=0){logger("$opt_statusopmonlog data access: $modestatus Mytime: $mytime --- Result: $resultstatus");}

	# --- If result is most 5 minutes --- #
	if($resultperf>=300){$flagerrors3++;}				
	if($resultstatus>=300){$flagerrors3++;}				
	
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("FLAGERRORS3: $flagerrors3");}

	# --- Verify in directory how many archives found --- #
	my $flagerrors4=0;
	my $flagerrors5=0;
	my $counterperf=0;
	my $counterstatus=0;
	my @myfilesperf=();
	my @myfilesstatus=();

	# --- PERF DIRECTORY --- #
	opendir(DIR, $opt_perfdir) or do { logger("CRITICAL - Can't opendir $opt_perfdir: $!"); exit(2);};
	@myfilesperf = grep (/perf/, readdir(DIR));
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("$opt_perfdir DIRECTORY FILES:");}

	closedir DIR;

	if($myfilesperf[4]){$flagerrors4++;}

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("FLAGERRORS4: $flagerrors4");}

	foreach(@myfilesperf){
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){chomp($_);logger("$_");}
		$counterperf++;	
	}
	
	# --- STATUS DIRECTORY --- #
	opendir(DIR, $opt_statusdir) or do { logger("CRITICAL - Can't opendir $opt_statusdir: $!"); exit(2);};
	#        @myfilesstatus = grep (/perf/, readdir(DIR));
	@myfilesstatus = readdir(DIR);
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("$opt_statusdir DIRECTORY FILES:");}
	closedir DIR;
	if($myfilesstatus[4]) {
		$flagerrors5++;
	}
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("FLAGERRORS5: $flagerrors5");}
	foreach(@myfilesstatus){
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){chomp($_);logger("$_");}
		$counterstatus++;
	}

	my $counterstatuspri=0;
	opendir(DIR, $opt_statuspridir) or do { logger("CRITICAL - Can't opendir $opt_statuspridir: $!"); exit(2);};
		@myfilesstatus = readdir(DIR);
		# --- VERBOSE MODE --- #
		if($opt_verbose!=0){logger("$opt_statuspridir DIRECTORY FILES:");}
		closedir DIR;
		foreach(@myfilesstatus) {
			# --- VERBOSE MODE --- #
			if($opt_verbose!=0){chomp($_);logger("$_");}
			$counterstatuspri++;
		}
		$counterstatuspri=$counterstatuspri-2;

	# --- Generate metrics and returns --- #
	$return[2]=$counterperf;
	$return[3]=$counterstatus;
	$return[7]=$counterstatuspri;
	
	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("RETURN PERF: $return[2]");}
	if($opt_verbose!=0){logger("RETURN STATUS: $return[3]");}

	# --- Comments problem --- #

	# --- Connect in DB --- #
        my $test=0;
        my $dbh = DBI->connect ("dbi:mysql:dbname=opmon4;host=127.0.0.1", "root", "", {RaiseError=>0,PrintError=>0})
                or do { $test++;};

        if($test==1){

                $dbh = DBI->connect ( "dbi:mysql:dbname=opmon4;host=127.0.0.1", "root", "oppass")
                        or do{  logger("CRITICAL - Can't connect in DB: $DBI::errstr\n"); exit(2);};

        }

        # --- Verify entries --- #
        my $sql="
        SELECT entry_time 
                FROM opmon_cmd
                ORDER BY entry_time 
                DESC LIMIT 1;";

        # --- Expected return: 2009-07-23 12:56:59 --- #
        my $sth = $dbh->prepare($sql);

                $sth->execute;
                my $commentsdate = $sth->fetchrow();
                $sth->finish;

        # --- DB disconnect --- #
        $dbh->disconnect;

        # --- Verify date entrie --- #
	my $realtime=time();
        my $myday=strftime("%d",localtime);
        my $mymonth=strftime("%m",localtime);
        my $myyear=strftime("%Y",localtime);
        my @commenttime1=split(/ /,$commentsdate); my @commenttime2=split(/:/,$commenttime1[1]);

        my $dbcomment=date_to_epoch($myday,$mymonth,$myyear,$commenttime2[0],$commenttime2[1],$commenttime2[2]);
	if(not defined $commentsdate){$dbcomment=$realtime;}
        my $difftime=$realtime-$dbcomment;	

	# --- VERBOSE MODE --- #
	if($opt_verbose!=0){logger("DIFFTIME: $difftime");}

	my $flagerrors6=0;

	# --- Verify opmon.log --- #

	if(-e $opmonlog){

		# -- Log rotate and set log position --- # 
        	my $position=getposition();

	        open(POS, "$opmonlog");
	        seek(POS,0,SEEK_END);
	        my $tmp=tell POS;

	        if ($tmp<$position){

        	        $position=$tmp;

	        }

        	close(POS);

		# --- Verify lines --- #
		open(FILE, "$opmonlog");
                seek(FILE,$position,SEEK_SET);

		while(<FILE>){

			if($_=~/opmonconnector/ && ($_=~/ERRO/ or $_=~/erro/)){
	
				$flagerrors6++;					
				# --- VERBOSE MODE --- #
				if($opt_verbose!=0){logger("Line OpMonConnector: $_");}

			}	
		
		}
			$position= tell FILE;
			#$position = seek(FILE,0,SEEK_CUR);
	                setposition($position);
			close(FILE);

	}

	# --- Set return --- #
	$return[4]=$flagerrors6;


	# --- Thresholds --- # 
# ------------------------------- # ----------------------- # --------------------------- # --------------------------- #

	# --- Many errors --- #
	
	my $error_string="CRITICAL - ";
	if ($opstatuspri_errors>1) {
		$error_string=$error_string."opstatuspri insert fail / ";
	}
	if ($flagerrors1>1) {
		$error_string=$error_string."$linkperf perfdata insert fail / ";
	}
	if ($flagerrors2>1) {
		$error_string=$error_string."opstatus insert fail / ";
	}
	if ($difftime>600) {
		$error_string=$error_string."table 'opmon_cmd' with comments more than 10 minutes / ";
	}
	if ($flagerrors6>0) {
		$error_string=$error_string."OpMonConnector error / ";
	}
	if($flagerrors3>0) {
		$error_string=$error_string."'$opt_perfopmonlog' or '$opt_statusopmonlog' last update more than 5 minutes - perfdirectory=$counterperf statusdirectory=$counterstatus / ";
	}
	if($return[2]>100){
		$error_string=$error_string."'$opt_perfdir' with $counterperf files / ";
	}
	if($return[3]>100){
		$error_string=$error_string."'$opt_statusdir' with $counterstatus files / ";
	}
	if($return[7]>100){
		$error_string=$error_string."'$opt_statuspridir' with $counterstatuspri files / ";
	}

	if (length($error_string)>12) {
		logger("$error_string");
		exit(2);
	}
	else {
		logger("OK - Service without errors");
		exit(0);
	}
}
#--------------------------------------------------------------------------------------
sub getoption  {
     Getopt::Long::Configure('bundling');
     GetOptions(
            'V|version'                 => \$opt_version,
            'h|help'                    => \$opt_help,
            'v|verbose=i'               => \$opt_verbose,
        );

     if($opt_help){

             printHelp();
              exit(1);

     }

     if($opt_version){

             print "$name.pl - '$version'\n";
             exit(1);
 
     }

     if(!$opt_verbose){

             $opt_verbose = 0;

     }

}

#--------------------------------------------------------------------------------------
sub logger {
	
	return (0) if (not defined $opt_verbose);
	
	my $msg = shift (@_);
	my $perf = "";
	my $log = "$path/$name.log";
	my $counter = 0;

	foreach(@metrics) {
		$perf .= "$_=$return[$counter];;;0; ";
		$counter++;
	}
	
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
	$wday++;
	$yday++;
	$mon++;
	$year+=1900;
	$isdst++;
	
 	if ($opt_verbose == 0) {
		if (@metrics){
			print "$msg | $perf\n";
		}
		else {
			print "$msg\n";
		}
	}
	
	elsif ($opt_verbose == 1){
		print "$msg\n";
	}
	else {
		open(LOG, ">>$log");
		printf LOG ("%02i/%02i/%i - %02i:%02i:%02i => %s\n",$mday,$mon,$year,$hour,$min,$sec,$msg);
		close(LOG);
	}
}
#--------------------------------------------------------------------------------------

sub printUsage {

       print <<EOB

Usage: $name.pl [OPTION]...

        -V, --version      	 Show version
        -h, --help         	 Show help

        -v, --verbose      	 0 = Print out to see in OpMon(Default)
                           	 1 = Print out in console for debug
			    	 2 = Send log to file

EOB

}
#--------------------------------------------------------------------------------------

sub printHelp {

		my $help = <<'HELP';


		This Agent verify perfdata and status errors in OpMon:

		Functions: 

		-> Verify if file -$opt_perfopmonlogerrors- found
		-> Verify if file -$opt_statusopmonlogerrors- found
		-> Verify if file -$opt_statusrpiopmonlogerrors- found
		-> Verify if 'Access' stat of archive -$opt_perfopmonlog- is less of five minutes
		-> Verify if 'Access' stat of archive -$opt_statusopmonlog- is less of five minutes
		-> Locate archives in directory '/usr/local/opmon/var/perfdata/' 
		-> Locate archives in directory '/usr/local/opmon/var/statusdata/' 
		-> Verify comments more than 10 minutes in table 'opmon_db'
		-> Verify if in file 'opmon.log' had entrie 'opmonconnector' with string 'ERROR' in the same line

		Support: suporte@opservices.com.br
		Develop: Gabriel Prestes

		
		Wish list Agent:

		-> Ignore perfdata errors if in array '@ignore'
		-> Eventhandler for 'opmonconnector' and 'opmoncmd' 






		God's words: 
		"Cordeiro de Deus, retirai os pecados do mundo, tende piedade de nos..."




HELP

		system("clear");
		print $help;

}
#--------------------------------------------------------------------------------------

sub date_to_epoch {

        my $day = shift;
        my $mon = shift;
        my $year = shift;
        my $hour = shift;
        my $min = shift;
        my $sec = shift;
        my $wday = 0;
        my $yday = 0;

        my $epoch = mktime($sec,$min,$hour,$day,($mon-1),($year-1900),$wday,$yday,-1);

        return($epoch)
}
#--------------------------------------------------------------------------------------

sub getposition {

        my $mypositionlog="$path/logverify.db";

        if(!-f $mypositionlog){

                return 0;

        }

        open(LOG,"$mypositionlog");

        my $pos=<LOG>;

        close(LOG);
        chomp($pos);

        return $pos;

}
#--------------------------------------------------------------------------------------

sub setposition {

        my $mypositionlog="$path/logverify.db";
        my $pos = shift;

        open(LOG,">$mypositionlog");

        print LOG $pos;

        close(LOG);

}
#--------------------------------------------------------------------------------------
&main
