File Coverage

blib/lib/Monitoring/GLPlugin.pm
Criterion Covered Total %
statement 258 901 28.6
branch 89 392 22.7
condition 33 176 18.7
subroutine 31 89 34.8
pod 0 71 0.0
total 411 1629 25.2


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