#!/usr/bin/perl -w # check_ont_condition - nagios plugin # # by Frank Bulk # # 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, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # use Net::Telnet::Cisco; use Getopt::Long; # change to your CMS' IP my $cms = '0.0.0.0'; # change to your CMS' username and password my @cms_node = ($cms, 'username', 'password', 0, 'CMS'); # list each *network* (not shelf) by it's name. Two examples are listed. my @networks = ('SHELF 200', 'NODE 100 VT'); my $network; my @shelves; my $shelf; my $Aid; my @temp_array; my @results; my $score = 0; my $total_score = 0; my $temp_score_ref = {}; my %score = ( CR => 0, MJ => 0, MN => 0, NA => 0, NR => 0, ); my %ERRORS = ( 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2', 'UNKNOWN' => '3', ); my $state = "UNKNOWN"; my $warn_level; my $critical_level; Getopt::Long::Configure("no_ignore_case"); my $status = GetOptions( "w|warn=i" => \$warn_level, "c|critical=i" => \$critical_level, ); if (!defined($warn_level)) { $warn_level = 2; } if (!defined($critical_level)) { $critical_level = 5; } $c = calix_login(0, @cms_node); if ($ARGV[0]) { @networks = $ARGV[0]; } foreach $network (@networks) { if ($ARGV[1]) { $shelves[0] = $ARGV[1]; } else { @shelves = get_calix_shelves($c, $network); } @shelves = unique_sort(@shelves); foreach $shelf (@shelves) { $Aid = $shelf . "-ALL"; ($temp_score_ref, @temp_array) = retrieve_cond_ont($c, $Aid); foreach my $key (keys %$temp_score_ref) { $score{$key} += $temp_score_ref->{$key}; } push(@results, @temp_array); } } @results = reverse sort @results; calix_logout(0, $c); if ($score{CR} || $score{MJ} || ($score{MN} >= $critical_level)) { $state = "CRITICAL"; } elsif ($total_score >= $warn_level) { $state = "WARNING"; } else { $state = "OK"; } print ("$state: Critical: $score{CR}; Major: $score{MJ}; Minor: $score{MN}\n"); print grep(!/Not Reported/, @results); print grep(/Not Reported/, @results); exit $ERRORS{$state}; exit; sub calix_login { ($print, @calix_node) = @_; my $login_count = 3; my $logged_in = 0; my $inhmsg_count = 3; my $inhibit_messages = 0; my $cmd_string = ''; my @empty; my @lines; if ($print) { print "Logging into $calix_node[4] Calix ($calix_node[0])..."; } my $c = Net::Telnet->new( Host => $calix_node[0], Port => 2626, ErrMode => 'return', Timeout => 15, TelnetMode => $calix_node[3], ); if (!$c) { print "\n\007Timed out trying to login to $calix_node[4] Calix ($calix_node[0])!\n"; return; } do { @empty = $c->waitfor('/> /'); $cmd_string = 'ACT-USER::' . $calix_node[1] . ':::' . $calix_node[2]; @lines = $c->cmd(String => $cmd_string, Prompt => '/;/'); foreach (@lines) { if ($_ =~ 'DENY') { $c->close; if ($print) { print "failed"; } $c = Net::Telnet->new( Host => $calix_node[0], Timeout => 15, TelnetMode => $calix_node[3], ); } if ($_ =~ 'COMPLD') { $logged_in = 1; } } $login_count--; @empty = $c->telnetmode(1); if ($print) { print '.'; } } while (($login_count) && (!$logged_in)); if (!$logged_in) { $c->close; die "\007failed, exiting!\n"; } do { @lines = $c->cmd(String => 'INH-MSG-ALL', Prompt => '/;/', ); foreach (@lines) { if ($_ =~ 'COMPLD') { $inhibit_messages = 1; } } $inhmsg_count--; if ($print) { print '.'; } } while (($inhmsg_count) && (!$inhibit_messages)); if (!$inhibit_messages) { $c->close; die "\007incomplete, exiting!\n"; } if ($print) { print "successful.\n\n"; } return $c; } sub calix_logout { my $print = shift; my $c = shift; if ($print) { print "Logging out..."; } my @nothing = $c->cmd(String => 'CANC-USER', Prompt => '/;/'); $c->close; return; } sub retrieve_cond_ont { my ($c, $Aid) = @_; my %NotificationConds = ( CR => 'Critical', MJ => 'Major', MN => 'Minor', NA => 'Not Alarmed', NR => 'Not Reported', ); my %CondTypeOnt = ( BADPID => 'ONT Password Mismatch.', BATMISS => 'Battery backup is enabled but not present.', BATTERY => 'Battery failure.', BE => 'Block error, upstream BIP8 error.', CPE => 'Cell Phase Error.', EQPT => 'Critical alarm caused by equipment failure.', EQPTCOMM => 'Equipment communications failure.', LCD => 'Loss of Cell Delineation.', LOA => 'Loss of ACK.', LOS => 'Loss of Signal.', LWBATVG => 'Low battery voltage.', MEA => 'Mismatch of equipment provisioning.', MEM => 'Message Error Message, unknown PLOAM message received from ONT.', NORMAL => 'Normal state.', OAML => 'Loss of PLOAM cells.', ONTDF => 'Deactivate Failure.', ONTDLFAIL => 'ONT software download failed.', OPENDR => 'Door or box open.', PEE => 'Physical Equipment Error.', POWER => 'Commercial power failure.', PROVFAIL => 'Provisioning Failure.', REI => 'Remote Error Indication, or downstream BIP8 error.', RFVIDRETLEOL => 'RF Video Return Laser End of Life', RINH => 'Receive Alarm Inhibit, ONT\'s dying grasp that it has departed due to loss of power without battery backup.', SDBER => 'Signal Degrade.', STF => 'ONT has failed autonomous self-test.', SUF => 'Startup Failure Indication.', SWDLINPROG => 'Software Download in Progress.', "T-BES" => 'Threshold violation for BIP8 Errored Seconds.', "T-BIP8" => 'Threshold violation for BIP8 errors.', "T-MES" => 'Threshold violation for Missing Errored Seconds.', "T-MISS" => 'Threshold violation for Missing Burst Errors.', "T-SES" => 'Threshold violation for BIP8 Severely Errored Seconds.', "T-UAS" => 'Threshold violation for BIP8 Unavailable Seconds.', VRPNOTSUPPORTED => 'Video Return Path Not Supported.', ); my %ServiceEffect = ( NSA => 'Non-Service affecting condition', SA => 'Service affecting condition', ); my @monthnames = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)); my $tmpvar1; my $tmpvar2; my @raw_array; my @temp_array; my @temp_array2; my $score_ref = {}; my $value; my $temp_string; my @temp_string_array; my $desc; my $NTFCNCDE; my $CONDTYPE; my $string = "RTRV-COND-ONT:" . $Aid; (my $network, undef) = split (/:/, $Aid); my @lines = $c->cmd(String => $string, Timeout => 30, Prompt => '/processed/'); foreach $line (@lines) { chomp $line; if ($line =~ /ONT/) { $line = trimwhitespace($line); $line = substr($line, 1); push (@raw_array, $line); } } foreach (@raw_array) { $desc = ''; chomp; @temp_array = split (/:/, $_); @temp_array2 = split (/,/, $temp_array[0]); my $port = $temp_array2[0]; @temp_array2 = split (/,|"/, $temp_array[1]); $value = $temp_array2[0]; $score_ref->{$value}++; if ($value =~ /CR|MJ|MN/) { $desc = find_calix_ont_info($c, $network, $port); } $NTFCNCDE = $NotificationConds{$value}; $value = $temp_array2[1]; if ($value) { $CONDTYPE = $CondTypeOnt{$value}; } else { $CONDTYPE = ''; } $value = $temp_array2[2]; if ($value) { $SRVEFF = $ServiceEffect{$value}; } else { $SRVEFF = ''; } (my $month, my $day) = split(/-/, $temp_array2[3]); my $time = $temp_array2[4]; $time =~ tr/-/:/; if ($desc) { $temp_string = "$month-$day $time $port ($desc) $NTFCNCDE: $CONDTYPE $SRVEFF\n"; } else { $temp_string = "$month-$day $time $port $NTFCNCDE: $CONDTYPE $SRVEFF\n"; } push (@temp_string_array, $temp_string); } return $score_ref, @temp_string_array; } sub trimwhitespace { my $string = shift; if ($string) { $string =~ s/^\s+//; $string =~ s/\s+$//; } else { $string = ''; } return $string; } sub get_calix_shelves { my $c = shift; my $network = shift; my $string; my @lines; my $shelf; my @return_array; $string = "RTRV-PON:" . $network . ":ALL"; @lines = $c->cmd(String => $string, Timeout => 30, Prompt => '/processed/'); foreach $line (@lines) { chomp $line; if ($line =~ /TYPE=GPON/) { (my @temp_array) = split (/"|-/, $line); $shelf = $network . ":" . join('-', @temp_array[1 .. 2]); push (@return_array, $shelf); } } return @return_array; } sub unique_sort { my @array = @_; my @temp_array; my $last_value = ''; my $i = 0; @array = sort(@array); foreach (@array) { if ($last_value ne $_) { $temp_array[$i] = $_; $last_value = $_; $i++; } } return @temp_array; } sub find_calix_ont_info { (my $c, my $network, my $Aid) = @_; my @lines; my $temp_str = ''; my @temp_array = ''; my $desc; my $string = "RTRV-ONT:" . $network . ":" . $Aid; @lines = $c->cmd(String => $string, Prompt => '/processed/'); foreach (@lines) { if ($_ =~ /$Aid:/) { (undef, undef, $temp_str) = split /:/; @temp_array = split (/,/, $temp_str); } } foreach (@temp_array) { if ($_ =~ 'DESC') { (undef, $desc, undef) = split /\\"/; } } if (!$desc) { $desc = find_calix_ont_eth_info($c, $network, $Aid); } return $desc; } sub find_calix_ont_eth_info { (my $c, my $network, my $Aid) = @_; my @lines = ''; my $temp_str = ''; my @temp_array = ''; my $i = 0; my $desc; my $string = "RTRV-ETH:" . $network . ":" . $Aid . "-ALL"; @lines = $c->cmd(String => $string, Prompt => '/processed/'); foreach (@lines) { if ($_ =~ /$Aid/) { (undef, undef, $temp_str) = split /:/; @temp_array = split (/,/, $temp_str); } } foreach (@temp_array) { if ($_ =~ 'DESC') { (undef, $desc, undef) = split /\\"/; } } return $desc; }