#! /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 . # # 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 # # check_value -f "The cpu is used %s %d" -m CPU -u "%" use strict; use Getopt::Long; require "@NAGIOS_PLUGINS@/Centreon/SNMP/Utils.pm"; my $PROGNAME = "$0"; my %OPTION = ('host' => undef, 'help' => undef, 'warning' => '5', 'critical' => '10', 'snmpversion' => 1, 'display' => 0, 'snmpcomm' => 'public', 'min' => 0, 'max' => 0, 'host' => undef,'username' => undef, 'authpassword' => undef, 'authprotocol' => undef, 'privprotocol' => undef , 'privpassword' => undef, 'snmpport' => 161, 'type' => 'GAUGE', 'base' => 1000, 'output' => 'The value is %f', 'metric' =>'value', 'unit' => 'nounit', 'divide' => 1); my %ERRORS = ('OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3); my $prefix = ""; sub print_help (); sub print_usage (); Getopt::Long::Configure('bundling'); GetOptions ("h" => \$OPTION{'help'}, "help" => \$OPTION{'help'}, "P=s" => \$OPTION{'snmpport'}, "snmpport=s" => \$OPTION{'snmpport'}, "V" => \$OPTION{'pluginversion'}, "version" => \$OPTION{'pluginversion'}, "u=s" => \$OPTION{'username'}, "username=s" => \$OPTION{'username'}, "a=s" => \$OPTION{'authprotocol'}, "authprotocol=s" => \$OPTION{'authprotocol'}, "A=s" => \$OPTION{'authpassword'}, "authpassword=s" => \$OPTION{'authpassword'}, "x=s" => \$OPTION{'privprotocol'}, "privprotocol=s" => \$OPTION{'privprotocol'}, "X=s" => \$OPTION{'privpassword'}, "privpassword=s" => \$OPTION{'privpassword'}, "v=s" => \$OPTION{'snmpversion'}, "snmp=s" => \$OPTION{'snmpversion'}, "C=s" => \$OPTION{'snmpcomm'}, "community=s" => \$OPTION{'snmpcomm'}, "w=s" => \$OPTION{'warning'}, "warning=s" => \$OPTION{'warning'}, "c=s" => \$OPTION{'critical'}, "critical=s" => \$OPTION{'critical'}, "H=s" => \$OPTION{'host'}, "host=s" => \$OPTION{'host'}, "W=s" => \$OPTION{'warning_table'}, "warning_table=s" => \$OPTION{'warning_table'}, "T=s" => \$OPTION{'critical_table'}, "critical_table=s" => \$OPTION{'critical_table'}, "O=s" => \$OPTION{'ok_table'}, "ok_table=s" => \$OPTION{'ok_table'}, "o=s" => \$OPTION{'oid'}, "oid=s" => \$OPTION{'oid'}, "t=s" => \$OPTION{'type'}, "type=s" => \$OPTION{'type'}, "d=s" => \$OPTION{'divide'}, "divide=s" => \$OPTION{'divide'}, "U=s" => \$OPTION{'unit'}, "unit=s" => \$OPTION{'unit'}, "max=s" => \$OPTION{'max'}, "convert" => \$OPTION{'convert'}, "debug" => \$OPTION{'debug'}, "min=s" => \$OPTION{'min'}, "base=s" => \$OPTION{'base'}, "64-bits=s" => \$OPTION{'64-bits'}, "f=s" => \$OPTION{'output'}, "output=s" => \$OPTION{'output'}, "m=s" => \$OPTION{'metric'}, "metric=s" => \$OPTION{'metric'} ); # For counter metric type my $metricsname = undef; my $unit = undef; my $output = undef; my $min = undef; my $max = undef; my $cache = undef; my $divide = undef; # Used for counter type metric my $previousValue = undef; my $previousTime = undef; my $currentTime = time(); my $currentValue = undef; # Table used when personnal threshold are set my @critical_table = (); my @warning_table = (); my @ok_table = (); if ($OPTION{'critical_table'}){ @critical_table = split(/\,/, $OPTION{'critical_table'}); } if ($OPTION{'warning_table'}){ @warning_table = split(/\,/, $OPTION{'warning_table'}); } if ($OPTION{'ok_table'}){ @ok_table = split(/\,/, $OPTION{'ok_table'}); } if (defined($OPTION{'pluginversion'})) { print("$PROGNAME 1.1"); exit $ERRORS{'UNKNOWN'}; } if (defined($OPTION{'help'})) { print_help(); exit $ERRORS{'UNKNOWN'}; } if (!$OPTION{'host'}) { print_usage(); exit $ERRORS{'UNKNOWN'}; } if (!$OPTION{'oid'}) { print_usage(); exit $ERRORS{'UNKNOWN'}; } my $cacheFile = "@CENTREON_VARLIB@/centplugins/snmp_value".$OPTION{'host'}."-".$OPTION{'oid'}; # Store option values in simpler variables if ($OPTION{'divide'} ne "" && $OPTION{'metric'} ne "" && $OPTION{'unit'} ne "" && $OPTION{'output'} ne "" && $OPTION{'min'} ne "" && $OPTION{'max'} ne "") { $metricsname = $OPTION{'metric'}; $unit = $OPTION{'unit'}; # Output Verification? $output = $OPTION{'output'}; # check parameter format if ($OPTION{'base'} !~ /^[0-9]*\.?[0-9]*$/) { print(" Base option should be a numerical \n"); exit $ERRORS{'UNKNOWN'}; } if ($OPTION{'min'} !~ /^[0-9]*\.?[0-9]*$/) { print(" Min option should be a numerical \n"); exit $ERRORS{'UNKNOWN'}; } if ($OPTION{'max'} !~ /^[0-9]*\.?[0-9]*$/) { print(" Max option should be a numerical \n"); exit $ERRORS{'UNKNOWN'}; } if ($OPTION{'divide'} !~ /^[0-9]*\.?[0-9]*$/) { print(" -d option should be a numerical \n"); exit $ERRORS{'UNKNOWN'}; } if ($OPTION{'warning'} !~ /^[0-9]*\.?[0-9]*$/ || $OPTION{'critical'} !~ /^[0-9]*\.?[0-9]*$/) { print(" Option warning &/or critical should be numerical \n"); exit $ERRORS{'UNKNOWN'}; } $min = $OPTION{'min'}; $max = $OPTION{'max'}; $divide = $OPTION{'divide'}; } else { print("One or more arguments are not set \n"); exit $ERRORS{'UNKNOWN'}; } # Check if version passed in option exists $OPTION{'snmpversion'} =~ s/v//g; exit $ERRORS{'UNKNOWN'} if(!Centreon::SNMP::Utils->checkVersion($OPTION{'snmpversion'})); # Check which connection mode is used my $sessionType = 1; if ($OPTION{'snmpversion'} =~ /3/) { $sessionType = Centreon::SNMP::Utils->checkSessiontype($OPTION{'username'},$OPTION{'authprotocol'},$OPTION{'authpassword'},$OPTION{'privprotocol'},$OPTION{'privpassword'}); exit $ERRORS{'UNKNOWN'} if(!$sessionType); } my $DS_type = "GAUGE"; $DS_type = $1 if ($OPTION{'type'} =~ /(GAUGE)/ || $OPTION{'type'} =~ /(COUNTER)/); my $critical = $1 if ($OPTION{'critical'} =~ /([0-9]+)/); my $warning = $1 if ($OPTION{'warning'} =~ /([0-9]+)/); if ($critical < $warning){ print "(--critical) must be superior to (--warning)"; print_usage(); exit $ERRORS{'UNKNOWN'}; } if (!$OPTION{'oid'}) { print "Option -o needed.\n"; exit $ERRORS{'UNKNOWN'}; } elsif (!($OPTION{'oid'} =~ /^[0-9\.]+$/)) { print "Wrong OID format\n"; exit $ERRORS{'UNKNOWN'}; } # Plugin snmp connection my ($session); if (!($session = Centreon::SNMP::Utils->connection($sessionType,\%OPTION))) { exit $ERRORS{'UNKNOWN'}; } # Get the value returned by OID my $result = $session->get_request(-varbindlist => [$OPTION{'oid'}]); if (!defined($result)) { printf("UNKNOWN: %s.\n", $session->error); $session->close; exit $ERRORS{'UNKNOWN'}; } $currentValue = $result->{$OPTION{'oid'}}; # Check if value returned is a number and then save it if(!defined($currentValue) || $currentValue =~ /noSuch/){ print("No instance on OID $OPTION{'oid'} \n "); exit $ERRORS{'UNKNOWN'}; } if (defined($currentValue)){ if ($currentValue !~ /^[-+]?[0-9]*\.?[0-9]*/) { print "Snmp returned value isn't numeric (signed/float values included) .\n"; exit $ERRORS{'UNKNOWN'}; } } # If metric type = counter, use the cache file to get the last value (or create cache file) if ($DS_type eq 'COUNTER') { #If file exist if (-e $cacheFile){ my @cache; open(FILE,"<".$cacheFile); my $countLine = 0; my $row = ; @cache = split(/\;/, $row); $previousTime = $cache[0]; $previousValue = $cache[1]; close(FILE); # Set new values in cache file open(FILE,">".$cacheFile); print FILE $currentTime.";".$currentValue; close(FILE); } else { #If the file doesnt exist, a new file is created and values are inserted unless (open(FILE,">".$cacheFile)){ print "Check temporary file's rights : ".$cacheFile."...\n"; exit $ERRORS{"UNKNOWN"}; } my $currentTime = time(); print FILE $currentTime.";".$currentValue; print("Buffer in creation . . . please wait \n"); exit $ERRORS{"OK"}; close(FILE); } } #=== Plugin return ==== if (defined($currentValue)){ my $returnValue = $currentValue; my $status = "UNKNOWN"; my $state= "unknownState"; $returnValue = 7 if($OPTION{'debug'}); ############################################################### # If personnal tresholds are set for warning and / or critical # ############################################################### if ($OPTION{'warning_table'} || $OPTION{'critical_table'} || $OPTION{'ok_table'}) { print "Mode personal threshold ON \n" if($OPTION{'debug'}); if ($OPTION{'ok_table'}) { my $max_ok= scalar(@ok_table); my $i = 0; while ($i < $max_ok) { print "OK[$i]: $ok_table[$i] / returnValue = $returnValue \n" if($OPTION{'debug'}); if($ok_table[$i] == $returnValue) { $status = "OK"; $state = $ok_table[$i+1]; } $i = $i+2; } } if ($OPTION{'warning_table'}){ my $max_warn= scalar(@warning_table); my $i = 0; while ($i < $max_warn) { print "Warning[$i]: $warning_table[$i] / returnValue = $returnValue \n" if($OPTION{'debug'}); if($warning_table[$i] == $returnValue) { $status = "WARNING"; $state = $warning_table[$i+1]; } $i = $i+2; } } if ($OPTION{'critical_table'}) { my $i = 0; my $max_crit= scalar(@critical_table); while ($i < $max_crit) { print "Critical[$i] = $critical_table[$i] / returnValue = $returnValue \n" if($OPTION{'debug'}); if ($critical_table[$i] == $returnValue) { $status = "CRITICAL"; $state = $critical_table[$i+1]; } $i = $i +2; } } print(" Statut = $status \n ") if($OPTION{'debug'}); printf($output."\n",$state,$returnValue); exit $ERRORS{$status}; } if ($DS_type eq 'COUNTER') { #calculate value for counter metric type # if counter has been reseted between 2 checks if ($currentValue - $previousValue < 0) { if (defined($OPTION{'64-bits'})) { $returnValue = ((18446744073709551616) - $previousValue + $currentValue)/($currentTime - $previousTime); } else { $returnValue = ((4294967296) - $previousValue + $currentValue) / ($currentTime - $previousTime); } } else { $returnValue = ($currentValue - $previousValue) / ($currentTime - $previousTime); } } my $i =0; my $perfdata = $returnValue; while ($returnValue > $OPTION{'base'}) { $returnValue = $returnValue / $OPTION{'base'}; $i++; } if($OPTION{'base'} == 1024){ $prefix = "ki" if($i == 1); $prefix = "Mi" if($i == 2); $prefix = "Gi" if($i == 3); $prefix = "Ti" if($i == 4); } if($OPTION{'base'} == 1000){ $prefix = "k" if($i == 1); $prefix = "M" if($i == 2); $prefix = "G" if($i == 3); $prefix = "T" if($i == 4); } if(defined($OPTION{'convert'})){ $warning = ($OPTION{'warning'} * $max)/100; $critical = ($OPTION{'critical'} * $max)/100; } else { $warning = $OPTION{'warning'}; $critical = $OPTION{'critical'}; } if ($perfdata < $warning) { printf("OK :".$output." ".$prefix." ".$unit."|".$metricsname."=".$perfdata.$unit.";".$warning.";".$critical.";".$min.";".$max."\n",$returnValue); $status = "OK"; exit $ERRORS{$status}; } elsif ($perfdata >= $warning && $perfdata < $critical) { printf("WARNING :".$output." ".$prefix.$unit."|".$metricsname."=".$perfdata.$unit.";".$warning.";".$critical.";".$min.";".$max."\n",$returnValue); $status = "WARNING"; exit $ERRORS{$status}; } elsif ($perfdata >= $critical) { printf("CRITICAL :".$output." ".$prefix.$unit."|".$metricsname."=".$perfdata.$unit.";".$warning.";".$critical.";".$min.";".$max."\n",$returnValue); $status = "CRITICAL"; exit $ERRORS{$status}; } } else { print "CRITICAL Host unavailable\n"; exit $ERRORS{'CRITICAL'}; } # Define Common functions sub print_usage () { print "Usage:"; print "$PROGNAME\n"; print " -H (--hostname) \t Hostname to query - (required)\n"; print " -C (--community) \t SNMP read community (defaults to public,\n"; print " \t \t used with SNMP v1 and v2c\n"; print " -v (--snmp_version) \t 1 for SNMP v1 (default)\n"; print " \t 2 for SNMP v2c\n"; print " -t (--type) \t Data Source Type (GAUGE or COUNTER) (GAUGE by default)\n"; print " -o (--oid) \t OID to check\n"; print " -u (--username) \t snmp v3 username \n"; print " -a (--authprotocol) \t protocol MD5/SHA1 (v3)\n"; print " -A (--authpassword) \t password (v3) \n"; print " -x (--privprotocol) \t encryption system (DES/AES)(v3) \n"; print " -X (--privpassword)\t passphrase (v3) \n"; print " -w (--warning) \t Warning level \n"; print " -c (--critical) \t Critical level \n"; print " -W (--wtreshold) \t Personal warning threshold : -W 1,normal,... \n"; print " -T (--ctreshold) \t Personal critical threshold : -T 3,notResponding,4,NotFunctionning,... \n"; print " --convert \t \t If critical and warning have to be converted regarding to the max value \n"; print " -m (--metric) \t Metric Name\n"; print " --64-bits \t \t If counter type to use = 64-bits \n"; print " -U (--unit) \t Metric's unit ( /!\\ for % write %% ) \n"; print " -f (--output) \t Output format (ex : -f \"My metric's percentage value = %f %%\" \n"; print " --min \t \t min value for the metric (default = 0) \n"; print " --max \t \t max value for the metric (default = 0)\n"; print " --base \t \t will divide the returned number by base until it's inferior to it. \n"; print " \t \t ex: 2000000 in base 1000 will be transformed to 2M (default 1000) \n"; print " -O (--ctreshold) \t Personal critical threshold : -O okstate1,okstate2... \n"; print " -V (--version) \t Plugin version\n"; print " -h (--help) \t usage help\n"; } sub print_help () { print "##############################################\n"; print "# Copyright (c) 2004-2011 Centreon #\n"; print "# Bugs to http://forge.centreon.com/ #\n"; print "##############################################\n"; print_usage(); print "\n"; }