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

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