/[mon-modules]/monshow.cgi
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /monshow.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Sat Aug 10 16:33:09 2002 UTC (16 years, 10 months ago) by dpavlin
Branch: MAIN
import of monshow 1.7

1 dpavlin 1.1 #!/usr/bin/perl -T
2     #
3     # monshow - concise, user view-based opstatus summary
4     #
5     # Jim Trocki, trockij@transmeta.com
6     #
7     # $Id: monshow 1.7 Sun, 24 Jun 2001 22:41:40 -0400 trockij $
8     #
9     # Copyright (C) 1998, Jim Trocki
10     #
11     # This program is free software; you can redistribute it and/or modify
12     # it under the terms of the GNU General Public License as published by
13     # the Free Software Foundation; either version 2 of the License, or
14     # (at your option) any later version.
15     #
16     # This program is distributed in the hope that it will be useful,
17     # but WITHOUT ANY WARRANTY; without even the implied warranty of
18     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     # GNU General Public License for more details.
20     #
21     # You should have received a copy of the GNU General Public License
22     # along with this program; if not, write to the Free Software
23     # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24     #
25     use strict "vars";
26    
27     use Getopt::Long;
28     use English;
29     use CGI;
30     use Text::Wrap;
31     use Mon::Client;
32     use Data::Dumper;
33    
34     #
35     # forward declarations
36     #
37     sub usage;
38     sub get_auth;
39     sub read_cf;
40     sub err_die;
41     sub expand_watch;
42     sub secs_to_hms;
43     sub display_allok;
44     sub compose_detail;
45     sub compose_header;
46     sub compose_disabled;
47     sub compose_table;
48     sub compose_trailer;
49     sub get_client_status;
50     sub opstatus_color;
51     sub pre_pad_if_empty;
52     sub tdiff_string;
53    
54     #
55     # set this to the path of your view configuration files
56     #
57     my $VIEWPATH = "/etc/mon/monshow";
58    
59     my %OPSTAT = %Mon::Client::OPSTAT;
60     my $WORD = '[a-zA-Z0-9_-]+';
61     my $OUT_BUF = "";
62     my $e;
63     $= = 1000;
64     $SIG{INT} = \&handle_sig;
65     $SIG{TERM} = \&handle_sig;
66    
67     # safe $PATH for taint mode
68     $ENV{PATH} = '/usr/local/bin:/usr/bin:/bin';
69    
70     my ($DEP, $GROUP, $SERVICE, $STATUS, $TIME, $NEXT, $ALERTS, $SUMMARY, $DESC);
71    
72     # Untaint args, tainting is just for stuff which comes from CGI.
73     for (@ARGV) {
74     /(.*)/s or die;
75     $_ = $1;
76     }
77    
78     my %opt;
79     GetOptions (\%opt, "showall", "auth", "help", "full", "disabled",
80     "rcfile=s", "login=s", "server=s", "port=i", "prot=s",
81     "detail=s", "view=s") || usage;
82    
83     @ARGV == 0 || usage "No non-switch args expected\n";
84    
85     my $CGI;
86     my %QUERY_ARGS;
87     if (defined $ENV{"REQUEST_METHOD"})
88     {
89     unless ($CGI = new CGI)
90     {
91     $CGI = 1;
92     err_die ("Can't create CGI object\n");
93     }
94     }
95    
96     if (!$CGI && $opt{"help"})
97     {
98     usage;
99     }
100    
101     if ($CGI)
102     {
103     foreach my $e (split (/\?/, $ENV{"QUERY_STRING"}))
104     {
105     next if ($e !~ /=/);
106    
107     my ($var, $val) = split (/=/, $e);
108    
109     $QUERY_ARGS{$var} = $val;
110     }
111     }
112    
113     my $CF = {
114     "host" => "localhost",
115     "full" => 0,
116     "show-disabled" => 0,
117     "bg" => "d5d5d5",
118     "bg-ok" => "a0d0a0",
119     "bg-fail" => "e088b7",
120     "bg-untested" => "e0e0e0",
121     "table-color" => "cccccc",
122     "summary-len" => 20,
123     };
124    
125     my $GLOBAL = {
126     "view-name" => undef,
127     };
128    
129     #
130     # read config file
131     #
132     my ($e, $what) = read_cf ($CF);
133    
134     if ($e ne "")
135     {
136     err_die ("while reading config file, $e");
137     }
138    
139     #
140     # cmdline args override config file
141     #
142     if (!$CGI)
143     {
144     $CF->{"all"} = 1 if ($opt{"showall"});
145     $CF->{"full"} = 1 if ($opt{"full"});
146     $CF->{"detail"} = $opt{"detail"} if ($opt{"detail"} ne "");
147     $CF->{"host"} = $opt{"server"} if ($opt{"server"});
148     $CF->{"port"} = $opt{"port"} if ($opt{"port"});
149     $CF->{"prot"} = $opt{"prot"} if ($opt{"prot"});
150     }
151    
152     #
153     # retrieve client status
154     #
155     my ($e, $st) = get_client_status ($what);
156    
157     if ($e ne "")
158     {
159     err_die ($e);
160     }
161    
162     expand_watch ($what, $st);
163    
164     my $rows = select_table ($what, $st);
165    
166     compose_header ($st->{"state"});
167    
168     #
169     # CGI invocation
170     #
171     if ($CGI)
172     {
173     if ($QUERY_ARGS{"disabled"})
174     {
175     compose_disabled ($st->{"disabled"});
176     }
177    
178     elsif (!$QUERY_ARGS{"detail"})
179     {
180     compose_table ($rows, $st);
181    
182     compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"});
183     }
184    
185     elsif ($QUERY_ARGS{"detail"})
186     {
187     compose_detail ($QUERY_ARGS{"detail"}, $st);
188     }
189     }
190    
191     #
192     # cmdline invocation
193     #
194     else
195     {
196     if ($opt{"disabled"})
197     {
198     compose_disabled ($st->{"disabled"});
199     }
200    
201     elsif ($CF->{"detail"} ne "")
202     {
203     compose_detail ($CF->{"detail"}, $st);
204     }
205    
206     else
207     {
208     compose_table ($rows, $st);
209    
210     compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"});
211     }
212     }
213    
214     compose_trailer;
215    
216     if ($CGI)
217     {
218     print <<EOF;
219     Content-type: text/html
220    
221     $OUT_BUF
222     EOF
223     }
224    
225     else
226     {
227     print "\n";
228     }
229    
230     exit;
231    
232     #-----------------------------------------------------------------------------
233    
234     format STDOUT_TOP =
235    
236     GROUP SERVICE STATUS LAST NEXT ALERTS SUMMARY
237     .
238    
239    
240     #
241     # usage
242     #
243     sub usage
244     {
245     print STDERR @_, <<EOF;
246    
247     usage: monshow [--auth] [--showall] [--full] [--login user] [--disabled]
248     [--server host] [--port num] [--rcfile file]
249     [--detail group,service] [--view name]
250     --showall do not read rcfile and show opstatus of all services
251     --full show disabled, failures, successes, and untested
252     --detail g,s show detail (alert acks, etc.) for group,service
253     --view name display a pre-defined view
254     --auth authenticate to mon server
255     --disabled show disabled
256     --prot ver set protocol version, must match 1.2.3 format
257     --login user use "login" as username while authenticating
258     --server host use "host" as monhost, instead of MONHOST
259     --port num use "num" as port number instead of default
260     --rcfile file use "file" as config file instead of \$HOME/.monshowrc
261    
262     EOF
263    
264     exit 1;
265     }
266    
267    
268     #
269     # signal handler
270     #
271     sub handle_sig
272     {
273     system "stty echo" unless ($CGI);
274     exit;
275     }
276    
277    
278     #
279     # get auth info
280     #
281     # returns a list "error", "login", "password"
282     #
283     sub get_auth
284     {
285     my ($login, $pass);
286    
287     if ($CGI)
288     {
289     $login = $CGI->query ("login");
290     $pass = $CGI->query ("password");
291     }
292    
293     else
294     {
295     if ($opt{"login"})
296     {
297     $login = $opt{"login"};
298     }
299    
300     else
301     {
302     return "could not determine username"
303     if (!defined ($login = getpwuid($EUID)));
304     }
305    
306     if (-t STDIN)
307     {
308     system "stty -echo";
309     print "Password: ";
310     chop ($pass = <STDIN>);
311     print "\n";
312     system "stty echo";
313     return "invalid password" if ($pass =~ /^\s*$/);
314     }
315    
316     else
317     {
318     my $cmd;
319    
320     while (defined ($cmd = <>))
321     {
322     chomp $cmd;
323     if ($cmd =~ /^user=(\S+)$/i)
324     {
325     $login = $1;
326     }
327    
328     elsif ($cmd =~ /^pass=(\S+)$/i)
329     {
330     $pass = $1;
331     }
332    
333     last if (defined ($login) && defined ($pass));
334     }
335     }
336     }
337    
338     return "inadequate authentication information supplied"
339     if ($login eq "" || $pass eq "");
340    
341     return ("", $login, $pass);
342     }
343    
344     #
345     # config file
346     #
347     sub read_cf
348     {
349     my $CF = shift;
350    
351     my ($group, $service);
352     my @RC;
353     my $view = 0;
354    
355     my $RC = "/etc/mon/monshowrc";
356    
357     if ($CGI)
358     {
359     if ($ENV{"PATH_INFO"} =~ /^\/\S+/)
360     {
361     my $p=$ENV{"PATH_INFO"};
362     $p =~ s/^[.\/]*//;
363     $p =~ s/\/*$//;
364     $p =~ s/\.\.//g;
365     $RC = "$VIEWPATH/$p";
366     $GLOBAL->{"view-name"} = $p;
367     $view = 1;
368     }
369    
370     elsif ($QUERY_ARGS{"view"} ne "")
371     {
372     $QUERY_ARGS{"view"} =~ s/^[.\/]*//;
373     $QUERY_ARGS{"view"} =~ s/\.\.//g;
374     $GLOBAL->{"view-name"} = $QUERY_ARGS{"view"};
375     $RC = "$VIEWPATH/$QUERY_ARGS{view}";
376     $view = 1;
377     }
378    
379     elsif (-f ".monshowrc")
380     {
381     $RC = ".monshowrc";
382     }
383     }
384    
385     else
386     {
387     if ($opt{"rcfile"})
388     {
389     $RC = $opt{"rcfile"};
390     }
391    
392     elsif ($opt{"view"} ne "")
393     {
394     $RC = "$VIEWPATH/$opt{view}";
395     $GLOBAL->{"view-name"} = $opt{"view"};
396     $view = 1;
397     }
398    
399     elsif (-f "$ENV{HOME}/.monshowrc")
400     {
401     $RC = "$ENV{HOME}/.monshowrc";
402     }
403     }
404    
405     if ($opt{"old"})
406     {
407     $CF->{"prot"} = "0.37.0";
408     $CF->{"port"} = 32777;
409     }
410    
411     if (-f $RC)
412     {
413     open (IN, $RC) || return "could not read $RC: $!";
414    
415     my $html_header = 0;
416     my $link_text = 0;
417     my $link_group = "";
418     my $link_service = "";
419    
420     while (<IN>)
421     {
422     next if (/^\s*#/ || /^\s*$/);
423    
424     if ($html_header)
425     {
426     if (/^END\s*$/)
427     {
428     $html_header = 0;
429     next;
430     }
431    
432     else
433     {
434     $CF->{"html-header"} .= $_;
435     next;
436     }
437     }
438    
439     elsif ($link_text)
440     {
441     if (/^END\s*$/)
442     {
443     $link_text = 0;
444     next;
445     }
446    
447     else
448     {
449     $CF->{"links"}->{$link_group}->{$link_service}->{"link-text"} .= $_;
450     next;
451     }
452     }
453    
454     else
455     {
456     chomp;
457     s/^\s*//;
458     s/\s*$//;
459     }
460    
461     if (/^set \s+ (\S+) \s* (\S+)?/ix)
462     {
463     my $cmd = $1;
464     my $arg = $2;
465     if ($cmd eq "show-disabled") { }
466     elsif ($cmd eq "host") { }
467     elsif ($cmd eq "prot") { }
468     elsif ($cmd eq "port") { }
469     elsif ($cmd eq "full") { }
470     elsif ($cmd eq "bg") { }
471     elsif ($cmd eq "bg-ok") { }
472     elsif ($cmd eq "bg-fail") { }
473     elsif ($cmd eq "bg-untested") { }
474     elsif ($cmd eq "table-color") { }
475     elsif ($cmd eq "html-header") { $html_header = 1; next; }
476     elsif ($cmd eq "refresh") { }
477     elsif ($cmd eq "summary-len") { }
478     else
479     {
480     print STDERR "unknown set, line $.\n";
481     next;
482     }
483    
484     if ($arg ne "")
485     {
486     $CF->{$cmd} = $arg;
487     }
488    
489     else
490     {
491     $CF->{$cmd} = 1;
492     }
493     }
494    
495     elsif (/^watch \s+ (\S+)/x)
496     {
497     push (@RC, [$1]);
498     }
499    
500     elsif (/^service \s+ (\S+) \s+ (\S+)/x)
501     {
502     push (@RC, [$1, $2]);
503     }
504    
505     elsif (/^link \s+ (\S+) \s+ (\S+) \s+ (.*)\s*/ix)
506     {
507     $CF->{"links"}->{$1}->{$2}->{"link"} = $3;
508     }
509    
510     elsif (/^link-text \s+ (\S+) \s+ (\S+)/ix)
511     {
512     $link_text = 1;
513     $link_group = $1;
514     $link_service = $2;
515     next;
516     }
517    
518     else
519     {
520     my $lnum = $.;
521     close (IN);
522     err_die ("error in config file, line $.");
523     }
524     }
525     close (IN);
526     }
527    
528     elsif (! -f $RC && $view)
529     {
530     err_die ("no view found");
531     }
532    
533     return ("", \@RC);
534     }
535    
536    
537     sub secs_to_hms
538     {
539     my ($s) = @_;
540     my ($dd, $hh, $mm, $ss);
541    
542     $dd = int ($s / 86400);
543     $s -= $dd * 86400;
544    
545     $hh = int ($s / 3600);
546     $s -= $hh * 3600;
547    
548     $mm = int ($s / 60);
549     $s -= $mm * 60;
550    
551     $ss = $s;
552    
553     if ($dd == 0)
554     {
555     sprintf("%02d:%02d", $hh, $mm);
556     }
557    
558     else
559     {
560     sprintf("%d days, %02d:%02d", $dd, $hh, $mm);
561     }
562     }
563    
564    
565     #
566     # exit displaying error in appropriate output format
567     #
568     sub err_die
569     {
570     my $msg = shift;
571    
572     if ($CGI)
573     {
574     print <<EOF;
575     Content-type: text/html
576    
577     <html>
578     <head>
579     <title> Error </title>
580     </head>
581     <body>
582     <h2> Error </h2>
583     <pre>
584     $msg
585     </pre>
586     </body>
587     </html>
588     EOF
589     }
590    
591     else
592     {
593     print <<EOF;
594     Error: $msg
595    
596     EOF
597     }
598    
599     exit 1;
600     }
601    
602    
603     #
604     # everything is cool
605     #
606     sub display_allok
607     {
608     if ($CGI)
609     {
610     $OUT_BUF .= <<EOF;
611     <h2> All systems OK </h2>
612     <p>
613    
614     EOF
615     }
616    
617     else
618     {
619     print "\nAll systems OK\n";
620     }
621     }
622    
623    
624     #
625     # client status
626     #
627     # return ("", $state, \%opstatus, \%disabled, \%deps, \%groups, \%descriptions);
628     #
629     sub get_client_status {
630     my $what = shift;
631    
632     my $cl;
633    
634     if (!defined ($cl = Mon::Client->new))
635     {
636     return "could not create client object: $@";
637     }
638    
639     my ($username, $pass);
640    
641     if ($opt{"auth"} && !$CGI)
642     {
643     my $e;
644     ($e, $username, $pass) = get_auth;
645     if ($e ne "")
646     {
647     return "$e";
648     }
649     $cl->username ($username);
650     $cl->password ($pass);
651     }
652    
653     $cl->host ($CF->{"host"}) if (defined $CF->{"host"});
654     $cl->port ($CF->{"port"}) if (defined $CF->{"port"});
655     $cl->port ($CF->{"prot"}) if (defined $CF->{"prot"});
656    
657     $cl->connect;
658    
659     if ($cl->error) {
660     return "Could not connect to server: " . $cl->error;
661     }
662    
663     #
664     # authenticate self to the server if necessary
665     #
666     if ($opt{"auth"} && !defined ($cl->login)) {
667     my $e = $cl->error;
668     $cl->disconnect;
669     return "Could authenticate: $e";
670     }
671    
672     #
673     # get disabled things
674     #
675     my %disabled = $cl->list_disabled;
676     if ($cl->error) {
677     my $e = $cl->error;
678     $cl->disconnect;
679     return "could not get disabled: $e";
680     }
681    
682     #
683     # get state
684     #
685     my ($running, $t) = $cl->list_state;
686     if ($cl->error) {
687     my $e = $cl->error;
688     $cl->disconnect;
689     return "could not get state: $e";
690     }
691    
692     my $state;
693     if ($running) {
694     $state = $t;
695     }
696    
697     else
698     {
699     $state = "scheduler stopped since " . localtime ($t);
700     }
701    
702     #
703     # group/service list
704     #
705     my @watch = $cl->list_watch;
706    
707     if ($cl->error) {
708     my $e = $cl->error;
709     $cl->disconnect;
710     return "could not get opstatus: $e";
711     }
712    
713     #
714     # get opstatus
715     #
716     my %opstatus;
717     if (@{$what} == 0)
718     {
719     %opstatus = $cl->list_opstatus;
720     if ($cl->error) {
721     my $e = $cl->error;
722     $cl->disconnect;
723     return "could not get opstatus: $e";
724     }
725     }
726    
727     else
728     {
729     my @list;
730     foreach my $r (@{$what})
731     {
732     if (@{$r} == 2)
733     {
734     push @list, $r;
735     }
736    
737     else
738     {
739     foreach my $w (@watch)
740     {
741     next if ($r->[0] ne $w->[0]);
742     push @list, $w;
743     }
744     }
745     }
746    
747     %opstatus = $cl->list_opstatus (@list);
748     if ($cl->error) {
749     my $e = $cl->error;
750     $cl->disconnect;
751     return "could not get opstatus: $e";
752     }
753     }
754    
755     #
756     # dependencies
757     #
758     my %deps;
759     if ($opt{"deps"}) {
760     %deps = $cl->list_deps;
761     if ($cl->error) {
762     my $e = $cl->error;
763     $cl->disconnect;
764     return "could not list deps: $e";
765     }
766     }
767    
768     #
769     # descriptions
770     #
771     my %desc;
772     %desc = $cl->list_descriptions;
773     if ($cl->error) {
774     my $e = $cl->error;
775     $cl->disconnect;
776     return "could not list descriptions: $e";
777     }
778    
779     #
780     # groups
781     #
782     my %groups;
783    
784     if ($QUERY_ARGS{"detail"} || $CF->{"detail"} ne "")
785     {
786     foreach my $g (keys %opstatus)
787     {
788     my @g = $cl->list_group ($g);
789     if ($cl->error)
790     {
791     my $e = $cl->error;
792     $cl->disconnect;
793     return "could not list group: $e";
794     }
795    
796     grep {s/\*//} @g;
797     $groups{$g} = [@g];
798     }
799     }
800    
801     #
802     # log out
803     #
804     if (!defined $cl->disconnect) {
805     return "error while disconnecting: " . $cl->error;
806     }
807    
808    
809     return ("", {
810     "state" => $state,
811     "opstatus" => \%opstatus,
812     "disabled" => \%disabled,
813     "deps" => \%deps,
814     "groups" => \%groups,
815     "desc" => \%desc,
816     "watch" => \@watch,
817     });
818     }
819    
820    
821     sub compose_header {
822     my $state = shift;
823    
824     my $t = localtime;
825    
826     #
827     # HTML stuff
828     #
829     if ($CGI)
830     {
831     $OUT_BUF = <<EOF;
832     <html>
833     <head>
834     <title> Operational Status </title>
835     EOF
836    
837     if ($CF->{"refresh"})
838     {
839     $OUT_BUF .= <<EOF;
840     <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
841     <META HTTP-EQUIV="Refresh" CONTENT=$CF->{refresh}>
842     EOF
843     }
844    
845     $OUT_BUF .= <<EOF;
846     </head>
847     <body bgcolor="#$CF->{'bg'}">
848     EOF
849    
850     if ($CF->{"html-header"} ne "")
851     {
852     $OUT_BUF .= $CF->{"html-header"};
853     }
854    
855     $OUT_BUF .= <<EOF;
856     <h1><FONT FACE="sans-serif">Operational Status</font></h1>
857    
858     <table width="100%">
859     <tr>
860     <td>
861     <table>
862     <tr>
863     <td align=right><b>Server:</b></td>
864     <td> $CF->{host} </td>
865     </tr>
866     <tr>
867     <td align=right><b>Time:</b></td>
868     <td> $t </td>
869     </tr>
870     <tr>
871     <td align=right><b>State:</b></td>
872     <td> $state </td>
873     </tr>
874     EOF
875    
876     if ($GLOBAL->{"view-name"} ne "")
877     {
878     $OUT_BUF .= <<EOF;
879     <tr>
880     <td align=right><b>View:</b></td>
881     <td><b>$GLOBAL->{"view-name"}</b></td>
882     </tr>
883     EOF
884     }
885    
886     $OUT_BUF .= <<EOF;
887     </table>
888     </td>
889    
890     <td>
891     <table>
892     <tr>
893     <td><FONT FACE="sans-serif">Color legend</FONT></td>
894     </tr>
895     <tr>
896     <td bgcolor="#$CF->{'bg-ok'}"> all is OK </td>
897     </tr>
898     <tr>
899     <td bgcolor="#$CF->{'bg-fail'}"> failure </td>
900     </tr>
901     <tr>
902     <td bgcolor="#$CF->{'bg-untested'}"> untested </td>
903     </tr>
904     </table>
905     </td>
906     </tr>
907     </table>
908     <p>
909     <hr>
910     EOF
911     }
912    
913     else
914     {
915     print <<EOF;
916    
917     server: $CF->{host}
918     time: $t
919     state: $state
920     EOF
921     }
922     }
923    
924    
925     sub select_table {
926     my ($what, $st) = @_;
927    
928     my @rows;
929    
930     #
931     # display everything real nice
932     #
933     if ($CF->{"all"} || @{$what} == 0)
934     {
935     foreach my $group (keys %{$st->{"opstatus"}})
936     {
937     foreach my $service (keys %{$st->{"opstatus"}->{$group}})
938     {
939     push (@rows, [$group, $service]);
940     }
941     }
942     }
943    
944     else
945     {
946     @rows = @{$what};
947     }
948    
949     my (%DEP, %DEPROOT);
950    
951     foreach my $l (@rows)
952     {
953     my ($group, $service) = @{$l};
954    
955     my $sref = \%{$st->{"opstatus"}->{$group}->{$service}};
956    
957     next if (!defined $sref->{"opstatus"});
958    
959     #
960     # disabled things
961     #
962     # fuckin' Perl, man. Just be referencing
963     # $st->{"disabled"}->{"watches"}->{$group}, perl automagically
964     # defines that hash element for you. Great.
965     #
966     if (defined ($st->{"disabled"}->{"watches"}) &&
967     defined ($st->{"disabled"}->{"watches"}->{$group}))
968     {
969     next;
970     }
971    
972     elsif (defined ($st->{"disabled"}->{"services"}) &&
973     defined ($st->{"disabled"}->{"services"}->{$group}) &&
974     defined ($st->{"disabled"}->{"services"}->{$service}))
975     {
976     next;
977     }
978    
979     #
980     # potential root dependencies
981     #
982     elsif ($sref->{"depend"} eq "")
983     {
984     push (@{$DEPROOT{$sref->{"opstatus"}}}, ["R", $group, $service]);
985     }
986    
987     #
988     # things which have dependencies
989     #
990     else
991     {
992     push (@{$DEP{$sref->{"opstatus"}}}, ["D", $group, $service]);
993     }
994     }
995    
996     if ($CF->{"full"})
997     {
998     [
999     @{$DEPROOT{$OPSTAT{"fail"}}},
1000     @{$DEPROOT{$OPSTAT{"linkdown"}}},
1001     @{$DEPROOT{$OPSTAT{"timeout"}}},
1002     @{$DEPROOT{$OPSTAT{"coldstart"}}},
1003     @{$DEPROOT{$OPSTAT{"warmstart"}}},
1004     @{$DEPROOT{$OPSTAT{"untested"}}},
1005     @{$DEPROOT{$OPSTAT{"unknown"}}},
1006    
1007     @{$DEP{$OPSTAT{"fail"}}},
1008     @{$DEP{$OPSTAT{"linkdown"}}},
1009     @{$DEP{$OPSTAT{"timeout"}}},
1010     @{$DEP{$OPSTAT{"coldstart"}}},
1011     @{$DEP{$OPSTAT{"warmstart"}}},
1012    
1013     @{$DEPROOT{$OPSTAT{"ok"}}},
1014     @{$DEP{$OPSTAT{"ok"}}},
1015     @{$DEP{$OPSTAT{"untested"}}},
1016     @{$DEP{$OPSTAT{"unknown"}}},
1017     ];
1018     }
1019    
1020     else
1021     {
1022     [
1023     @{$DEPROOT{$OPSTAT{"fail"}}},
1024     @{$DEPROOT{$OPSTAT{"linkdown"}}},
1025     @{$DEPROOT{$OPSTAT{"timeout"}}},
1026     @{$DEPROOT{$OPSTAT{"coldstart"}}},
1027     @{$DEPROOT{$OPSTAT{"warmstart"}}},
1028    
1029     @{$DEP{$OPSTAT{"fail"}}},
1030     @{$DEP{$OPSTAT{"linkdown"}}},
1031     @{$DEP{$OPSTAT{"timeout"}}},
1032     @{$DEP{$OPSTAT{"coldstart"}}},
1033     @{$DEP{$OPSTAT{"warmstart"}}},
1034     ];
1035     }
1036     }
1037    
1038    
1039     #
1040     # build the table
1041     #
1042     sub compose_table {
1043     my ($rows, $st) = @_;
1044    
1045     if (@{$rows} == 0)
1046     {
1047     display_allok;
1048     return;
1049     }
1050    
1051     #
1052     # display the failure table
1053     #
1054     if ($CGI)
1055     {
1056     $OUT_BUF .= <<EOF;
1057    
1058     <table cellpadding=2 cellspacing=1 bgcolor="#$CF->{'table-color'}" width="100%">
1059     <tr>
1060     <th><FONT FACE="sans-serif">Dep</FONT></th>
1061     <th><FONT FACE="sans-serif">Group</FONT></th>
1062     <th><FONT FACE="sans-serif">Service</FONT></th>
1063     <th><FONT FACE="sans-serif">Desc.</FONT></th>
1064     <th><FONT FACE="sans-serif">Last check</FONT></th>
1065     <th><FONT FACE="sans-serif">Next check</FONT></th>
1066     <th><FONT FACE="sans-serif">Alerts</FONT></th>
1067     <th><FONT FACE="sans-serif">Status</FONT></th>
1068     <th><FONT FACE="sans-serif">Summary</FONT></th>
1069     </tr>
1070    
1071     EOF
1072     }
1073    
1074     foreach my $l (@{$rows})
1075     {
1076     my ($depstate, $group, $service) = @{$l};
1077    
1078     my $sref = \%{$st->{"opstatus"}->{$group}->{$service}};
1079    
1080     $STATUS = "unknown";
1081     $TIME = "";
1082     $DEP = $depstate;
1083     my $last = "";
1084     my $bgcolor = opstatus_color ($sref->{"opstatus"});
1085    
1086     if ($sref->{"opstatus"} == $OPSTAT{"untested"})
1087     {
1088     $STATUS = "untested";
1089     $TIME = "untested";
1090     }
1091    
1092     elsif ($sref->{"opstatus"} == $OPSTAT{"ok"})
1093     {
1094     $STATUS = "-";
1095     }
1096    
1097     elsif ($sref->{"opstatus"} == $OPSTAT{"fail"})
1098     {
1099     if ($sref->{"ack"})
1100     {
1101     if ($CGI) {
1102     $STATUS = "<a href=\"$ENV{SCRIPT_NAME}?detail=$group,$service\">" .
1103     "<b>ACK FAIL</b></a>";
1104     } else {
1105     $STATUS = "ACK FAIL";
1106     }
1107     }
1108    
1109     else
1110     {
1111     $STATUS = "FAIL";
1112     }
1113     }
1114    
1115     if ($depstate eq "")
1116     {
1117     $DEP = "-";
1118     }
1119    
1120     $GROUP = $group;
1121     $SERVICE = $service;
1122     $DESC = $st->{"desc"}->{$group}->{$service};
1123    
1124     $DESC = pre_pad_if_empty ($DESC) if ($CGI);
1125    
1126    
1127     if ($TIME eq "")
1128     {
1129     $TIME = tdiff_string (time - $sref->{"last_check"});
1130     }
1131    
1132     if ($sref->{"timer"} < 60)
1133     {
1134     $NEXT = "$sref->{timer}s";
1135     }
1136    
1137     else
1138     {
1139     $NEXT = secs_to_hms ($sref->{"timer"});
1140     }
1141    
1142     if (length ($sref->{"last_summary"}) > $CF->{"summary-len"})
1143     {
1144     $SUMMARY = substr ($sref->{"last_summary"}, 0, $CF->{"summary-len"}) . "...";
1145     }
1146    
1147     else
1148     {
1149     $SUMMARY = $sref->{"last_summary"};
1150     }
1151    
1152    
1153     $ALERTS = $sref->{"alerts_sent"} || "none";
1154    
1155     my $fmt;
1156     if (!$CGI)
1157     {
1158     $fmt = <<EOF;
1159     format STDOUT =
1160     @ @<<<<<<<<<<<<<< @<<<<<<<<<<< @<<<<<<<<< @<<<<<<< @<<<<<<<<< @<<< @
1161     EOF
1162     chomp $fmt;
1163     $fmt .= "<" x length($SUMMARY) . "\n";
1164     $fmt .= <<'EOF';
1165     $DEP, $GROUP, $SERVICE, $STATUS, $TIME, $NEXT, $ALERTS, $SUMMARY
1166     .
1167     EOF
1168     eval $fmt;
1169     write;
1170     }
1171    
1172     else
1173     {
1174     if ($SUMMARY =~ /^[\s\n]*$/)
1175     {
1176     $SUMMARY = "<pre> </pre>";
1177     }
1178    
1179     else
1180     {
1181     $SUMMARY = "<small>$SUMMARY</small>";
1182     }
1183    
1184     if ($bgcolor ne "")
1185     {
1186     $bgcolor = "bgcolor=\"#$bgcolor\"";
1187     }
1188     $OUT_BUF .= <<EOF;
1189    
1190     <tr $bgcolor>
1191     <td> $DEP </td>
1192     <td> $GROUP </td>
1193     <td> <a href="$ENV{SCRIPT_NAME}?detail=$group,$service">$SERVICE</a> </td>
1194     <td> <small>$DESC</small> </td>
1195     <td> $TIME </td>
1196     <td> $NEXT </td>
1197     <td> $ALERTS </td>
1198     <td> $STATUS </td>
1199     <td> $SUMMARY </td>
1200     </tr>
1201     EOF
1202    
1203     }
1204     }
1205    
1206     if ($CGI)
1207     {
1208     $OUT_BUF .= <<EOF;
1209     </table>
1210    
1211     EOF
1212     }
1213     }
1214    
1215    
1216     sub compose_disabled {
1217     my $disabled = shift;
1218    
1219     if (!keys %{$disabled->{"watches"}} &&
1220     !keys %{$disabled->{"services"}} &&
1221     !keys %{$disabled->{"hosts"}})
1222     {
1223     if ($CGI)
1224     {
1225     $OUT_BUF .= <<EOF;
1226     <br>
1227     Nothing is disabled.
1228     <p>
1229     EOF
1230     }
1231    
1232     else
1233     {
1234     print "\nNothing is disabled.\n";
1235     }
1236    
1237     return;
1238     }
1239    
1240     if (keys %{$disabled->{"watches"}})
1241     {
1242     if ($CGI)
1243     {
1244     $OUT_BUF .= <<EOF;
1245    
1246     <h2> Disabled Watches </h2>
1247    
1248     EOF
1249     }
1250    
1251     else
1252     {
1253     print "\nDISABLED WATCHES:\n";
1254     }
1255    
1256     foreach my $watch (keys %{$disabled->{"watches"}})
1257     {
1258     if ($CGI)
1259     {
1260     $OUT_BUF .= "$watch <br>\n";
1261     }
1262    
1263     else
1264     {
1265     print "$watch\n";
1266     }
1267     }
1268     }
1269    
1270     my @disabled_services;
1271     foreach my $watch (keys %{$disabled->{"services"}})
1272     {
1273     foreach my $service (keys %{$disabled->{"services"}{$watch}})
1274     {
1275     push (@disabled_services, "$watch $service");;
1276     }
1277     }
1278    
1279     if (@disabled_services)
1280     {
1281     if ($CGI)
1282     {
1283     $OUT_BUF .= <<EOF;
1284    
1285     <h2> Disabled Services </h2>
1286    
1287     EOF
1288     }
1289    
1290     else
1291     {
1292     print "\nDISABLED SERVICES\n";
1293     }
1294     for (@disabled_services)
1295     {
1296     if ($CGI)
1297     {
1298     $OUT_BUF .= "$_ <br>\n";
1299     }
1300    
1301     else
1302     {
1303     print "$_\n";
1304     }
1305     }
1306     }
1307    
1308     if (keys %{$disabled->{"hosts"}})
1309     {
1310     if ($CGI)
1311     {
1312     $OUT_BUF .= <<EOF;
1313    
1314     <h2> Disabled Hosts </h2>
1315    
1316     EOF
1317     }
1318    
1319     else
1320     {
1321     print "\nDISABLED HOSTS:\n";
1322     }
1323     foreach my $group (keys %{$disabled->{"hosts"}})
1324     {
1325     my @HOSTS = ();
1326     foreach my $host (keys %{$disabled->{"hosts"}{$group}})
1327     {
1328     push (@HOSTS, $host);
1329     }
1330     if ($CGI)
1331     {
1332     $OUT_BUF .= sprintf ("%-15s %s <br>\n", $group, "@HOSTS");
1333     }
1334    
1335     else
1336     {
1337     printf ("%-15s %s\n", $group, "@HOSTS");
1338     }
1339     }
1340     }
1341     }
1342    
1343    
1344     sub compose_trailer {
1345     if ($CGI)
1346     {
1347     $OUT_BUF .= <<EOF;
1348     </body>
1349     </html>
1350     EOF
1351     }
1352     }
1353    
1354    
1355     sub compose_detail {
1356     my ($args, $st) = @_;
1357    
1358     my ($group, $service) = split (/,/, $args, 2);
1359    
1360     if (!defined ($st->{"opstatus"}->{$group}->{$service}))
1361     {
1362     err_die ("$group/$service not a valid service");
1363     }
1364    
1365     my $sref = \%{$st->{"opstatus"}->{$group}->{$service}};
1366    
1367     my $d;
1368    
1369     my $bgcolor = opstatus_color ($sref->{"opstatus"});
1370    
1371     $bgcolor = "bgcolor=\"#$bgcolor\"" if ($bgcolor ne "");
1372    
1373     foreach my $k (keys %OPSTAT)
1374     {
1375     if ($OPSTAT{$k} == $sref->{"opstatus"})
1376     {
1377     $sref->{"opstatus"} = "$k ($sref->{opstatus})";
1378     last;
1379     }
1380     }
1381    
1382     foreach my $k (qw (opstatus exitval last_check timer ack ackcomment))
1383     {
1384     if ($CGI && $sref->{$k} =~ /^\s*$/)
1385     {
1386     $d->{$k} = "<pre> </pre>";
1387     }
1388    
1389     else
1390     {
1391     $d->{$k} = $sref->{$k};
1392     }
1393     }
1394    
1395     my $t = time;
1396    
1397     $d->{"last_check"} = tdiff_string ($t - $d->{"last_check"}) . " ago";
1398     $d->{"timer"} = "in " . tdiff_string ($d->{"timer"});
1399    
1400     foreach my $k (qw (last_success last_failure first_failure last_alert))
1401     {
1402     if ($sref->{$k})
1403     {
1404     $d->{$k} = localtime ($sref->{$k});
1405     }
1406     }
1407    
1408     if ($sref->{"first_failure"})
1409     {
1410     $d->{"failure_duration"} = secs_to_hms ($sref->{"failure_duration"});
1411     }
1412    
1413    
1414     #
1415     # HTML output
1416     #
1417     if ($CGI)
1418     {
1419     my $sum = pre_pad_if_empty ($sref->{"last_summary"});
1420     my $descr = pre_pad_if_empty ($st->{"desc"}->{$group}->{$service});
1421     my $hosts = pre_pad_if_empty ("@{$st->{groups}->{$group}}");
1422    
1423     $OUT_BUF .= <<EOF;
1424    
1425     <h2><FONT FACE="sans-serif">Detail for $group/$service</font></h2>
1426    
1427     <table width="100%">
1428     <tr $bgcolor>
1429     <td align=right width="15%"> <b> Description: </b> <td> $descr
1430     <tr $bgcolor>
1431     <td align=right width="15%"> <b> Summary: </b> <td> $sum
1432     <tr $bgcolor>
1433     <td align=right width="15%"> <b> Hosts: </b> <td> $hosts
1434     <tr $bgcolor>
1435     <td valign=top align=right width="15%"> <b> Detail: </b>
1436     <td>
1437     <pre>
1438     $sref->{last_detail}
1439     </pre>
1440     </table>
1441     EOF
1442    
1443     if ($d->{"ack"}) {
1444     my $comment = pre_pad_if_empty ($d->{"ackcomment"});
1445    
1446     $OUT_BUF .= <<EOF;
1447     <table width="100%">
1448     <tr>
1449     <td align=right width="15%"> <h2>Acknowledgment of failure</h2> </td>
1450     <tr>
1451     <td align=right width="15%"> $comment
1452     </table>
1453    
1454     EOF
1455     }
1456    
1457     $OUT_BUF .= <<EOF;
1458     <table cellpadding=2 cellspacing=1 bgcolor="#CCCCCC" width="100%">
1459     EOF
1460    
1461     #
1462     # 0 = nothing special
1463     # 1 = do not display if zero
1464     # 2 = do not display if eq ""
1465     #
1466     foreach my $k (
1467     ["opstatus", "Operational Status", 0],
1468     ["exitval", "Exit Value", 0],
1469     ["depend", "Dependency", 2],
1470     ["monitor", "Monitor Program", 2],
1471     ["last_check", "Last Check", 2],
1472     ["timer", "Next Check", 2],
1473     ["last_success", "Last Success", 2],
1474     ["last_failure", "Last Failure", 2],
1475     ["first_failure", "First Failure", 2],
1476     ["failure_duration", "Failure Duration", 2],
1477     ["interval", "Schedule Interval", 0],
1478     ["exclude_period", "Exclude Period", 2],
1479     ["exclude_hosts", "Exclude Hosts", 2],
1480     ["randskew", "Random Skew", 1],
1481     ["alerts_sent", "Alerts Sent", 1],
1482     ["last_alert", "Last Alert", 2])
1483     {
1484     my $v = undef;
1485    
1486     if ($d->{$k->[0]} ne "") {
1487     $v = \$d->{$k->[0]};
1488    
1489     } elsif ($sref->{$k->[0]} ne "") {
1490     $v = \$sref->{$k->[0]};
1491     }
1492    
1493     next if ($k->[2] == 1 && $$v == 0);
1494     next if ($k->[2] == 2 && $$v eq "");
1495    
1496     $OUT_BUF .= <<EOF;
1497     <tr>
1498     <td align=right width="15%"><b>$k->[1]:</b></td>
1499     <td> $$v </td>
1500     EOF
1501     }
1502    
1503     $OUT_BUF .= <<EOF;
1504     </table>
1505    
1506     EOF
1507    
1508     #
1509     # custom links
1510     #
1511     if (defined ($CF->{"links"}->{$group}->{$service}))
1512     {
1513     if (defined ($CF->{"links"}->{$group}->{$service}->{"link-text"}))
1514     {
1515     $OUT_BUF .= <<EOF;
1516     <p>
1517     <h2><a href=\"$CF->{links}->{$group}->{$service}->{link}\">More Information</a></h2>
1518     $CF->{links}->{$group}->{$service}->{'link-text'}
1519    
1520     EOF
1521     }
1522    
1523     else
1524     {
1525     $OUT_BUF .= <<EOF;
1526     <p>
1527     <a href="$CF->{links}->{$group}->{$service}->{link}">$CF->{links}->{$group}->{$service}->{link}</a>
1528    
1529     EOF
1530     }
1531     }
1532    
1533     $OUT_BUF .= <<EOF;
1534     <p>
1535     <a href="$ENV{SCRIPT_NAME}">Back to summary table</a>
1536     <p>
1537    
1538     EOF
1539     }
1540    
1541     #
1542     # text output
1543     #
1544     else
1545     {
1546     my $n;
1547     $Text::Wrap::columns = 70;
1548     $n->{"desc"} = wrap (" ", " ", $st->{"desc"}->{$group}->{$service});
1549     $n->{"last_summary"} = wrap (" ", " ", $sref->{"last_summary"});
1550     $n->{"hosts"} = wrap (" ", " ", join (" ", @{$st->{groups}->{$group}}));
1551    
1552     print <<EOF;
1553    
1554     Detail for group $group service $service
1555    
1556     description
1557     -----------
1558     $n->{desc}
1559     summary
1560     -------
1561     $n->{last_summary}
1562     hosts
1563     -----
1564     $n->{hosts}
1565    
1566     -----DETAIL-----
1567     $sref->{last_detail}
1568     -----DETAIL-----
1569    
1570     EOF
1571     if ($d->{"ack"})
1572     {
1573     print <<EOF;
1574     alert ack: $d->{ackcomment}
1575    
1576     EOF
1577     }
1578    
1579     print <<EOF;
1580     opstatus: $d->{opstatus}
1581     exitval: $d->{exitval}
1582     depend: $d->{depend}
1583     monitor: $d->{monitor}
1584     last check: $d->{last_check}
1585     next_check: $d->{timer}
1586    
1587     EOF
1588     }
1589     }
1590    
1591    
1592     sub opstatus_color {
1593     my $o = shift;
1594    
1595     my %color_hash = (
1596     $OPSTAT{"untested"} => $CF->{"bg-untested"},
1597     $OPSTAT{"ok"} => $CF->{"bg-ok"},
1598     $OPSTAT{"fail"} => $CF->{"bg-fail"},
1599     );
1600    
1601     $color_hash{$o} || "";
1602     }
1603    
1604    
1605     sub tdiff_string {
1606     my $time = shift;
1607    
1608     my $s;
1609    
1610     if ($time <= 90)
1611     {
1612     $s = "${time}s";
1613     }
1614    
1615     else
1616     {
1617     $s = secs_to_hms ($time);
1618     }
1619     }
1620    
1621    
1622     #
1623     # for each watch entry which specifies only "group",
1624     # expand it into "group service"
1625     #
1626     sub expand_watch {
1627     my $what = shift;
1628     my $st = shift;
1629    
1630     for (my $i=0; $i<@{$what}; $i++)
1631     {
1632     if (@{$what->[$i]} == 1)
1633     {
1634     my @list;
1635     foreach my $l (@{$st->{"watch"}})
1636     {
1637     if ($l->[0] eq $what->[$i]->[0])
1638     {
1639     push @list, $l;
1640     }
1641     }
1642     splice (@{$what}, $i, 1, @list);
1643     }
1644     }
1645     }
1646    
1647    
1648     sub pre_pad_if_empty
1649     {
1650     my $l = shift;
1651    
1652     return "<pre> </pre>" if ($l =~ /^\s*$/);
1653     $l;
1654     }

  ViewVC Help
Powered by ViewVC 1.1.26