508 lines
14 KiB
Perl
Executable File
508 lines
14 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
|
|
#####################################
|
|
#####################################
|
|
### ______ _ =) ###
|
|
### | ___ \ | | ###
|
|
### | |_/ / __ _ _ __ | | ###
|
|
### | / / _` || '_ \ | | ###
|
|
### | |\ \| (_| || | | || |____ ###
|
|
### \_| \_|\__,_||_| |_|\_____/ ###
|
|
#####################################
|
|
#####################################
|
|
|
|
use strict;
|
|
use Net::SNMP;
|
|
my $stat;
|
|
my $msg;
|
|
my $perf;
|
|
my $days = 14;
|
|
my $script_name = "check-cisco.pl";
|
|
|
|
### SNMP OIDs
|
|
###############
|
|
# Temperature
|
|
my $S_temp = ".1.3.6.1.4.1.9.9.13.1.3.1.3";
|
|
# Memory
|
|
my $S_mem_used = ".1.3.6.1.4.1.9.9.48.1.1.1.5.1"; # Byte
|
|
my $S_mem_free = ".1.3.6.1.4.1.9.9.48.1.1.1.6.1"; # Byte
|
|
# CPU Load
|
|
my $S_load_5s = ".1.3.6.1.4.1.9.2.1.56.0";
|
|
my $S_load_1m = ".1.3.6.1.4.1.9.2.1.57.0";
|
|
my $S_load_5m = ".1.3.6.1.4.1.9.2.1.58.0";
|
|
# Power Supply
|
|
my $S_ps = ".1.3.6.1.4.1.9.9.13.1.5.1";
|
|
my $S_ps_name = "$S_ps.2";
|
|
my $S_ps_stat = "$S_ps.3";
|
|
# Fan
|
|
my $S_fan = ".1.3.6.1.4.1.9.9.13.1.4.1";
|
|
my $S_fan_name = "$S_fan.2";
|
|
my $S_fan_stat = "$S_fan.3";
|
|
# Module
|
|
my $S_module_status = ".1.3.6.1.4.1.9.9.117.1.2.1.1.2";
|
|
# Interfaces
|
|
my $S_int_entry = ".1.3.6.1.2.1.2.2.1";
|
|
my $S_int_desc = "$S_int_entry.2";
|
|
my $S_int_adminstatus = "$S_int_entry.7";
|
|
my $S_int_operstatus = "$S_int_entry.8";
|
|
my $S_int_lastchange = "$S_int_entry.9";
|
|
my $S_int_InOctets = "$S_int_entry.10";
|
|
my $S_int_OutOctets = "$S_int_entry.16";
|
|
my $S_int_number = ".1.3.6.1.2.1.2.1.0";
|
|
|
|
# SNMP Status Codes
|
|
my %phy_dev_status = (
|
|
1 => 'normal',
|
|
2 => 'warning',
|
|
3 => 'critical',
|
|
4 => 'shutdown',
|
|
5 => 'notPresent',
|
|
6 => 'notFunctioning',
|
|
);
|
|
my %module_status_code = (
|
|
1 => 'unknown',
|
|
2 => 'ok',
|
|
3 => 'disabled',
|
|
4 => 'okButDiagFailed',
|
|
5 => 'boot',
|
|
6 => 'selfTest',
|
|
7 => 'failed',
|
|
8 => 'missing',
|
|
9 => 'mismatchWithParent',
|
|
10 => 'mismatchConfig',
|
|
11 => 'diagFailed',
|
|
12 => 'dormant',
|
|
13 => 'outOfServiceAdmin',
|
|
14 => 'outOfServiceEnvTemp',
|
|
15 => 'poweredDown',
|
|
16 => 'poweredUp',
|
|
17 => 'powerDenied',
|
|
18 => 'powerCycled',
|
|
19 => 'okButPowerOverWarning',
|
|
20 => 'okButPowerOverCritical',
|
|
21 => 'syncInProgress',
|
|
);
|
|
my %int_status_index = (
|
|
1 => 'up',
|
|
2 => 'down',
|
|
3 => 'testing',
|
|
4 => 'unknown',
|
|
5 => 'notPresent',
|
|
6 => 'lowerLayerDown',
|
|
);
|
|
|
|
### Functions
|
|
###############
|
|
sub _create_session {
|
|
my ($server, $comm) = @_;
|
|
my $version = 1;
|
|
my ($sess, $err) = Net::SNMP->session( -hostname => $server, -version => $version, -community => $comm);
|
|
if (!defined($sess)) {
|
|
print "Can't create SNMP session to $server\n";
|
|
exit(1);
|
|
}
|
|
return $sess;
|
|
}
|
|
|
|
sub FSyntaxError {
|
|
print "Syntax Error !\n";
|
|
# print "$0 -H [ip|dnsname] -C [snmp community] -t [temp|fan|ps|cpu|mem|module|freeint] -w [warning value] -c [critical value] -d [days]\n";
|
|
print "$script_name\n";
|
|
print "-H = Ip/Dns Name of the Switch\n";
|
|
print "-C = SNMP Community\n";
|
|
print "-t = Check type\n";
|
|
print "\ttemp - Temperature\n";
|
|
print "\tfan - Fan Fail\n";
|
|
print "\tps - Power Supply Fail\n";
|
|
print "\tcpu - CPU Load\n";
|
|
print "\tmem - Memory\n";
|
|
print "\tmodule - Module Health\n";
|
|
print "\tfreeint - Free eth interfaces for X days (-d)\n";
|
|
print "\tint - Interface Operation Stat (use with -i or -o)\n";
|
|
print "-w = Warning Value\n";
|
|
print "-c = Critical Value\n";
|
|
print "-d = number of days that th ethernet interface hasn't change state, default is 14 (only for -t freeint)\n";
|
|
print "-i = Interface Name (only for -t int)\n";
|
|
print "-o = Interface OID (only for -t int)\n";
|
|
exit(3);
|
|
}
|
|
|
|
if($#ARGV < 5 or $#ARGV > 11) {
|
|
FSyntaxError;
|
|
}
|
|
|
|
### Gather input from user
|
|
#############################
|
|
my $switch;
|
|
my $community;
|
|
my $check_type;
|
|
my $warn = 0;
|
|
my $crit = 0;
|
|
my $int;
|
|
my $oidint;
|
|
|
|
while(@ARGV) {
|
|
my $temp = shift(@ARGV);
|
|
if("$temp" eq '-H') {
|
|
$switch = shift(@ARGV);
|
|
} elsif("$temp" eq '-C') {
|
|
$community = shift(@ARGV);
|
|
} elsif("$temp" eq '-t') {
|
|
$check_type = shift(@ARGV);
|
|
} elsif("$temp" eq '-w') {
|
|
$warn = shift(@ARGV);
|
|
} elsif("$temp" eq '-c') {
|
|
$crit = shift(@ARGV);
|
|
} elsif("$temp" eq '-i') {
|
|
$int = shift(@ARGV);
|
|
} elsif("$temp" eq '-o') {
|
|
$oidint = shift(@ARGV);
|
|
} elsif("$temp" eq '-d') {
|
|
$days = shift(@ARGV);
|
|
if("$days" eq "") {
|
|
$days = 14;
|
|
}
|
|
} else {
|
|
FSyntaxError();
|
|
}
|
|
}
|
|
|
|
# Validate Warning
|
|
if("$check_type" ne "temp") {
|
|
if($warn > $crit and "$check_type" ne "freeint" and "$check_type" ne "mem") {
|
|
print "Warning can't be larger then Critical: $warn > $crit\n";
|
|
FSyntaxError();
|
|
} elsif($warn < $crit and "$check_type" eq "freeint") {
|
|
print "Warning can't be smaller then Critical: $warn < $crit in intfree check\n";
|
|
FSyntaxError();
|
|
} elsif($warn < $crit and "$check_type" eq "mem") {
|
|
print "Warning can't be smaller then Critical: $warn < $crit in intfree check\n";
|
|
FSyntaxError();
|
|
}
|
|
}
|
|
|
|
# Establish SNMP Session
|
|
our $snmp_session = _create_session($switch,$community);
|
|
|
|
### Temperature ###
|
|
if($check_type =~ /^temp/) {
|
|
my $temp;
|
|
my $R_tbl = $snmp_session->get_table($S_temp);
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
$temp = "$$R_tbl{$oid}";
|
|
last;
|
|
}
|
|
|
|
if("$temp" eq "") {
|
|
print "The switch $switch can't report temperature via SNMP\n";
|
|
FSyntaxError();
|
|
}
|
|
|
|
if($temp > 1) {
|
|
if($warn > $crit and "$check_type") {
|
|
print "Warning can't be larger then Critical: $warn > $crit\n";
|
|
FSyntaxError();
|
|
}
|
|
if($temp <= $warn) {
|
|
$stat = 0;
|
|
$msg = "Temperature: OK - Temperature is $temp Celsius";
|
|
} elsif($temp > $warn and $temp < $crit) {
|
|
$stat = 1;
|
|
$msg = "Temperature: Warn - Temperature is $temp Celsius";
|
|
} elsif($temp >= $crit) {
|
|
$stat = 2;
|
|
$msg = "Temperature: CRIT - Tempeture is $temp Celsius";
|
|
}
|
|
$perf = "temperature=$temp;$warn;$crit";
|
|
} else {
|
|
if($warn > 0 or $crit > 0) {
|
|
print "ERR:\nSome switches only show boolean value 0=OK 1=ERROR\nplease dont use -w and -c arguments\n\n";
|
|
FSyntaxError();
|
|
}
|
|
if($temp == 1) {
|
|
$stat = 0;
|
|
$msg = "Temperature: OK";
|
|
} else {
|
|
$stat = 2;
|
|
$msg = "Temperature: CRIT";
|
|
}
|
|
$perf = "temperature=$temp";
|
|
}
|
|
|
|
### Memory ###
|
|
|
|
} elsif($check_type eq "mem") {
|
|
my $R_mem_used = $snmp_session->get_request(-varbindlist => [$S_mem_used]);
|
|
my $mem_used = "$R_mem_used->{$S_mem_used}";
|
|
my $R_mem_free = $snmp_session->get_request(-varbindlist => [$S_mem_free]);
|
|
my $mem_free = "$R_mem_free->{$S_mem_free}";
|
|
my $mem_total = $mem_free + $mem_used;
|
|
|
|
$mem_used = int($mem_used / 1024 / 1024);
|
|
$mem_free = int($mem_free / 1024 / 1024);
|
|
$mem_total = int($mem_total / 1024 / 1024);
|
|
|
|
my $mem_free_perc = int($mem_free / $mem_total * 100);
|
|
|
|
if($mem_free_perc > $warn) {
|
|
$stat = 0;
|
|
$msg = "Memory: OK - Free Memory $mem_free_perc%";
|
|
} elsif($mem_free_perc <= $warn and $mem_free_perc > $crit) {
|
|
$stat = 1;
|
|
$msg = "Memory: Warn - Free Memory $mem_free_perc %";
|
|
} elsif($mem_free_perc <= $crit) {
|
|
$stat = 2;
|
|
$msg = "Memory: CRIT - Free Memory $mem_free_perc %";
|
|
}
|
|
|
|
$perf = "memory_total=$mem_total\MB memory_used=$mem_used\MB";
|
|
|
|
### Interface Stat ###
|
|
|
|
} elsif($check_type eq "int") {
|
|
my $R_tbl;
|
|
if ($oidint) {
|
|
$R_tbl = $snmp_session->get_request(-varbindlist => ["$oidint"]);
|
|
$int = $$R_tbl{"$oidint"};
|
|
} else {
|
|
$R_tbl = $snmp_session->get_table($S_int_desc);
|
|
}
|
|
my $is_int_exists = 0;
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
my $name = "$$R_tbl{$oid}";
|
|
if($name eq $int) {
|
|
$is_int_exists++;
|
|
my $id = "$oid";
|
|
$id =~ s/$S_int_desc\.//;
|
|
my $R_stat = $snmp_session->get_request(-varbindlist => ["$S_int_operstatus.$id"]);
|
|
my $int_stat = $R_stat->{"$S_int_operstatus.$id"};
|
|
if($int_stat != 1) {
|
|
$stat = 2;
|
|
$msg = "CRIT: $int -> $int_status_index{$int_stat}";
|
|
$perf = "int=0";
|
|
} else {
|
|
$stat = 0;
|
|
$msg = "OK: $int -> $int_status_index{$int_stat}";
|
|
$perf = "int=1";
|
|
}
|
|
last;
|
|
}
|
|
|
|
}
|
|
|
|
if($is_int_exists == 0) {
|
|
$stat = 3;
|
|
$msg = "UNKNOWN: $int does not exists";
|
|
$perf = "int=0";
|
|
}
|
|
|
|
### CPU Load ###
|
|
|
|
} elsif($check_type eq "cpu") {
|
|
my $R_load_5s = $snmp_session->get_request(-varbindlist => [$S_load_5s]);
|
|
my $load_5s = "$R_load_5s->{$S_load_5s}";
|
|
my $R_load_1m = $snmp_session->get_request(-varbindlist => [$S_load_1m]);
|
|
my $load_1m = "$R_load_1m->{$S_load_1m}";
|
|
my $R_load_5m = $snmp_session->get_request(-varbindlist => [$S_load_5m]);
|
|
my $load_5m = "$R_load_5m->{$S_load_5m}";
|
|
|
|
if($load_5s <= $warn) {
|
|
$stat = 0;
|
|
$msg = "Cpu: OK - Cpu Load $load_5s% $load_1m% $load_5m%";
|
|
} elsif($load_5s > $warn and $load_5s < $crit) {
|
|
$stat = 1;
|
|
$msg = "Cpu: Warn - Cpu Load $load_5s% $load_1m% $load_5m%";
|
|
} elsif($load_5s >= $crit) {
|
|
$stat = 2;
|
|
$msg = "Cpu: CRIT - Cpu Load $load_5s% $load_1m% $load_5m%";
|
|
}
|
|
|
|
$perf = "cpu_5s=$load_5s\percent;$warn;$crit cpu_1m=$load_1m\percent cpu_5m=$load_5m\percent";
|
|
|
|
### Fan Status ###
|
|
|
|
} elsif($check_type eq "fan") {
|
|
my $R_tbl = $snmp_session->get_table($S_fan_name);
|
|
my $total_err = 0;
|
|
my $err_msg;
|
|
my $sum = 0;
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
$sum = $sum + 1;
|
|
my $name = "$$R_tbl{$oid}";
|
|
my $id = "$oid";
|
|
$id =~ s/$S_fan_name\.//;
|
|
my $R_stat = $snmp_session->get_request(-varbindlist => ["$S_fan_stat.$id"]);
|
|
my $stat = $R_stat->{"$S_fan_stat.$id"};
|
|
if($stat != 1) {
|
|
$total_err = $total_err + 1;
|
|
$err_msg = "$err_msg $name -> $phy_dev_status{$stat}";
|
|
}
|
|
}
|
|
|
|
if($total_err != 0) {
|
|
$err_msg = ", $err_msg have an error";
|
|
} else {
|
|
$err_msg = "all good";
|
|
}
|
|
|
|
if($total_err <= $warn) {
|
|
$stat = 0;
|
|
$msg = "Fans: OK - $sum Fans are running $err_msg";
|
|
} elsif($total_err > $warn and $total_err < $crit) {
|
|
$stat = 1;
|
|
$msg = "Fans: Warn - $sum Fans are running $err_msg";
|
|
} elsif($total_err >= $crit) {
|
|
$stat = 2;
|
|
$msg = "Fans: Crit - $sum Fans are running $err_msg";
|
|
}
|
|
|
|
$perf = "total=$sum err=$total_err";
|
|
|
|
### Power Supplies ###
|
|
|
|
} elsif($check_type eq "ps") {
|
|
my $R_tbl = $snmp_session->get_table($S_ps_name);
|
|
my $total_err = 0;
|
|
my $err_msg;
|
|
my $sum = 0;
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
$sum = $sum + 1;
|
|
my $name = "$$R_tbl{$oid}";
|
|
my $id = "$oid";
|
|
$id =~ s/$S_ps_name\.//;
|
|
my $R_stat = $snmp_session->get_request(-varbindlist => ["$S_ps_stat.$id"]);
|
|
my $stat = $R_stat->{"$S_ps_stat.$id"};
|
|
if($stat != 1) {
|
|
$total_err = $total_err + 1;
|
|
$err_msg = "$err_msg $name -> $phy_dev_status{$stat}";
|
|
}
|
|
}
|
|
|
|
if($total_err != 0) {
|
|
$err_msg = ", $err_msg have an error";
|
|
} else {
|
|
$err_msg = "all good";
|
|
}
|
|
|
|
if($total_err <= $warn) {
|
|
$stat = 0;
|
|
$msg = "PS: OK - $sum PS are running $err_msg";
|
|
} elsif($total_err > $warn and $total_err < $crit) {
|
|
$stat = 1;
|
|
$msg = "PS: Warn - $sum PS are running $err_msg";
|
|
} elsif($total_err >= $crit) {
|
|
$stat = 2;
|
|
$msg = "PS: Crit - $sum PS are running $err_msg";
|
|
}
|
|
|
|
$perf = "total=$sum err=$total_err";
|
|
|
|
### Module Status ###
|
|
|
|
} elsif($check_type eq "module") {
|
|
my $R_tbl = $snmp_session->get_table($S_module_status);
|
|
my $total_err = 0;
|
|
my $err_msg;
|
|
my $sum = 0;
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
$sum = $sum + 1;
|
|
my $module_status = "$$R_tbl{$oid}";
|
|
my $id = "$oid";
|
|
$id =~ s/$S_module_status\.//;
|
|
if($module_status != 2) {
|
|
$total_err = $total_err + 1;
|
|
$err_msg = "$err_msg $id -> $module_status_code{$module_status}";
|
|
}
|
|
}
|
|
|
|
if($sum == 0) {
|
|
print "The switch $switch doesn't have any modules\n";
|
|
FSyntaxError();
|
|
}
|
|
|
|
if($total_err != 0) {
|
|
$err_msg = ", $err_msg have an error";
|
|
} else {
|
|
$err_msg = "all good";
|
|
}
|
|
|
|
if($total_err <= $warn) {
|
|
$stat = 0;
|
|
$msg = "Modules: OK - $sum Modules are running $err_msg";
|
|
} elsif($total_err > $warn and $total_err < $crit) {
|
|
$stat = 1;
|
|
$msg = "Modules: Warn - $sum Modules are running $err_msg";
|
|
} elsif($total_err >= $crit) {
|
|
$stat = 2;
|
|
$msg = "Modules: Crit - $sum Modules are running $err_msg";
|
|
}
|
|
|
|
$perf = "total=$sum err=$total_err";
|
|
|
|
### Free Interfaces ###
|
|
|
|
} elsif($check_type eq "freeint") {
|
|
|
|
my $R_int_number = $snmp_session->get_request(-varbindlist => [$S_int_number]);
|
|
my $int_number = $R_int_number->{$S_int_number};
|
|
|
|
my $R_tbl = $snmp_session->get_table($S_int_desc);
|
|
my @ints;
|
|
my $down = 0;
|
|
my $sum = 0;
|
|
|
|
foreach my $oid ( keys %$R_tbl) {
|
|
if($$R_tbl{$oid} =~ /Ethernet/) {
|
|
$sum++;
|
|
my $id = "$oid";
|
|
$id =~ s/$S_int_desc\.//;
|
|
|
|
# Admin Status
|
|
my $R_int_adminstatus = $snmp_session->get_request(-varbindlist => ["$S_int_adminstatus.$id"]);
|
|
my $int_adminstatus = $R_int_adminstatus->{"$S_int_adminstatus.$id"};
|
|
# Oper Status
|
|
my $R_int_operstatus = $snmp_session->get_request(-varbindlist => ["$S_int_operstatus.$id"]);
|
|
my $int_operstatus = $R_int_operstatus->{"$S_int_operstatus.$id"};
|
|
# Inbout
|
|
my $R_int_InOctets = $snmp_session->get_request(-varbindlist => ["$S_int_InOctets.$id"]);
|
|
my $int_InOctets = $R_int_InOctets->{"$S_int_InOctets.$id"};
|
|
# Outbound
|
|
my $R_int_OutOctets = $snmp_session->get_request(-varbindlist => ["$S_int_OutOctets.$id"]);
|
|
my $int_OutOctets = $R_int_OutOctets->{"$S_int_OutOctets.$id"};
|
|
# Last Change
|
|
my $R_int_lastchange = $snmp_session->get_request(-varbindlist => ["$S_int_lastchange.$id"]);
|
|
my $int_lastchange = $R_int_lastchange->{"$S_int_lastchange.$id"};
|
|
my @lastchanged = split(" ",$int_lastchange);
|
|
|
|
if($int_adminstatus == 2 or $int_operstatus == 2) {
|
|
if(("$lastchanged[1]" eq "days," and $lastchanged[1] => $days) or ($int_OutOctets == 0 and $int_InOctets == 0)) {
|
|
$down++;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if($down >= $warn) {
|
|
$stat = 0;
|
|
$msg = "Free Interfaces: OK - $down/$sum free interfaces for $days days";
|
|
} elsif($down < $warn and $down > $crit) {
|
|
$stat = 1;
|
|
$msg = "Free Interfaces: Warn - $down/$sum free interfaces for $days days";
|
|
} elsif($down <= $crit) {
|
|
$stat = 2;
|
|
$msg = "Free Interfaces: CRIT - $down/$sum free interfaces for $days days";
|
|
}
|
|
|
|
$perf = "total_int=$int_number total_eth=$sum total_eth_free=$down";
|
|
|
|
### Bad Syntax ###
|
|
|
|
} else {
|
|
FSyntaxError();
|
|
}
|
|
|
|
|
|
print "$msg | $perf\n";
|
|
exit($stat);
|