#!/usr/bin/perl =pod =head1 NAME check_snmp_cisco_cpu.pl - Check CPU utilization on a Cisco device. =head1 SYNOPSIS This script will check the 5 minute CPU % utilization on a Cisco device. Specify thresholds for utilization with the warning and critical switches. The thresholds will be checked for each CPU on the device if the device has multiple CPUs. The script will output perfdata that also includes the 5 second and 1 minute CPU utilization metrics for the device. =cut # CISCO-PROCESS-MIB # * cpmCPUTotal5secRev: 1.3.6.1.4.1.9.9.109.1.1.1.1.6 # * cpmCPUTotal1minRev: 1.3.6.1.4.1.9.9.109.1.1.1.1.7 # * cpmCPUTotal5minRev: 1.3.6.1.4.1.9.9.109.1.1.1.1.8 # * cpmCPUTotalPhysicalIndex: 1.3.6.1.4.1.9.9.109.1.1.1.1.2 # # ENTITY-MIB (table) # * entPhysicalName: 1.3.6.1.2.1.47.1.1.1.1.7 # # Get 5 minute average, grab OID index for it, poll table # .1.3.6.1.4.1.9.9.109.1.1.1.1.2., if that OID has # a non-zero value, save the index OID and poll # .1.3.6.1.2.1.47.1.1.1.1.7. to get the human-readable # description of the component the CPU is on. # # If .1.3.6.1.4.1.9.9.109.1.1.1.1.2. returns a zero value # there is no mapping to a physical component description. sub check_snmp_cisco_cpu { use strict; use FindBin; use lib "$FindBin::Bin/lib"; use Nagios::Plugin::SNMP; use Nenm::Utils; my $LABEL = 'SNMP-CISCO-CPU'; my $USAGE = <new( 'shortname' => $LABEL, 'usage' => $USAGE ); $plugin->getopts; $Nenm::Utils::DEBUG = $plugin->opts->get('snmp-debug'); my $WARN = $plugin->opts->get('warning'); $plugin->nagios_die("Missing warning threshold!") unless $WARN; my $CRIT = $plugin->opts->get('critical'); $plugin->nagios_die("Missing critical threshold!") unless $CRIT; my %OIDS = qw( cpmCPUTotalPhysicalIndex 1.3.6.1.4.1.9.9.109.1.1.1.1.2 cpmCPUTotal5secRev 1.3.6.1.4.1.9.9.109.1.1.1.1.6 cpmCPUTotal1minRev 1.3.6.1.4.1.9.9.109.1.1.1.1.7 cpmCPUTotal5minRev 1.3.6.1.4.1.9.9.109.1.1.1.1.8 ); my %cpu; my $phys_results = $plugin->walk($OIDS{'cpmCPUTotalPhysicalIndex'}); delete $OIDS{'cpmCPUTOtalPhysicalIndex'}; my $phys_names = $phys_results->{$OIDS{'cpmCPUTotalPhysicalIndex'}}; my $cpu_counter = 0; for my $row (keys %$phys_names) { my $idx = ($row =~ m/^.+\.(\d+)$/)[0]; my $ent_name = "CPU_$cpu_counter"; Nenm::Utils::debug( "CPU index $idx has physical entity index $phys_names->{$row}"); if ($phys_names->{$row} > 0) { $ent_name = get_physical_name($plugin, $phys_names->{$row}); if ($ent_name eq 'CPU') { $ent_name = "CPU_$cpu_counter"; } } Nenm::Utils::debug("CPU index $idx now has cpuName $ent_name"); $cpu_counter++; $cpu{$idx} = { 'cpuName' => $ent_name }; } for my $oid (values %OIDS) { Nenm::Utils::debug("Walk OID $oid"); my $results = $plugin->walk($oid); for my $base_oid (keys %$results) { if (! defined $results->{$base_oid}) { $plugin->nagios_die("Device does not support CISCO-PROCESS-MIB") } my $idx = ($base_oid =~ m/^.+\.(\d+)$/)[0]; my %table = %{$results->{$base_oid}}; my $ent_name; for my $row (keys %table) { Nenm::Utils::debug("Received $row: $table{$row}"); my ($base, $entity) = ($row =~ m/^(.+)?\.(\d+)$/)[0,1]; for my $o (keys %OIDS) { my $v = $OIDS{$o}; if ($v eq $base) { Nenm::Utils::debug("Index $entity: $o = $table{$row}"); $cpu{$entity}->{$o} = $table{$row}; } } } } } # Check 5 min CPu value for all CPUs my $CRITICAL = $plugin->opts->get('critical'); my $WARNING = $plugin->opts->get('warning'); my @critical; my @warning; my @ok; for my $cpu_idx (keys %cpu) { my $cpu5min = $cpu{$cpu_idx}->{'cpmCPUTotal5minRev'}; my $name = $cpu{$cpu_idx}->{'cpuName'}; Nenm::Utils::debug("$name 5 minute utilization is $cpu5min"); if ($cpu5min > $CRITICAL) { push(@critical, "$name (${cpu5min}\% > ${CRITICAL}\%)"); } elsif ($cpu5min > $WARNING) { push(@warning, "$name (${cpu5min}\% > ${WARNING}\%)"); } else { push(@ok, "$name ${cpu5min}\%"); } } my $output = "$LABEL "; my $level = OK; if (scalar(@critical) > 0) { $output .= 'CRITICAL - ' . join(', ', @critical) . ' '; $level = CRITICAL; } if (scalar(@warning) > 0) { $output .= ' WARNING - ' . join(', ', @warning) . ' '; $level = WARNING unless $level == CRITICAL; } if (scalar(@ok) > 0) { $output .= ' OK - ' . join(', ', @ok); } print "$output | " . make_perfdata(\%cpu) . "\n"; return $level; sub get_physical_name { my $plugin = shift; my $idx = shift; my $oid = "1.3.6.1.2.1.47.1.1.1.1.7.$idx"; Nenm::Utils::debug("Getting physical name OID $oid"); my $result = $plugin->get($oid); my $name = $result->{$oid}; Nenm::Utils::debug("Physical name for index $idx is $name"); return $name; } sub make_perfdata { my $stats = shift; my $perfdata = ""; for my $cpu (keys %$stats) { my $name = lc($stats->{$cpu}->{'cpuName'}); $name =~ s/\s+/_/g; my $cpu5sec = $stats->{$cpu}->{'cpmCPUTotal5secRev'}; my $cpu1min = $stats->{$cpu}->{'cpmCPUTotal1minRev'}; my $cpu5min = $stats->{$cpu}->{'cpmCPUTotal5minRev'}; $perfdata .= "'${name}_5sec'=$cpu5sec;0;0 " . "'${name}_1min'=$cpu1min;0;0 " . "'${name}_5min'=$cpu5min;$WARNING;$CRITICAL "; } return $perfdata; } } exit check_snmp_cisco_cpu();