source: trunk/nagios-velvice/velvice.cgi @ 387

Last change on this file since 387 was 387, checked in by g7moreau, 5 years ago
  • Better doc on refreshment
  • Property svn:keywords set to Id
File size: 23.7 KB
Line 
1#!/usr/bin/env perl
2#
3# 2014/05/15 Gabriel Moreau <Gabriel.Moreau@univ-grenoble-alpes.fr>
4# 2017/06/22 Gabriel Moreau - big update
5# 2018/06/25 Gabriel Moreau - make velvice generic
6# 2018/11/03 Gabriel Moreau - ajax
7#
8# velvice.cgi
9# Copyright (C) 2014-2019, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
10#
11# Need NagiosStatus http://exchange.nagios.org/directory/Addons/APIs/Perl/NagiosStatus-2Epm/details
12# Possible command http://old.nagios.org/developerinfo/externalcommands/commandlist.php
13#
14# apt-get install perl-modules libnagios-object-perl libhtml-parser-perl liburi-encode-perl libcolor-calc-perl libyaml-syck-perl
15# apt-get install libdatetime-event-recurrence-perl libdatetime-set-perl
16
17use strict;
18use warnings;
19use version; our $VERSION = version->declare('0.10.12');
20
21use CGI;
22use HTML::Entities ();
23use Nagios::StatusLog;
24use URI::Encode qw(uri_encode uri_decode);
25use Color::Calc ();
26use YAML::Syck;
27
28my $query           = CGI->new();
29my $cgi_check       = uri_decode($query->param('check'));
30my $cgi_script_name = $query->script_name();
31my $cgi_path        = $cgi_script_name =~ s{/[^/]+\.cgi$}{}r;
32my $cgi_only;
33$cgi_only++ if uri_decode($query->param('only')) eq 'body';
34undef $query;
35
36my %STATUS_DB = (
37   CRITICAL => {id => 5, color => '#F88888'},
38   UNKNOWN  => {id => 4, color => '#FFBB55'},  # #4488FF
39   WARNING  => {id => 3, color => '#FFFF00'},
40   PENDING  => {id => 2, color => '#E0E0E0'},
41   OK       => {id => 1, color => '#88D066'},
42   );
43
44my $config = {};
45$config = YAML::Syck::LoadFile('/etc/nagios3/velvice.yml') if -e '/etc/nagios3/velvice.yml';
46$config->{'nagios-server'}                ||= {};
47$config->{'nagios-server'}{'status-file'} ||= '/var/cache/nagios3/status.dat';
48$config->{'nagios-server'}{'nagios-cmd'}  ||= '/var/lib/nagios3/rw/nagios.cmd';
49$config->{'nagios-server'}{'portal-url'}  ||= $cgi_path =~ s{/cgi-bin/}{/}r . '/';
50$config->{'nagios-server'}{'status-cgi'}  ||= "$cgi_path/status.cgi";
51$config->{'nagios-server'}{'stylesheets'} ||= $config->{'nagios-server'}{'portal-url'} =~ s{/?$}{/stylesheets}r;
52$config->{'nagios-server'}{'image'}       ||= $config->{'nagios-server'}{'portal-url'} =~ s{/?$}{/images}r;
53$config->{'host-mapping'}                 ||= {};
54$config->{'color-downtime'}               ||= {};
55$config->{'color-downtime'}{'day-min'}    ||=  3;
56$config->{'color-downtime'}{'day-max'}    ||= 50;
57$config->{'color-downtime'}{'factor'}     ||=  0.7;
58$config->{'remote-action'}                ||= {};
59$config->{'refresh'}                      ||=  0;
60
61sub hostmapping {
62   my $host = shift;
63
64   return exists $config->{'host-mapping'}{$host} ? $config->{'host-mapping'}{$host} : $host;
65   }
66
67sub downtime {
68   my ($time_change) = @_;
69
70   my $now = time;
71   return sprintf '%.1f', ($now - $time_change) / (60 * 3600);
72   }
73
74sub alertcolor {
75   my ($status, $downtime) = @_;
76
77   my $color = '#0000FF';
78   $color = $STATUS_DB{$status}->{'color'} if exists $STATUS_DB{$status};
79
80   $downtime = $downtime - $config->{'color-downtime'}{'day-min'}; # same color first days
81   $downtime = $config->{'color-downtime'}{'day-max'} if $downtime > $config->{'color-downtime'}{'day-max'}; # max 50 days for color
82   $downtime =  0 if $downtime <  0;
83
84   my $factor = ($downtime * $config->{'color-downtime'}{'factor'}) / $config->{'color-downtime'}{'day-max'};
85   return Color::Calc::color_light_html($color, $factor);
86   }
87
88sub nosbreak {
89   my ($str) = @_;
90   
91   return $str =~ s/\s/\&nbsp;/gr;
92   }
93
94my $log = Nagios::StatusLog->new(
95   Filename => $config->{'nagios-server'}{'status-file'},
96   Version  => 3.0
97   );
98
99# refresh configuration
100if (exists $config->{'refreshments'}) {
101   require DateTime::Event::Recurrence;
102   require DateTime::SpanSet;
103
104   my @refreshments;
105   SET:
106   for my $set (@{$config->{'refreshments'}}) {
107      my $start   = DateTime::Event::Recurrence->weekly(days => $set->{'days'}, hours => $set->{'start'});
108      my $end     = DateTime::Event::Recurrence->weekly(days => $set->{'days'}, hours => $set->{'end'});
109      my $spanset = DateTime::SpanSet->from_sets(start_set => $start, end_set => $end);
110      push @refreshments, {refresh => $set->{'refresh'}, spanset => $spanset};
111      }
112
113   my $now = DateTime->now(time_zone => 'local');
114   SET:
115   for my $set (@refreshments) {
116      next SET if not $set->{'spanset'}->contains($now);
117 
118      $config->{'refresh'} = $set->{'refresh'};
119      last SET;
120      }
121   }
122
123my %hostdown;
124my @serviceproblems;
125my %hostcount;
126my @futurecheck;
127HOST:
128for my $host (sort $log->list_hosts()) {
129   my $host_stat = $log->host($host);
130
131   if ($host_stat->status eq 'DOWN') {TESTIF:{
132      for my $srv ($log->list_services_on_host($host)) {
133         last TESTIF if $log->service($host, $srv)->status eq 'OK' or $log->service($host, $srv)->status eq 'PENDING';
134         }
135
136      $hostdown{$host} = $host_stat;
137      next HOST;
138      }}
139
140   SRV:
141   for my $srv ($log->list_services_on_host($host)) {
142      my $status = $log->service($host, $srv)->status;
143
144      next SRV if $status eq 'OK';
145
146      push @serviceproblems, $log->service($host, $srv);
147   
148      my $downtime = downtime($log->service($host, $srv)->last_state_change);
149      my $color    = alertcolor($status, $downtime);
150
151      my $status_id = 0;
152      $status_id = $STATUS_DB{$status}->{'id'} if exists $STATUS_DB{$status};
153
154      #$hostcount{$host}++;
155      $hostcount{$host} ||= {count => 0, color => $color, status_id => $status_id, downtime => $downtime};
156      $hostcount{$host}->{'count'}++;
157      if (($status_id > $hostcount{$host}->{'status_id'})
158            or (($status_id == $hostcount{$host}->{'status_id'}) and ($downtime < $hostcount{$host}->{'downtime'}))) {
159         $hostcount{$host}->{'downtime'}  = $downtime;
160         $hostcount{$host}->{'status_id'} = $status_id;
161         $hostcount{$host}->{'color'}     = $color;
162         }
163      }
164   }
165
166my $now = time;
167my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $now;
168$year += 1900;
169$mon++;
170# my $date_sec = sprintf '%04i-%02i-%02i %02i:%02i:%02i', $year, $mon, $mday, $hour, $min, $sec;
171my $date_min = nosbreak(sprintf '%04i-%02i-%02i %02i:%02i', $year, $mon, $mday, $hour, $min);
172
173my $htmlpage;
174
175$htmlpage .= <<"ENDH" if not $cgi_only;
176Content-Type: text/html
177
178<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
179<html lang="en">
180<head>
181 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
182ENDH
183
184$htmlpage .= <<"ENDH" if $cgi_only;
185Content-Type: text/xml
186
187<?xml version="1.0" encoding="utf-8"?>
188<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
189ENDH
190
191#$htmlpage .= " <meta http-equiv=\"Refresh\" content=\"$config->{'refresh'}\">" if $config->{'refresh'} > 59; # minimum 1 min
192$htmlpage .= <<"ENDH" if not $cgi_only;
193 <title>Nagios  Velvice</title>
194 <link rel="stylesheet"    type="text/css"  href="$config->{'nagios-server'}{'stylesheets'}/velvice.css">
195 <link rel="shortcut icon" type="image/ico" href="$config->{'nagios-server'}{'image'}/favicon.ico">
196 <script type="text/javascript">
197   var refresh_sec = 900; // 15 min = 900 s
198   var refresh_interval;
199   function refresh() {
200      var req = new XMLHttpRequest();
201      var datenow = new Date();
202      console.log("Grabbing Value");
203      req.open("GET", '$cgi_script_name?only=body', true); // Grabs whatever you've written in this file
204      req.onload = function () {
205         if (req.status == 200) {
206            document.getElementById('master-body').innerHTML = req.responseXML.getElementById('master-body').innerHTML;
207            console.log("Update Page at", datenow.toLocaleTimeString());
208
209            refresh_next = req.responseXML.getElementById('master-body').getAttribute("refresh");
210            if (refresh_next < 60 && refresh_next != 0) {
211               refresh_next = 60;
212               }
213            if (refresh_next != refresh_sec) {
214               refresh_sec = refresh_next;
215               clearInterval(refresh_interval);
216               refresh_interval = setInterval(refresh, refresh_sec * 1000);
217               console.log("Update at", datenow.toLocaleTimeString(), "Refresh Interval:", refresh_sec);
218               document.getElementById('master-body').setAttribute("refresh", refresh_sec);
219               }
220            }
221         }
222      req.send(null);
223      }
224
225   function init() { // This is the function the browser first runs when it's loaded.
226      refresh_sec = document.getElementById('master-body').getAttribute("refresh");
227      if (refresh_sec < 60 && refresh_sec != 0) {
228         refresh_sec = 60;
229         }
230      // Set the refresh() function to run every 900 seconds. 1 second would be 1000
231      refresh_interval = setInterval(refresh, refresh_sec * 1000);
232      console.log("Start Refresh Interval:", refresh_sec);
233      }
234</script>
235</head>
236ENDH
237
238$htmlpage .= <<"ENDH";
239<body id="master-body" onload="init()" refresh="$config->{'refresh'}">
240<div class="header">
241 <h1>
242  <ul>
243    <li>Nagios Velvice Alert Panel : <a href="$config->{'nagios-server'}{'portal-url'}">Core Server</a></li>
244    <li><small><a id="refresh" href="$cgi_script_name">$date_min</a></small></li>
245  </ul>
246 </h1>
247</div>
248ENDH
249
250my %service_name   = ();
251my %service_status = ();
252for my $srv (@serviceproblems) {
253   $service_name{$srv->service_description}++;
254   $service_status{$srv->status}++;
255   }
256
257if (scalar @serviceproblems == 0) {
258   $htmlpage .= "<p>No alert to recheck.</p>\n";
259   }
260else {
261
262   $htmlpage .= "<p>Alert to recheck - Level:\n";
263   $htmlpage .= join ",\n",
264      " <span class='button'><a href='$cgi_script_name?check=all'>ALL</a><small>" . scalar(@serviceproblems) . '</small></span>',
265      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>$_</a><small>$service_status{$_}</small></span>",
266         sort keys %service_status);
267   $htmlpage .= ".\n";
268   $htmlpage .= " <br />\n";
269   $htmlpage .= " Service:\n";
270   $htmlpage .= join ",\n",
271      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>" . nosbreak($_) . "</a><small>$service_name{$_}</small></span>",
272         sort keys %service_name);
273   $htmlpage .= ".\n";
274   $htmlpage .= "</p>\n";
275
276   my $nagios_cmd;
277   open $nagios_cmd, '>>', $config->{'nagios-server'}{'nagios-cmd'} or die "Can't open file filename: $!";
278
279   my %remote_sshdown = ();
280   my %remote_db      = ();
281   my $remote_flag;
282
283   my $current_host  = '';
284   $htmlpage .= "<table border=\"1\">\n";
285   SERVICE_PROBLEMS:
286   for my $srv (@serviceproblems) {
287      my $hostname = $srv->host_name;
288      my $service  = $srv->service_description;
289      my $status   = $srv->status;
290      my $downtime = downtime($srv->last_state_change);
291      my $output   = HTML::Entities::encode($srv->plugin_output) =~ s/^[A-Z_\s]+?[:-]//r;
292
293      my $color = alertcolor($status, $downtime);
294      my $stylecolor = "style='background:$color;'";
295      $htmlpage .= " <tr>\n";
296      if ($hostname ne $current_host) {
297         $current_host  = $hostname;
298         my $rowspan    = $hostcount{$hostname}->{'count'};
299         my $rowcolor   = "style='background:" . $hostcount{$hostname}->{'color'} . ";'";
300         $htmlpage .= "  <td $rowcolor rowspan='$rowspan'>"
301            . "<a href=\"$cgi_script_name?check=" . uri_encode($hostname) . '">&#8623;</a></td>' . "\n";
302         $htmlpage .= "  <td $rowcolor class='hoop' rowspan='$rowspan'>"
303            . "<a href=\"$config->{'nagios-server'}{'status-cgi'}?host=" . uri_encode($hostname) . "\">$hostname</a></td>\n";
304         }
305
306      my $bold;
307      ACTION_STYLE:
308      for my $act_name (keys %{$config->{'remote-action'}}) {
309         my $act_regex = $config->{'remote-action'}{$act_name}{'regex'};
310         $bold++ if $service =~ m/$act_regex/ and $config->{'remote-action'}{$act_name}{'style'} eq 'bold';
311         }
312      $htmlpage .= $bold ? "  <td $stylecolor class='hoop bold'>" : "  <td $stylecolor class='hoop'>";
313      $htmlpage .= "$service</td>\n";
314
315      $htmlpage .= "  <td $stylecolor class='hoop'>$status</td>\n";
316      $htmlpage .= "  <td $stylecolor class='comment'>$output</td>\n";
317      $htmlpage .= "  <td $stylecolor class='days'>$downtime days</td>\n";
318
319      if (($cgi_check =~ m/all/i)
320            or ($cgi_check =~ m/^$service$/i)
321            or ($cgi_check =~ m/critical/i and $status eq 'CRITICAL')
322            or ($cgi_check =~ m/warning/i  and $status eq 'WARNING')
323            or ($cgi_check =~ m/pending/i  and $status eq 'PENDING')
324            or ($cgi_check eq $hostname    and $status =~ m/^(CRITICAL|WARNING|PENDING)$/)
325            ) {
326         $now++;
327         my $interval = $srv->next_check() - $srv->last_check() || 300; # 5 * 60 = 300
328         $interval =  240 if $interval <  240;
329         $interval = 3000 if $interval > 3000;
330         my $future = $now + 20 + int(rand($interval - 20));
331
332         $htmlpage .= "  <td class='checking'>" . ($future - $now) . "</td>\n";
333         #$htmlpage .= " -- <b>CHECK</b> [$now/" . ($future - $now) . "]";
334         printf $nagios_cmd "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n", $now, $hostname, $service, $now;
335         # delay future command
336         push @futurecheck, sprintf "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu", $future, $hostname, $service, $future;
337         }
338
339      ACTION_PUSH_AND_DEPEND:
340      for my $act_name (keys %{$config->{'remote-action'}}) {
341         my $act_regex  = $config->{'remote-action'}{$act_name}{'regex'};
342         my $act_status = $config->{'remote-action'}{$act_name}{'status'} || 'ALL';
343         my $act_depend = $config->{'remote-action'}{$act_name}{'depend'} || 'SSH';
344
345         if ($service =~ m/$act_regex/ and ($act_status eq 'ALL' or $status =~ m/$act_status/)) {
346            $remote_db{$act_name} ||= [];
347            push @{$remote_db{$act_name}}, $hostname;
348            $remote_flag++;
349            }
350
351         # check depend service otherwise
352         $remote_sshdown{$act_depend} ||= {};
353         $remote_sshdown{$act_depend}->{$hostname}++ if $service =~ m/$act_depend/;
354         }
355
356      $htmlpage .= " </tr>\n";
357      }
358
359   $htmlpage .= "</table>\n";
360   close $nagios_cmd;
361
362   # host down
363   if (%hostdown) {
364      $htmlpage .= "<br />\n";
365      $htmlpage .= "<table border='1'>\n";
366      HOST_DOWN:
367      for my $host (sort keys %hostdown) {
368         my $host_stat = $hostdown{$host};
369         my $hostname = $host_stat->host_name;
370         my $downtime = downtime($host_stat->last_state_change);
371         my $color = alertcolor('CRITICAL', $downtime);
372         my $stylecolor = "style='background:$color;'";
373         $htmlpage .= " <tr>\n";
374         $htmlpage .= "  <td $stylecolor>" . "<a href=\"$cgi_script_name?check=" . uri_encode($hostname) . '">&#8623;</a></td>' . "\n";
375         $htmlpage .= "  <td $stylecolor class='hoop'><a href=\"$config->{'nagios-server'}{'status-cgi'}?host=" . uri_encode($hostname) . "\">$hostname</a></td>\n";
376         my @host_service;
377         for my $srv ($log->list_services_on_host($host)) {
378            my $service = $log->service($host, $srv)->service_description;
379            push @host_service, $service;
380            if ($cgi_check eq $hostname) {
381               $now++;
382               printf $nagios_cmd "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n", $now, $hostname, $service, $now;
383               }
384            }
385         $htmlpage .= "  <td $stylecolor><small>" . join(', ', @host_service) . "</small></td>\n";
386         $htmlpage .= "  <td style='background:$color; text-align:right;'>$downtime days</td>\n";
387         $htmlpage .= "  <td class='checking'></td>\n" if $cgi_check eq $hostname;
388         $htmlpage .= " </tr>\n";
389         }
390      $htmlpage .= "</table>\n";
391      }
392
393   # remote action
394   if ($remote_flag) {
395      require Nagios::Object::Config;
396      my $parser = Nagios::Object::Config->new();
397      $parser->parse("/var/cache/nagios3/objects.cache");
398
399      $htmlpage .= "<div class='action'>\n";
400      REMOTE_ACTION:
401      for my $act_name (keys %remote_db) {
402         my $act_depend = $config->{'remote-action'}{$act_name}{'depend'} || 'SSH';
403
404         my @action = grep !exists $remote_sshdown{$act_depend}->{$_}, @{$remote_db{$act_name}};
405         if (@action) {
406            my $srv_title = $config->{'remote-action'}{$act_name}{'title'} || "Action: $act_name";
407            $htmlpage .= "<h2>$srv_title</h2>\n";
408            $htmlpage .= "<pre>\n";
409            my $remote_action = $config->{'remote-action'}{$act_name}{'command'};
410            $remote_action = $config->{'remote-action'}{$act_name}{'command-one'}
411               if @action == 1 and exists $config->{'remote-action'}{$act_name}{'command-one'};
412            my @hosts;
413            for my $host (@action) {
414               my $object = $parser->find_object("$host", "Nagios::Host");
415               push @hosts, hostmapping($object->address =~ s/\..*$//r);
416               }
417            my $hosts_list = join ' ', @hosts;
418            $htmlpage .= ' ' . $remote_action =~ s{\%m}{$hosts_list}r;
419            $htmlpage .= "</pre>\n";
420            }
421         }
422      $htmlpage .= "</div>\n";
423      }
424   }
425
426$htmlpage .= <<"ENDH";
427<hr clear="all" />
428<div class="footer">
429 <b><a href="http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/wiki/SoftWare/NagiosVelvice">Velvice</a>
430   - version: $VERSION</b>
431   (<a href="http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.html">online manual</a>)
432   - Written by Gabriel Moreau
433 <ul>
434  <li>Licence GNU GPL version 2 or later and Perl equivalent</li>
435  <li>Copyright (C) 2014-2019, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France</li>
436 </ul>
437</div>
438</body>
439ENDH
440
441$htmlpage .= <<"ENDH" if not $cgi_only;
442</html>
443ENDH
444
445print $htmlpage;
446
447# delayed future check
448if (@futurecheck) {
449   sleep 2;
450   my $nagios_cmd;
451   open $nagios_cmd, '>>', $config->{'nagios-server'}{'nagios-cmd'} or die "Can't open file filename: $!";
452   print $nagios_cmd "$_\n" for @futurecheck;
453   close $nagios_cmd;
454   }
455
456__END__
457
458
459=head1 NAME
460
461velvice.cgi - nagios velvice alert panel
462
463=head1 USAGE
464
465 velvice.cgi
466 velvice.cgi?check=XXX
467
468
469=head1 DESCRIPTION
470
471=begin html
472
473<img width="700" alt="Nagios Velvice Alert Panel" title="Nagios Velvice Alert Panel" style="float:right;" src="velvice.png" />
474
475=end html
476
477Nagios VELVICE is an acronym for "Nagios leVEL serVICE status".
478
479The Nagios web page is sometimes very graphically charged
480and does not necessarily contain the information you need at a glance.
481For example, it is quite complicated to restart controls on multiple hosts in one click.
482
483For example, a server that is down should take only one line and not one per service...
484Similarly, a service that has been down for 5 minutes or since yesterday
485has more weight than a service that has fallen for 15 days.
486
487With Velvice Panel, a broken down server takes only one line.
488Services that have been falling for a long time gradually lose their color and become pastel colors.
489
490With Velvice Panel, it is possible through a single click
491to redo a check of all services that are in the CRITICAL state.
492Similarly, it is possible to restart a check on all SSH services in breakdowns ...
493In order not to clog the Nagios server, checks are shifted by 2 seconds in time.
494
495There is also a link to the web page of the main Nagios server.
496For each computer, you have a direct link to its dedicated web page on this server.
497
498
499=head1 CONFIGURATION FILE SPECIFICATION
500
501The configuration file must be F</etc/nagios3/velvice.yml>.
502This is not a required file.
503The file is in YAML format because this is a human-readable text file style.
504Other formats could have been Plain XML, RDF, JSON... but they are much less readable.
505
506You can find in the software nagios-velvice an example of configuration:
507L<velvice.sample.yml|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.sample.yml>.
508This one is in fact the master reference specification!
509
510The main keys C<nagios-server> and C<color-downtime> have good default values.
511No secondary key is required...
512The Velvice script try hard to replace ~ by the good value automatically.
513
514 nagios-server:
515   status-file: /var/cache/nagios3/status.dat
516   nagios-cmd:  /var/lib/nagios3/rw/nagios.cmd
517   portal-url:  ~/nagios3/
518   status-cgi:  ~/cgi-bin/nagios3/status.cgi
519   stylesheets: ~/nagios3/stylesheets
520
521The background color of the faulty service line display remains stable with a bright color for at least 3 days.
522Then, it decreases and becomes pastel after 53 days with an intensity of 70% (100% is white and 0% is black).
523
524 color-downtime:
525   day-min:  3
526   day-max: 50
527   factor:   0.7
528
529With key C<host-mapping>,
530it's good to map C<localhost> to the real name of the computer (hostname).
531
532 host-mapping:
533   localhost:  srv-nagios
534   toto:       titi
535
536The only important key is C<remote-action>.
537You can affiliate as many subkeys as you want.
538Let's take an example:
539
540 remote-action:
541   oom-killer:
542     regex: ^OOM Killer
543     title:  OOM Killer
544     command:     tssh -c 'sudo rm /var/lib/nagios3/nagios_oom_killer.log' %m
545     command-one: ssh %m 'sudo rm /var/lib/nagios3/nagios_oom_killer.log'
546     depend: ^SSH
547     status: ALL
548     style: bold
549
550C<oom-killer> is just a key for your remote action.
551The regex is used to find which service has a problem...
552The title is use in the result web page (not mandatory - otherwise, it will be C<Action: oom-killer>).
553The C<command> is just written on this web page.
554You have the responsibility to copy / cut it on a terminal.
555For security reasons, the nagios server does not have the right to launch the command on the remote host.
556The wildcard C<%m> is replaced by the list of the host (separated by the space).
557Sometime, the command could be different if there is only one computer (just SSH and no parallel SSH).
558If your command is based on SSH,
559you can have an SSH action only if the remote SSH is running.
560So you can make the remote action depend on the SSH service through a regular expression of your choice.
561
562The last two keys.
563The C<status> key is for CRITICAL or WARNING (or ALL).
564The key C<style> is there to mark in bold the service in error on the web page.
565
566The web page will be partially updated every 15 minutes by default (if Javascript is enabled in your browser).
567It is possible to have a finer setting depending on the time of day and the day of the week
568by using Perl objects C<DateTime::Event::Recurrence> via some YAML parameters in the configuration file.
569See the sample configuration file
570L<velvice.sample.yml|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.sample.yml>
571for a very detailed case.
572With the following configuration,
573the refresh of the web page will take place every 5 min (300 s) from 9 am to noon and from 1 pm to 6 pm from Monday to Friday.
574From noon to 1 pm and from 6 pm to 8 pm on weekdays, this will take place every 10 minutes.
575
576 refreshments:
577   -
578     refresh: 300
579     days:  [ 1 .. 5 ]
580     start: [  9, 13 ]
581     end:   [ 12, 18 ]
582   -
583     refresh: 600
584     days:  [ 1 .. 5 ]
585     start: [ 12, 18 ]
586     end:   [ 13, 20 ]
587
588
589=head1 SEE ALSO
590
591yamllint(1), ysh(1), YAML, Nagios::StatusLog, Color::Calc, DateTime::Event::Recurrence
592
593In Debian GNU/Linux distribution, packages for C<yamllint> and C<ysh> are:
594
595=over
596
597=item * C<yamllint> - Linter for YAML files (Python)
598
599=item * C<libyaml-shell-perl> - YAML test shell (Perl)
600
601=back
602
603
604Own project ressources:
605
606=over
607
608=item * L<Web Site|http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/wiki/SoftWare/NagiosVelvice>
609
610=item * L<Online Manual|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.html>
611
612=item * L<SVN Repository|http://servforge.legi.grenoble-inp.fr/svn/soft-trokata/trunk/nagios-velvice> -
613        L<Forge Browser|http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/browser/trunk/nagios-velvice>
614
615=item * L<Debian Package|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/download/>
616
617=back
618
619
620=head1 VERSION
621
622$Id: velvice.cgi 387 2019-04-28 08:16:59Z g7moreau $
623
624
625=head1 AUTHOR
626
627Written by Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>, LEGI UMR 5519, CNRS, Grenoble - France
628
629
630=head1 LICENSE AND COPYRIGHT
631
632Licence GNU GPL version 2 or later and Perl equivalent
633
634Copyright (C) 2014-2019, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
Note: See TracBrowser for help on using the repository browser.