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

Last change on this file since 370 was 370, checked in by g7moreau, 6 years ago
  • Try to update refresh time
  • Property svn:keywords set to Id
File size: 22.2 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.1');
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').innerText = req.responseXML.getElementById('master-body').innerText;
214            document.getElementById('master-body').outerHTML = req.responseXML.getElementById('master-body').outerHTML;
215            console.log("Update Value");
216           
217            refresh_next = req.responseXML.getElementById('master-body').getAttribute("refresh");
218            if (refresh_next < 60 && refresh_next != 0) {
219               refresh_next = 60;
220               }
221            if (refresh_next != refresh_sec) {
222               refresh_sec = refresh_next;
223               clearInterval(refresh_interval);
224               refresh_interval = setInterval(refresh, refresh_sec * 1000);
225               }
226            }
227         }
228      req.send(null);
229      }
230
231   function init() { // This is the function the browser first runs when it's loaded.
232      // refresh() // Then runs the refresh function for the first time.
233      refresh_sec = document.getElementById('master-body').getAttribute("refresh");
234      if (refresh_sec < 60 && refresh_sec != 0) {
235         refresh_sec = 60;
236         }
237      refresh_interval = setInterval(refresh, refresh_sec * 1000); // Set the refresh() function to run every 900 seconds. 1 second would be 1000
238      }
239</script>
240</head>
241ENDH
242
243$htmlpage .= <<"ENDH";
244<body id="master-body" onload="init()" refresh="$config->{'refresh'}">
245<div class="header">
246 <h1>
247  <ul>
248    <li>Nagios Velvice Alert Panel : <a href="$config->{'nagios-server'}{'portal-url'}">Core Server</a></li>
249    <li><small><a id="refresh" href="$cgi_script_name">$date</a></small></li>
250  </ul>
251 </h1>
252</div>
253ENDH
254
255my %service_name   = ();
256my %service_status = ();
257for my $srv (@serviceproblems) {
258   $service_name{$srv->service_description}++;
259   $service_status{$srv->status}++;
260   }
261
262if (scalar @serviceproblems == 0) {
263   $htmlpage .= "<p>No alert to recheck.</p>\n";
264   }
265else {
266
267   $htmlpage .= "<p>Alert to recheck - Level:\n";
268   $htmlpage .= join ",\n",
269      " <span class='button'><a href='$cgi_script_name?check=all'>ALL</a><small>" . scalar(@serviceproblems) . '</small></span>',
270      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>$_</a><small>$service_status{$_}</small></span>",
271         sort keys %service_status);
272   $htmlpage .= ".\n";
273   $htmlpage .= " <br />\n";
274   $htmlpage .= " Service:\n";
275   $htmlpage .= join ",\n",
276      map(" <span class='button'><a href='$cgi_script_name?check=" . lc(uri_encode($_)) . "'>" . nosbreak($_) . "</a><small>$service_name{$_}</small></span>",
277         sort keys %service_name);
278   $htmlpage .= ".\n";
279   $htmlpage .= "</p>\n";
280
281   my $nagios_cmd;
282   open $nagios_cmd, '>>', $config->{'nagios-server'}{'nagios-cmd'} or die "Can't open file filename: $!";
283
284   my %remote_sshdown = ();
285   my %remote_db      = ();
286   my $remote_flag;
287
288   my $current_host  = '';
289   $htmlpage .= "<table border=\"1\">\n";
290   SERVICE_PROBLEMS:
291   for my $srv (@serviceproblems) {
292      my $hostname = $srv->host_name;
293      my $service  = $srv->service_description;
294      my $status   = $srv->status;
295      my $downtime = downtime($srv->last_state_change);
296      my $output   = HTML::Entities::encode($srv->plugin_output) =~ s/^[A-Z_\s]+?[:-]//r;
297
298      my $color = alertcolor($status, $downtime);
299      my $stylecolor = "style='background:$color;'";
300      $htmlpage .= " <tr>\n";
301      if ($hostname ne $current_host) {
302         $current_host  = $hostname;
303         my $rowspan    = $hostcount{$hostname}->{'count'};
304         my $rowcolor   = "style='background:" . $hostcount{$hostname}->{'color'} . ";'";
305         $htmlpage .= "  <td $rowcolor rowspan='$rowspan'>"
306            . "<a href=\"$cgi_script_name?check=" . uri_encode($hostname) . '">&#8623;</a></td>' . "\n";
307         $htmlpage .= "  <td $rowcolor class='hoop' rowspan='$rowspan'>"
308            . "<a href=\"$config->{'nagios-server'}{'status-cgi'}?host=" . uri_encode($hostname) . "\">$hostname</a></td>\n";
309         }
310
311      my $bold;
312      ACTION_STYLE:
313      for my $act_name (keys %{$config->{'remote-action'}}) {
314         my $act_regex = $config->{'remote-action'}{$act_name}{'regex'};
315         $bold++ if $service =~ m/$act_regex/ and $config->{'remote-action'}{$act_name}{'style'} eq 'bold';
316         }
317      $htmlpage .= $bold ? "  <td $stylecolor class='hoop bold'>" : "  <td $stylecolor class='hoop'>";
318      $htmlpage .= "$service</td>\n";
319
320      $htmlpage .= "  <td $stylecolor class='hoop'>$status</td>\n";
321      $htmlpage .= "  <td $stylecolor class='comment'>$output</td>\n";
322      $htmlpage .= "  <td $stylecolor class='days'>$downtime days</td>\n";
323
324      if (($cgi_check =~ m/all/i)
325            or ($cgi_check =~ m/^$service$/i)
326            or ($cgi_check =~ m/critical/i and $status eq 'CRITICAL')
327            or ($cgi_check =~ m/warning/i  and $status eq 'WARNING')
328            or ($cgi_check =~ m/pending/i  and $status eq 'PENDING')
329            or ($cgi_check eq $hostname    and $status =~ m/^(CRITICAL|WARNING|PENDING)$/)
330            ) {
331         $now++;
332         my $interval = $srv->next_check() - $srv->last_check() || 300; # 5 * 60 = 300
333         $interval =  240 if $interval <  240;
334         $interval = 3000 if $interval > 3000;
335         my $future = $now + 20 + int(rand($interval - 20));
336
337         $htmlpage .= "  <td class='checking'>" . ($future - $now) . "</td>\n";
338         #$htmlpage .= " -- <b>CHECK</b> [$now/" . ($future - $now) . "]";
339         printf $nagios_cmd "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n", $now, $hostname, $service, $now;
340         # delay future command
341         push @futurecheck, sprintf "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu", $future, $hostname, $service, $future;
342         }
343
344      ACTION_PUSH_AND_DEPEND:
345      for my $act_name (keys %{$config->{'remote-action'}}) {
346         my $act_regex  = $config->{'remote-action'}{$act_name}{'regex'};
347         my $act_status = $config->{'remote-action'}{$act_name}{'status'} || 'ALL';
348         my $act_depend = $config->{'remote-action'}{$act_name}{'depend'} || 'SSH';
349
350         if ($service =~ m/$act_regex/ and ($act_status eq 'ALL' or $status =~ m/$act_status/)) {
351            $remote_db{$act_name} ||= [];
352            push @{$remote_db{$act_name}}, $hostname;
353            $remote_flag++;
354            }
355
356         # check depend service otherwise
357         $remote_sshdown{$act_depend} ||= {};
358         $remote_sshdown{$act_depend}->{$hostname}++ if $service =~ m/$act_depend/;
359         }
360
361      $htmlpage .= " </tr>\n";
362      }
363
364   $htmlpage .= "</table>\n";
365   close $nagios_cmd;
366
367   # host down
368   if (%hostdown) {
369      $htmlpage .= "<br />\n";
370      $htmlpage .= "<table border='1'>\n";
371      HOST_DOWN:
372      for my $host (sort keys %hostdown) {
373         my $host_stat = $hostdown{$host};
374         my $hostname = $host_stat->host_name;
375         my $downtime = downtime($host_stat->last_state_change);
376         my $color = alertcolor('CRITICAL', $downtime);
377         $htmlpage .= " <tr style='background:$color'>\n";
378         $htmlpage .= "  <td 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            push @host_service, $log->service($host, $srv)->service_description;
382            }
383         $htmlpage .= "  <td><small>" . join(', ', @host_service) . "</small></td>\n";
384         $htmlpage .= "  <td style='text-align:right;'>$downtime days</td>\n";
385         $htmlpage .= " </tr>\n";
386         }
387      $htmlpage .= "</table>\n";
388      }
389
390   # remote action
391   if ($remote_flag) {
392      require Nagios::Object::Config;
393      my $parser = Nagios::Object::Config->new();
394      $parser->parse("/var/cache/nagios3/objects.cache");
395
396      $htmlpage .= "<div class='action'>\n";
397      REMOTE_ACTION:
398      for my $act_name (keys %remote_db) {
399         my $act_depend = $config->{'remote-action'}{$act_name}{'depend'} || 'SSH';
400
401         my @action = grep !exists $remote_sshdown{$act_depend}->{$_}, @{$remote_db{$act_name}};
402         if (@action) {
403            my $srv_title = $config->{'remote-action'}{$act_name}{'title'} || "Action: $act_name";
404            $htmlpage .= "<h2>$srv_title</h2>\n";
405            $htmlpage .= "<pre>\n";
406            my $remote_action = $config->{'remote-action'}{$act_name}{'command'};
407            $remote_action = $config->{'remote-action'}{$act_name}{'command-one'}
408               if @action == 1 and exists $config->{'remote-action'}{$act_name}{'command-one'};
409            my @hosts;
410            for my $host (@action) {
411               my $object = $parser->find_object("$host", "Nagios::Host");
412               push @hosts, hostmapping($object->address =~ s/\..*$//r);
413               }
414            my $hosts_list = join ' ', @hosts;
415            $htmlpage .= ' ' . $remote_action =~ s{\%m}{$hosts_list}r;
416            $htmlpage .= "</pre>\n";
417            }
418         }
419      $htmlpage .= "</div>\n";
420      }
421   }
422
423$htmlpage .= <<"ENDH";
424<hr clear="all" />
425<div class="footer">
426 <b><a href="http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/wiki/SoftWare/NagiosVelvice">Velvice</a>
427   - version: $VERSION</b>
428   (<a href="http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.html">online manual</a>)
429   - Written by Gabriel Moreau
430 <ul>
431  <li>Licence GNU GPL version 2 or later and Perl equivalent</li>
432  <li>Copyright (C) 2014-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France</li>
433 </ul>
434</div>
435</body>
436ENDH
437
438$htmlpage .= <<"ENDH" if not $cgi_only;
439</html>
440ENDH
441
442print $htmlpage;
443
444# delayed future check
445if (@futurecheck) {
446   sleep 2;
447   my $nagios_cmd;
448   open $nagios_cmd, '>>', $config->{'nagios-server'}{'nagios-cmd'} or die "Can't open file filename: $!";
449   print $nagios_cmd "$_\n" for @futurecheck;
450   close $nagios_cmd;
451   }
452
453__END__
454
455
456=head1 NAME
457
458velvice.cgi - nagios velvice alert panel
459
460=head1 USAGE
461
462 velvice.cgi
463 velvice.cgi?check=XXX
464
465
466=head1 DESCRIPTION
467
468=begin html
469
470<img width="700" alt="Nagios Velvice Alert Panel" title="Nagios Velvice Alert Panel" style="float:right" src="velvice.png" />
471
472=end html
473
474Nagios VELVICE is an acronym for "Nagios leVEL serVICE status".
475
476The Nagios web page is sometimes very graphically charged
477and does not necessarily contain the information you need at a glance.
478For example, it is quite complicated to restart controls on multiple hosts in one click.
479
480For example, a server that is down should take only one line and not one per service...
481Similarly, a service that has been down for 5 minutes or since yesterday
482has more weight than a service that has fallen for 15 days.
483
484With Velvice Panel, a broken down server takes only one line.
485Services that have been falling for a long time gradually lose their color and become pastel colors.
486
487With Velvice Panel, it is possible through a single click
488to redo a check of all services that are in the CRITICAL state.
489Similarly, it is possible to restart a check on all SSH services in breakdowns ...
490In order not to clog the Nagios server, checks are shifted by 2 seconds in time.
491
492There is also a link to the web page of the main Nagios server.
493For each computer, you have a direct link to its dedicated web page on this server.
494
495
496=head1 CONFIGURATION FILE SPECIFICATION
497
498The configuration file must be F</etc/nagios3/velvice.yml>.
499This is not a required file.
500The file is in YAML format because this is a human-readable text file style.
501Other formats could have been Plain XML, RDF, JSON... but they are much less readable.
502
503You can find in the software nagios-velvice an example of configuration:
504L<velvice.sample.yml|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.sample.yml>.
505This one is in fact the master reference specification!
506
507The main keys C<nagios-server> and C<color-downtime> have good default values.
508No secondary key is required...
509The Velvice script try hard to replace ~ by the good value automatically.
510
511 nagios-server:
512   status-file: /var/cache/nagios3/status.dat
513   nagios-cmd:  /var/lib/nagios3/rw/nagios.cmd
514   portal-url:  ~/nagios3/
515   status-cgi:  ~/cgi-bin/nagios3/status.cgi
516   stylesheets: ~/nagios3/stylesheets
517
518The background color of the faulty service line display remains stable with a bright color for at least 3 days.
519Then, it decreases and becomes pastel after 53 days with an intensity of 70% (100% is white and 0% is black).
520
521 color-downtime:
522   day-min:  3
523   day-max: 50
524   factor:   0.7
525
526With key C<host-mapping>,
527it's good to map C<localhost> to the real name of the computer (hostname).
528
529 host-mapping:
530   localhost:  srv-nagios
531   toto:       titi
532
533The only important key is C<remote-action>.
534You can affiliate as many subkeys as you want.
535Let's take an example:
536
537 remote-action:
538   oom-killer:
539     regex: ^OOM Killer
540     title:  OOM Killer
541     command:     tssh -c 'sudo rm /var/lib/nagios3/nagios_oom_killer.log' %m
542     command-one: ssh %m 'sudo rm /var/lib/nagios3/nagios_oom_killer.log'
543     depend: ^SSH
544     status: ALL
545     style: bold
546
547C<oom-killer> is just a key for your remote action.
548The regex is used to find which service has a problem...
549The title is use in the result web page (not mandatory - otherwise, it will be C<Action: oom-killer>).
550The C<command> is just written on this web page.
551You have the responsibility to copy / cut it on a terminal.
552For security reasons, the nagios server does not have the right to launch the command on the remote host.
553The wildcard C<%m> is replaced by the list of the host (separated by the space).
554Sometime, the command could be different if there is only one computer (just SSH and no parallel SSH).
555If your command is based on SSH,
556you can have an SSH action only if the remote SSH is running.
557So you can make the remote action depend on the SSH service through a regular expression of your choice.
558
559The last two keys.
560The C<status> key is for CRITICAL or WARNING (or ALL).
561The key C<style> is there to mark in bold the service in error on the web page.
562
563=head1 SEE ALSO
564
565yamllint(1), ysh(1), YAML, Nagios::StatusLog, Color::Calc
566
567In Debian GNU/Linux distribution, packages for C<yamllint> and C<ysh> are:
568
569=over
570
571=item * C<yamllint> - Linter for YAML files (Python)
572
573=item * C<libyaml-shell-perl> - YAML test shell (Perl)
574
575=back
576
577
578Own project ressources:
579
580=over
581
582=item * L<Web Site|http://servforge.legi.grenoble-inp.fr/projects/soft-trokata/wiki/SoftWare/NagiosVelvice>
583
584=item * L<Online Manual|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/velvice.html>
585
586=item * L<SVN Repository|http://servforge.legi.grenoble-inp.fr/svn/soft-trokata/trunk/nagios-velvice>
587
588=item * L<Debian Package|http://servforge.legi.grenoble-inp.fr/pub/soft-trokata/nagios-velvice/download/>
589
590=back
591
592
593=head1 VERSION
594
595$Id: velvice.cgi 370 2018-11-03 19:25:47Z g7moreau $
596
597
598=head1 AUTHOR
599
600Written by Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>, LEGI UMR 5519, CNRS, Grenoble - France
601
602
603=head1 LICENSE AND COPYRIGHT
604
605Licence GNU GPL version 2 or later and Perl equivalent
606
607Copyright (C) 2014-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
Note: See TracBrowser for help on using the repository browser.