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

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