File Coverage

blib/lib/Monitoring/GLPlugin.pm
Criterion Covered Total %
statement 256 893 28.6
branch 86 376 22.8
condition 29 155 18.7
subroutine 31 89 34.8
pod 0 71 0.0
total 402 1584 25.3


line stmt bran cond sub pod time code
1             package Monitoring::GLPlugin;
2              
3             =head1 Monitoring::GLPlugin
4              
5             Monitoring::GLPlugin - infrastructure functions to build a monitoring plugin
6              
7             =cut
8              
9 3     3   89727 use strict;
  3         5  
  3         85  
10 3     3   1397 use IO::File;
  3         19107  
  3         292  
11 3     3   15 use File::Basename;
  3         10  
  3         143  
12 3     3   12 use Digest::MD5 qw(md5_hex);
  3         3  
  3         104  
13 3     3   405 use Errno;
  3         895  
  3         87  
14 3     3   1544 use Data::Dumper;
  3         14394  
  3         200  
15             our $AUTOLOAD;
16             *VERSION = \'2.3';
17              
18 3     3   14 use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
  3         3  
  3         6198  
19              
20             {
21             our $mode = undef;
22             our $plugin = undef;
23             our $pluginname = basename($ENV{'NAGIOS_PLUGIN'} || $0);
24             our $blacklist = undef;
25             our $info = [];
26             our $extendedinfo = [];
27             our $summary = [];
28             our $variables = {};
29             our $survive_sudo_env = ["LD_LIBRARY_PATH", "SHLIB_PATH"];
30             }
31              
32             sub new {
33 3     3 0 640 my ($class, %params) = @_;
34 3         6 my $self = {};
35 3         5 bless $self, $class;
36             require Monitoring::GLPlugin::Commandline
37 3 100       949 if ! grep /BEGIN/, keys %Monitoring::GLPlugin::Commandline::;
38             require Monitoring::GLPlugin::Item
39 3 100       749 if ! grep /BEGIN/, keys %Monitoring::GLPlugin::Item::;
40             require Monitoring::GLPlugin::TableItem
41 3 100       733 if ! grep /BEGIN/, keys %Monitoring::GLPlugin::TableItem::;
42 3         21 $Monitoring::GLPlugin::plugin = Monitoring::GLPlugin::Commandline->new(%params);
43 3         15 return $self;
44             }
45              
46             sub init {
47 0     0 0 0 my ($self) = @_;
48 0 0 0     0 if ($self->opts->can("blacklist") && $self->opts->blacklist &&
      0        
49             -f $self->opts->blacklist) {
50 0         0 $self->opts->blacklist = do {
51 0         0 local (@ARGV, $/) = $self->opts->blacklist; <> };
  0         0  
52             }
53             }
54              
55             sub dumper {
56 0     0 0 0 my ($self, $object) = @_;
57 0         0 my $run = $object->{runtime};
58 0         0 delete $object->{runtime};
59 0         0 printf STDERR "%s\n", Data::Dumper::Dumper($object);
60 0         0 $object->{runtime} = $run;
61             }
62              
63             sub no_such_mode {
64 0     0 0 0 my ($self) = @_;
65 0         0 printf "Mode %s is not implemented for this type of device\n",
66             $self->opts->mode;
67 0         0 exit 3;
68             }
69              
70             #########################################################
71             # framework-related. setup, options
72             #
73             sub add_default_args {
74 3     3 0 14 my ($self) = @_;
75 3         10 $self->add_arg(
76             spec => 'mode=s',
77             help => "--mode
78             A keyword which tells the plugin what to do",
79             required => 1,
80             );
81 3         7 $self->add_arg(
82             spec => 'regexp',
83             help => "--regexp
84             Parameter name/name2/name3 will be interpreted as (perl) regular expression",
85             required => 0,);
86 3         5 $self->add_arg(
87             spec => 'warning=s',
88             help => "--warning
89             The warning threshold",
90             required => 0,);
91 3         6 $self->add_arg(
92             spec => 'critical=s',
93             help => "--critical
94             The critical threshold",
95             required => 0,);
96 3         6 $self->add_arg(
97             spec => 'warningx=s%',
98             help => '--warningx
99             The extended warning thresholds
100             e.g. --warningx db_msdb_free_pct=6: to override the threshold for a
101             specific item ',
102             required => 0,
103             );
104 3         6 $self->add_arg(
105             spec => 'criticalx=s%',
106             help => '--criticalx
107             The extended critical thresholds',
108             required => 0,
109             );
110 3         5 $self->add_arg(
111             spec => 'units=s',
112             help => "--units
113             One of %, B, KB, MB, GB, Bit, KBi, MBi, GBi. (used for e.g. mode interface-usage)",
114             required => 0,
115             );
116 3         6 $self->add_arg(
117             spec => 'name=s',
118             help => "--name
119             The name of a specific component to check",
120             required => 0,
121             );
122 3         7 $self->add_arg(
123             spec => 'name2=s',
124             help => "--name2
125             The secondary name of a component",
126             required => 0,
127             );
128 3         6 $self->add_arg(
129             spec => 'name3=s',
130             help => "--name3
131             The tertiary name of a component",
132             required => 0,
133             );
134 3         5 $self->add_arg(
135             spec => 'extra-opts=s',
136             help => "--extra-opts
137             read command line arguments from an external file",
138             required => 0,
139             );
140 3         5 $self->add_arg(
141             spec => 'blacklist|b=s',
142             help => '--blacklist
143             Blacklist some (missing/failed) components',
144             required => 0,
145             default => '',
146             );
147 3         6 $self->add_arg(
148             spec => 'mitigation=s',
149             help => "--mitigation
150             The parameter allows you to change a critical error to a warning.",
151             required => 0,
152             );
153 3         6 $self->add_arg(
154             spec => 'lookback=s',
155             help => "--lookback
156             The amount of time you want to look back when calculating average rates.
157             Use it for mode interface-errors or interface-usage. Without --lookback
158             the time between two runs of check_nwc_health is the base for calculations.
159             If you want your checkresult to be based for example on the past hour,
160             use --lookback 3600. ",
161             required => 0,
162             );
163 3         10 $self->add_arg(
164             spec => 'environment|e=s%',
165             help => "--environment
166             Add a variable to the plugin's environment",
167             required => 0,
168             );
169 3         5 $self->add_arg(
170             spec => 'negate=s%',
171             help => "--negate
172             Emulate the negate plugin. --negate warning=critical --negate unknown=critical",
173             required => 0,
174             );
175 3         6 $self->add_arg(
176             spec => 'morphmessage=s%',
177             help => '--morphmessage
178             Modify the final output message',
179             required => 0,
180             );
181 3         3 $self->add_arg(
182             spec => 'morphperfdata=s%',
183             help => "--morphperfdata
184             The parameter allows you to change performance data labels.
185             It's a perl regexp and a substitution.
186             Example: --morphperfdata '(.*)ISATAP(.*)'='\$1patasi\$2'",
187             required => 0,
188             );
189 3         5 $self->add_arg(
190             spec => 'selectedperfdata=s',
191             help => "--selectedperfdata
192             The parameter allows you to limit the list of performance data. It's a perl regexp.
193             Only matching perfdata show up in the output",
194             required => 0,
195             );
196 3         7 $self->add_arg(
197             spec => 'report=s',
198             help => "--report
199             Can be used to shorten the output",
200             required => 0,
201             default => 'long',
202             );
203 3         8 $self->add_arg(
204             spec => 'multiline',
205             help => '--multiline
206             Multiline output',
207             required => 0,
208             );
209 3         5 $self->add_arg(
210             spec => 'with-mymodules-dyn-dir=s',
211             help => "--with-mymodules-dyn-dir
212             Add-on modules for the my-modes will be searched in this directory",
213             required => 0,
214             );
215 3         5 $self->add_arg(
216             spec => 'statefilesdir=s',
217             help => '--statefilesdir
218             An alternate directory where the plugin can save files',
219             required => 0,
220             env => 'STATEFILESDIR',
221             );
222 3         5 $self->add_arg(
223             spec => 'isvalidtime=i',
224             help => '--isvalidtime
225             Signals the plugin to return OK if now is not a valid check time',
226             required => 0,
227             default => 1,
228             );
229 3         4 $self->add_arg(
230             spec => 'reset',
231             help => "--reset
232             remove the state file",
233             required => 0,
234             hidden => 1,
235             );
236 3         5 $self->add_arg(
237             spec => 'runas=s',
238             help => "--runas
239             run as a different user",
240             required => 0,
241             hidden => 1,
242             );
243 3         5 $self->add_arg(
244             spec => 'shell',
245             help => "--shell
246             forget what you see",
247             required => 0,
248             hidden => 1,
249             );
250 3         23 $self->add_arg(
251             spec => 'drecksptkdb=s',
252             help => "--drecksptkdb
253             This parameter must be used instead of --name, because Devel::ptkdb is stealing the latter from the command line",
254             aliasfor => "name",
255             required => 0,
256             hidden => 1,
257             );
258             }
259              
260             sub add_modes {
261 0     0 0 0 my ($self, $modes) = @_;
262 0         0 my $modestring = "";
263 0         0 my @modes = @{$modes};
  0         0  
264 0         0 my $longest = length ((reverse sort {length $a <=> length $b} map { $_->[1] } @modes)[0]);
  0         0  
  0         0  
265             my $format = " %-".
266 0         0 (length ((reverse sort {length $a <=> length $b} map { $_->[1] } @modes)[0])).
  0         0  
  0         0  
267             "s\t(%s)\n";
268 0         0 foreach (@modes) {
269 0         0 $modestring .= sprintf $format, $_->[1], $_->[3];
270             }
271 0         0 $modestring .= sprintf "\n";
272 0         0 $Monitoring::GLPlugin::plugin->{modestring} = $modestring;
273             }
274              
275             sub add_arg {
276 84     84 0 131 my ($self, %args) = @_;
277 84 100       126 if ($args{help} =~ /^--mode/) {
278 3         30 $args{help} .= "\n".$Monitoring::GLPlugin::plugin->{modestring};
279             }
280 84         156 $Monitoring::GLPlugin::plugin->{opts}->add_arg(%args);
281             }
282              
283             sub mod_arg {
284 0     0 0 0 my ($self, @arg) = @_;
285 0         0 $Monitoring::GLPlugin::plugin->{opts}->mod_arg(@arg);
286             }
287              
288             sub add_mode {
289 3     3 0 24 my ($self, %args) = @_;
290 3         5 push(@{$Monitoring::GLPlugin::plugin->{modes}}, \%args);
  3         6  
291 3         5 my $longest = length ((reverse sort {length $a <=> length $b} map { $_->{spec} } @{$Monitoring::GLPlugin::plugin->{modes}})[0]);
  0         0  
  3         13  
  3         5  
292             my $format = " %-".
293 3         5 (length ((reverse sort {length $a <=> length $b} map { $_->{spec} } @{$Monitoring::GLPlugin::plugin->{modes}})[0])).
  0         0  
  3         11  
  3         4  
294             "s\t(%s)\n";
295 3         6 $Monitoring::GLPlugin::plugin->{modestring} = "";
296 3         3 foreach (@{$Monitoring::GLPlugin::plugin->{modes}}) {
  3         6  
297 3         14 $Monitoring::GLPlugin::plugin->{modestring} .= sprintf $format, $_->{spec}, $_->{help};
298             }
299 3         8 $Monitoring::GLPlugin::plugin->{modestring} .= "\n";
300             }
301              
302             sub validate_args {
303 2     2 0 9 my ($self) = @_;
304 2 50 33     5 if ($self->opts->mode =~ /^my-([^\-.]+)/) {
    50          
    50          
    50          
305 0         0 my $param = $self->opts->mode;
306 0         0 $param =~ s/\-/::/g;
307 0         0 $self->add_mode(
308             internal => $param,
309             spec => $self->opts->mode,
310             alias => undef,
311             help => 'my extension',
312             );
313             } elsif ($self->opts->mode eq 'encode') {
314 0         0 my $input = <>;
315 0         0 chomp $input;
316 0         0 $input =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
  0         0  
317 0         0 printf "%s\n", $input;
318 0         0 exit 0;
319             } elsif ($self->opts->mode eq 'decode') {
320 0 0       0 if (! -t STDIN) {
321 0         0 my $input = <>;
322 0         0 chomp $input;
323 0         0 $input =~ s/%([A-Za-z0-9]{2})/chr(hex($1))/seg;
  0         0  
324 0         0 printf "%s\n", $input;
325 0         0 exit OK;
326             } else {
327 0 0       0 if ($self->opts->name) {
328 0         0 my $input = $self->opts->name;
329 0         0 $input =~ s/%([A-Za-z0-9]{2})/chr(hex($1))/seg;
  0         0  
330 0         0 printf "%s\n", $input;
331 0         0 exit OK;
332             } else {
333 0         0 printf "i can't find your encoded statement. use --name or pipe it in my stdin\n";
334 0         0 exit UNKNOWN;
335             }
336             }
337             } elsif ((! grep { $self->opts->mode eq $_ } map { $_->{spec} } @{$Monitoring::GLPlugin::plugin->{modes}}) &&
338             (! grep { $self->opts->mode eq $_ } map { defined $_->{alias} ? @{$_->{alias}} : () } @{$Monitoring::GLPlugin::plugin->{modes}})) {
339 0         0 printf "UNKNOWN - mode %s\n", $self->opts->mode;
340 0         0 $self->opts->print_help();
341 0         0 exit 3;
342             }
343 2 50 33     5 if ($self->opts->name && $self->opts->name =~ /(%22)|(%27)/) {
344 0         0 my $name = $self->opts->name;
345 0         0 $name =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
  0         0  
346 0         0 $self->override_opt('name', $name);
347             }
348             $Monitoring::GLPlugin::mode = (
349 2         6 map { $_->{internal} }
350             grep {
351             ($self->opts->mode eq $_->{spec}) ||
352 2 50 0     4 ( defined $_->{alias} && grep { $self->opts->mode eq $_ } @{$_->{alias}})
  0         0  
  0         0  
353 2         3 } @{$Monitoring::GLPlugin::plugin->{modes}}
  2         7  
354             )[0];
355 2 50       6 if ($self->opts->multiline) {
356 0         0 $ENV{NRPE_MULTILINESUPPORT} = 1;
357             } else {
358 2         17 $ENV{NRPE_MULTILINESUPPORT} = 0;
359             }
360 2 50 33     6 if ($self->opts->can("statefilesdir") && ! $self->opts->statefilesdir) {
361 0 0       0 if ($^O =~ /MSWin/) {
    0          
362 0 0       0 if (defined $ENV{TEMP}) {
    0          
    0          
363 0         0 $self->override_opt('statefilesdir', $ENV{TEMP}."/".$Monitoring::GLPlugin::plugin->{name});
364             } elsif (defined $ENV{TMP}) {
365 0         0 $self->override_opt('statefilesdir', $ENV{TMP}."/".$Monitoring::GLPlugin::plugin->{name});
366             } elsif (defined $ENV{windir}) {
367 0         0 $self->override_opt('statefilesdir', File::Spec->catfile($ENV{windir}, 'Temp')."/".$Monitoring::GLPlugin::plugin->{name});
368             } else {
369 0         0 $self->override_opt('statefilesdir', "C:/".$Monitoring::GLPlugin::plugin->{name});
370             }
371             } elsif (exists $ENV{OMD_ROOT}) {
372 0         0 $self->override_opt('statefilesdir', $ENV{OMD_ROOT}."/var/tmp/".$Monitoring::GLPlugin::plugin->{name});
373             } else {
374 0         0 $self->override_opt('statefilesdir', "/var/tmp/".$Monitoring::GLPlugin::plugin->{name});
375             }
376             }
377 2 50       4 $Monitoring::GLPlugin::plugin->{statefilesdir} = $self->opts->statefilesdir
378             if $self->opts->can("statefilesdir");
379 2 50 33     5 if ($self->opts->can("warningx") && $self->opts->warningx) {
380 0         0 foreach my $key (keys %{$self->opts->warningx}) {
  0         0  
381             $self->set_thresholds(metric => $key,
382 0         0 warning => $self->opts->warningx->{$key});
383             }
384             }
385 2 50 33     6 if ($self->opts->can("criticalx") && $self->opts->criticalx) {
386 0         0 foreach my $key (keys %{$self->opts->criticalx}) {
  0         0  
387             $self->set_thresholds(metric => $key,
388 0         0 critical => $self->opts->criticalx->{$key});
389             }
390             }
391 2 50       32 $self->set_timeout_alarm() if ! $SIG{'ALRM'};
392             }
393              
394             sub set_timeout_alarm {
395 2     2 0 3 my ($self, $timeout, $handler) = @_;
396 2   33     9 $timeout ||= $self->opts->timeout;
397             $handler ||= sub {
398             printf "UNKNOWN - %s timed out after %d seconds\n",
399 0     0   0 $Monitoring::GLPlugin::plugin->{name}, $self->opts->timeout;
400 0         0 exit 3;
401 2   50     14 };
402 3     3   1547 use POSIX ':signal_h';
  3         13072  
  3         14  
403 2 50       10 if ($^O =~ /MSWin/) {
404 0         0 local $SIG{'ALRM'} = $handler;
405             } else {
406 2         29 my $mask = POSIX::SigSet->new( SIGALRM );
407 2         14 my $action = POSIX::SigAction->new(
408             $handler, $mask
409             );
410 2         22 my $oldaction = POSIX::SigAction->new();
411 2         74 sigaction(SIGALRM ,$action ,$oldaction );
412             }
413 2         23 alarm(int($timeout)); # 1 second before the global unknown timeout
414             }
415              
416             #########################################################
417             # global helpers
418             #
419             sub set_variable {
420 2     2 0 4 my ($self, $key, $value) = @_;
421 2         7 $Monitoring::GLPlugin::variables->{$key} = $value;
422             }
423              
424             sub get_variable {
425 130     130 0 133 my ($self, $key, $fallback) = @_;
426             return exists $Monitoring::GLPlugin::variables->{$key} ?
427 130 50       486 $Monitoring::GLPlugin::variables->{$key} : $fallback;
428             }
429              
430             sub debug {
431 130     130 0 7195 my ($self, $format, @message) = @_;
432 130         223 my $tracefile = "/tmp/".$Monitoring::GLPlugin::pluginname.".trace";
433 130 50       1166 $self->{trace} = -f $tracefile ? 1 : 0;
434 130 50 33     281 if ($self->get_variable("verbose") &&
435             $self->get_variable("verbose") > $self->get_variable("verbosity", 10)) {
436 0         0 printf("%s: ", scalar localtime);
437 0         0 printf($format, @message);
438 0         0 printf "\n";
439             }
440 130 50       302 if ($self->{trace}) {
441 0         0 my $logfh = IO::File->new();
442 0         0 $logfh->autoflush(1);
443 0 0       0 if ($logfh->open($tracefile, "a")) {
444 0         0 $logfh->printf("%s: ", scalar localtime);
445 0         0 $logfh->printf($format, @message);
446 0         0 $logfh->printf("\n");
447 0         0 $logfh->close();
448             }
449             }
450             }
451              
452             sub filter_namex {
453 0     0 0 0 my ($self, $opt, $name) = @_;
454 0 0       0 if ($opt) {
455 0 0       0 if ($self->opts->regexp) {
456 0 0       0 if ($name =~ /$opt/i) {
457 0         0 return 1;
458             }
459             } else {
460 0 0       0 if (lc $opt eq lc $name) {
461 0         0 return 1;
462             }
463             }
464             } else {
465 0         0 return 1;
466             }
467 0         0 return 0;
468             }
469              
470             sub filter_name {
471 0     0 0 0 my ($self, $name) = @_;
472 0         0 return $self->filter_namex($self->opts->name, $name);
473             }
474              
475             sub filter_name2 {
476 0     0 0 0 my ($self, $name) = @_;
477 0         0 return $self->filter_namex($self->opts->name2, $name);
478             }
479              
480             sub filter_name3 {
481 0     0 0 0 my ($self, $name) = @_;
482 0         0 return $self->filter_namex($self->opts->name3, $name);
483             }
484              
485             sub version_is_minimum {
486 0     0 0 0 my ($self, $version) = @_;
487 0         0 my $installed_version;
488 0         0 my $newer = 1;
489 0 0       0 if ($self->get_variable("version")) {
    0          
490 0         0 $installed_version = $self->get_variable("version");
491             } elsif (exists $self->{version}) {
492 0         0 $installed_version = $self->{version};
493             } else {
494 0         0 return 0;
495             }
496 0 0       0 my @v1 = map { $_ eq "x" ? 0 : $_ } split(/\./, $version);
  0         0  
497 0         0 my @v2 = split(/\./, $installed_version);
498 0 0       0 if (scalar(@v1) > scalar(@v2)) {
    0          
499 0         0 push(@v2, (0) x (scalar(@v1) - scalar(@v2)));
500             } elsif (scalar(@v2) > scalar(@v1)) {
501 0         0 push(@v1, (0) x (scalar(@v2) - scalar(@v1)));
502             }
503 0         0 foreach my $pos (0..$#v1) {
504 0 0       0 if ($v2[$pos] > $v1[$pos]) {
    0          
505 0         0 $newer = 1;
506 0         0 last;
507             } elsif ($v2[$pos] < $v1[$pos]) {
508 0         0 $newer = 0;
509 0         0 last;
510             }
511             }
512 0         0 return $newer;
513             }
514              
515             sub accentfree {
516 0     0 0 0 my ($self, $text) = @_;
517             # thanks mycoyne who posted this accent-remove-algorithm
518             # http://www.experts-exchange.com/Programming/Languages/Scripting/Perl/Q_23275533.html#a21234612
519 0         0 my @transformed;
520 0         0 my %replace = (
521             '9a' => 's', '9c' => 'oe', '9e' => 'z', '9f' => 'Y', 'c0' => 'A', 'c1' => 'A',
522             'c2' => 'A', 'c3' => 'A', 'c4' => 'A', 'c5' => 'A', 'c6' => 'AE', 'c7' => 'C',
523             'c8' => 'E', 'c9' => 'E', 'ca' => 'E', 'cb' => 'E', 'cc' => 'I', 'cd' => 'I',
524             'ce' => 'I', 'cf' => 'I', 'd0' => 'D', 'd1' => 'N', 'd2' => 'O', 'd3' => 'O',
525             'd4' => 'O', 'd5' => 'O', 'd6' => 'O', 'd8' => 'O', 'd9' => 'U', 'da' => 'U',
526             'db' => 'U', 'dc' => 'U', 'dd' => 'Y', 'e0' => 'a', 'e1' => 'a', 'e2' => 'a',
527             'e3' => 'a', 'e4' => 'a', 'e5' => 'a', 'e6' => 'ae', 'e7' => 'c', 'e8' => 'e',
528             'e9' => 'e', 'ea' => 'e', 'eb' => 'e', 'ec' => 'i', 'ed' => 'i', 'ee' => 'i',
529             'ef' => 'i', 'f0' => 'o', 'f1' => 'n', 'f2' => 'o', 'f3' => 'o', 'f4' => 'o',
530             'f5' => 'o', 'f6' => 'o', 'f8' => 'o', 'f9' => 'u', 'fa' => 'u', 'fb' => 'u',
531             'fc' => 'u', 'fd' => 'y', 'ff' => 'y',
532             );
533 0         0 my @letters = split //, $text;;
534 0         0 for (my $i = 0; $i <= $#letters; $i++) {
535 0         0 my $hex = sprintf "%x", ord($letters[$i]);
536 0 0       0 $letters[$i] = $replace{$hex} if (exists $replace{$hex});
537             }
538 0         0 push @transformed, @letters;
539 0         0 return join '', @transformed;
540             }
541              
542             sub dump {
543 0     0 0 0 my ($self) = @_;
544 0         0 my $class = ref($self);
545 0         0 $class =~ s/^.*:://;
546 0 0       0 if (exists $self->{flat_indices}) {
547 0         0 printf "[%s_%s]\n", uc $class, $self->{flat_indices};
548             } else {
549 0         0 printf "[%s]\n", uc $class;
550             }
551 0         0 foreach (grep !/^(info|trace|warning|critical|blacklisted|extendedinfo|flat_indices|indices)$/, sort keys %{$self}) {
  0         0  
552 0 0 0     0 printf "%s: %s\n", $_, $self->{$_} if defined $self->{$_} && ref($self->{$_}) ne "ARRAY";
553             }
554 0 0       0 if ($self->{info}) {
555 0         0 printf "info: %s\n", $self->{info};
556             }
557 0         0 printf "\n";
558 0         0 foreach (grep !/^(info|trace|warning|critical|blacklisted|extendedinfo|flat_indices|indices)$/, sort keys %{$self}) {
  0         0  
559 0 0 0     0 if (defined $self->{$_} && ref($self->{$_}) eq "ARRAY") {
560 0         0 my $have_flat_indices = 1;
561 0         0 foreach my $obj (@{$self->{$_}}) {
  0         0  
562 0 0 0     0 $have_flat_indices = 0 if (ref($obj) ne "HASH" || ! exists $obj->{flat_indices});
563             }
564 0 0       0 if ($have_flat_indices) {
565 0         0 foreach my $obj (sort {
566 0         0 join('', map { sprintf("%30d",$_) } split( /\./, $a->{flat_indices})) cmp
567 0         0 join('', map { sprintf("%30d",$_) } split( /\./, $b->{flat_indices}))
  0         0  
568 0         0 } @{$self->{$_}}) {
569 0         0 $obj->dump();
570             }
571             } else {
572 0         0 foreach my $obj (@{$self->{$_}}) {
  0         0  
573 0 0 0     0 $obj->dump() if UNIVERSAL::can($obj, "isa") && $obj->can("dump");
574             }
575             }
576             }
577             }
578             }
579              
580             sub table_ascii {
581 0     0 0 0 my ($self, $table, $titles) = @_;
582 0         0 my $text = "";
583 0         0 my $column_length = {};
584 0         0 my $column = 0;
585 0         0 foreach (@{$titles}) {
  0         0  
586 0         0 $column_length->{$column++} = length($_);
587             }
588 0         0 foreach my $tr (@{$table}) {
  0         0  
589 0 0       0 @{$tr} = map { ref($_) eq "ARRAY" ? $_->[0] : $_; } @{$tr};
  0         0  
  0         0  
  0         0  
590 0         0 $column = 0;
591 0         0 foreach my $td (@{$tr}) {
  0         0  
592 0 0       0 if (length($td) > $column_length->{$column}) {
593 0         0 $column_length->{$column} = length($td);
594             }
595 0         0 $column++;
596             }
597             }
598 0         0 $column = 0;
599 0         0 foreach (@{$titles}) {
  0         0  
600 0         0 $column_length->{$column} = "%".($column_length->{$column} + 3)."s";
601 0         0 $column++;
602             }
603 0         0 $column = 0;
604 0         0 foreach (@{$titles}) {
  0         0  
605 0         0 $text .= sprintf $column_length->{$column++}, $_;
606             }
607 0         0 $text .= "\n";
608 0         0 foreach my $tr (@{$table}) {
  0         0  
609 0         0 $column = 0;
610 0         0 foreach my $td (@{$tr}) {
  0         0  
611 0         0 $text .= sprintf $column_length->{$column++}, $td;
612             }
613 0         0 $text .= "\n";
614             }
615 0         0 return $text;
616             }
617              
618             sub table_html {
619 0     0 0 0 my ($self, $table, $titles) = @_;
620 0         0 my $text = "";
621 0         0 $text .= ""; "; ", $_; "; "; ", $class, $td; ";
622 0         0 $text .= "
623 0         0 foreach (@{$titles}) {
  0         0  
624 0         0 $text .= sprintf "%s
625             }
626 0         0 $text .= "
627 0         0 foreach my $tr (@{$table}) {
  0         0  
628 0         0 $text .= "
629 0         0 foreach my $td (@{$tr}) {
  0         0  
630 0         0 my $class = "statusOK";
631 0 0       0 if (ref($td) eq "ARRAY") {
632             $class = {
633             0 => "statusOK",
634             1 => "statusWARNING",
635             2 => "statusCRITICAL",
636             3 => "statusUNKNOWN",
637 0         0 }->{$td->[1]};
638 0         0 $td = $td->[0];
639             }
640 0         0 $text .= sprintf "%s
641             }
642 0         0 $text .= "
643             }
644 0         0 $text .= "
";
645 0         0 return $text;
646             }
647              
648             sub load_my_extension {
649 0     0 0 0 my ($self) = @_;
650 0 0       0 if ($self->opts->mode =~ /^my-([^-.]+)/) {
651 0         0 my $class = $1;
652 0         0 my $loaderror = undef;
653 0         0 substr($class, 0, 1) = uc substr($class, 0, 1);
654 0 0       0 if (! $self->opts->get("with-mymodules-dyn-dir")) {
655 0         0 $self->override_opt("with-mymodules-dyn-dir", "");
656             }
657 0         0 my $plugin_name = $Monitoring::GLPlugin::pluginname;
658 0         0 $plugin_name =~ /check_(.*?)_health/;
659 0         0 my $deprecated_class = "DBD::".(uc $1)."::Server";
660 0         0 $plugin_name = "Check".uc(substr($1, 0, 1)).substr($1, 1)."Health";
661 0         0 foreach my $libpath (split(":", $self->opts->get("with-mymodules-dyn-dir"))) {
662 0         0 foreach my $extmod (glob $libpath."/".$plugin_name."*.pm") {
663 0         0 my $stderrvar;
664 0         0 *SAVEERR = *STDERR;
665 0         0 open OUT ,'>',\$stderrvar;
666 0         0 *STDERR = *OUT;
667 0         0 eval {
668 0         0 $self->debug(sprintf "loading module %s", $extmod);
669 0         0 require $extmod;
670             };
671 0         0 *STDERR = *SAVEERR;
672 0 0       0 if ($@) {
673 0         0 $loaderror = $extmod;
674 0         0 $self->debug(sprintf "failed loading module %s: %s", $extmod, $@);
675             }
676             }
677             }
678 0         0 my $original_class = ref($self);
679 0         0 my $original_init = $self->can("init");
680 0 0       0 $self->compatibility_class() if $self->can('compatibility_class');
681 0         0 bless $self, "My$class";
682 0 0 0     0 $self->compatibility_methods() if $self->can('compatibility_methods') &&
683             $self->isa($deprecated_class);
684 0 0       0 if ($self->isa("Monitoring::GLPlugin")) {
685 0         0 my $new_init = $self->can("init");
686 0 0       0 if ($new_init == $original_init) {
687 0         0 $self->add_unknown(
688             sprintf "Class %s needs an init() method", ref($self));
689             } else {
690             # now go back to check_*_health.pl where init() will be called
691             }
692             } else {
693 0         0 bless $self, $original_class;
694 0 0       0 $self->add_unknown(
695             sprintf "Class %s is not a subclass of Monitoring::GLPlugin%s",
696             "My$class",
697             $loaderror ? sprintf " (syntax error in %s?)", $loaderror : "" );
698 0         0 my ($code, $message) = $self->check_messages(join => ', ', join_all => ', ');
699 0         0 $self->nagios_exit($code, $message);
700             }
701             }
702             }
703              
704             sub decode_password {
705 0     0 0 0 my ($self, $password) = @_;
706 0 0 0     0 if ($password && $password =~ /^rfc3986:\/\/(.*)/) {
707 0         0 $password = $1;
708 0         0 $password =~ s/%([A-Za-z0-9]{2})/chr(hex($1))/seg;
  0         0  
709             }
710 0         0 return $password;
711             }
712              
713             sub number_of_bits {
714 0     0 0 0 my ($self, $unit) = @_;
715             # https://en.wikipedia.org/wiki/Data_rate_units
716 0         0 my $bits = {
717             'bit' => 1, # Bit per second
718             'B' => 8, # Byte per second, 8 bits per second
719             'kbit' => 1000, # Kilobit per second, 1,000 bits per second
720             'kb' => 1000, # Kilobit per second, 1,000 bits per second
721             'Kibit' => 1024, # Kibibit per second, 1,024 bits per second
722             'kB' => 8000, # Kilobyte per second, 8,000 bits per second
723             'KiB' => 8192, # Kibibyte per second, 1,024 bytes per second
724             'Mbit' => 1000000, # Megabit per second, 1,000,000 bits per second
725             'Mb' => 1000000, # Megabit per second, 1,000,000 bits per second
726             'Mibit' => 1048576, # Mebibit per second, 1,024 kibibits per second
727             'MB' => 8000000, # Megabyte per second, 1,000 kilobytes per second
728             'MiB' => 8388608, # Mebibyte per second, 1,024 kibibytes per second
729             'Gbit' => 1000000000, # Gigabit per second, 1,000 megabits per second
730             'Gb' => 1000000000, # Gigabit per second, 1,000 megabits per second
731             'Gibit' => 1073741824, # Gibibit per second, 1,024 mebibits per second
732             'GB' => 8000000000, # Gigabyte per second, 1,000 megabytes per second
733             'GiB' => 8589934592, # Gibibyte per second, 8192 mebibits per second
734             'Tbit' => 1000000000000, # Terabit per second, 1,000 gigabits per second
735             'Tb' => 1000000000000, # Terabit per second, 1,000 gigabits per second
736             'Tibit' => 1099511627776, # Tebibit per second, 1,024 gibibits per second
737             'TB' => 8000000000000, # Terabyte per second, 1,000 gigabytes per second
738             # eigene kreationen
739             'Bits' => 1,
740             'Bit' => 1, # Bit per second
741             'KB' => 1024, # Kilobyte (like disk kilobyte)
742             'KBi' => 1024, # -"-
743             'MBi' => 1024 * 1024, # Megabyte (like disk megabyte)
744             'GBi' => 1024 * 1024 * 1024, # Gigybate (like disk gigybyte)
745             };
746 0 0       0 if (exists $bits->{$unit}) {
747 0         0 return $bits->{$unit};
748             } else {
749 0         0 return 0;
750             }
751             }
752              
753              
754             #########################################################
755             # runtime methods
756             #
757             sub mode : lvalue {
758 74     74 0 68 my ($self) = @_;
759 74         161 $Monitoring::GLPlugin::mode;
760             }
761              
762             sub statefilesdir {
763 169     169 0 791 my ($self) = @_;
764 169         990 return $Monitoring::GLPlugin::plugin->{statefilesdir};
765             }
766              
767             sub opts { # die beiden _nicht_ in AUTOLOAD schieben, das kracht!
768 277     277 0 274 my ($self) = @_;
769 277         633 return $Monitoring::GLPlugin::plugin->opts();
770             }
771              
772             sub getopts {
773 2     2 0 11 my ($self, $envparams) = @_;
774 2   50     11 $envparams ||= [];
775 2         3 my $needs_restart = 0;
776 2         3 my @restart_opts = ();
777 2         10 $Monitoring::GLPlugin::plugin->getopts();
778             # es kann sein, dass beim aufraeumen zum schluss als erstes objekt
779             # das $Monitoring::GLPlugin::plugin geloescht wird. in anderen destruktoren
780             # (insb. fuer dbi disconnect) steht dann $self->opts->verbose
781             # nicht mehr zur verfuegung bzw. $Monitoring::GLPlugin::plugin->opts ist undef.
782 2         11 $self->set_variable("verbose", $self->opts->verbose);
783             #
784             # die gueltigkeit von modes wird bereits hier geprueft und nicht danach
785             # in validate_args. (zwischen getopts und validate_args wird
786             # normalerweise classify aufgerufen, welches bereits eine verbindung
787             # zum endgeraet herstellt. bei falschem mode waere das eine verschwendung
788             # bzw. durch den exit3 ein evt. unsauberes beenden der verbindung.
789 2 0 33     4 if ((! grep { $self->opts->mode eq $_ } map { $_->{spec} } @{$Monitoring::GLPlugin::plugin->{modes}}) &&
  2         6  
  2         6  
  2         5  
790 0 0       0 (! grep { $self->opts->mode eq $_ } map { defined $_->{alias} ? @{$_->{alias}} : () } @{$Monitoring::GLPlugin::plugin->{modes}})) {
  0         0  
  0         0  
  0         0  
791 0 0       0 if ($self->opts->mode !~ /^my-/) {
792 0         0 printf "UNKNOWN - mode %s\n", $self->opts->mode;
793 0         0 $self->opts->print_help();
794 0         0 exit 3;
795             }
796             }
797 2 50       7 if ($self->opts->environment) {
798             # wenn die gewuenschten Environmentvariablen sich von den derzeit
799             # gesetzten unterscheiden, dann restart. Denn $ENV aendert
800             # _nicht_ das Environment des laufenden Prozesses.
801             # $ENV{ZEUGS} = 1 bedeutet lediglich, dass $ENV{ZEUGS} bei weiterer
802             # Verwendung 1 ist, bedeutet aber _nicht_, dass diese Variable
803             # im Environment des laufenden Prozesses existiert.
804 0         0 foreach (keys %{$self->opts->environment}) {
  0         0  
805 0 0 0     0 if ((! $ENV{$_}) || ($ENV{$_} ne $self->opts->environment->{$_})) {
806 0         0 $needs_restart = 1;
807 0         0 $ENV{$_} = $self->opts->environment->{$_};
808 0         0 $self->debug(sprintf "new %s=%s forces restart\n", $_, $ENV{$_});
809             }
810             }
811             }
812 2 50       6 if ($self->opts->runas) {
813             # exec sudo $0 ... und dann ohne --runas
814 0         0 $needs_restart = 1;
815             # wenn wir environmentvariablen haben, die laut survive_sudo_env als
816             # wichtig erachtet werden, dann muessen wir die ueber einen moeglichen
817             # sudo-aufruf rueberretten, also in zusaetzliche --environment umwandenln.
818             # sudo putzt das Environment naemlich aus.
819 0         0 foreach my $survive_env (@{$Monitoring::GLPlugin::survive_sudo_env}) {
  0         0  
820 0 0 0     0 if ($ENV{$survive_env} && ! scalar(grep { /^$survive_env=/ }
  0         0  
821 0         0 keys %{$self->opts->environment})) {
822 0         0 $self->opts->environment->{$survive_env} = $ENV{$survive_env};
823             printf STDERR "add important --environment %s=%s\n",
824 0 0       0 $survive_env, $ENV{$survive_env} if $self->opts->verbose >= 2;
825 0         0 push(@restart_opts, '--environment');
826             push(@restart_opts, sprintf '%s=%s',
827 0         0 $survive_env, $ENV{$survive_env});
828             }
829             }
830             }
831 2 50       7 if ($needs_restart) {
832 0         0 foreach my $option (keys %{$self->opts->all_my_opts}) {
  0         0  
833             # der fliegt raus, sonst gehts gleich wieder in needs_restart rein
834 0 0       0 next if $option eq "runas";
835 0         0 foreach my $spec (map { $_->{spec} } @{$Monitoring::GLPlugin::plugin->opts->{_args}}) {
  0         0  
  0         0  
836 0 0       0 if ($spec =~ /^(\w+)=(.*)/) {
    0          
837 0 0 0     0 if ($1 eq $option && $2 =~ /s%/) {
    0          
838 0         0 foreach (keys %{$self->opts->$option()}) {
  0         0  
839 0         0 push(@restart_opts, sprintf "--%s", $option);
840 0         0 push(@restart_opts, sprintf "%s=%s", $_, $self->opts->$option()->{$_});
841             }
842             } elsif ($1 eq $option) {
843 0         0 push(@restart_opts, sprintf "--%s", $option);
844 0         0 push(@restart_opts, sprintf "%s", $self->opts->$option());
845             }
846             } elsif ($spec eq $option) {
847 0         0 push(@restart_opts, sprintf "--%s", $option);
848             }
849             }
850             }
851 0 0 0     0 if ($self->opts->runas && ($> == 0)) {
    0          
852             # Ja, es gibt so Narrische, die gehen mit check_by_ssh als root
853             # auf Datenbankmaschinen drauf und lassen dann dort check_oracle_health
854             # laufen. Damit OPS$-Anmeldung dann funktioniert, wird mit --runas
855             # auf eine andere Kennung umgeschwenkt. Diese Kennung gleich fuer
856             # ssh zu verwenden geht aus Sicherheitsgruenden nicht. Narrische halt.
857 0         0 exec "su", "-c", sprintf("%s %s", $0, join(" ", @restart_opts)), "-", $self->opts->runas;
858             } elsif ($self->opts->runas) {
859 0         0 exec "sudo", "-S", "-u", $self->opts->runas, $0, @restart_opts;
860             } else {
861 0         0 exec $0, @restart_opts;
862             # dadurch werden SHLIB oder LD_LIBRARY_PATH sauber gesetzt, damit beim
863             # erneuten Start libclntsh.so etc. gefunden werden.
864             }
865 0         0 exit;
866             }
867 2 50       6 if ($self->opts->shell) {
868             # So komme ich bei den Narrischen zu einer root-Shell.
869 0         0 system("/bin/sh");
870             }
871             }
872              
873              
874             sub add_ok {
875 0     0 0 0 my ($self, $message) = @_;
876 0   0     0 $message ||= $self->{info};
877 0         0 $self->add_message(OK, $message);
878             }
879              
880             sub add_warning {
881 0     0 0 0 my ($self, $message) = @_;
882 0   0     0 $message ||= $self->{info};
883 0         0 $self->add_message(WARNING, $message);
884             }
885              
886             sub add_critical {
887 0     0 0 0 my ($self, $message) = @_;
888 0   0     0 $message ||= $self->{info};
889 0         0 $self->add_message(CRITICAL, $message);
890             }
891              
892             sub add_unknown {
893 0     0 0 0 my ($self, $message) = @_;
894 0   0     0 $message ||= $self->{info};
895 0         0 $self->add_message(UNKNOWN, $message);
896             }
897              
898             sub add_ok_mitigation {
899 0     0 0 0 my ($self, $message) = @_;
900 0 0       0 if (defined $self->opts->mitigation()) {
901 0         0 $self->add_message($self->opts->mitigation(), $message);
902             } else {
903 0         0 $self->add_ok($message);
904             }
905             }
906              
907             sub add_warning_mitigation {
908 0     0 0 0 my ($self, $message) = @_;
909 0 0       0 if (defined $self->opts->mitigation()) {
910 0         0 $self->add_message($self->opts->mitigation(), $message);
911             } else {
912 0         0 $self->add_warning($message);
913             }
914             }
915              
916             sub add_critical_mitigation {
917 0     0 0 0 my ($self, $message) = @_;
918 0 0       0 if (defined $self->opts->mitigation()) {
919 0         0 $self->add_message($self->opts->mitigation(), $message);
920             } else {
921 0         0 $self->add_critical($message);
922             }
923             }
924              
925             sub add_unknown_mitigation {
926 0     0 0 0 my ($self, $message) = @_;
927 0 0       0 if (defined $self->opts->mitigation()) {
928 0         0 $self->add_message($self->opts->mitigation(), $message);
929             } else {
930 0         0 $self->add_unknown($message);
931             }
932             }
933              
934             sub add_message {
935 0     0 0 0 my ($self, $level, $message) = @_;
936 0   0     0 $message ||= $self->{info};
937 0 0       0 $Monitoring::GLPlugin::plugin->add_message($level, $message)
938             unless $self->is_blacklisted();
939 0 0       0 if (exists $self->{failed}) {
940 0 0 0     0 if ($level == UNKNOWN && $self->{failed} == OK) {
    0          
941 0         0 $self->{failed} = $level;
942             } elsif ($level > $self->{failed}) {
943 0         0 $self->{failed} = $level;
944             }
945             }
946             }
947              
948             sub clear_ok {
949 0     0 0 0 my ($self) = @_;
950 0         0 $self->clear_messages(OK);
951             }
952              
953             sub clear_warning {
954 0     0 0 0 my ($self) = @_;
955 0         0 $self->clear_messages(WARNING);
956             }
957              
958             sub clear_critical {
959 0     0 0 0 my ($self) = @_;
960 0         0 $self->clear_messages(CRITICAL);
961             }
962              
963             sub clear_unknown {
964 0     0 0 0 my ($self) = @_;
965 0         0 $self->clear_messages(UNKNOWN);
966             }
967              
968             sub clear_all { # deprecated, use clear_messages
969 0     0 0 0 my ($self) = @_;
970 0         0 $self->clear_ok();
971 0         0 $self->clear_warning();
972 0         0 $self->clear_critical();
973 0         0 $self->clear_unknown();
974             }
975              
976             sub set_level {
977 0     0 0 0 my ($self, $code) = @_;
978 0 0       0 $code = (qw(ok warning critical unknown))[$code] if $code =~ /^\d+$/;
979 0         0 $code = lc $code;
980 0 0       0 if (! exists $self->{tmp_level}) {
981             $self->{tmp_level} = {
982 0         0 ok => 0,
983             warning => 0,
984             critical => 0,
985             unknown => 0,
986             };
987             }
988 0         0 $self->{tmp_level}->{$code}++;
989             }
990              
991             sub get_level {
992 0     0 0 0 my ($self) = @_;
993 0 0       0 return OK if ! exists $self->{tmp_level};
994 0         0 my $code = OK;
995 0 0 0     0 $code ||= CRITICAL if $self->{tmp_level}->{critical};
996 0 0 0     0 $code ||= WARNING if $self->{tmp_level}->{warning};
997 0 0 0     0 $code ||= UNKNOWN if $self->{tmp_level}->{unknown};
998 0         0 return $code;
999             }
1000              
1001             #########################################################
1002             # blacklisting
1003             #
1004             sub blacklist {
1005 0     0 0 0 my ($self) = @_;
1006 0         0 $self->{blacklisted} = 1;
1007             }
1008              
1009             sub add_blacklist {
1010 0     0 0 0 my ($self, $list) = @_;
1011 0         0 $Monitoring::GLPlugin::blacklist = join('/',
1012             (split('/', $self->opts->blacklist), $list));
1013             }
1014              
1015             sub is_blacklisted {
1016 0     0 0 0 my ($self) = @_;
1017 0 0       0 if (! $self->opts->can("blacklist")) {
1018 0         0 return 0;
1019             }
1020 0 0       0 if (! exists $self->{blacklisted}) {
1021 0         0 $self->{blacklisted} = 0;
1022             }
1023 0 0 0     0 if (exists $self->{blacklisted} && $self->{blacklisted}) {
1024 0         0 return $self->{blacklisted};
1025             }
1026             # FAN:459,203/TEMP:102229/ENVSUBSYSTEM
1027             # FAN_459,FAN_203,TEMP_102229,ENVSUBSYSTEM
1028 0 0       0 if ($self->opts->blacklist =~ /_/) {
1029 0         0 foreach my $bl_item (split(/,/, $self->opts->blacklist)) {
1030 0 0       0 if ($bl_item eq $self->internal_name()) {
1031 0         0 $self->{blacklisted} = 1;
1032             }
1033             }
1034             } else {
1035 0         0 foreach my $bl_items (split(/\//, $self->opts->blacklist)) {
1036 0 0       0 if ($bl_items =~ /^(\w+):([\:\d\-,]+)$/) {
    0          
1037 0         0 my $bl_type = $1;
1038 0         0 my $bl_names = $2;
1039 0         0 foreach my $bl_name (split(/,/, $bl_names)) {
1040 0 0       0 if ($bl_type."_".$bl_name eq $self->internal_name()) {
1041 0         0 $self->{blacklisted} = 1;
1042             }
1043             }
1044             } elsif ($bl_items =~ /^(\w+)$/) {
1045 0 0       0 if ($bl_items eq $self->internal_name()) {
1046 0         0 $self->{blacklisted} = 1;
1047             }
1048             }
1049             }
1050             }
1051 0         0 return $self->{blacklisted};
1052             }
1053              
1054             #########################################################
1055             # additional info
1056             #
1057             sub add_info {
1058 0     0 0 0 my ($self, $info) = @_;
1059 0 0       0 $info = $self->is_blacklisted() ? $info.' (blacklisted)' : $info;
1060 0         0 $self->{info} = $info;
1061 0         0 push(@{$Monitoring::GLPlugin::info}, $info);
  0         0  
1062             }
1063              
1064             sub annotate_info {
1065 0     0 0 0 my ($self, $annotation) = @_;
1066 0         0 my $lastinfo = pop(@{$Monitoring::GLPlugin::info});
  0         0  
1067 0         0 $lastinfo .= sprintf ' (%s)', $annotation;
1068 0         0 $self->{info} = $lastinfo;
1069 0         0 push(@{$Monitoring::GLPlugin::info}, $lastinfo);
  0         0  
1070             }
1071              
1072             sub add_extendedinfo { # deprecated
1073 0     0 0 0 my ($self, $info) = @_;
1074 0         0 $self->{extendedinfo} = $info;
1075 0 0       0 return if ! $self->opts->extendedinfo;
1076 0         0 push(@{$Monitoring::GLPlugin::extendedinfo}, $info);
  0         0  
1077             }
1078              
1079             sub get_info {
1080 0     0 0 0 my ($self, $separator) = @_;
1081 0   0     0 $separator ||= ' ';
1082 0         0 return join($separator , @{$Monitoring::GLPlugin::info});
  0         0  
1083             }
1084              
1085             sub get_last_info {
1086 0     0 0 0 my ($self) = @_;
1087 0         0 return pop(@{$Monitoring::GLPlugin::info});
  0         0  
1088             }
1089              
1090             sub get_extendedinfo {
1091 0     0 0 0 my ($self, $separator) = @_;
1092 0   0     0 $separator ||= ' ';
1093 0         0 return join($separator, @{$Monitoring::GLPlugin::extendedinfo});
  0         0  
1094             }
1095              
1096             sub add_summary { # deprecated
1097 0     0 0 0 my ($self, $summary) = @_;
1098 0         0 push(@{$Monitoring::GLPlugin::summary}, $summary);
  0         0  
1099             }
1100              
1101             sub get_summary {
1102 0     0 0 0 my ($self) = @_;
1103 0         0 return join(', ', @{$Monitoring::GLPlugin::summary});
  0         0  
1104             }
1105              
1106             #########################################################
1107             # persistency
1108             #
1109             sub valdiff {
1110 31     31 0 40021137 my ($self, $pparams, @keys) = @_;
1111 31         52 my %params = %{$pparams};
  31         188  
1112 31         75 my $now = time;
1113 31         50 my $newest_history_set = {};
1114 31 50       152 $params{freeze} = 0 if ! $params{freeze};
1115 31         48 my $mode = "normal";
1116 31 50 66     109 if ($self->opts->lookback && $self->opts->lookback == 99999 && $params{freeze} == 0) {
    50 33        
    50 66        
    100 33        
      66        
      33        
1117 0         0 $mode = "lookback_freeze_chill";
1118             } elsif ($self->opts->lookback && $self->opts->lookback == 99999 && $params{freeze} == 1) {
1119 0         0 $mode = "lookback_freeze_shockfrost";
1120             } elsif ($self->opts->lookback && $self->opts->lookback == 99999 && $params{freeze} == 2) {
1121 0         0 $mode = "lookback_freeze_defrost";
1122             } elsif ($self->opts->lookback) {
1123 21         42 $mode = "lookback";
1124             }
1125             # lookback=99999, freeze=0(default)
1126             # nimm den letzten lauf und schreib ihn nach {cold}
1127             # vergleich dann
1128             # wenn es frozen gibt, vergleich frozen und den letzten lauf
1129             # sonst den letzten lauf und den aktuellen lauf
1130             # lookback=99999, freeze=1
1131             # wird dann aufgerufen,wenn nach dem freeze=0 ein problem festgestellt wurde
1132             # (also als 2.valdiff hinterher)
1133             # schreib cold nach frozen
1134             # lookback=99999, freeze=2
1135             # wird dann aufgerufen,wenn nach dem freeze=0 wieder alles ok ist
1136             # (also als 2.valdiff hinterher)
1137             # loescht frozen
1138             #
1139 31   66     139 my $last_values = $self->load_state(%params) || eval {
1140             my $empty_events = {};
1141             foreach (@keys) {
1142             if (ref($self->{$_}) eq "ARRAY") {
1143             $empty_events->{$_} = [];
1144             } else {
1145             $empty_events->{$_} = 0;
1146             }
1147             }
1148             $empty_events->{timestamp} = 0;
1149             if ($mode eq "lookback") {
1150             $empty_events->{lookback_history} = {};
1151             } elsif ($mode eq "lookback_freeze_chill") {
1152             $empty_events->{cold} = {};
1153             $empty_events->{frozen} = {};
1154             }
1155             $empty_events;
1156             };
1157 31         87 $self->{'delta_timestamp'} = $now - $last_values->{timestamp};
1158 31         65 foreach (@keys) {
1159 51 50       136 if ($mode eq "lookback_freeze_chill") {
    100          
1160             # die werte vom letzten lauf wegsichern.
1161             # vielleicht gibts gleich einen freeze=1, dann muessen die eingefroren werden
1162 0 0       0 if (exists $last_values->{$_}) {
1163 0 0       0 if (ref($self->{$_}) eq "ARRAY") {
1164 0         0 $last_values->{cold}->{$_} = [];
1165 0         0 foreach my $value (@{$last_values->{$_}}) {
  0         0  
1166 0         0 push(@{$last_values->{cold}->{$_}}, $value);
  0         0  
1167             }
1168             } else {
1169 0         0 $last_values->{cold}->{$_} = $last_values->{$_};
1170             }
1171             } else {
1172 0 0       0 if (ref($self->{$_}) eq "ARRAY") {
1173 0         0 $last_values->{cold}->{$_} = [];
1174             } else {
1175 0         0 $last_values->{cold}->{$_} = 0;
1176             }
1177             }
1178             # es wird so getan, als sei der frozen wert vom letzten lauf
1179 0 0       0 if (exists $last_values->{frozen}->{$_}) {
1180 0 0       0 if (ref($self->{$_}) eq "ARRAY") {
1181 0         0 $last_values->{$_} = [];
1182 0         0 foreach my $value (@{$last_values->{frozen}->{$_}}) {
  0         0  
1183 0         0 push(@{$last_values->{$_}}, $value);
  0         0  
1184             }
1185             } else {
1186 0         0 $last_values->{$_} = $last_values->{frozen}->{$_};
1187             }
1188             }
1189             } elsif ($mode eq "lookback") {
1190             # find a last_value in the history which fits lookback best
1191             # and overwrite $last_values->{$_} with historic data
1192 37 100       95 if (exists $last_values->{lookback_history}->{$_}) {
1193 34         40 foreach my $date (sort {$a <=> $b} keys %{$last_values->{lookback_history}->{$_}}) {
  365         339  
  34         208  
1194 190         212 $newest_history_set->{$_} = $last_values->{lookback_history}->{$_}->{$date};
1195 190         187 $newest_history_set->{timestamp} = $date;
1196             }
1197 34         54 foreach my $date (sort {$a <=> $b} keys %{$last_values->{lookback_history}->{$_}}) {
  365         284  
  34         97  
1198 42 100       82 if ($date >= ($now - $self->opts->lookback)) {
1199 32         53 $last_values->{$_} = $last_values->{lookback_history}->{$_}->{$date};
1200 32         62 $last_values->{timestamp} = $date;
1201 32 100       75 if (ref($last_values->{$_}) eq "ARRAY") {
1202             $self->debug(sprintf "oldest value of %s within lookback is size %s (age %d)",
1203 14         20 $_, scalar(@{$last_values->{$_}}), time - $date);
  14         76  
1204             } else {
1205             $self->debug(sprintf "oldest value of %s within lookback is %s (age %d)",
1206 18         146 $_, $last_values->{$_}, time - $date);
1207             }
1208 32         56 last;
1209             } else {
1210 10         48 $self->debug(sprintf "deprecate %s of age %d", $_, time - $date);
1211 10         28 delete $last_values->{lookback_history}->{$_}->{$date};
1212             }
1213             }
1214             }
1215             }
1216 51 50 66     243 if ($mode eq "normal" || $mode eq "lookback" || $mode eq "lookback_freeze_chill") {
      33        
1217 51 100       333 if ($self->{$_} =~ /^\d+\.*\d*$/) {
    50          
1218 31 50       87 $last_values->{$_} = 0 if ! exists $last_values->{$_};
1219 31 100       98 if ($self->{$_} >= $last_values->{$_}) {
    50          
1220 15         45 $self->{'delta_'.$_} = $self->{$_} - $last_values->{$_};
1221             } elsif ($self->{$_} eq $last_values->{$_}) {
1222             # dawischt! in einem fall wurde 131071.999023438 >= 131071.999023438 da oben nicht erkannt
1223             # subtrahieren ging auch daneben, weil ein winziger negativer wert rauskam.
1224 0         0 $self->{'delta_'.$_} = 0;
1225             } else {
1226 16 50       46 if ($mode =~ /lookback_freeze/) {
    100          
1227             # hier koennen delta-werte auch negativ sein, wenn z.b. peers verschwinden
1228 0         0 $self->{'delta_'.$_} = $self->{$_} - $last_values->{$_};
1229             } elsif (exists $params{lastarray}) {
1230 15         58 $self->{'delta_'.$_} = $self->{$_} - $last_values->{$_};
1231             } else {
1232             # vermutlich db restart und zaehler alle auf null
1233 1         3 $self->{'delta_'.$_} = $self->{$_};
1234             }
1235             }
1236 31         326 $self->debug(sprintf "delta_%s %f", $_, $self->{'delta_'.$_});
1237             $self->{$_.'_per_sec'} = $self->{'delta_timestamp'} ?
1238 31 100       177 $self->{'delta_'.$_} / $self->{'delta_timestamp'} : 0;
1239             } elsif (ref($self->{$_}) eq "ARRAY") {
1240 20 50 33     265 if ((! exists $last_values->{$_} || ! defined $last_values->{$_}) && exists $params{lastarray}) {
    50 33        
    50 33        
      33        
1241             # innerhalb der lookback-zeit wurde nichts in der lookback_history
1242             # gefunden. allenfalls irgendwas aelteres. normalerweise
1243             # wuerde jetzt das array als [] initialisiert.
1244             # d.h. es wuerde ein delta geben, @found s.u.
1245             # wenn man das nicht will, sondern einfach aktuelles array mit
1246             # dem array des letzten laufs vergleichen will, setzt man lastarray
1247 0         0 $last_values->{$_} = %{$newest_history_set} ?
1248 0 0       0 $newest_history_set->{$_} : []
1249             } elsif ((! exists $last_values->{$_} || ! defined $last_values->{$_}) && ! exists $params{lastarray}) {
1250 0 0       0 $last_values->{$_} = [] if ! exists $last_values->{$_};
1251             } elsif (exists $last_values->{$_} && ! defined $last_values->{$_}) {
1252             # $_ kann es auch ausserhalb des lookback_history-keys als normalen
1253             # key geben. der zeigt normalerweise auf den entspr. letzten
1254             # lookback_history eintrag. wurde der wegen ueberalterung abgeschnitten
1255             # ist der hier auch undef.
1256 0         0 $last_values->{$_} = %{$newest_history_set} ?
1257 0 0       0 $newest_history_set->{$_} : []
1258             }
1259 20         30 my %saved = map { $_ => 1 } @{$last_values->{$_}};
  80         143  
  20         55  
1260 20         31 my %current = map { $_ => 1 } @{$self->{$_}};
  68         97  
  20         40  
1261 20         25 my @found = grep(!defined $saved{$_}, @{$self->{$_}});
  20         76  
1262 20         30 my @lost = grep(!defined $current{$_}, @{$last_values->{$_}});
  20         55  
1263 20         44 $self->{'delta_found_'.$_} = \@found;
1264 20         89 $self->{'delta_lost_'.$_} = \@lost;
1265             }
1266             }
1267             }
1268 31         44 $params{save} = eval {
1269 31         38 my $empty_events = {};
1270 31         58 foreach (@keys) {
1271 51         104 $empty_events->{$_} = $self->{$_};
1272 51 50       106 if ($mode =~ /lookback_freeze/) {
1273 0 0       0 if (exists $last_values->{frozen}->{$_}) {
1274 0 0       0 if (ref($last_values->{frozen}->{$_}) eq "ARRAY") {
1275 0         0 @{$empty_events->{cold}->{$_}} = @{$last_values->{frozen}->{$_}};
  0         0  
  0         0  
1276             } else {
1277 0         0 $empty_events->{cold}->{$_} = $last_values->{frozen}->{$_};
1278             }
1279             } else {
1280 0 0       0 if (ref($last_values->{cold}->{$_}) eq "ARRAY") {
1281 0         0 @{$empty_events->{cold}->{$_}} = @{$last_values->{cold}->{$_}};
  0         0  
  0         0  
1282             } else {
1283 0         0 $empty_events->{cold}->{$_} = $last_values->{cold}->{$_};
1284             }
1285             }
1286 0         0 $empty_events->{cold}->{timestamp} = $last_values->{cold}->{timestamp};
1287             }
1288 51 50       128 if ($mode eq "lookback_freeze_shockfrost") {
1289 0 0       0 if (ref($empty_events->{cold}->{$_}) eq "ARRAY") {
1290 0         0 @{$empty_events->{frozen}->{$_}} = @{$empty_events->{cold}->{$_}};
  0         0  
  0         0  
1291             } else {
1292 0         0 $empty_events->{frozen}->{$_} = $empty_events->{cold}->{$_};
1293             }
1294 0         0 $empty_events->{frozen}->{timestamp} = $now;
1295             }
1296             }
1297 31         59 $empty_events->{timestamp} = $now;
1298 31 100       77 if ($mode eq "lookback") {
1299 21         36 $empty_events->{lookback_history} = $last_values->{lookback_history};
1300 21         37 foreach (@keys) {
1301 37 100       68 if (ref($self->{$_}) eq "ARRAY") {
1302 16         17 @{$empty_events->{lookback_history}->{$_}->{$now}} = @{$self->{$_}};
  16         60  
  16         33  
1303             } else {
1304 21         55 $empty_events->{lookback_history}->{$_}->{$now} = $self->{$_};
1305             }
1306             }
1307             }
1308 31 50       72 if ($mode eq "lookback_freeze_defrost") {
1309 0         0 delete $empty_events->{freeze};
1310             }
1311 31         71 $empty_events;
1312             };
1313 31         118 $self->save_state(%params);
1314             }
1315              
1316             sub create_statefilesdir {
1317 31     31 0 34 my ($self) = @_;
1318 31 50       60 if (! -d $self->statefilesdir()) {
    50          
1319 0         0 eval {
1320 3     3   16521 use File::Path;
  3         3  
  3         4197  
1321 0         0 mkpath $self->statefilesdir();
1322             };
1323 0 0 0     0 if ($@ || ! -w $self->statefilesdir()) {
1324 0         0 $self->add_message(UNKNOWN,
1325             sprintf "cannot create status dir %s! check your filesystem (permissions/usage/integrity) and disk devices", $self->statefilesdir());
1326             }
1327             } elsif (! -w $self->statefilesdir()) {
1328 0         0 $self->add_message(UNKNOWN,
1329             sprintf "cannot write status dir %s! check your filesystem (permissions/usage/integrity) and disk devices", $self->statefilesdir());
1330             }
1331             }
1332              
1333             sub create_statefile {
1334 74     74 0 867 my ($self, %params) = @_;
1335 74         94 my $extension = "";
1336 74 100       173 $extension .= $params{name} ? '_'.$params{name} : '';
1337 74         154 $extension =~ s/\//_/g;
1338 74         66 $extension =~ s/\(/_/g;
1339 74         69 $extension =~ s/\)/_/g;
1340 74         69 $extension =~ s/\*/_/g;
1341 74         121 $extension =~ s/\s/_/g;
1342 74         156 return sprintf "%s/%s%s", $self->statefilesdir(),
1343             $self->clean_path($self->mode), $self->clean_path(lc $extension);
1344             }
1345              
1346             sub clean_path {
1347 148     148 0 163 my ($self, $path) = @_;
1348 148 50       346 if ($^O =~ /MSWin/) {
1349 0         0 $path =~ s/:/_/g;
1350             }
1351 148         944 return $path;
1352             }
1353              
1354             sub schimpf {
1355 0     0 0 0 my ($self) = @_;
1356 0         0 printf "statefilesdir %s is not writable.\nYou didn't run this plugin as root, didn't you?\n", $self->statefilesdir();
1357             }
1358              
1359             # $self->protect_value('1.1-flat_index', 'cpu_busy', 'percent');
1360             sub protect_value {
1361 0     0 0 0 my ($self, $ident, $key, $validfunc) = @_;
1362 0 0 0     0 if (ref($validfunc) ne "CODE" && $validfunc eq "percent") {
    0 0        
1363             $validfunc = sub {
1364 0     0   0 my $value = shift;
1365 0 0       0 return 0 if $value !~ /^[-+]?([0-9]+(\.[0-9]+)?|\.[0-9]+)$/;
1366 0 0 0     0 return ($value < 0 || $value > 100) ? 0 : 1;
1367 0         0 };
1368             } elsif (ref($validfunc) ne "CODE" && $validfunc eq "positive") {
1369             $validfunc = sub {
1370 0     0   0 my $value = shift;
1371 0 0       0 return 0 if $value !~ /^[-+]?([0-9]+(\.[0-9]+)?|\.[0-9]+)$/;
1372 0 0       0 return ($value < 0) ? 0 : 1;
1373 0         0 };
1374             }
1375 0 0       0 if (&$validfunc($self->{$key})) {
1376             $self->save_state(name => 'protect_'.$ident.'_'.$key, save => {
1377 0         0 $key => $self->{$key},
1378             exception => 0,
1379             });
1380             } else {
1381             # if the device gives us an clearly wrong value, simply use the last value.
1382 0         0 my $laststate = $self->load_state(name => 'protect_'.$ident.'_'.$key);
1383             $self->debug(sprintf "self->{%s} is %s and invalid for the %dth time",
1384 0         0 $key, $self->{$key}, $laststate->{exception} + 1);
1385 0 0       0 if ($laststate->{exception} <= 5) {
1386             # but only 5 times.
1387             # if the error persists, somebody has to check the device.
1388 0         0 $self->{$key} = $laststate->{$key};
1389             }
1390             $self->save_state(name => 'protect_'.$ident.'_'.$key, save => {
1391             $key => $laststate->{$key},
1392             exception => ++$laststate->{exception},
1393 0         0 });
1394             }
1395             }
1396              
1397             sub save_state {
1398 31     31 0 80 my ($self, %params) = @_;
1399 31         82 $self->create_statefilesdir();
1400 31         101 my $statefile = $self->create_statefile(%params);
1401 31         83 my $tmpfile = $self->statefilesdir().'/check__health_tmp_'.$$;
1402 31 50 33     165 if ((ref($params{save}) eq "HASH") && exists $params{save}->{timestamp}) {
1403 31         868 $params{save}->{localtime} = scalar localtime $params{save}->{timestamp};
1404             }
1405 31         239 my $seekfh = IO::File->new();
1406 31 50       1154 if ($seekfh->open($tmpfile, "w")) {
1407 31         3584 $seekfh->printf("%s", Data::Dumper::Dumper($params{save}));
1408 31         5071 $seekfh->flush();
1409 31         141 $seekfh->close();
1410             $self->debug(sprintf "saved %s to %s",
1411 31         514 Data::Dumper::Dumper($params{save}), $statefile);
1412             }
1413 31 50       335289 if (! rename $tmpfile, $statefile) {
1414 0         0 $self->add_message(UNKNOWN,
1415             sprintf "cannot write status file %s! check your filesystem (permissions/usage/integrity) and disk devices", $statefile);
1416             }
1417             }
1418              
1419             sub load_state {
1420 31     31 0 75 my ($self, %params) = @_;
1421 31         105 my $statefile = $self->create_statefile(%params);
1422 31 100       752 if ( -f $statefile) {
1423 26         37 our $VAR1;
1424 26         64 eval {
1425 26 100       134 delete $INC{$statefile} if exists $INC{$statefile}; # else unit tests fail
1426 26         3739 require $statefile;
1427             };
1428 26 50       245 if($@) {
1429 0         0 printf "rumms\n";
1430             }
1431 26         149 $self->debug(sprintf "load %s from %s", Data::Dumper::Dumper($VAR1), $statefile);
1432 26         383 return $VAR1;
1433             } else {
1434 5         20 return undef;
1435             }
1436             }
1437              
1438             #########################################################
1439             # daemon mode
1440             #
1441             sub check_pidfile {
1442 0     0 0 0 my ($self) = @_;
1443 0         0 my $fh = IO::File->new();
1444 0 0       0 if ($fh->open($self->{pidfile}, "r")) {
1445 0         0 my $pid = $fh->getline();
1446 0         0 $fh->close();
1447 0 0       0 if (! $pid) {
1448             $self->debug("Found pidfile %s with no valid pid. Exiting.",
1449 0         0 $self->{pidfile});
1450 0         0 return 0;
1451             } else {
1452 0         0 $self->debug("Found pidfile %s with pid %d", $self->{pidfile}, $pid);
1453 0         0 kill 0, $pid;
1454 0 0       0 if ($! == Errno::ESRCH) {
1455 0         0 $self->debug("This pidfile is stale. Writing a new one");
1456 0         0 $self->write_pidfile();
1457 0         0 return 1;
1458             } else {
1459 0         0 $self->debug("This pidfile is held by a running process. Exiting");
1460 0         0 return 0;
1461             }
1462             }
1463             } else {
1464 0         0 $self->debug("Found no pidfile. Writing a new one");
1465 0         0 $self->write_pidfile();
1466 0         0 return 1;
1467             }
1468             }
1469              
1470             sub write_pidfile {
1471 0     0 0 0 my ($self) = @_;
1472 0 0       0 if (! -d dirname($self->{pidfile})) {
1473 0         0 eval "require File::Path;";
1474 0 0       0 if (defined(&File::Path::mkpath)) {
1475 0         0 import File::Path;
1476 0         0 eval { mkpath(dirname($self->{pidfile})); };
  0         0  
1477             } else {
1478 0         0 my @dirs = ();
1479             map {
1480 0         0 push @dirs, $_;
1481 0 0 0     0 mkdir(join('/', @dirs))
1482             if join('/', @dirs) && ! -d join('/', @dirs);
1483 0         0 } split(/\//, dirname($self->{pidfile}));
1484             }
1485             }
1486 0         0 my $fh = IO::File->new();
1487 0         0 $fh->autoflush(1);
1488 0 0       0 if ($fh->open($self->{pidfile}, "w")) {
1489 0         0 $fh->printf("%s", $$);
1490 0         0 $fh->close();
1491             } else {
1492 0         0 $self->debug("Could not write pidfile %s", $self->{pidfile});
1493 0         0 die "pid file could not be written";
1494             }
1495             }
1496              
1497             sub system_vartmpdir {
1498 0     0 0 0 my ($self) = @_;
1499 0 0       0 if ($^O =~ /MSWin/) {
1500 0         0 return $self->system_tmpdir();
1501             } else {
1502 0         0 return "/var/tmp/".$Monitoring::GLPlugin::pluginname;
1503             }
1504             }
1505              
1506             sub system_tmpdir {
1507 0     0 0 0 my ($self) = @_;
1508 0 0       0 if ($^O =~ /MSWin/) {
1509 0 0       0 return $ENV{TEMP} if defined $ENV{TEMP};
1510 0 0       0 return $ENV{TMP} if defined $ENV{TMP};
1511             return File::Spec->catfile($ENV{windir}, 'Temp')
1512 0 0       0 if defined $ENV{windir};
1513 0         0 return 'C:\Temp';
1514             } else {
1515 0         0 return "/tmp";
1516             }
1517             }
1518              
1519             sub convert_scientific_numbers {
1520 0     0 0 0 my ($self, $n) = @_;
1521             # mostly used to convert numbers in scientific notation
1522 0 0       0 if ($n =~ /^\s*\d+\s*$/) {
    0          
    0          
    0          
1523 0         0 return $n;
1524             } elsif ($n =~ /^\s*([-+]?)(\d*[\.,]*\d*)[eE]{1}([-+]?)(\d+)\s*$/) {
1525 0         0 my ($vor, $num, $sign, $exp) = ($1, $2, $3, $4);
1526 0         0 $n =~ s/E/e/g;
1527 0         0 $n =~ s/,/\./g;
1528 0         0 $num =~ s/,/\./g;
1529 0 0       0 my $sig = $sign eq '-' ? "." . ($exp - 1 + length $num) : '';
1530 0         0 my $dec = sprintf "%${sig}f", $n;
1531 0         0 $dec =~ s/\.[0]+$//g;
1532 0         0 return $dec;
1533             } elsif ($n =~ /^\s*([-+]?)(\d+)[\.,]*(\d*)\s*$/) {
1534 0         0 return $1.$2.".".$3;
1535             } elsif ($n =~ /^\s*(.*?)\s*$/) {
1536 0         0 return $1;
1537             } else {
1538 0         0 return $n;
1539             }
1540             }
1541              
1542             sub compatibility_methods {
1543 0     0 0 0 my ($self) = @_;
1544             # add_perfdata
1545             # add_message
1546             # nagios_exit
1547             # ->{warningrange}
1548             # ->{criticalrange}
1549             # ...
1550 0         0 $self->{warningrange} = ($self->get_thresholds())[0];
1551 0         0 $self->{criticalrange} = ($self->get_thresholds())[1];
1552 0         0 my $old_init = $self->can('init');
1553 0         0 my %params = (
1554             'mode' => join('::', split(/-/, $self->opts->mode)),
1555             'name' => $self->opts->name,
1556             'name2' => $self->opts->name2,
1557             );
1558             {
1559 3     3   21 no strict 'refs';
  3         4  
  3         95  
  0         0  
1560 3     3   11 no warnings 'redefine';
  3         4  
  3         2144  
1561 0         0 *{ref($self).'::init'} = sub {
1562 0     0   0 $self->$old_init(%params);
1563 0         0 $self->nagios(%params);
1564 0         0 };
1565 0         0 *{ref($self).'::add_nagios'} = \&{"Monitoring::GLPlugin::add_message"};
  0         0  
  0         0  
1566 0         0 *{ref($self).'::add_nagios_ok'} = \&{"Monitoring::GLPlugin::add_ok"};
  0         0  
  0         0  
1567 0         0 *{ref($self).'::add_nagios_warning'} = \&{"Monitoring::GLPlugin::add_warning"};
  0         0  
  0         0  
1568 0         0 *{ref($self).'::add_nagios_critical'} = \&{"Monitoring::GLPlugin::add_critical"};
  0         0  
  0         0  
1569 0         0 *{ref($self).'::add_nagios_unknown'} = \&{"Monitoring::GLPlugin::add_unknown"};
  0         0  
  0         0  
1570 0         0 *{ref($self).'::add_perfdata'} = sub {
1571 0     0   0 my $self = shift;
1572 0         0 my $message = shift;
1573 0         0 foreach my $perfdata (split(/\s+/, $message)) {
1574 0         0 my ($label, $perfstr) = split(/=/, $perfdata);
1575 0         0 my ($value, $warn, $crit, $min, $max) = split(/;/, $perfstr);
1576 0         0 $value =~ /^([\d\.\-\+]+)(.*)$/;
1577 0         0 $value = $1;
1578 0         0 my $uom = $2;
1579 0         0 $Monitoring::GLPlugin::plugin->add_perfdata(
1580             label => $label,
1581             value => $value,
1582             uom => $uom,
1583             warn => $warn,
1584             crit => $crit,
1585             min => $min,
1586             max => $max,
1587             );
1588             }
1589 0         0 };
1590 0         0 *{ref($self).'::check_thresholds'} = sub {
1591 0     0   0 my $self = shift;
1592 0         0 my $value = shift;
1593 0         0 my $defaultwarningrange = shift;
1594 0         0 my $defaultcriticalrange = shift;
1595 0         0 $Monitoring::GLPlugin::plugin->set_thresholds(
1596             metric => 'default',
1597             warning => $defaultwarningrange,
1598             critical => $defaultcriticalrange,
1599             );
1600 0         0 $self->{warningrange} = ($self->get_thresholds())[0];
1601 0         0 $self->{criticalrange} = ($self->get_thresholds())[1];
1602 0         0 return $Monitoring::GLPlugin::plugin->check_thresholds(
1603             metric => 'default',
1604             value => $value,
1605             warning => $defaultwarningrange,
1606             critical => $defaultcriticalrange,
1607             );
1608 0         0 };
1609             }
1610             }
1611              
1612              
1613             sub AUTOLOAD {
1614 6     6   2990 my ($self, @params) = @_;
1615 6 50       27 return if ($AUTOLOAD =~ /DESTROY/);
1616 6 50       18 $self->debug("AUTOLOAD %s\n", $AUTOLOAD)
1617             if $self->opts->verbose >= 2;
1618 6 50       88 if ($AUTOLOAD =~ /^(.*)::analyze_and_check_(.*)_subsystem$/) {
    50          
    50          
    50          
    0          
1619 0         0 my $class = $1;
1620 0         0 my $subsystem = $2;
1621 0         0 my $analyze = sprintf "analyze_%s_subsystem", $subsystem;
1622 0         0 my $check = sprintf "check_%s_subsystem", $subsystem;
1623 0 0       0 if (@params) {
1624             # analyzer class
1625 0         0 my $subsystem_class = shift @params;
1626 0         0 $self->{components}->{$subsystem.'_subsystem'} = $subsystem_class->new();
1627 0         0 $self->debug(sprintf "\$self->{components}->{%s_subsystem} = %s->new()",
1628             $subsystem, $subsystem_class);
1629             } else {
1630 0         0 $self->$analyze();
1631 0         0 $self->debug("call %s()", $analyze);
1632             }
1633 0         0 $self->$check();
1634             } elsif ($AUTOLOAD =~ /^(.*)::check_(.*)_subsystem$/) {
1635 0         0 my $class = $1;
1636 0         0 my $subsystem = sprintf "%s_subsystem", $2;
1637 0         0 $self->{components}->{$subsystem}->check();
1638 0 0       0 $self->{components}->{$subsystem}->dump()
1639             if $self->opts->verbose >= 2;
1640             } elsif ($AUTOLOAD =~ /^.*::(status_code|check_messages|nagios_exit|html_string|perfdata_string|selected_perfdata|check_thresholds|get_thresholds|opts|pandora_string)$/) {
1641 0         0 return $Monitoring::GLPlugin::plugin->$1(@params);
1642             } elsif ($AUTOLOAD =~ /^.*::(reduce_messages|reduce_messages_short|clear_messages|suppress_messages|add_html|add_perfdata|override_opt|create_opt|set_thresholds|force_thresholds|add_pandora)$/) {
1643 6         52 $Monitoring::GLPlugin::plugin->$1(@params);
1644             } elsif ($AUTOLOAD =~ /^.*::mod_arg_(.*)$/) {
1645 0           return $Monitoring::GLPlugin::plugin->mod_arg($1, @params);
1646             } else {
1647 0           $self->debug("AUTOLOAD: class %s has no method %s\n",
1648             ref($self), $AUTOLOAD);
1649             }
1650             }
1651              
1652             1;
1653              
1654             __END__