/[nagraffiti]/backend/lib/Nagraph.pm
ViewVC logotype

Contents of /backend/lib/Nagraph.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations) (download)
Wed Apr 24 12:58:51 2013 UTC (7 years, 7 months ago) by racvision
File size: 23124 byte(s)
Add logs, better handling of "no value"
1 #!/usr/bin/perl
2 #
3 ## Copyright (c) 2008-2012 St├ęphane Urbanovski <s.urbanosvki@ac-nancy-metz.fr>
4 ##
5 ## With lot of code from PNP :
6 ## Copyright (c) 2006-2008 Joerg Linge (http://www.pnp4nagios.org)
7 ##
8 ## This program is free software; you can redistribute it and/or
9 ## modify it under the terms of the GNU General Public License
10 ## as published by the Free Software Foundation; either version 2
11 ## of the License, or (at your option) any later version.
12 ##
13 ## This program is distributed in the hope that it will be useful,
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ## GNU General Public License for more details.
17 ##
18 ## You should have received a copy of the GNU General Public License
19 ## along with this program; if not, write to the Free Software
20 ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #
22 # $Id: $
23 #
24
25 package Nagraph;
26
27 use strict;
28 use warnings;
29 use utf8;
30
31 use Time::HiRes qw(time);
32 use RRDs;
33
34 use Log::Log4perl;
35
36 use Data::Dumper;
37
38 our $VERSION = '2.0';
39
40 our %conf = (
41 # 'CFG_DIR' => '/etc/nagraffiti',
42 # 'SPOOL_DIR' => '/var/lib/nagraffiti',
43 # 'SPOOL_DIR' => './lib',
44 'RRA_STEP' => 60,
45 'RRD_HEARTBEAT' => 600
46 );
47
48 our %NAGIOS_STATES = (
49 0 => 'OK',
50 1 => 'WARNING',
51 2 => 'CRITICAL',
52 3 => 'UNKNOWN'
53 );
54
55
56
57
58 # Number of checks to group together before flushing to rrd
59 # our $GROUP_BY_COUNT = 20;
60
61 sub new {
62 my($class, %args) = @_;
63 my $self = {
64 # 'check_command' => '__undef__',
65 'last_sample_ts' => 0,
66 'last_sample' => undef,
67 'last_save' => 0,
68 'last_check' => undef,
69 };
70 $self->{'logger'} = Log::Log4perl->get_logger(__PACKAGE__);
71
72 $self->{'hostname'} = $args{'hostname'} or $self->{'logger'}->logcroak('Hostname not defined !');
73 $self->{'service'} = $args{'service'} or $self->{'logger'}->logcroak('Service not defined !');
74 $self->{'config'} = $args{'config'} or $self->{'config'}->logcroak('config not defined !');
75
76 # Don't know why this does not work :
77 # $self->{'logger'}->more_logging($self->{'config'}{'debugLvl'});
78
79 $self->{'logger'}->level($self->{'config'}{'debugLvl'});
80
81
82 $self->{'checkdata'} = [];
83 $self->{'dsInfos'} = {
84 '_state_' => {
85 'label' => '_state_',
86 'value' => undef,
87 'uom' => '%',
88 'dstype' => 'GAUGE',
89 },
90 };
91 $self->{'dsInfosNeedUpdate'} = 1;
92 $self->{'total_check_count'} = 0;
93 $self->{'group_check_count'} = 0;
94 $self->{'rra_config'} = undef;
95 $self->{'rrd_time'} = 0;
96 $self->{'mode'} = 'fifo';
97
98
99 bless ($self, $class);
100
101 $self->updateDsInfo('_state_','rrdfile',$self->getSrvDirName().'/ds-_state_.rrd');
102
103 return $self;
104 }
105
106
107 sub updateDsInfo {
108 my ($self,$ds,$k,$v) = @_;
109
110 if ( !defined($self->{'dsInfos'}{$ds}{$k}) ) {
111 if ( defined($v) ) {
112 # new value
113 $self->{'dsInfos'}{$ds}{$k} = $v;
114 $self->{'dsInfosNeedUpdate'} = 1;
115 return 1;
116 }
117 } else {
118 if ( defined($v) ) {
119 if ($v ne $self->{'dsInfos'}{$ds}{$k}) {
120 $self->{'logger'}->info("Parameter '$k' change for ds '$ds' : ".$self->{'dsInfos'}{$ds}{$k}.' => '.$v);
121 $self->{'logger'}->info(sprintf(' for %s / \'%s\'',$self->{'hostname'},$self->{'service'}));
122 $self->{'dsInfos'}{$ds}{$k} = $v;
123 $self->{'dsInfosNeedUpdate'} = 1;
124 return 1;
125 }
126 } else {
127 $self->{'logger'}->info("Parameter '$k' removed for ds '$ds' !");
128 $self->{'logger'}->info(sprintf(' for %s / \'%s\'',$self->{'hostname'},$self->{'service'}));
129 # FIXME: delete too ?
130
131 return 1;
132 }
133 }
134 return 0;
135
136 }
137 sub saveCheckResult($) {
138 my ($self,%check) = @_;
139 $self->{'logger'}->trace('saveCheckResult()');
140
141
142 my %dsData = (
143 'ds' => {},
144 'start_ts' => $check{'start_ts'},
145 );
146
147 my $dsValues = $self->parsePerfdata($check{'perfdata'});
148
149 foreach my $ds ( keys(%{$dsValues}) ) {
150
151 my $p = $dsValues->{$ds};
152
153
154 if ( !defined($self->{'dsInfos'}{$ds}) ) {
155 $self->{'dsInfos'}{$ds} = {
156 'uomConv' => sub { return $_[0]; }, #passthrue
157 'dstype' => 'GAUGE',
158 };
159 }
160
161 #
162 # Convert values using uom (Unit Of Mesure) if required
163 #
164
165 if ( defined($p->{'uom'}) ) {
166 if ( $p->{'uom'} eq 'KB' ) {
167 $self->{'dsInfos'}{$ds}{'uomConv'} = sub { return $_[0] * 1024 };
168 $p->{'uom'} = 'B';
169 } elsif ( $p->{'uom'} eq 'MB' ) {
170 $self->{'dsInfos'}{$ds}{'uomConv'} = sub { return $_[0] * 1048576 };
171 $p->{'uom'} = 'B';
172 } elsif ( $p->{'uom'} eq 'ms' ) {
173 $self->{'dsInfos'}{$ds}{'uomConv'} = sub { return $_[0] /1000 };
174 $p->{'uom'} = 's';
175 } elsif ( $p->{'uom'} eq 'c' ) {
176 $p->{'uom'} = '';
177 $p->{'dstype'} = 'COUNTER';
178 }
179 }
180 $self->updateDsInfo($ds,'uom',$p->{'uom'});
181
182 foreach my $k ('min','max','w','w_min','w_max','c','c_min','c_max') {
183 if (defined($p->{$k})) {
184 $p->{$k} = &{$self->{'dsInfos'}{$ds}{'uomConv'}}($p->{$k});
185 }
186 $self->updateDsInfo($ds,$k,$p->{$k});
187 }
188 foreach my $k ('w_range_type','c_range_type') {
189 $self->updateDsInfo($ds,$k,$p->{$k});
190 }
191
192 if ( $self->updateDsInfo($ds,'label',$p->{'label'}) ) {
193 $self->updateDsInfo($ds,'rrdfile',$self->getSrvDirName().sprintf('/ds-%s.rrd',$self->urlencode($p->{'label'})));
194 }
195
196
197 if (defined($p->{'value'})) {
198 $p->{'value'} = &{$self->{'dsInfos'}{$ds}{'uomConv'}}($p->{'value'});
199 }
200 $dsData{'ds'}{$ds} = {
201 'value' => $p->{'value'}
202 };
203
204 }
205
206 $dsData{'ds'}{'_state_'}{'value'} = $self->processServiceState($check{'state'});
207
208 # print Dumper(\%dsData);
209 # print Dumper($self->{'dsInfos'});
210
211 push ( @{$self->{'checkdata'}}, \%dsData );
212 $self->{'last_sample'} = \%dsData;
213 # $self->{'last_check'} = \%check;
214
215 my $ret = $self->saveToRrd();
216
217 if ( $ret == 0 ) {
218 if ( $self->{'dsInfosNeedUpdate'} > 0 ) {
219 $self->updateXmlTemplate();
220 }
221
222
223 # my $data_file = $self->getDataFilename();
224 #
225 # if ( open (DATA, ">$data_file") ) {
226 # print DATA 'TIMET='.$self->{'last_sample_ts'}."\n";
227 # # print DATA 'start_time='.$start_time."\n";
228 # close (DATA);
229 #
230 # } else {
231 # $self->{'logger'}->error("Enable to write to $data_file: ".$!) ;
232 # }
233 }
234 if ( 1 ) {
235 my $debugFile = $self->getHostDirName().'/debug.log';
236
237 if ( -f $debugFile ) {
238 if ( open (DEBUG, ">>$debugFile") ) {
239 # print DEBUG '$dsValues='.Dumper($dsValues)."\n";
240
241 print DEBUG $check{'start_ts'}.':'.$self->{'service'}.':';
242 foreach my $ds (keys %{$dsValues}) {
243 print DEBUG ' '.$dsValues->{$ds}{'label'}.'='.$dsValues->{$ds}{'value'}.$dsValues->{$ds}{'uom'};
244 }
245 print DEBUG "\n ".$check{'perfdata'}."\n";
246 close (DEBUG);
247
248 } else {
249 $self->{'logger'}->error("Enable to write to $debugFile: ".$!) ;
250 exit 1;
251 }
252 }
253 }
254 $self->{'total_check_count'}++;
255 $self->{'group_check_count'}++;
256
257 }
258
259 # get a nagios state and return a datasource hash
260 sub processServiceState($) {
261 my ($self,$state) = @_;
262 # $self->{'logger'}->trace("processServiceState($state)");
263
264 if ( $state eq 'OK' ) {
265 return 100;
266 } elsif ( $state eq 'WARNING' ) {
267 return 50;
268 } elsif ( $state eq 'CRITICAL' ) {
269 return 0;
270 } elsif ( $state eq 'UNKNOWN' ) {
271 # NaN
272 return undef;
273 }
274 $self->{'logger'}->warn("processServiceState($state) : unknown state for ".$self->{'hostname'}.'/'.$self->{'service'});
275
276 return undef;
277 }
278
279
280 #
281 # Parse $perfdata and return a datasource hash
282 #
283 sub parsePerfdata($) {
284 my ($self,$perfdata) = @_;
285
286 my %dsValues = ();
287 if ( $perfdata =~/^\s+$/ ) {
288 return \%dsValues;
289 }
290 $self->{'logger'}->trace("parsePerfdata($perfdata)");
291
292 my $ds = 0;
293 my $lm = 0; # end of last match
294
295 $perfdata =~ s/,/./g;
296
297 # Part adpated from Nagios::Plugin::Performance
298 # Thanks to Gavin Carr and Ton Voon
299
300 while ( $perfdata =~ /'?([^=']+)'?\s*=\s*([\d\.-]+)([\w\/%]*);?([\d\.-:~@]+)?;?([\d\.-:~@]+)?;?([\d\.-]+)?;?([\d\.-]+)?\s*/g ) {
301 # loop on each datasources
302 my $cm = $-[0]; # start of current match
303 # $self->{'logger'}->trace("MATCH : ".substr( $perfdata,$cm,$+[0] - $cm));
304
305 if ( $cm > $lm ) {
306 # something daesn't match
307 $self->{'logger'}->warn("Can't match this perfdata : ".substr( $perfdata,$lm,$cm - $lm));
308 }
309 $lm = $+[0]; # end of last match
310
311 my %p = (
312 'label' => $1,
313 'value' => $2,
314 'uom' => $3,
315 'w' => $4,
316 'c' => $5,
317 'min' => $6,
318 'max' => $7
319 );
320
321 if ( !defined($p{'label'}) ) {
322 $self->{'logger'}->warn(sprintf('Invalid Perfdata detected for %s / \'%s\' : %s',$self->{'hostname'},$self->{'service'},$perfdata));
323 next;
324 }
325
326 $ds++;
327
328 # else {
329 # $p{'label'} =~ s/\'//g; # remove quotes
330 # $p{'label'} =~ s/([\\:])/\\$1/g; # escape colons and \
331 # }
332
333
334 #
335 # Check for warning and critical ranges
336 #
337 foreach my $level ('w','c') {
338 if ( $p{$level} && $p{$level} =~ /^([\d\.~@]+)?:([\d\.~@]+)?$/ ) {
339 # $self->{'logger'}->trace("parseSinglePerfData: Processing warning ranges ( $p{$level} )");
340 $p{$level.'_min'} = $1;
341 $p{$level.'_max'} = $2;
342 delete($p{$level});
343
344 $p{$level.'_range_type'} = 'outside';
345 if (defined($p{$level.'_min'})) {
346 if ( $p{$level.'_min'} =~ /^@/ ) {
347 $p{$level.'_range_type'} = 'inside';
348 $p{$level.'_min'} =~ s/@//;
349 }
350 }
351 if (defined($p{$level.'_max'})) {
352 $p{$level.'_max'} =~ s/@//;
353 }
354
355 }
356 }
357
358
359 # TODO: look for check_multi
360
361
362 $dsValues{$ds} = \%p;
363
364 }
365 if ( $lm < length($perfdata) ) {
366 # some characters remains but don't match regex
367 $self->{'logger'}->warn("Can't match this perfdata : ".substr( $perfdata,$lm,length($perfdata) - $lm));
368 }
369
370
371 # if ( $ds == 0 ) {
372 # # no datasource found
373 # $self->{'logger'}->warn("No data source found in this check : ");
374 # return;
375 # }
376 return \%dsValues;
377
378 }
379
380
381 #
382 # Save the current check queue ($self->{'checkdata'}) to rrd
383 #
384 sub saveToRrd {
385 my ($self) = @_;
386 $self->{'logger'}->trace("saveToRrd() called");
387
388 # print Dumper(\$self->{'checkdata'});
389
390 my $sample_total = scalar(@{$self->{'checkdata'}});
391 if ( $sample_total == 0 ) {
392 return 1;
393 }
394
395 my $sample_count = 0;
396 my %ds_update = ();
397 my %ds_info = ();
398 my $firstsample_ts = time();
399 my $lastsample_ts = undef;
400
401 # print Dumper(\%ds_info);
402
403 while ( my $sample = shift ( @{$self->{'checkdata'}}) ) {
404 $lastsample_ts = $sample->{'start_ts'};
405
406 my $haveData = 0;
407 foreach my $ds ( sort(keys(%{$sample->{'ds'}})) ) {
408 if ( !exists($ds_update{$ds}) ) {
409 $ds_update{$ds} = [];
410 }
411
412 if ( !defined($ds_info{$ds}) ) {
413 $ds_update{$ds} = [];
414 $ds_info{$ds} = {
415 'label' => $sample->{'ds'}{$ds}{'label'},
416 # 'dstype' => $sample->{'ds'}{$ds}{'dstype'},
417 # 'rrdfile' => $self->getSrvDirName().sprintf('/ds-%s.rrd',$self->urlencode($sample->{'ds'}{$ds}{'label'}))
418 };
419
420 if ( $self->{'mode'} eq 'ndo' ) {
421 # ndo can store old values
422 # my $rrdFile = $self->getSrvDirName().sprintf('/ds-%s.rrd',$self->urlencode($ds_info{$ds}{'label'}));
423 my $info = RRDs::info( $self->{'dsInfos'}{$ds}{'rrdfile'} );
424 $self->{'dsInfos'}{$ds}{'rrd_last_update'} = $info->{'last_update'} || 0;
425 $self->{'logger'}->debug("RRDs::info (ds=$ds): ".$self->{'dsInfos'}{$ds}{'rrdfile'}." lastupdate=".$self->{'dsInfos'}{$ds}{'rrd_last_update'});
426
427 } else {
428 $self->{'dsInfos'}{$ds}{'rrd_last_update'} = 0;
429 }
430
431 if ( $lastsample_ts < $firstsample_ts ) {
432 $firstsample_ts = $lastsample_ts;
433 }
434 }
435
436 if ( $lastsample_ts <= $self->{'dsInfos'}{$ds}{'rrd_last_update'} ) {
437 $self->{'logger'}->debug("Drop outdated sample (based on rrd last_update) : ".$lastsample_ts.' < '.$self->{'dsInfos'}{$ds}{'rrd_last_update'});
438 next;
439 }
440
441 if ( defined($sample->{'ds'}{$ds}{'value'} ) ) {
442 push(@{$ds_update{$ds}}, $sample->{'start_ts'}.':'.$sample->{'ds'}{$ds}{'value'});
443 $haveData = 1;
444 } elsif ( $ds ne '_state_' ) {
445 $self->{'logger'}->error('Value not set for "'.$self->{'hostname'}.'/'.$self->{'service'}.'" ds='.$ds.' : '.Dumper($sample));
446 }
447 }
448 $sample_count += $haveData;
449 }
450
451 #
452 # Create or Update the RRD Files
453 #
454
455 my $rrdState = -1;
456 my $logMsg = '';
457
458
459 foreach my $ds ( sort(keys(%{$self->{'dsInfos'}})) ) {
460
461 my $dsName = $self->{'dsInfos'}{$ds}{'label'};
462
463 if ( !exists($ds_update{$ds}) || scalar(@{$ds_update{$ds}} <= 0) ) {
464 $self->{'logger'}->debug('skip '.$ds);
465 next;
466 }
467 # $self->{'logger'}->trace("rrd file (ds=$ds): ".$self->{'dsInfos'}{$ds}{'rrdfile'});
468
469 if (! -e $self->{'dsInfos'}{$ds}{'rrdfile'}) {
470 if ( $self->loadRraConfig() != 0 ) {
471 return 1;
472 }
473
474 my $dir = $self->getHostDirName();
475 unless ( -d $dir ) {
476 unless ( mkdir $dir ) {
477 $self->{'logger'}->error ("mkdir $dir failed : ".$!);
478 return 1;
479 }
480 }
481 $dir = $self->getSrvDirName();
482 unless ( -d $dir ) {
483 unless ( mkdir $dir ) {
484 $self->{'logger'}->error ("mkdir $dir failed : ".$!);
485 return 1;
486 }
487 }
488
489 # my $dsType = $self->{'dsInfos'}{$ds}{'dstype'} == COUNTER ? 'COUNTER':'GAUGE';
490 my $ds_create = "DS:1:".$self->{'dsInfos'}{$ds}{'dstype'}.':'.$conf{'RRD_HEARTBEAT'}.':U:U';
491 my $rrd_start = $firstsample_ts-60;
492
493 my $rrd_timer = time();
494 RRDs::create ( $self->{'dsInfos'}{$ds}{'rrdfile'}, @{$self->{'rra_config'}}, $ds_create, '--step='.$conf{'RRA_STEP'},'--start='.$rrd_start );
495 $self->{'rrd_time'} += time() - $rrd_timer;
496
497 my $err = RRDs::error();
498
499 if ($err) {
500 $rrdState = 1;
501 $self->{'logger'}->error('RRDs::create '.$self->{'dsInfos'}{$ds}{'rrdfile'}.' error : '.$err);
502 } else {
503 $rrdState = 0;
504 $self->{'logger'}->debug('RRDs::create '.$self->{'dsInfos'}{$ds}{'rrdfile'}.' successfuly created start='.$rrd_start);
505 }
506 }
507
508 $self->{'logger'}->trace("RRD data ".join(',',@{$ds_update{$ds}}));
509
510 my $rrd_timer = time();
511 RRDs::update( $self->{'dsInfos'}{$ds}{'rrdfile'}, @{$ds_update{$ds}});
512 # $self->printLog( $dsName.':'.join('#',@{$ds_update{$ds}}) );
513 $self->{'rrd_time'} += time() - $rrd_timer;
514
515 my $err = RRDs::error();
516
517 if ($err) {
518 $rrdState = 1;
519 $self->{'logger'}->error('RRDs::update '.$self->{'dsInfos'}{$ds}{'rrdfile'}.' error : '.$err);
520 } else {
521 $rrdState = 0;
522 $self->{'logger'}->debug('RRDs::update '.$self->{'dsInfos'}{$ds}{'rrdfile'}.' successfuly updated');
523 }
524
525 }
526
527 $self->{'last_sample_ts'} = $lastsample_ts;
528
529 $self->{'logger'}->debug('saveToRrd() '.$sample_count.' sample saved.');
530 return $rrdState;
531
532 }
533
534 ##
535 # Return true if we have more than $GROUP_BY_COUNT checks to be flushed to RRD
536 #
537 # sub needFlush {
538 # my ($self) = @_;
539 # return $self->{'group_check_count'} > $GROUP_BY_COUNT;
540 # }
541
542 ##
543 # Parse rra.cfg
544 #
545 sub loadRraConfig {
546 my ($self) = @_;
547
548 if ( defined($self->{'rra_config'}) ) {
549 # already loaded
550 return 0;
551 }
552
553 my @rrd_create = ();
554
555 my $rrafile = $self->getRraConfigFilename();
556
557 if ( ! -e $rrafile ) {
558 $self->{'logger'}->error("RRA config not found () ! ");
559 return 1;
560 }
561
562 $self->{'logger'}->debug("Reading RRA $rrafile");
563
564 open ( RRA, "<$rrafile" );
565 while (<RRA>) {
566 next if /^#/;
567 next if /^$/;
568 s/#.*//;
569 chomp;
570 push @rrd_create, "$_";
571 }
572 close RRA;
573 $self->{'rra_config'} = \@rrd_create;
574
575 return 0;
576
577 }
578
579 #
580 # Get the timestamp from the last saved data
581 #
582
583 # sub getLastTimet {
584 # my ($self) = @_;
585 # my $last_save = 0;
586 # my $data_file = $self->getDataFilename();
587 # if ( -f $data_file ) {
588 # open (DATA, "<$data_file");
589 # while ( my $l = <DATA>) {
590 # if ( $l =~ /^TIMET=(\d+)$/ ) {
591 # $last_save = $1;
592 # last;
593 # }
594 # }
595 # close (DATA);
596 # }
597 # $self->{'last_save'} = $last_save;
598 #
599 #
600 # return $last_save;
601 # }
602
603 ################################################################################################
604 # PNP xml template
605 ################################################################################################
606
607
608 sub updateXmlTemplate_old {
609 my ($self) = @_;
610
611 $self->{'logger'}->trace('updateXmlTemplate()');
612
613 # print Dumper(\$sample);
614
615 #
616 # Create PHP Template File
617 #
618
619 my $xmlFilename = $self->getXmlFilename();
620 # unlink $xmlFilename;
621
622 if ( open(XML, ">".$xmlFilename) ) {
623 print XML "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
624 print XML "<NAGIOS>\n";
625
626 foreach my $dsNum ( sort keys(%{$self->{'last_sample'}{'ds'}}) ) {
627
628 my $ds = $self->{'last_sample'}{'ds'}{$dsNum};
629
630 # my $uom = $sample->{$ds}{uom} eq '%' ? '%%' : $sample->{$ds}{uom};
631
632 print XML " <DATASOURCE>\n";
633 print XML $self->_write_to_template("TEMPLATE", $self->{'template'});
634 print XML $self->_write_to_template("DS", $dsNum);
635 print XML $self->_write_to_template("NAME", $ds->{label});
636 print XML $self->_write_to_template("UNIT", $ds->{uom});
637 print XML $self->_write_to_template("ACT", $ds->{value});
638 print XML $self->_write_to_template("WARN", $ds->{w});
639 print XML $self->_write_to_template("WARN_MIN", $ds->{w_min}) if ( defined($ds->{w_min}) );
640 print XML $self->_write_to_template("WARN_MAX", $ds->{w_max}) if ( defined($ds->{w_max}) );
641 print XML $self->_write_to_template("WARN_RANGE_TYPE", $ds->{w_range_type});
642 print XML $self->_write_to_template("CRIT", $ds->{c});
643 print XML $self->_write_to_template("CRIT_MIN", $ds->{c_min}) if ( defined($ds->{c_min}) );
644 print XML $self->_write_to_template("CRIT_MAX", $ds->{c_max}) if ( defined($ds->{c_max}) );
645 print XML $self->_write_to_template("CRIT_RANGE_TYPE", $ds->{c_range_type});
646 print XML $self->_write_to_template("MIN", $ds->{min}) if ( defined($ds->{min}) );
647 print XML $self->_write_to_template("MAX", $ds->{max}) if ( defined($ds->{max}) );
648 print XML " </DATASOURCE>\n";
649
650 }
651
652 #
653 # Store Nagios ENV
654 #
655 print XML $self->_write_to_template("NAGIOS_HOSTNAME", $self->{'hostname'});
656 print XML $self->_write_to_template("NAGIOS_SERVICEDESC", $self->{'service'});
657 print XML $self->_write_to_template("NAGIOS_SERVICEPERFDATA", (defined($self->{'last_check'}{'perfdata'}) ? $self->{'last_check'}{'perfdata'} : '')) ;
658
659 #
660 # Store the last rrd report
661 #
662 # printf( XML " <RRD>\n");
663 # printf( XML " <RC>%s</RC>\n",0);
664 # # printf( XML " <TXT>%s</TXT>\n", 'TODO !!!');
665 # printf( XML " </RRD>\n");
666
667 printf( XML "</NAGIOS>\n");
668 close(XML);
669
670 $self->{'dsInfosNeedUpdate'} = 0;
671
672 } else {
673 $self->{'logger'}->error("Can't write to template ($xmlFilename) :". $!);
674 }
675 }
676
677
678 sub updateXmlTemplate {
679 my ($self) = @_;
680
681 $self->{'logger'}->trace("updateXmlTemplate() called");
682
683
684 # my $sample_total = scalar(@{$self->{'checkdata'}});
685 # if ( ! defined($self->{'last_check'}) ) {
686 # return;
687 # }
688
689 $self->{'logger'}->trace('updateXmlTemplate()');
690
691 # print Dumper(\$sample);
692
693 #
694 # Create PHP Template File
695 #
696
697 my $xmlFilename = $self->getXmlFilename();
698 # unlink $xmlFilename;
699
700 if ( open(XML, ">".$xmlFilename) ) {
701 print XML "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
702 print XML "<NAGIOS>\n";
703
704 foreach my $dsNum ( sort keys(%{$self->{'dsInfos'}}) ) {
705
706 my $ds = $self->{'dsInfos'}{$dsNum};
707
708 # my $uom = $sample->{$ds}{uom} eq '%' ? '%%' : $sample->{$ds}{uom};
709
710 print XML " <DATASOURCE>\n";
711 print XML $self->_write_to_template("TEMPLATE", $self->{'template'});
712 print XML $self->_write_to_template("DS", $dsNum);
713 print XML $self->_write_to_template("NAME", $ds->{label});
714 print XML $self->_write_to_template("UNIT", $ds->{uom});
715 print XML $self->_write_to_template("ACT", $ds->{value});
716 print XML $self->_write_to_template("WARN", $ds->{w});
717 print XML $self->_write_to_template("WARN_MIN", $ds->{w_min}) if ( defined($ds->{w_min}) );
718 print XML $self->_write_to_template("WARN_MAX", $ds->{w_max}) if ( defined($ds->{w_max}) );
719 print XML $self->_write_to_template("WARN_RANGE_TYPE", $ds->{w_range_type});
720 print XML $self->_write_to_template("CRIT", $ds->{c});
721 print XML $self->_write_to_template("CRIT_MIN", $ds->{c_min}) if ( defined($ds->{c_min}) );
722 print XML $self->_write_to_template("CRIT_MAX", $ds->{c_max}) if ( defined($ds->{c_max}) );
723 print XML $self->_write_to_template("CRIT_RANGE_TYPE", $ds->{c_range_type});
724 print XML $self->_write_to_template("MIN", $ds->{min}) if ( defined($ds->{min}) );
725 print XML $self->_write_to_template("MAX", $ds->{max}) if ( defined($ds->{max}) );
726 print XML " </DATASOURCE>\n";
727
728 }
729
730 #
731 # Store Nagios ENV
732 #
733 print XML $self->_write_to_template("NAGIOS_HOSTNAME", $self->{'hostname'});
734 print XML $self->_write_to_template("NAGIOS_SERVICEDESC", $self->{'service'});
735 print XML $self->_write_to_template("NAGIOS_SERVICEPERFDATA", (defined($self->{'last_check'}{'perfdata'}) ? $self->{'last_check'}{'perfdata'} : '')) ;
736
737 #
738 # Store the last rrd report
739 #
740 # printf( XML " <RRD>\n");
741 # printf( XML " <RC>%s</RC>\n",0);
742 # # printf( XML " <TXT>%s</TXT>\n", 'TODO !!!');
743 # printf( XML " </RRD>\n");
744
745 printf( XML "</NAGIOS>\n");
746 close(XML);
747 } else {
748 $self->{'logger'}->error("Can't write to template ($xmlFilename) :". $!);
749 }
750 }
751
752
753
754
755
756 #
757 # return xml line
758 #
759 sub _write_to_template {
760 my ($self,$tag,$data) = @_;
761 if (!defined $data) {
762 $data = '';
763 }
764 return sprintf( " <%s>%s</%s>\n", $tag, $data, $tag);
765
766 }
767
768 ################################################################################################
769 # Getter and setter
770 ################################################################################################
771
772
773 #
774 #
775 #
776 # sub setCheckCommand ($) {
777 # my ($self, $value) = @_;
778 # $self->{'check_command'} = $value;
779 # }
780
781 #
782 # Get the name of the spool directory for the current host
783 #
784 sub getHostDirName ($) {
785 my ($self) = @_;
786 # return $conf{'SPOOL_DIR'}.'/'.$self->urlencode($self->{'hostname'});
787 return $self->{'config'}{'dataPath'}.'/'.$self->urlencode($self->{'hostname'});
788 }
789
790 #
791 # Get the base name of files used by the current service
792 #
793 sub getSrvDirName ($) {
794 my ($self) = @_;
795 return $self->getHostDirName().'/'.$self->urlencode($self->{'service'});
796 }
797
798 #
799 # Get Nagraph specific data file
800 #
801 sub getDataFilename ($) {
802 my ($self) = @_;
803 return $self->getSrvDirName().'/last_update.txt';
804 }
805
806 #
807 # Get the RRD file name
808 #
809 # sub getRrdFilename ($) {
810 # my ($self) = @_;
811 # return $self->getSrvDirName().'/ds-%s.rrd';
812 # }
813
814 #
815 # Get the PNP xml file name
816 #
817 sub getXmlFilename ($) {
818 my ($self) = @_;
819 return $self->getSrvDirName().'/info.xml';
820 }
821
822 #
823 # Get template dir name
824 #
825 # sub getTemplateDirname ($) {
826 # my ($self) = @_;
827 # return $conf{'CFG_DIR'}.'/check_commands';
828 # }
829
830 #
831 # Get RRA config
832 #
833 sub getRraConfigFilename ($) {
834 my ($self) = @_;
835 # return $conf{'CFG_DIR'}.'/rra.cfg';
836 return $self->{'config'}{'configPath'}.'/rra.cfg';
837 }
838
839 sub getLastData () {
840 my ($self) = @_;
841 return $self->{'checkdata'}[-1];
842 }
843
844
845 ################################################################################################
846 # Various utilities
847 ################################################################################################
848
849 #
850 # Urlencode special caracters
851 #
852 sub urlencode ($) {
853 my ($self,$url) = @_;
854 $url =~ s/([^\w\-\ \.])/"%".uc(unpack("H2", $1))/ge;
855 return $url;
856 }
857
858 ## Logging function
859 sub printLog {
860 my ($self,$msg) = @_;
861 my $f = $self->getSrvDirName().'/trace.log';
862 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
863 open(TRACE,'>>',$f) or die ("Can't open ".$f." !");
864 printf TRACE ("%02d-%02d-%02d %02d:%02d:%02d %s\n",$year+1900,$mon+1,$mday,$hour,$min,$sec,$msg);
865 close(TRACE);
866
867 }
868
869
870 1;

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.8