PageRenderTime 60ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 2ms

/check_nwc_health

https://github.com/bigbrozer/netplugins
Perl | 8210 lines | 7207 code | 735 blank | 268 comment | 541 complexity | c44bbd95e4109065b20a9f1f133f9323 MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. #! /usr/bin/perl -w
  2. package Nagios::MiniPlugin;
  3. use strict;
  4. use Getopt::Long qw(:config no_ignore_case bundling);
  5. our @STATUS_CODES = qw(OK WARNING CRITICAL UNKNOWN DEPENDENT);
  6. require Exporter;
  7. our @ISA = qw(Exporter);
  8. our @EXPORT = (@STATUS_CODES, qw(nagios_exit nagios_die check_messages));
  9. our @EXPORT_OK = qw(%ERRORS);
  10. use constant OK => 0;
  11. use constant WARNING => 1;
  12. use constant CRITICAL => 2;
  13. use constant UNKNOWN => 3;
  14. use constant DEPENDENT => 4;
  15. our %ERRORS = (
  16. 'OK' => OK,
  17. 'WARNING' => WARNING,
  18. 'CRITICAL' => CRITICAL,
  19. 'UNKNOWN' => UNKNOWN,
  20. 'DEPENDENT' => DEPENDENT,
  21. );
  22. our %STATUS_TEXT = reverse %ERRORS;
  23. sub new {
  24. my $class = shift;
  25. my %params = @_;
  26. my $self = {
  27. perfdata => [],
  28. messages => {
  29. ok => [],
  30. warning => [],
  31. critical => [],
  32. unknown => [],
  33. },
  34. args => [],
  35. opts => Nagios::MiniPlugin::Getopt->new(%params),
  36. };
  37. foreach (qw(shortname usage version url plugin blurb extra
  38. license timeout)) {
  39. $self->{$_} = $params{$_};
  40. }
  41. bless $self, $class;
  42. }
  43. sub add_arg {
  44. my $self = shift;
  45. $self->{opts}->add_arg(@_);
  46. }
  47. sub getopts {
  48. my $self = shift;
  49. $self->{opts}->getopts();
  50. }
  51. sub override_opt {
  52. my $self = shift;
  53. $self->{opts}->override_opt(@_);
  54. }
  55. sub opts {
  56. my $self = shift;
  57. return $self->{opts};
  58. }
  59. sub add_message {
  60. my $self = shift;
  61. my ($code, @messages) = @_;
  62. $code = (qw(ok warning critical unknown))[$code] if $code =~ /^\d+$/;
  63. $code = lc $code;
  64. push @{$self->{messages}->{$code}}, @messages;
  65. }
  66. sub add_perfdata {
  67. my ($self, %args) = @_;
  68. #if ($args{label} =~ /\s/) {
  69. $args{label} = '\''.$args{label}.'\'';
  70. #}
  71. if (! exists $args{places}) {
  72. $args{places} = 2;
  73. }
  74. my $format = '%d';
  75. if ($args{value} =~ /\./) {
  76. $format = '%.'.$args{places}.'f';
  77. }
  78. my $str = $args{label}.'='.sprintf $format, $args{value};
  79. if ($args{uom}) {
  80. $str .= $args{uom};
  81. }
  82. if ($args{warning}) {
  83. $str .= ';'.$args{warning};
  84. }
  85. if ($args{critical}) {
  86. $str .= ';'.$args{critical};
  87. }
  88. push @{$self->{perfdata}}, $str;
  89. }
  90. sub clear_messages {
  91. my $self = shift;
  92. my $code = shift;
  93. $code = (qw(ok warning critical unknown))[$code] if $code =~ /^\d+$/;
  94. $code = lc $code;
  95. $self->{messages}->{$code} = [];
  96. }
  97. sub check_messages {
  98. my $self = shift;
  99. my %args = @_;
  100. # Add object messages to any passed in as args
  101. for my $code (qw(critical warning unknown ok)) {
  102. my $messages = $self->{messages}->{$code} || [];
  103. if ($args{$code}) {
  104. unless (ref $args{$code} eq 'ARRAY') {
  105. if ($code eq 'ok') {
  106. $args{$code} = [ $args{$code} ];
  107. }
  108. }
  109. push @{$args{$code}}, @$messages;
  110. } else {
  111. $args{$code} = $messages;
  112. }
  113. }
  114. my %arg = %args;
  115. $arg{join} = ' ' unless defined $arg{join};
  116. # Decide $code
  117. my $code = OK;
  118. $code ||= CRITICAL if @{$arg{critical}};
  119. $code ||= WARNING if @{$arg{warning}};
  120. $code ||= UNKNOWN if @{$arg{unknown}};
  121. return $code unless wantarray;
  122. # Compose message
  123. my $message = '';
  124. if ($arg{join_all}) {
  125. $message = join( $arg{join_all},
  126. map { @$_ ? join( $arg{'join'}, @$_) : () }
  127. $arg{critical},
  128. $arg{warning},
  129. $arg{unknown},
  130. $arg{ok} ? (ref $arg{ok} ? $arg{ok} : [ $arg{ok} ]) : []
  131. );
  132. }
  133. else {
  134. $message ||= join( $arg{'join'}, @{$arg{critical}} )
  135. if $code == CRITICAL;
  136. $message ||= join( $arg{'join'}, @{$arg{warning}} )
  137. if $code == WARNING;
  138. $message ||= join( $arg{'join'}, @{$arg{unknown}} )
  139. if $code == UNKNOWN;
  140. $message ||= ref $arg{ok} ? join( $arg{'join'}, @{$arg{ok}} ) : $arg{ok}
  141. if $arg{ok};
  142. }
  143. return ($code, $message);
  144. }
  145. sub nagios_exit {
  146. my $self = shift;
  147. my ($code, $message, $arg) = @_;
  148. $code = $ERRORS{$code} if defined $code && exists $ERRORS{$code};
  149. $code = UNKNOWN unless defined $code && exists $STATUS_TEXT{$code};
  150. $message = '' unless defined $message;
  151. if (ref $message && ref $message eq 'ARRAY') {
  152. $message = join(' ', map { chomp; $_ } @$message);
  153. } else {
  154. chomp $message;
  155. }
  156. my $output = "$STATUS_TEXT{$code}";
  157. $output .= " - $message" if defined $message && $message ne '';
  158. if (scalar (@{$self->{perfdata}})) {
  159. $output .= " | ".join(" ", @{$self->{perfdata}});
  160. }
  161. $output .= "\n";
  162. print $output;
  163. exit $code;
  164. }
  165. sub set_thresholds {
  166. my $self = shift;
  167. my %params = @_;
  168. $self->{mywarning} = $self->opts->warning || $params{warning} || 0;
  169. $self->{mycritical} = $self->opts->critical || $params{critical} || 0;
  170. }
  171. sub get_thresholds {
  172. my $self = shift;
  173. return ($self->{mywarning}, $self->{mycritical});
  174. }
  175. sub check_thresholds {
  176. my $self = shift;
  177. my @params = @_;
  178. my $level = $ERRORS{OK};
  179. my $warningrange;
  180. my $criticalrange;
  181. my $value;
  182. if (scalar(@params) > 1) {
  183. my %params = @params;
  184. $value = $params{check};
  185. $warningrange = (defined $params{warning}) ?
  186. $params{warning} : $self->{mywarning};
  187. $criticalrange = (defined $params{critical}) ?
  188. $params{critical} : $self->{mycritical};
  189. } else {
  190. $value = $params[0];
  191. $warningrange = $self->{mywarning};
  192. $criticalrange = $self->{mycritical};
  193. }
  194. if ($warningrange !~ /:/ && $criticalrange !~ /:/) {
  195. # warning = 10, critical = 20, warn if > 10, crit if > 20
  196. $level = $ERRORS{WARNING} if $value > $warningrange;
  197. $level = $ERRORS{CRITICAL} if $value > $criticalrange;
  198. } elsif ($warningrange =~ /(\d+):/ &&
  199. $criticalrange =~ /(\d+):/) {
  200. # warning = 98:, critical = 95:, warn if < 98, crit if < 95
  201. $warningrange =~ /(\d+):/;
  202. $level = $ERRORS{WARNING} if $value < $1;
  203. $criticalrange =~ /(\d+):/;
  204. $level = $ERRORS{CRITICAL} if $value < $1;
  205. }
  206. return $level;
  207. #
  208. # syntax error must be reported with returncode -1
  209. #
  210. }
  211. package Nagios::MiniPlugin::Getopt;
  212. use strict;
  213. use File::Basename;
  214. use Data::Dumper;
  215. use Getopt::Long qw(:config no_ignore_case bundling);
  216. # Standard defaults
  217. my %DEFAULT = (
  218. timeout => 15,
  219. verbose => 0,
  220. license =>
  221. "This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
  222. It may be used, redistributed and/or modified under the terms of the GNU
  223. General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).",
  224. );
  225. # Standard arguments
  226. my @ARGS = ({
  227. spec => 'usage|?',
  228. help => "-?, --usage\n Print usage information",
  229. }, {
  230. spec => 'help|h',
  231. help => "-h, --help\n Print detailed help screen",
  232. }, {
  233. spec => 'version|V',
  234. help => "-V, --version\n Print version information",
  235. }, {
  236. #spec => 'extra-opts:s@',
  237. #help => "--extra-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load extra options (may repeat)",
  238. }, {
  239. spec => 'timeout|t=i',
  240. help => sprintf("-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)", $DEFAULT{timeout}),
  241. default => $DEFAULT{timeout},
  242. }, {
  243. spec => 'verbose|v+',
  244. help => "-v, --verbose\n Show details for command-line debugging (can repeat up to 3 times)",
  245. default => $DEFAULT{verbose},
  246. },
  247. );
  248. # Standard arguments we traditionally display last in the help output
  249. my %DEFER_ARGS = map { $_ => 1 } qw(timeout verbose);
  250. sub _init
  251. {
  252. my $self = shift;
  253. my %params = @_;
  254. # Check params
  255. my $plugin = basename($ENV{NAGIOS_PLUGIN} || $0);
  256. #my %attr = validate( @_, {
  257. my %attr = (
  258. usage => 1,
  259. version => 0,
  260. url => 0,
  261. plugin => { default => $plugin },
  262. blurb => 0,
  263. extra => 0,
  264. 'extra-opts' => 0,
  265. license => { default => $DEFAULT{license} },
  266. timeout => { default => $DEFAULT{timeout} },
  267. );
  268. # Add attr to private _attr hash (except timeout)
  269. $self->{timeout} = delete $attr{timeout};
  270. $self->{_attr} = { %attr };
  271. foreach (keys %{$self->{_attr}}) {
  272. if (exists $params{$_}) {
  273. $self->{_attr}->{$_} = $params{$_};
  274. } else {
  275. $self->{_attr}->{$_} = $self->{_attr}->{$_}->{default}
  276. if ref ($self->{_attr}->{$_}) eq 'HASH' &&
  277. exists $self->{_attr}->{$_}->{default};
  278. }
  279. }
  280. # Chomp _attr values
  281. chomp foreach values %{$self->{_attr}};
  282. # Setup initial args list
  283. $self->{_args} = [ grep { exists $_->{spec} } @ARGS ];
  284. $self
  285. }
  286. sub new
  287. {
  288. my $class = shift;
  289. my $self = bless {}, $class;
  290. $self->_init(@_);
  291. }
  292. sub add_arg {
  293. my $self = shift;
  294. my %arg = @_;
  295. push (@{$self->{_args}}, \%arg);
  296. }
  297. sub getopts {
  298. my $self = shift;
  299. my %commandline = ();
  300. my @params = map { $_->{spec} } @{$self->{_args}};
  301. if (! GetOptions(\%commandline, @params)) {
  302. $self->print_help();
  303. exit 0;
  304. } else {
  305. no strict 'refs';
  306. do { $self->print_help(); exit 0; } if $commandline{help};
  307. do { $self->print_version(); exit 0 } if $commandline{version};
  308. do { $self->print_usage(); exit 0 } if $commandline{usage};
  309. foreach (map { $_->{spec} =~ /^([\w\-]+)/; $1; } @{$self->{_args}}) {
  310. my $field = $_;
  311. *{"$field"} = sub {
  312. return $self->{opts}->{$field};
  313. };
  314. }
  315. foreach (grep { exists $_->{default} } @{$self->{_args}}) {
  316. $_->{spec} =~ /^([\w\-]+)/;
  317. my $spec = $1;
  318. $self->{opts}->{$spec} = $_->{default};
  319. }
  320. foreach (keys %commandline) {
  321. $self->{opts}->{$_} = $commandline{$_};
  322. }
  323. }
  324. }
  325. sub override_opt {
  326. my $self = shift;
  327. my $key = shift;
  328. my $value = shift;
  329. $self->{opts}->{$key} = $value;
  330. }
  331. sub get {
  332. my $self = shift;
  333. my $opt = shift;
  334. return $self->{opts}->{$opt};
  335. }
  336. sub print_help {
  337. my $self = shift;
  338. $self->print_version();
  339. printf "\n%s\n", $self->{_attr}->{license};
  340. printf "\n%s\n\n", $self->{_attr}->{blurb};
  341. $self->print_usage();
  342. foreach (@{$self->{_args}}) {
  343. printf " %s\n", $_->{help};
  344. }
  345. exit 0;
  346. }
  347. sub print_usage {
  348. my $self = shift;
  349. printf $self->{_attr}->{usage}, $self->{_attr}->{plugin};
  350. print "\n";
  351. }
  352. sub print_version {
  353. my $self = shift;
  354. printf "%s %s", $self->{_attr}->{plugin}, $self->{_attr}->{version};
  355. printf " [%s]", $self->{_attr}->{url} if $self->{_attr}->{url};
  356. print "\n";
  357. }
  358. sub print_license {
  359. my $self = shift;
  360. printf "%s\n", $self->{_attr}->{license};
  361. print "\n";
  362. }
  363. package Server::Linux;
  364. use strict;
  365. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  366. our @ISA = qw(NWC::Device);
  367. sub init {
  368. my $self = shift;
  369. $self->{components} = {
  370. interface_subsystem => undef,
  371. };
  372. $self->{serial} = 'unknown';
  373. $self->{product} = 'unknown';
  374. $self->{romversion} = 'unknown';
  375. if (! $self->check_messages()) {
  376. if ($self->mode =~ /device::interfaces/) {
  377. $self->analyze_interface_subsystem();
  378. $self->check_interface_subsystem();
  379. }
  380. }
  381. }
  382. sub analyze_interface_subsystem {
  383. my $self = shift;
  384. $self->{components}->{interface_subsystem} =
  385. Server::Linux::Component::InterfaceSubsystem->new();
  386. }
  387. sub check_interface_subsystem {
  388. my $self = shift;
  389. $self->{components}->{interface_subsystem}->check();
  390. $self->{components}->{interface_subsystem}->dump()
  391. if $self->opts->verbose >= 2;
  392. }
  393. package Server::Linux::Component::InterfaceSubsystem;
  394. our @ISA = qw(Server::Linux);
  395. use strict;
  396. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  397. sub new {
  398. my $class = shift;
  399. my %params = @_;
  400. my $self = {
  401. interfaces => [],
  402. blacklisted => 0,
  403. info => undef,
  404. extendedinfo => undef,
  405. };
  406. bless $self, $class;
  407. $self->init(%params);
  408. return $self;
  409. }
  410. sub init {
  411. my $self = shift;
  412. my %params = @_;
  413. if ($self->mode =~ /device::interfaces::list/) {
  414. foreach (glob "/sys/class/net/*") {
  415. my $name = $_;
  416. $name =~ s/.*\///g;
  417. my $tmpif = {
  418. ifDescr => $name,
  419. };
  420. push(@{$self->{interfaces}},
  421. Server::Linux::Component::InterfaceSubsystem::Interface->new(%{$tmpif}));
  422. }
  423. } else {
  424. foreach (glob "/sys/class/net/*") {
  425. my $name = $_;
  426. $name =~ s/.*\///g;
  427. if ($self->opts->name) {
  428. if ($self->opts->regexp) {
  429. my $pattern = $self->opts->name;
  430. if ($name !~ /$pattern/i) {
  431. next;
  432. }
  433. } elsif (lc $name ne lc $self->opts->name) {
  434. next;
  435. }
  436. }
  437. my $tmpif = {
  438. ifDescr => $name,
  439. ifSpeed => (-f "/sys/class/net/$name/speed" ? do { local (@ARGV, $/) = "/sys/class/net/$name/speed"; my $x = <>; close ARGV; $x} * 1024*1024 : 1024*1024*1024),
  440. ifInOctets => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/rx_bytes"; my $x = <>; close ARGV; $x},
  441. ifInDiscards => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/rx_dropped"; my $x = <>; close ARGV; $x},
  442. ifInErrors => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/rx_errors"; my $x = <>; close ARGV; $x},
  443. ifOutOctets => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/tx_bytes"; my $x = <>; close ARGV; $x},
  444. ifOutDiscards => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/tx_dropped"; my $x = <>; close ARGV; $x},
  445. ifOutErrors => do { local (@ARGV, $/) = "/sys/class/net/$name/statistics/tx_errors"; my $x = <>; close ARGV; $x},
  446. };
  447. foreach (keys %{$tmpif}) {
  448. chomp($tmpif->{$_});
  449. }
  450. push(@{$self->{interfaces}},
  451. Server::Linux::Component::InterfaceSubsystem::Interface->new(%{$tmpif}));
  452. }
  453. }
  454. }
  455. sub check {
  456. my $self = shift;
  457. my $errorfound = 0;
  458. $self->add_info('checking interfaces');
  459. $self->blacklist('ff', '');
  460. if (scalar(@{$self->{interfaces}}) == 0) {
  461. $self->add_message(UNKNOWN, 'no interfaces');
  462. return;
  463. }
  464. if ($self->mode =~ /device::interfaces::list/) {
  465. foreach (sort {$a->{ifDescr} cmp $b->{ifDescr}} @{$self->{interfaces}}) {
  466. $_->list();
  467. }
  468. } else {
  469. if (scalar (@{$self->{interfaces}}) == 0) {
  470. } else {
  471. foreach (@{$self->{interfaces}}) {
  472. $_->check();
  473. }
  474. }
  475. }
  476. }
  477. sub dump {
  478. my $self = shift;
  479. foreach (@{$self->{interfaces}}) {
  480. $_->dump();
  481. }
  482. }
  483. package Server::Linux::Component::InterfaceSubsystem::Interface;
  484. our @ISA = qw(Server::Linux::Component::InterfaceSubsystem);
  485. use strict;
  486. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  487. sub new {
  488. my $class = shift;
  489. my %params = @_;
  490. my $self = {
  491. ifDescr => $params{ifDescr},
  492. ifSpeed => $params{ifSpeed},
  493. ifInOctets => $params{ifInOctets},
  494. ifInDiscards => $params{ifInDiscards},
  495. ifInErrors => $params{ifInErrors},
  496. ifOutOctets => $params{ifOutOctets},
  497. ifOutDiscards => $params{ifOutDiscards},
  498. ifOutErrors => $params{ifOutErrors},
  499. blacklisted => 0,
  500. info => undef,
  501. extendedinfo => undef,
  502. };
  503. foreach my $key (keys %params) {
  504. $self->{$key} = 0 if ! defined $params{$key};
  505. }
  506. bless $self, $class;
  507. $self->init();
  508. return $self;
  509. }
  510. sub init {
  511. my $self = shift;
  512. if ($self->mode =~ /device::interfaces::traffic/) {
  513. $self->valdiff({name => $self->{ifDescr}}, qw(ifInOctets ifInDiscards ifInErrors ifOutOctets ifOutDiscards ifOutErrors));
  514. } elsif ($self->mode =~ /device::interfaces::usage/) {
  515. $self->valdiff({name => $self->{ifDescr}}, qw(ifInOctets ifOutOctets));
  516. if ($self->{ifSpeed} == 0) {
  517. # vlan graffl
  518. $self->{inputUtilization} = 0;
  519. $self->{outputUtilization} = 0;
  520. } else {
  521. $self->{inputUtilization} = $self->{delta_ifInOctets} * 8 * 100 /
  522. ($self->{delta_timestamp} * $self->{ifSpeed});
  523. $self->{outputUtilization} = $self->{delta_ifOutOctets} * 8 * 100 /
  524. ($self->{delta_timestamp} * $self->{ifSpeed});
  525. }
  526. $self->{inputRate} = $self->{delta_ifInOctets} / $self->{delta_timestamp};
  527. $self->{outputRate} = $self->{delta_ifOutOctets} / $self->{delta_timestamp};
  528. my $factor = 1/8; # default Bits
  529. if ($self->opts->units) {
  530. if ($self->opts->units eq "GB") {
  531. $factor = 1024 * 1024 * 1024;
  532. } elsif ($self->opts->units eq "MB") {
  533. $factor = 1024 * 1024;
  534. } elsif ($self->opts->units eq "KB") {
  535. $factor = 1024;
  536. } elsif ($self->opts->units eq "GBi") {
  537. $factor = 1024 * 1024 * 1024 / 8;
  538. } elsif ($self->opts->units eq "MBi") {
  539. $factor = 1024 * 1024 / 8;
  540. } elsif ($self->opts->units eq "KBi") {
  541. $factor = 1024 / 8;
  542. } elsif ($self->opts->units eq "B") {
  543. $factor = 1;
  544. } elsif ($self->opts->units eq "Bit") {
  545. $factor = 1/8;
  546. }
  547. }
  548. $self->{inputRate} /= $factor;
  549. $self->{outputRate} /= $factor;
  550. } elsif ($self->mode =~ /device::interfaces::errors/) {
  551. $self->valdiff({name => $self->{ifDescr}}, qw(ifInErrors ifOutErrors ifInDiscards ifOutDiscards));
  552. $self->{inputErrorRate} = $self->{delta_ifInErrors}
  553. / $self->{delta_timestamp};
  554. $self->{outputErrorRate} = $self->{delta_ifOutErrors}
  555. / $self->{delta_timestamp};
  556. $self->{inputDiscardRate} = $self->{delta_ifInDiscards}
  557. / $self->{delta_timestamp};
  558. $self->{outputDiscardRate} = $self->{delta_ifOutDiscards}
  559. / $self->{delta_timestamp};
  560. $self->{inputRate} = ($self->{delta_ifInErrors} + $self->{delta_ifInDiscards})
  561. / $self->{delta_timestamp};
  562. $self->{outputRate} = ($self->{delta_ifOutErrors} + $self->{delta_ifOutDiscards})
  563. / $self->{delta_timestamp};
  564. } elsif ($self->mode =~ /device::interfaces::operstatus/) {
  565. }
  566. return $self;
  567. }
  568. sub check {
  569. my $self = shift;
  570. $self->blacklist('if', $self->{ifDescr});
  571. if ($self->mode =~ /device::interfaces::traffic/) {
  572. } elsif ($self->mode =~ /device::interfaces::usage/) {
  573. my $info = sprintf 'interface %s usage is in:%.2f%% (%s) out:%.2f%% (%s)',
  574. $self->{ifDescr},
  575. $self->{inputUtilization},
  576. sprintf("%.2f%s/s", $self->{inputRate},
  577. ($self->opts->units ? $self->opts->units : 'Bits')),
  578. $self->{outputUtilization},
  579. sprintf("%.2f%s/s", $self->{outputRate},
  580. ($self->opts->units ? $self->opts->units : 'Bits'));
  581. $self->add_info($info);
  582. $self->set_thresholds(warning => 80, critical => 90);
  583. my $in = $self->check_thresholds($self->{inputUtilization});
  584. my $out = $self->check_thresholds($self->{outputUtilization});
  585. my $level = ($in > $out) ? $in : ($out > $in) ? $out : $in;
  586. $self->add_message($level, $info);
  587. $self->add_perfdata(
  588. label => $self->{ifDescr}.'_usage_in',
  589. value => $self->{inputUtilization},
  590. uom => '%',
  591. warning => $self->{warning},
  592. critical => $self->{critical},
  593. );
  594. $self->add_perfdata(
  595. label => $self->{ifDescr}.'_usage_out',
  596. value => $self->{outputUtilization},
  597. uom => '%',
  598. warning => $self->{warning},
  599. critical => $self->{critical},
  600. );
  601. $self->add_perfdata(
  602. label => $self->{ifDescr}.'_traffic_in',
  603. value => $self->{inputRate},
  604. uom => $self->opts->units,
  605. );
  606. $self->add_perfdata(
  607. label => $self->{ifDescr}.'_traffic_out',
  608. value => $self->{outputRate},
  609. uom => $self->opts->units,
  610. );
  611. } elsif ($self->mode =~ /device::interfaces::errors/) {
  612. my $info = sprintf 'interface %s errors in:%.2f/s out:%.2f/s '.
  613. 'discards in:%.2f/s out:%.2f/s',
  614. $self->{ifDescr},
  615. $self->{inputErrorRate} , $self->{outputErrorRate},
  616. $self->{inputDiscardRate} , $self->{outputDiscardRate};
  617. $self->add_info($info);
  618. $self->set_thresholds(warning => 1, critical => 10);
  619. my $in = $self->check_thresholds($self->{inputRate});
  620. my $out = $self->check_thresholds($self->{outputRate});
  621. my $level = ($in > $out) ? $in : ($out > $in) ? $out : $in;
  622. $self->add_message($level, $info);
  623. $self->add_perfdata(
  624. label => $self->{ifDescr}.'_errors_in',
  625. value => $self->{inputErrorRate},
  626. warning => $self->{warning},
  627. critical => $self->{critical},
  628. );
  629. $self->add_perfdata(
  630. label => $self->{ifDescr}.'_errors_out',
  631. value => $self->{outputErrorRate},
  632. warning => $self->{warning},
  633. critical => $self->{critical},
  634. );
  635. $self->add_perfdata(
  636. label => $self->{ifDescr}.'_discards_in',
  637. value => $self->{inputDiscardRate},
  638. warning => $self->{warning},
  639. critical => $self->{critical},
  640. );
  641. $self->add_perfdata(
  642. label => $self->{ifDescr}.'_discards_out',
  643. value => $self->{outputDiscardRate},
  644. warning => $self->{warning},
  645. critical => $self->{critical},
  646. );
  647. }
  648. }
  649. sub list {
  650. my $self = shift;
  651. printf "%s\n", $self->{ifDescr};
  652. }
  653. sub dump {
  654. my $self = shift;
  655. printf "[IF_%s]\n", $self->{ifDescr};
  656. foreach (qw(ifDescr ifSpeed ifInOctets ifInDiscards ifInErrors ifOutOctets ifOutDiscards ifOutErrors)) {
  657. printf "%s: %s\n", $_, defined $self->{$_} ? $self->{$_} : 'undefined';
  658. }
  659. # printf "info: %s\n", $self->{info};
  660. printf "\n";
  661. }
  662. package NWC::CiscoIOS::Component::CpuSubsystem;
  663. our @ISA = qw(NWC::CiscoIOS);
  664. use strict;
  665. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  666. sub new {
  667. my $class = shift;
  668. my %params = @_;
  669. my $self = {
  670. cpus => [],
  671. blacklisted => 0,
  672. info => undef,
  673. extendedinfo => undef,
  674. };
  675. bless $self, $class;
  676. $self->init(%params);
  677. return $self;
  678. }
  679. sub init {
  680. my $self = shift;
  681. my %params = @_;
  682. my $type = 0;
  683. foreach ($self->get_snmp_table_objects(
  684. 'CISCO-PROCESS-MIB', 'cpmCPUTotalTable')) {
  685. $_->{cpmCPUTotalIndex} ||= $type++;
  686. push(@{$self->{cpus}},
  687. NWC::CiscoIOS::Component::CpuSubsystem::Cpu->new(%{$_}));
  688. }
  689. if (scalar(@{$self->{cpus}}) == 0) {
  690. # maybe too old. i fake a cpu. be careful. this is a really bad hack
  691. my $response = $self->get_request(
  692. -varbindlist => [
  693. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1},
  694. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5},
  695. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{busyPer},
  696. ]
  697. );
  698. if (exists $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}}) {
  699. push(@{$self->{cpus}},
  700. NWC::CiscoIOS::Component::CpuSubsystem::Cpu->new(
  701. cpmCPUTotalPhysicalIndex => 0, #fake
  702. cpmCPUTotalIndex => 0, #fake
  703. cpmCPUTotal5sec => 0, #fake
  704. cpmCPUTotal5secRev => 0, #fake
  705. cpmCPUTotal1min => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}},
  706. cpmCPUTotal1minRev => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}},
  707. cpmCPUTotal5min => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5}},
  708. cpmCPUTotal5minRev => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5}},
  709. cpmCPUMonInterval => 0, #fake
  710. cpmCPUTotalMonIntervalValue => 0, #fake
  711. cpmCPUInterruptMonIntervalValue => 0, #fake
  712. ));
  713. }
  714. }
  715. }
  716. sub check {
  717. my $self = shift;
  718. my $errorfound = 0;
  719. $self->add_info('checking cpus');
  720. $self->blacklist('ff', '');
  721. if (scalar (@{$self->{cpus}}) == 0) {
  722. } else {
  723. foreach (@{$self->{cpus}}) {
  724. $_->check();
  725. }
  726. }
  727. }
  728. sub dump {
  729. my $self = shift;
  730. foreach (@{$self->{cpus}}) {
  731. $_->dump();
  732. }
  733. }
  734. package NWC::CiscoIOS::Component::CpuSubsystem::Cpu;
  735. our @ISA = qw(NWC::CiscoIOS::Component::CpuSubsystem);
  736. use strict;
  737. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  738. sub new {
  739. my $class = shift;
  740. my %params = @_;
  741. my $self = {
  742. blacklisted => 0,
  743. info => undef,
  744. extendedinfo => undef,
  745. };
  746. foreach my $param (qw(cpmCPUTotalIndex cpmCPUTotalPhysicalIndex
  747. cpmCPUTotal5sec cpmCPUTotal1min cpmCPUTotal5min
  748. cpmCPUTotal5secRev cpmCPUTotal1minRev cpmCPUTotal5minRev
  749. cpmCPUMonInterval cpmCPUTotalMonIntervalValue
  750. cpmCPUInterruptMonIntervalValue)) {
  751. if (exists $params{$param}) {
  752. $self->{$param} = $params{$param};
  753. }
  754. }
  755. bless $self, $class;
  756. if (exists $params{cpmCPUTotal5minRev}) {
  757. $self->{usage} = $params{cpmCPUTotal5minRev};
  758. } else {
  759. $self->{usage} = $params{cpmCPUTotal5min};
  760. }
  761. if ($self->{cpmCPUTotalPhysicalIndex}) {
  762. my $entPhysicalName = '1.3.6.1.2.1.47.1.1.1.1.7';
  763. $self->{entPhysicalName} = $self->get_request(
  764. -varbindlist => [$entPhysicalName.'.'.$self->{cpmCPUTotalPhysicalIndex}]
  765. );
  766. $self->{entPhysicalName} = $self->{entPhysicalName}->{$entPhysicalName.'.'.$self->{cpmCPUTotalPhysicalIndex}};
  767. } else {
  768. $self->{entPhysicalName} = $self->{cpmCPUTotalIndex};
  769. }
  770. return $self;
  771. }
  772. sub check {
  773. my $self = shift;
  774. $self->blacklist('c', $self->{cpmCPUTotalPhysicalIndex});
  775. my $info = sprintf 'cpu %s usage (5 min avg.) is %.2f%%',
  776. $self->{entPhysicalName}, $self->{usage};
  777. $self->add_info($info);
  778. $self->set_thresholds(warning => 80, critical => 90);
  779. $self->add_message($self->check_thresholds($self->{usage}), $info);
  780. $self->add_perfdata(
  781. label => 'cpu_'.$self->{entPhysicalName}.'_usage',
  782. value => $self->{usage},
  783. uom => '%',
  784. warning => $self->{warning},
  785. critical => $self->{critical},
  786. );
  787. }
  788. sub dump {
  789. my $self = shift;
  790. printf "[CPU_%s]\n", $self->{cpmCPUTotalPhysicalIndex};
  791. foreach (qw(cpmCPUTotalIndex cpmCPUTotalPhysicalIndex cpmCPUTotal5sec cpmCPUTotal1min cpmCPUTotal5min cpmCPUTotal5secRev cpmCPUTotal1minRev cpmCPUTotal5minRev cpmCPUMonInterval cpmCPUTotalMonIntervalValue cpmCPUInterruptMonIntervalValue)) {
  792. if (exists $self->{$_}) {
  793. printf "%s: %s\n", $_, $self->{$_};
  794. }
  795. }
  796. printf "info: %s\n", $self->{info};
  797. printf "\n";
  798. }
  799. package NWC::CiscoIOS::Component::MemSubsystem;
  800. our @ISA = qw(NWC::CiscoIOS);
  801. use strict;
  802. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  803. sub new {
  804. my $class = shift;
  805. my %params = @_;
  806. my $self = {
  807. runtime => $params{runtime},
  808. rawdata => $params{rawdata},
  809. mems => [],
  810. blacklisted => 0,
  811. info => undef,
  812. extendedinfo => undef,
  813. };
  814. bless $self, $class;
  815. $self->init(%params);
  816. return $self;
  817. }
  818. sub init {
  819. my $self = shift;
  820. my %params = @_;
  821. my $snmpwalk = $params{rawdata};
  822. my $ignore_redundancy = $params{ignore_redundancy};
  823. my $type = 0;
  824. foreach ($self->get_snmp_table_objects(
  825. 'CISCO-MEMORY-POOL-MIB', 'ciscoMemoryPoolTable')) {
  826. $_->{ciscoMemoryPoolType} ||= $type++;
  827. push(@{$self->{mems}},
  828. NWC::CiscoIOS::Component::MemSubsystem::Mem->new(%{$_}));
  829. }
  830. }
  831. sub check {
  832. my $self = shift;
  833. my $errorfound = 0;
  834. $self->add_info('checking mems');
  835. $self->blacklist('ff', '');
  836. if (scalar (@{$self->{mems}}) == 0) {
  837. } else {
  838. foreach (@{$self->{mems}}) {
  839. $_->check();
  840. }
  841. }
  842. }
  843. sub dump {
  844. my $self = shift;
  845. foreach (@{$self->{mems}}) {
  846. $_->dump();
  847. }
  848. }
  849. package NWC::CiscoIOS::Component::MemSubsystem::Mem;
  850. our @ISA = qw(NWC::CiscoIOS::Component::MemSubsystem);
  851. use strict;
  852. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  853. sub new {
  854. my $class = shift;
  855. my %params = @_;
  856. my $self = {
  857. blacklisted => 0,
  858. info => undef,
  859. extendedinfo => undef,
  860. };
  861. foreach my $param (qw(ciscoMemoryPoolTable ciscoMemoryPoolEntry
  862. ciscoMemoryPoolType ciscoMemoryPoolName ciscoMemoryPoolAlternate
  863. ciscoMemoryPoolValid ciscoMemoryPoolUsed ciscoMemoryPoolFree
  864. ciscoMemoryPoolLargestFree)) {
  865. $self->{$param} = $params{$param};
  866. }
  867. bless $self, $class;
  868. $self->{usage} = 100 * $params{ciscoMemoryPoolUsed} /
  869. ($params{ciscoMemoryPoolFree} + $params{ciscoMemoryPoolUsed});
  870. return $self;
  871. }
  872. sub check {
  873. my $self = shift;
  874. $self->blacklist('m', $self->{ciscoMemoryPoolType});
  875. my $info = sprintf 'mempool %s usage is %.2f%%',
  876. $self->{ciscoMemoryPoolName}, $self->{usage};
  877. $self->add_info($info);
  878. $self->set_thresholds(warning => 80, critical => 90);
  879. $self->add_message($self->check_thresholds($self->{usage}), $info);
  880. $self->add_perfdata(
  881. label => $self->{ciscoMemoryPoolName}.'_usage',
  882. value => $self->{usage},
  883. uom => '%',
  884. warning => $self->{warning},
  885. critical => $self->{critical}
  886. );
  887. }
  888. sub dump {
  889. my $self = shift;
  890. printf "[MEMPOOL_%s]\n", $self->{ciscoMemoryPoolType};
  891. foreach (qw(ciscoMemoryPoolType ciscoMemoryPoolName ciscoMemoryPoolAlternate ciscoMemoryPoolValid ciscoMemoryPoolUsed ciscoMemoryPoolFree ciscoMemoryPoolLargestFree)) {
  892. printf "%s: %s\n", $_, $self->{$_};
  893. }
  894. printf "info: %s\n", $self->{info};
  895. printf "\n";
  896. }
  897. package NWC::CiscoIOS::Component::EnvironmentalSubsystem;
  898. our @ISA = qw(NWC::CiscoIOS);
  899. use strict;
  900. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  901. sub new {
  902. my $class = shift;
  903. my %params = @_;
  904. my $self = {
  905. runtime => $params{runtime},
  906. rawdata => $params{rawdata},
  907. method => $params{method},
  908. condition => $params{condition},
  909. status => $params{status},
  910. fan_subsystem => undef,
  911. temperature_subsystem => undef,
  912. powersupply_subsystem => undef,
  913. voltage_subsystem => undef,
  914. blacklisted => 0,
  915. info => undef,
  916. extendedinfo => undef,
  917. };
  918. bless $self, $class;
  919. $self->init(%params);
  920. return $self;
  921. }
  922. sub init {
  923. my $self = shift;
  924. my %params = @_;
  925. #
  926. # 1.3.6.1.4.1.9.9.13.1.1.0 ciscoEnvMonPresent (irgendein typ of envmon)
  927. #
  928. $self->{fan_subsystem} =
  929. NWC::CiscoIOS::Component::FanSubsystem->new(%params);
  930. $self->{temperature_subsystem} =
  931. NWC::CiscoIOS::Component::TemperatureSubsystem->new(%params);
  932. $self->{powersupply_subsystem} =
  933. NWC::CiscoIOS::Component::SupplySubsystem->new(%params);
  934. $self->{voltage_subsystem} =
  935. NWC::CiscoIOS::Component::VoltageSubsystem->new(%params);
  936. }
  937. sub check {
  938. my $self = shift;
  939. my $errorfound = 0;
  940. $self->{fan_subsystem}->check();
  941. $self->{temperature_subsystem}->check();
  942. $self->{voltage_subsystem}->check();
  943. $self->{powersupply_subsystem}->check();
  944. if (! $self->check_messages()) {
  945. $self->add_message(OK, "environmental hardware working fine");
  946. }
  947. }
  948. sub dump {
  949. my $self = shift;
  950. $self->{fan_subsystem}->dump();
  951. $self->{temperature_subsystem}->dump();
  952. $self->{voltage_subsystem}->dump();
  953. $self->{powersupply_subsystem}->dump();
  954. }
  955. package NWC::CiscoIOS::Component::TemperatureSubsystem;
  956. our @ISA = qw(NWC::CiscoIOS::Component::EnvironmentalSubsystem);
  957. use strict;
  958. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  959. sub new {
  960. my $class = shift;
  961. my %params = @_;
  962. my $self = {
  963. temperatures => [],
  964. blacklisted => 0,
  965. info => undef,
  966. extendedinfo => undef,
  967. };
  968. bless $self, $class;
  969. $self->init(%params);
  970. return $self;
  971. }
  972. sub init {
  973. my $self = shift;
  974. my $tempcnt = 0;
  975. foreach ($self->get_snmp_table_objects(
  976. 'CISCO-ENVMON-MIB', 'ciscoEnvMonTemperatureStatusTable')) {
  977. $_->{ciscoEnvMonTemperatureStatusIndex} = $tempcnt++ if (! exists $_->{ciscoEnvMonTemperatureStatusIndex});
  978. push(@{$self->{temperatures}},
  979. NWC::CiscoIOS::Component::TemperatureSubsystem::Temperature->new(%{$_}));
  980. }
  981. }
  982. sub check {
  983. my $self = shift;
  984. my $errorfound = 0;
  985. $self->add_info('checking temperatures');
  986. $self->blacklist('t', '');
  987. if (scalar (@{$self->{temperatures}}) == 0) {
  988. } else {
  989. foreach (@{$self->{temperatures}}) {
  990. $_->check();
  991. }
  992. }
  993. }
  994. sub dump {
  995. my $self = shift;
  996. foreach (@{$self->{temperatures}}) {
  997. $_->dump();
  998. }
  999. }
  1000. package NWC::CiscoIOS::Component::TemperatureSubsystem::Temperature;
  1001. our @ISA = qw(NWC::CiscoIOS::Component::TemperatureSubsystem);
  1002. use strict;
  1003. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1004. sub new {
  1005. my $class = shift;
  1006. my %params = @_;
  1007. my $self = {
  1008. blacklisted => 0,
  1009. info => undef,
  1010. extendedinfo => undef,
  1011. };
  1012. foreach my $param (qw(ciscoEnvMonTemperatureStatusIndex
  1013. ciscoEnvMonTemperatureStatusDescr ciscoEnvMonTemperatureStatusValue
  1014. ciscoEnvMonTemperatureThreshold ciscoEnvMonTemperatureLastShutdown
  1015. ciscoEnvMonTemperatureState)) {
  1016. $self->{$param} = $params{$param};
  1017. }
  1018. $self->{ciscoEnvMonTemperatureStatusIndex} ||= 0;
  1019. $self->{ciscoEnvMonTemperatureLastShutdown} ||= 0;
  1020. if ($self->{ciscoEnvMonTemperatureStatusValue}) {
  1021. bless $self, $class;
  1022. } else {
  1023. bless $self, $class.'::Simple';
  1024. }
  1025. return $self;
  1026. }
  1027. sub check {
  1028. my $self = shift;
  1029. $self->blacklist('t', $self->{ciscoEnvMonTemperatureStatusIndex});
  1030. if ($self->{ciscoEnvMonTemperatureStatusValue} >
  1031. $self->{ciscoEnvMonTemperatureThreshold}) {
  1032. $self->add_info(sprintf 'temperature %d %s is too high (%d of %d max = %s)',
  1033. $self->{ciscoEnvMonTemperatureStatusIndex},
  1034. $self->{ciscoEnvMonTemperatureStatusDescr},
  1035. $self->{ciscoEnvMonTemperatureStatusValue},
  1036. $self->{ciscoEnvMonTemperatureThreshold},
  1037. $self->{ciscoEnvMonTemperatureState});
  1038. if ($self->{ciscoEnvMonTemperatureState} eq 'warning') {
  1039. $self->add_message(WARNING, $self->{info});
  1040. } elsif ($self->{ciscoEnvMonTemperatureState} eq 'critical') {
  1041. $self->add_message(CRITICAL, $self->{info});
  1042. }
  1043. } else {
  1044. $self->add_info(sprintf 'temperature %d %s is %d (of %d max = normal)',
  1045. $self->{ciscoEnvMonTemperatureStatusIndex},
  1046. $self->{ciscoEnvMonTemperatureStatusDescr},
  1047. $self->{ciscoEnvMonTemperatureStatusValue},
  1048. $self->{ciscoEnvMonTemperatureThreshold},
  1049. $self->{ciscoEnvMonTemperatureState});
  1050. }
  1051. $self->add_perfdata(
  1052. label => sprintf('temp_%s', $self->{ciscoEnvMonTemperatureStatusIndex}),
  1053. value => $self->{ciscoEnvMonTemperatureStatusValue},
  1054. warning => $self->{ciscoEnvMonTemperatureThreshold},
  1055. critical => undef,
  1056. );
  1057. }
  1058. sub dump {
  1059. my $self = shift;
  1060. printf "[TEMP_%s]\n", $self->{ciscoEnvMonTemperatureStatusIndex};
  1061. foreach (qw(ciscoEnvMonTemperatureStatusIndex ciscoEnvMonTemperatureStatusDescr ciscoEnvMonTemperatureStatusValue ciscoEnvMonTemperatureThreshold ciscoEnvMonTemperatureLastShutdown ciscoEnvMonTemperatureState)) {
  1062. printf "%s: %s\n", $_, $self->{$_};
  1063. }
  1064. printf "info: %s\n", $self->{info};
  1065. printf "\n";
  1066. }
  1067. package NWC::CiscoIOS::Component::TemperatureSubsystem::Temperature::Simple;
  1068. our @ISA = qw(NWC::CiscoIOS::Component::TemperatureSubsystem::Temperature);
  1069. use strict;
  1070. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1071. sub new {
  1072. my $class = shift;
  1073. my %params = @_;
  1074. my $self = {
  1075. runtime => $params{runtime},
  1076. ciscoEnvMonTemperatureStatusIndex => $params{ciscoEnvMonTemperatureStatusIndex} || 0,
  1077. ciscoEnvMonTemperatureStatusDescr => $params{ciscoEnvMonTemperatureStatusDescr},
  1078. ciscoEnvMonTemperatureState => $params{ciscoEnvMonTemperatureState},
  1079. blacklisted => 0,
  1080. info => undef,
  1081. extendedinfo => undef,
  1082. };
  1083. bless $self, $class;
  1084. return $self;
  1085. }
  1086. sub check {
  1087. my $self = shift;
  1088. $self->blacklist('t', $self->{ciscoEnvMonTemperatureStatusIndex});
  1089. $self->add_info(sprintf 'temperature %d %s is %s',
  1090. $self->{ciscoEnvMonTemperatureStatusIndex},
  1091. $self->{ciscoEnvMonTemperatureStatusDescr},
  1092. $self->{ciscoEnvMonTemperatureState});
  1093. if ($self->{ciscoEnvMonTemperatureState} ne 'normal') {
  1094. if ($self->{ciscoEnvMonTemperatureState} eq 'warning') {
  1095. $self->add_message(WARNING, $self->{info});
  1096. } elsif ($self->{ciscoEnvMonTemperatureState} eq 'critical') {
  1097. $self->add_message(CRITICAL, $self->{info});
  1098. }
  1099. } else {
  1100. }
  1101. }
  1102. sub dump {
  1103. my $self = shift;
  1104. printf "[TEMP_%s]\n", $self->{ciscoEnvMonTemperatureStatusIndex};
  1105. foreach (qw(ciscoEnvMonTemperatureStatusIndex ciscoEnvMonTemperatureStatusDescr ciscoEnvMonTemperatureState)) {
  1106. printf "%s: %s\n", $_, $self->{$_};
  1107. }
  1108. printf "info: %s\n", $self->{info};
  1109. printf "\n";
  1110. }
  1111. package NWC::CiscoIOS::Component::SupplySubsystem;
  1112. our @ISA = qw(NWC::CiscoIOS::Component::EnvironmentalSubsystem);
  1113. use strict;
  1114. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1115. sub new {
  1116. my $class = shift;
  1117. my %params = @_;
  1118. my $self = {
  1119. supplies => [],
  1120. blacklisted => 0,
  1121. info => undef,
  1122. extendedinfo => undef,
  1123. };
  1124. bless $self, $class;
  1125. $self->init(%params);
  1126. return $self;
  1127. }
  1128. sub init {
  1129. my $self = shift;
  1130. foreach ($self->get_snmp_table_objects(
  1131. 'CISCO-ENVMON-MIB', 'ciscoEnvMonSupplyStatusTable')) {
  1132. push(@{$self->{supplies}},
  1133. NWC::CiscoIOS::Component::SupplySubsystem::Supply->new(%{$_}));
  1134. }
  1135. }
  1136. sub check {
  1137. my $self = shift;
  1138. my $errorfound = 0;
  1139. $self->add_info('checking supplies');
  1140. $self->blacklist('ps', '');
  1141. if (scalar (@{$self->{supplies}}) == 0) {
  1142. } else {
  1143. foreach (@{$self->{supplies}}) {
  1144. $_->check();
  1145. }
  1146. }
  1147. }
  1148. sub dump {
  1149. my $self = shift;
  1150. foreach (@{$self->{supplies}}) {
  1151. $_->dump();
  1152. }
  1153. }
  1154. package NWC::CiscoIOS::Component::SupplySubsystem::Supply;
  1155. our @ISA = qw(NWC::CiscoIOS::Component::SupplySubsystem);
  1156. use strict;
  1157. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1158. sub new {
  1159. my $class = shift;
  1160. my %params = @_;
  1161. my $self = {
  1162. blacklisted => 0,
  1163. info => undef,
  1164. extendedinfo => undef,
  1165. };
  1166. foreach my $param (qw(ciscoEnvMonSupplyStatusIndex
  1167. ciscoEnvMonSupplyStatusDescr ciscoEnvMonSupplyState
  1168. ciscoEnvMonSupplySource)) {
  1169. $self->{$param} = $params{$param};
  1170. }
  1171. $self->{ciscoEnvMonSupplyStatusIndex} ||= 0;
  1172. bless $self, $class;
  1173. return $self;
  1174. }
  1175. sub check {
  1176. my $self = shift;
  1177. $self->blacklist('f', $self->{ciscoEnvMonSupplyStatusIndex});
  1178. $self->add_info(sprintf 'powersupply %d (%s) is %s',
  1179. $self->{ciscoEnvMonSupplyStatusIndex},
  1180. $self->{ciscoEnvMonSupplyStatusDescr},
  1181. $self->{ciscoEnvMonSupplyState});
  1182. if ($self->{ciscoEnvMonSupplyState} eq 'notPresent') {
  1183. } elsif ($self->{ciscoEnvMonSupplyState} ne 'normal') {
  1184. $self->add_message(CRITICAL, $self->{info});
  1185. }
  1186. }
  1187. sub dump {
  1188. my $self = shift;
  1189. printf "[PS_%s]\n", $self->{ciscoEnvMonSupplyStatusIndex};
  1190. foreach (qw(ciscoEnvMonSupplyStatusIndex ciscoEnvMonSupplyStatusDescr ciscoEnvMonSupplyState ciscoEnvMonSupplySource)) {
  1191. printf "%s: %s\n", $_, $self->{$_};
  1192. }
  1193. printf "info: %s\n", $self->{info};
  1194. printf "\n";
  1195. }
  1196. package NWC::CiscoIOS::Component::VoltageSubsystem;
  1197. our @ISA = qw(NWC::CiscoIOS::Component::EnvironmentalSubsystem);
  1198. use strict;
  1199. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1200. sub new {
  1201. my $class = shift;
  1202. my %params = @_;
  1203. my $self = {
  1204. voltages => [],
  1205. blacklisted => 0,
  1206. info => undef,
  1207. extendedinfo => undef,
  1208. };
  1209. bless $self, $class;
  1210. $self->init(%params);
  1211. return $self;
  1212. }
  1213. sub init {
  1214. my $self = shift;
  1215. my $index = 0;
  1216. foreach ($self->get_snmp_table_objects(
  1217. 'CISCO-ENVMON-MIB', 'ciscoEnvMonVoltageStatusTable')) {
  1218. $_->{ciscoEnvMonVoltageStatusIndex} ||= $index++;
  1219. push(@{$self->{voltages}},
  1220. NWC::CiscoIOS::Component::VoltageSubsystem::Voltage->new(%{$_}));
  1221. }
  1222. }
  1223. sub check {
  1224. my $self = shift;
  1225. my $errorfound = 0;
  1226. $self->add_info('checking voltages');
  1227. $self->blacklist('ff', '');
  1228. if (scalar (@{$self->{voltages}}) == 0) {
  1229. } else {
  1230. foreach (@{$self->{voltages}}) {
  1231. $_->check();
  1232. }
  1233. }
  1234. }
  1235. sub dump {
  1236. my $self = shift;
  1237. foreach (@{$self->{voltages}}) {
  1238. $_->dump();
  1239. }
  1240. }
  1241. package NWC::CiscoIOS::Component::VoltageSubsystem::Voltage;
  1242. our @ISA = qw(NWC::CiscoIOS::Component::VoltageSubsystem);
  1243. use strict;
  1244. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1245. sub new {
  1246. my $class = shift;
  1247. my %params = @_;
  1248. my $self = {
  1249. blacklisted => 0,
  1250. info => undef,
  1251. extendedinfo => undef,
  1252. };
  1253. foreach my $param (qw(ciscoEnvMonVoltageStatusTable
  1254. ciscoEnvMonVoltageStatusEntry ciscoEnvMonVoltageStatusIndex
  1255. ciscoEnvMonVoltageStatusDescr ciscoEnvMonVoltageStatusValue
  1256. ciscoEnvMonVoltageThresholdLow ciscoEnvMonVoltageThresholdHigh
  1257. ciscoEnvMonVoltageLastShutdown ciscoEnvMonVoltageState)) {
  1258. $self->{$param} = $params{$param};
  1259. }
  1260. bless $self, $class;
  1261. return $self;
  1262. }
  1263. sub check {
  1264. my $self = shift;
  1265. $self->blacklist('v', $self->{ciscoEnvMonVoltageStatusIndex});
  1266. $self->add_info(sprintf 'voltage %d (%s) is %s',
  1267. $self->{ciscoEnvMonVoltageStatusIndex},
  1268. $self->{ciscoEnvMonVoltageStatusDescr},
  1269. $self->{ciscoEnvMonVoltageState});
  1270. if ($self->{ciscoEnvMonVoltageState} eq 'notPresent') {
  1271. } elsif ($self->{ciscoEnvMonVoltageState} ne 'normal') {
  1272. $self->add_message(CRITICAL, $self->{info});
  1273. }
  1274. $self->add_perfdata(
  1275. label => sprintf('mvolt_%s', $self->{ciscoEnvMonVoltageStatusIndex}),
  1276. value => $self->{ciscoEnvMonVoltageStatusValue},
  1277. warning => $self->{ciscoEnvMonVoltageThresholdLow},
  1278. critical => $self->{ciscoEnvMonVoltageThresholdHigh},
  1279. );
  1280. }
  1281. sub dump {
  1282. my $self = shift;
  1283. printf "[VOLTAGE_%s]\n", $self->{ciscoEnvMonVoltageStatusIndex};
  1284. foreach (qw(ciscoEnvMonVoltageStatusTable ciscoEnvMonVoltageStatusEntry ciscoEnvMonVoltageStatusIndex ciscoEnvMonVoltageStatusDescr ciscoEnvMonVoltageStatusValue ciscoEnvMonVoltageThresholdLow ciscoEnvMonVoltageThresholdHigh ciscoEnvMonVoltageLastShutdown ciscoEnvMonVoltageState)) {
  1285. printf "%s: %s\n", $_, $self->{$_};
  1286. }
  1287. printf "info: %s\n", $self->{info};
  1288. printf "\n";
  1289. }
  1290. package NWC::CiscoIOS::Component::FanSubsystem;
  1291. our @ISA = qw(NWC::CiscoIOS::Component::EnvironmentalSubsystem);
  1292. use strict;
  1293. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1294. sub new {
  1295. my $class = shift;
  1296. my %params = @_;
  1297. my $self = {
  1298. fans => [],
  1299. blacklisted => 0,
  1300. info => undef,
  1301. extendedinfo => undef,
  1302. };
  1303. bless $self, $class;
  1304. $self->init(%params);
  1305. return $self;
  1306. }
  1307. sub init {
  1308. my $self = shift;
  1309. foreach ($self->get_snmp_table_objects(
  1310. 'CISCO-ENVMON-MIB', 'ciscoEnvMonFanStatusTable')) {
  1311. push(@{$self->{fans}},
  1312. NWC::CiscoIOS::Component::FanSubsystem::Fan->new(%{$_}));
  1313. }
  1314. }
  1315. sub check {
  1316. my $self = shift;
  1317. my $errorfound = 0;
  1318. $self->add_info('checking fans');
  1319. $self->blacklist('ff', '');
  1320. if (scalar (@{$self->{fans}}) == 0) {
  1321. } else {
  1322. foreach (@{$self->{fans}}) {
  1323. $_->check();
  1324. }
  1325. }
  1326. }
  1327. sub dump {
  1328. my $self = shift;
  1329. foreach (@{$self->{fans}}) {
  1330. $_->dump();
  1331. }
  1332. }
  1333. package NWC::CiscoIOS::Component::FanSubsystem::Fan;
  1334. our @ISA = qw(NWC::CiscoIOS::Component::FanSubsystem);
  1335. use strict;
  1336. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1337. sub new {
  1338. my $class = shift;
  1339. my %params = @_;
  1340. my $self = {
  1341. blacklisted => 0,
  1342. info => undef,
  1343. extendedinfo => undef,
  1344. };
  1345. foreach my $param (qw(ciscoEnvMonFanStatusIndex
  1346. ciscoEnvMonFanStatusDescr ciscoEnvMonFanState)) {
  1347. $self->{$param} = $params{$param};
  1348. }
  1349. $self->{ciscoEnvMonFanStatusIndex} ||= 0;
  1350. bless $self, $class;
  1351. return $self;
  1352. }
  1353. sub check {
  1354. my $self = shift;
  1355. $self->blacklist('f', $self->{ciscoEnvMonFanStatusIndex});
  1356. $self->add_info(sprintf 'fan %d (%s) is %s',
  1357. $self->{ciscoEnvMonFanStatusIndex},
  1358. $self->{ciscoEnvMonFanStatusDescr},
  1359. $self->{ciscoEnvMonFanState});
  1360. if ($self->{ciscoEnvMonFanState} eq 'notPresent') {
  1361. } elsif ($self->{ciscoEnvMonFanState} ne 'normal') {
  1362. $self->add_message(CRITICAL, $self->{info});
  1363. }
  1364. }
  1365. sub dump {
  1366. my $self = shift;
  1367. printf "[FAN_%s]\n", $self->{ciscoEnvMonFanStatusIndex};
  1368. foreach (qw(ciscoEnvMonFanStatusIndex ciscoEnvMonFanStatusDescr
  1369. ciscoEnvMonFanState)) {
  1370. printf "%s: %s\n", $_, $self->{$_};
  1371. }
  1372. printf "info: %s\n", $self->{info};
  1373. printf "\n";
  1374. }
  1375. package NWC::CiscoIOS;
  1376. use strict;
  1377. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1378. our @ISA = qw(NWC::Cisco);
  1379. sub init {
  1380. my $self = shift;
  1381. $self->{components} = {
  1382. powersupply_subsystem => undef,
  1383. fan_subsystem => undef,
  1384. temperature_subsystem => undef,
  1385. cpu_subsystem => undef,
  1386. memory_subsystem => undef,
  1387. disk_subsystem => undef,
  1388. environmental_subsystem => undef,
  1389. };
  1390. $self->{serial} = 'unknown';
  1391. $self->{product} = 'unknown';
  1392. $self->{romversion} = 'unknown';
  1393. # serial is 1.3.6.1.2.1.47.1.1.1.1.11.1
  1394. #$self->collect();
  1395. if (! $self->check_messages()) {
  1396. ##$self->set_serial();
  1397. if ($self->mode =~ /device::hardware::health/) {
  1398. $self->analyze_environmental_subsystem();
  1399. #$self->auto_blacklist();
  1400. $self->check_environmental_subsystem();
  1401. } elsif ($self->mode =~ /device::hardware::load/) {
  1402. $self->analyze_cpu_subsystem();
  1403. #$self->auto_blacklist();
  1404. $self->check_cpu_subsystem();
  1405. } elsif ($self->mode =~ /device::hardware::memory/) {
  1406. $self->analyze_mem_subsystem();
  1407. #$self->auto_blacklist();
  1408. $self->check_mem_subsystem();
  1409. } elsif ($self->mode =~ /device::interfaces/) {
  1410. $self->analyze_interface_subsystem();
  1411. $self->check_interface_subsystem();
  1412. } elsif ($self->mode =~ /device::shinken::interface/) {
  1413. $self->analyze_interface_subsystem();
  1414. $self->shinken_interface_subsystem();
  1415. } elsif ($self->mode =~ /device::hsrp/) {
  1416. $self->analyze_hsrp_subsystem();
  1417. $self->check_hsrp_subsystem();
  1418. }
  1419. }
  1420. }
  1421. sub analyze_hsrp_subsystem {
  1422. my $self = shift;
  1423. $self->{components}->{hsrp} =
  1424. NWC::HSRP::Component::HSRPSubsystem->new();
  1425. }
  1426. sub analyze_environmental_subsystem {
  1427. my $self = shift;
  1428. $self->{components}->{environmental_subsystem} =
  1429. NWC::CiscoIOS::Component::EnvironmentalSubsystem->new();
  1430. }
  1431. sub analyze_interface_subsystem {
  1432. my $self = shift;
  1433. $self->{components}->{interface_subsystem} =
  1434. NWC::IFMIB::Component::InterfaceSubsystem->new();
  1435. }
  1436. sub analyze_cpu_subsystem {
  1437. my $self = shift;
  1438. $self->{components}->{cpu_subsystem} =
  1439. NWC::CiscoIOS::Component::CpuSubsystem->new();
  1440. }
  1441. sub analyze_mem_subsystem {
  1442. my $self = shift;
  1443. $self->{components}->{mem_subsystem} =
  1444. NWC::CiscoIOS::Component::MemSubsystem->new();
  1445. }
  1446. sub check_hsrp_subsystem {
  1447. my $self = shift;
  1448. $self->{components}->{hsrp}->check();
  1449. $self->{components}->{hsrp}->dump()
  1450. if $self->opts->verbose >= 2;
  1451. }
  1452. sub check_environmental_subsystem {
  1453. my $self = shift;
  1454. $self->{components}->{environmental_subsystem}->check();
  1455. $self->{components}->{environmental_subsystem}->dump()
  1456. if $self->opts->verbose >= 2;
  1457. }
  1458. sub check_interface_subsystem {
  1459. my $self = shift;
  1460. $self->{components}->{interface_subsystem}->check();
  1461. $self->{components}->{interface_subsystem}->dump()
  1462. if $self->opts->verbose >= 2;
  1463. }
  1464. sub check_cpu_subsystem {
  1465. my $self = shift;
  1466. $self->{components}->{cpu_subsystem}->check();
  1467. $self->{components}->{cpu_subsystem}->dump()
  1468. if $self->opts->verbose >= 2;
  1469. }
  1470. sub check_mem_subsystem {
  1471. my $self = shift;
  1472. $self->{components}->{mem_subsystem}->check();
  1473. $self->{components}->{mem_subsystem}->dump()
  1474. if $self->opts->verbose >= 2;
  1475. }
  1476. sub shinken_interface_subsystem {
  1477. my $self = shift;
  1478. my $attr = sprintf "%s", join(',', map {
  1479. sprintf '%s$(%s)$$()$', $_->{ifDescr}, $_->{ifIndex}
  1480. } @{$self->{components}->{interface_subsystem}->{interfaces}});
  1481. printf <<'EOEO', $self->opts->hostname(), $self->opts->hostname(), $attr;
  1482. define host {
  1483. host_name %s
  1484. address %s
  1485. use default-host
  1486. _interfaces %s
  1487. }
  1488. EOEO
  1489. printf <<'EOEO', $self->opts->hostname();
  1490. define service {
  1491. host_name %s
  1492. service_description net_cpu
  1493. check_command check_nwc_health!cpu-load!80%%!90%%
  1494. }
  1495. EOEO
  1496. printf <<'EOEO', $self->opts->hostname();
  1497. define service {
  1498. host_name %s
  1499. service_description net_mem
  1500. check_command check_nwc_health!memory-usage!80%%!90%%
  1501. }
  1502. EOEO
  1503. printf <<'EOEO', $self->opts->hostname();
  1504. define service {
  1505. host_name %s
  1506. service_description net_ifusage_$KEY$
  1507. check_command check_nwc_health!interface-usage!$VALUE1$!$VALUE2$
  1508. duplicate_foreach _interfaces
  1509. default_value 80%%|90%%
  1510. }
  1511. EOEO
  1512. }
  1513. package NWC::CiscoNXOS::Component::CpuSubsystem;
  1514. our @ISA = qw(NWC::CiscoNXOS);
  1515. use strict;
  1516. use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  1517. sub new {
  1518. my $class = shift;
  1519. my %params = @_;
  1520. my $self = {
  1521. cpus => [],
  1522. blacklisted => 0,
  1523. info => undef,
  1524. extendedinfo => undef,
  1525. };
  1526. bless $self, $class;
  1527. $self->init(%params);
  1528. return $self;
  1529. }
  1530. sub init {
  1531. my $self = shift;
  1532. my %params = @_;
  1533. my $type = 0;
  1534. foreach ($self->get_snmp_table_objects(
  1535. 'CISCO-PROCESS-MIB', 'cpmCPUTotalTable')) {
  1536. $_->{cpmCPUTotalIndex} ||= $type++;
  1537. push(@{$self->{cpus}},
  1538. NWC::CiscoNXOS::Component::CpuSubsystem::Cpu->new(%{$_}));
  1539. }
  1540. if (scalar(@{$self->{cpus}}) == 0) {
  1541. # maybe too old. i fake a cpu. be careful. this is a really bad hack
  1542. my $response = $self->get_request(
  1543. -varbindlist => [
  1544. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1},
  1545. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5},
  1546. $NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{busyPer},
  1547. ]
  1548. );
  1549. if (exists $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}}) {
  1550. push(@{$self->{cpus}},
  1551. NWC::CiscoNXOS::Component::CpuSubsystem::Cpu->new(
  1552. cpmCPUTotalPhysicalIndex => 0, #fake
  1553. cpmCPUTotalIndex => 0, #fake
  1554. cpmCPUTotal5sec => 0, #fake
  1555. cpmCPUTotal5secRev => 0, #fake
  1556. cpmCPUTotal1min => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}},
  1557. cpmCPUTotal1minRev => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy1}},
  1558. cpmCPUTotal5min => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5}},
  1559. cpmCPUTotal5minRev => $response->{$NWC::Device::mibs_and_oids->{'OLD-CISCO-CPU-MIB'}->{avgBusy5}},
  1560. cpmCPUMonInterval => 0, #fake
  1561. cpmCPUTotalMonIntervalValue => 0, #fake
  1562. cpmCPUInterruptMonIntervalValue => 0, #fake
  1563. ));
  1564. }
  1565. }
  1566. }
  1567. sub check {
  1568. my $self = shift;
  1569. my $errorfound = 0;

Large files files are truncated, but you can click here to view the full file