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

Last change on this file since 372 was 372, checked in by g7moreau, 6 years ago
  • Small error in inner
  • Property svn:keywords set to Id
File size: 22.5 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-2018, 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.2');
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 => 3, color => '#F88888'},
38   WARNING  => {id => 2, color => '#FFFF00'},
39   PENDING  => {id => 1, color => '#E0E0E0'},
40   );
41
42my $config = {};
43$config = YAML::Syck::LoadFile('/etc/nagios3/velvice.yml') if -e '/etc/nagios3/velvice.yml';
44$config->{'nagios-server'}                ||= {};
45$config->{'nagios-server'}{'status-file'} ||= '/var/cache/nagios3/status.dat';
46$config->{'nagios-server'}{'nagios-cmd'}  ||= '/var/lib/nagios3/rw/nagios.cmd';
47$config->{'nagios-server'}{'portal-url'}  ||= $cgi_path =~ s{/cgi-bin/}{/}r . '/';
48$config->{'nagios-server'}{'status-cgi'}  ||= "$cgi_path/status.cgi";
49$config->{'nagios-server'}{'stylesheets'} ||= $config->{'nagios-server'}{'portal-url'} =~ s{/?$}{/stylesheets}r;
50$config->{'nagios-server'}{'image'}       ||= $config->{'nagios-server'}{'portal-url'} =~ s{/?$}{/images}r;
51$config->{'host-mapping'}                 ||= {};
52$config->{'color-downtime'}               ||= {};
53$config->{'color-downtime'}{'day-min'}    ||=  3;
54$config->{'color-downtime'}{'day-max'}    ||= 50;
55$config->{'color-downtime'}{'factor'}     ||=  0.7;
56$config->{'remote-action'}                ||= {};
57$config->{'refresh'}                      ||=  0;
58
59sub hostmapping {
60   my $host = shift;
61
62   return exists $config->{'host-mapping'}{$host} ? $config->{'host-mapping'}{$host} : $host;
63   }
64
65sub downtime {
66   my ($time_change) = @_;
67
68   my $now = time;
69   return sprintf '%.1f', ($now - $time_change) / (60 * 3600);
70   }
71
72sub alertcolor {
73   my ($status, $downtime) = @_;
74
75   my $color = '#0000FF';
76   $color = $STATUS_DB{$status}->{'color'} if exists $STATUS_DB{$status};
77
78   $downtime = $downtime - $config->{'color-downtime'}{'day-min'}; # same color first days
79   $downtime = $config->{'color-downtime'}{'day-max'} if $downtime > $config->{'color-downtime'}{'day-max'}; # max 50 days for color
80   $downtime =  0 if $downtime <  0;
81
82   my $factor = ($downtime * $config->{'color-downtime'}{'factor'}) / $config->{'color-downtime'}{'day-max'};
83   return Color::Calc::color_light_html($color, $factor);
84   }
85
86sub nosbreak {
87   my ($str) = @_;
88   
89   return $str =~ s/\s/\&nbsp;/gr;
90   }
91
92my $log = Nagios::StatusLog->new(
93   Filename => $config->{'nagios-server'}{'status-file'},
94   Version  => 3.0
95   );
96
97# refresh configuration
98if (exists $config->{'refreshments'}) {
99   require DateTime::Event::Recurrence;
100   require DateTime::SpanSet;
101
102   my @refreshments;
103   SET:
104   for my $set (@{$config->{'refreshments'}}) {
105      my $start   = DateTime::Event::Recurrence->weekly(days => $set->{'days'}, hours => $set->{'start'});
106      my $end     = DateTime::Event::Recurrence->weekly(days => $set->{'days'}, hours => $set->{'end'});
107      my $spanset = DateTime::SpanSet->from_sets(start_set => $start, end_set => $end);
108      push @refreshments, {refresh => $set->{'refresh'}, spanset => $spanset};
109      }
110
111   my $now = DateTime->now(time_zone => 'local');
112   SET:
113   for my $set (@refreshments) {
114      next SET if not $set->{'spanset'}->contains($now);
115 
116      $config->{'refresh'} = $set->{'refresh'};
117      last SET;
118      }
119   }
120
121my %hostdown;
122my @serviceproblems;
123my %hostcount;
124my @futurecheck;
125HOST:
126for my $host (sort $log->list_hosts()) {
127   my $host_stat = $log->host($host);
128
129   if ($host_stat->status eq 'DOWN') {TESTIF:{
130      for my $srv ($log->list_services_on_host($host)) {
131         last TESTIF if $log->service($host, $srv)->status eq 'OK' or $log->service($host, $srv)->status eq 'PENDING';
132         }
133
134      $hostdown{$host} = $host_stat;
135      next HOST;
136      }}
137
138   SRV:
139   for my $srv ($log->list_services_on_host($host)) {
140      my $status = $log->service($host, $srv)->status;
141
142      next SRV if $status eq 'OK';
143
144      push @serviceproblems, $log->service($host, $srv);
145   
146      my $downtime = downtime($log->service($host, $srv)->last_state_change);
147      my $color    = alertcolor($status, $downtime);
148
149      my $status_id = 0;
150      $status_id = $STATUS_DB{$status}->{'id'} if exists $STATUS_DB{$status};
151
152      #$hostcount{$host}++;
153      $hostcount{$host} ||= {count => 0, color => $color, status_id => $status_id, downtime => $downtime};
154      $hostcount{$host}->{'count'}++;
155      if (($status_id >= $hostcount{$host}->{'status_id'}) and ($downtime < $hostcount{$host}->{'downtime'})) {
156         $hostcount{$host}->{'downtime'}  = $downtime;
157         $hostcount{$host}->{'status_id'} = $status_id;
158         $hostcount{$host}->{'color'}     = $color;
159         }
160      }
161   }
162
163my $now = time;
164my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $now;
165$year += 1900;
166$mon++;
167#my $date = nosbreak(sprintf '%04i-%02i-%02i %02i:%02i:%02i', $year, $mon, $mday, $hour, $min, $sec);
168my $date = nosbreak(sprintf '%04i-%02i-%02i %02i:%02i', $year, $mon, $mday, $hour, $min);
169
170my $htmlpage;
171
172$htmlpage .= <<"ENDH" if not $cgi_only;
173Content-Type: text/html
174
175<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
176<html lang="en">
177<head>
178 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
179ENDH
180
181$htmlpage .= <<"ENDH" if $cgi_only;
182Content-Type: text/xml
183
184<?xml version="1.0" encoding="utf-8"?>
185<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
186ENDH
187
188#$htmlpage .= " <meta http-equiv=\"Refresh\" content=\"$config->{'refresh'}\">" if $config->{'refresh'} > 59; # minimum 1 min
189$htmlpage .= <<"ENDH" if not $cgi_only;
190 <title>Nagios  Velvice</title>
191 <link rel="stylesheet"    type="text/css"  href="$config->{'nagios-server'}{'stylesheets'}/velvice.css">
192 <link rel="shortcut icon" type="image/ico" href="$config->{'nagios-server'}{'image'}/favicon.ico">
193 <script type="text/javascript">
194   var first_loop  = 0;
195   var refresh_sec = 900; // 15 min = 900 s
196   var refresh_interval;
197   function refresh() {
198      if (first_loop == 0) {
199         first_loop++;
200         return;
201         }
202      var req = new XMLHttpRequest();
203      console.log("Grabbing Value");
204      // req.onreadystatechange = function () {
205      //    if (req.readyState == 4 && req.status == 200) {
206      //       document.getElementById('master-body').innerText = req.responseXML.getElementById('master-body').innerText;
207      //       }
208      //    }
209      // req.overrideMimeType('text/xml');
210      req.open("GET", '$cgi_script_name?only=body', true); // Grabs whatever you've written in this file
211      req.onload = function () {
212         if (req.status == 200) {
213            document.getElementById('master-body').innerHTML = req.responseXML.getElementById('master-body').innerHTML;
214            // document.getElementById('master-body').outerHTML = req.responseXML.getElementById('master-body').outerHTML;
215            console.log("Update Value");
216            // console.log("Update Value", req.responseXML.getElementById('master-body').outerHTML);
217
218            refresh_next = req.responseXML.getElementById('master-body').getAttribute("refresh");
219            if (refresh_next < 60 && refresh_next != 0) {
220               refresh_next = 60;
221               }
222            if (refresh_next != refresh_sec) {
223               refresh_sec = refresh_next;
224               clearInterval(refresh_interval);
225               refresh_interval = setInterval(refresh, refresh_sec * 1000);
226               console.log("Refresh Interval ", refresh_sec);
227               document.getElementById('master-body').setAttribute("refresh", refresh_sec);
228               }
229            }
230         }
231      req.send(null);
232      }
233
234   function init() { // This is the function the browser first runs when it's loaded.
235      // refresh() // Then runs the refresh function for the first time.
236      refresh_sec = document.getElementById('master-body').getAttribute("refresh");
237      if (refresh_sec < 60 && refresh_sec != 0) {
238         refresh_sec = 60;
239         }
240      refresh_interval = setInterval(refresh, refresh_sec * 1000); // Set the refresh() function to run every 900 seconds. 1 second would be 1000
241      }
242</script>
243</head>
244ENDH
245
246$htmlpage .= <<"ENDH";
247<body id="master-body" onload="init()" refresh="$config->{'refresh'}">
248<div class="header">
249 <h1>
250  <ul>
251    <li>Nagios Velvice Alert Panel : <a href="$config->{'nagios-server'}{'portal-url'}">Core Server</a></li>
252    <li><small><a id="refresh" href="$cgi_script_name">$date</a></small></li>
253  </ul>
254 </h1>
255</div>
256ENDH
257
258my %service_name   = ();
259my %service_status = ();
260for my $srv (@serviceproblems) {
261   $service_name{$srv->service_description}++;
262   $service_status{$srv->status}++;
263   }
264
265if (scalar @serviceproblems == 0) {
266   $htmlpage .= "<p>No alert to recheck.</p>\n";
267   }
268else {
269
270   $htmlpage .= "<p>Alert to recheck - Level:\n";
271   $htmlpage .= join ",\n",
272      " <span class='button'><a href='$cgi_script_name?check=all'>ALL</a><small>" . scalar(@serviceproblems) . '</small></span>',
273      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>$_</a><small>$service_status{$_}</small></span>",
274         sort keys %service_status);
275   $htmlpage .= ".\n";
276   $htmlpage .= " <br />\n";
277   $htmlpage .= " Service:\n";
278   $htmlpage .= join ",\n",
279      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>" . nosbreak($_) . "</a><small>$service_name{$_}</small></span>",
280         sort keys %service_name);
281   $htmlpage .= ".\n";
282   $htmlpage .= "</p>\n";
283
284   my $nagios_cmd;
285   open $nagios_cmd, '>>', $config->{'nagios-server'}{'nagios-cmd'} or die "Can't open file filename: $!";
286
287   my %remote_sshdown = ();
288   my %remote_db      = ();
289   my $remote_flag;
290
291   my $current_host  = '';
292   $htmlpage .= "<table border=\"1\">\n";
293   SERVICE_PROBLEMS:
294   for my $srv (@serviceproblems) {
295      my $hostname = $srv->host_name;
296      my $service  = $srv->service_description;
297      my $status   = $srv->status;
298      my $downtime = downtime($srv->last_state_change);
299      my $output   = HTML::Entities::encode($srv->plugin_output) =~ s/^[A-Z_\s]+?[:-]//r;
300
301      my $color = alertcolor($status, $downtime);
302      my $stylecolor = "style='background:$color;'";
303      $htmlpage .= " <tr>\n";
304      if ($hostname ne $current_host) {
305         $current_host  = $hostname;
306         my $rowspan    = $hostcount{$hostname}->{'count'};
307         my $rowcolor   = "style='background:" . $hostcount{$hostname}->{'color'} . ";'";
308         $htmlpage .= "  <td $rowcolor rowspan='$rowspan'>"
309            . "<a href=\"$cgi_script_name?check=" . uri_encode($hostname) . '">&#8623;</a></td>' . "\n";
310         $htmlpage .= "  <td $rowcolor class='hoop' rowspan='$rowspan'>"
311            . "<a href=\"$config->{'nagios-server'}{'status-cgi'}?host=" . uri_encode($hostname) . "\">$hostname</a></td>\n";
312         }
313
314      my $bold;
315      ACTION_STYLE:
316      for my $act_name (keys %{$config->{'remote-action'}}) {
317         my $act_regex = $config->{'remote-action'}{$act_name}{'regex'};
318         $bold++ if $service =~ m/$act_regex/ and $config->{'remote-action'}{$act_name}{'style'} eq 'bold';
319         }
320      $htmlpage .= $bold ? "  <td $stylecolor class='hoop bold'>" : "  <td $stylecolor class='hoop'>";
321      $htmlpage .= "$service</td>\n";
322
323      $htmlpage .= "  <td $stylecolor class='hoop'>$status</td>\n";
324      $htmlpage .= "  <td $stylecolor class='comment'>$output</td>\n";
325      $htmlpage .= "  <td $stylecolor class='days'>$downtime days</td>\n";
326
327      if (($cgi_check =~ m/all/i)
328            or ($cgi_check =~ m/^$service$/i)
329            or ($cgi_check =~ m/critical/i and $status eq 'CRITICAL')
330            or ($cgi_check =~ m/warning/i  and $status eq 'WARNING')
331            or ($cgi_check =~ m/pending/i  and $status eq 'PENDING')
332            or ($cgi_check eq $hostname    and $status =~ m/^(CRITICAL|WARNING|PENDING)$/)
333            ) {
334         $now++;
335         my $interval = $srv->next_check() - $srv->last_check() || 300; # 5 * 60 = 300
336         $interval =  240 if $interval <  240;
337         $interval = 3000 if $interval > 3000;
338         my $future = $now + 20 + int(rand($interval - 20));
339
340         $htmlpage .= "  <td class='checking'>" . ($future - $now) . "</td>\n";
341         #$htmlpage .= " -- <b>CHECK</b> [$now/" . ($future - $now) . "]";
342         printf $nagios_cmd "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n", $now, $hostname, $service, $now;
343         # delay future command
344         push @futurecheck, sprintf "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu", $future, $hostname, $service, $future;
345         }
346
347      ACTION_PUSH_AND_DEPEND:
348      for my $act_name (keys %{$config->{'remote-action'}}) {
349         my $act_regex  = $config->{'remote-action'}{$act_name}{'regex'};
350         my $act_status = $config->{'remote-action'}{$act_name}{'status'} || 'ALL';
351         my $act_depend = $config->{'remote-action'}{$act_name}{'depend'} || 'SSH';
352
353         if ($service =~ m/$act_regex/ and ($act_status eq 'ALL' or $status =~ m/$act_status/)) {
354            $remote_db{$act_name} ||= [];
355            push @{$remote_db{$act_name}}, $hostname;
356            $remote_flag++;
357            }
358
359         # check depend service otherwise
360         $remote_sshdown{$act_depend} ||= {};
361         $remote_sshdown{$act_depend}->{$hostname}++ if $service =~ m/$act_depend/;
362         }
363
364      $htmlpage .= " </tr>\n";
365      }
366
367   $htmlpage .= "</table>\n";
368   close $nagios_cmd;
369
370   # host down
371   if (%hostdown) {
372      $htmlpage .= "<br />\n";
373      $htmlpage .= "<table border='1'>\n";
374      HOST_DOWN:
375      for my $host (sort keys %hostdown) {
376         my $host_stat = $hostdown{$host};
377         my $hostname = $host_stat->host_name;
378         my $downtime = downtime($host_stat->last_state_change);
379         my $color = alertcolor('CRITICAL', $downtime);
380         $htmlpage .= " <tr style='background:$color'>\n";
381         $htmlpage .= "  <td class='hoop'><a href=\"$config->{'nagios-server'}{'status-cgi'}?host=" . uri_encode($hostname) . "\">$hostname</a></td>\n";
382         my @host_service;
383         for my $srv ($log->list_services_on_host($host)) {
384            push @host_service, $log->service($host, $srv)->service_description;
385            }
386         $htmlpage .= "  <td><small>" . join(', ', @host_service) . "</small></td>\n";
387         $htmlpage .= "  <td style='text-align:right;'>$downtime days</td>\n";
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-2018, 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
566=head1 SEE ALSO
567
568yamllint(1), ysh(1), YAML, Nagios::StatusLog, Color::Calc
569
570In Debian GNU/Linux distribution, packages for C<yamllint> and C<ysh> are:
571
572=over
573
574=item * C<yamllint> - Linter for YAML files (Python)
575
576=item * C<libyaml-shell-perl> - YAML test shell (Perl)
577
578=back
579
580
581Own project ressources:
582
583=over
584
585=item * L<Web Site|http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/wiki/SoftWare/NagiosVelvice>
586
587=item * L<Online Manual|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.html>
588
589=item * L<SVN Repository|http://servforge.legi.grenoble-inp.fr/svn/soft-trokata/trunk/nagios-velvice>
590
591=item * L<Debian Package|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/download/>
592
593=back
594
595
596=head1 VERSION
597
598$Id: velvice.cgi 372 2018-11-04 10:06:07Z g7moreau $
599
600
601=head1 AUTHOR
602
603Written by Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>, LEGI UMR 5519, CNRS, Grenoble - France
604
605
606=head1 LICENSE AND COPYRIGHT
607
608Licence GNU GPL version 2 or later and Perl equivalent
609
610Copyright (C) 2014-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
Note: See TracBrowser for help on using the repository browser.