#!/usr/bin/perl -wT
#
# all-in-one, no frills, just the information you need, web page for mon
# Copyright (C) 1998, Gilles Lamiral and Jim Trocki.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
use Socket;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard :html3);
use English;
use Getopt::Long;
use Time::Local;
# the local libraries are in ../lib
use Translation('load', 'translate', 'language');
use Mon::Client;
# analyse the command options
#
# You see there is a debug flag. Can be useful.
# ./minotaur.cgi --debug
GetOptions("configfile=s" => \$configurationFile,
"debug" => \$debug,
"Dconf" => \$debugConf,
"Ddisa" => \$debugDisable,
);
# sets some default values
&setDefaultValues();
# Read the configuration file, if any
# So, some default value are erased.
# If the file can not be open then go on.
readTheConfigurationFile($configurationFile, \%conf);
&cookieAndParamStuff();
# Get everything we need with the client API.
&getConfAndStatus();
$formatedDate = &formateDate($serverTime, $preferences{'language'});
#
&beginTheOutput();
&tryToMakeThingsClear();
print startform;
# Construct the top header
@topHeader = &make_top_header();
# Construct the status table
@statusTable = &make_status_table() if ($preferences{'Status'} eq 'yes');
# Construct the preferences table
@preferenceTable = &make_preference_table();
# Print the top header
print @topHeader;
# Print the infos section
print &make_infos_section if (param(-Name=>'infos') eq 'yes');
# Print the status table
print @statusTable if (param(-Name=>'Status') eq 'yes');
# Print the aliases table
&printAliases() if (param(-Name=>'aliases') eq 'yes');
# Print the historic table
&historic() if (param(-Name=>'historic') eq 'yes');
# Print the preferences table
print @preferenceTable;
# Near the end
print endform, "\n";
#print dump(),
end_html();
# The end
exit(0);
sub make_infos_section {
my(@infosection);
$debug and push @debug, "entering make_infos_section...
\n";
# the anchor, the navbar, centered
push(@infosection,
"
| ", $corpus->translate('Refresh'), " | ", $corpus->translate('Language'), " | ", $corpus->translate('Tables'), " |
|---|---|---|
| ", popup_menu(-name=>'refresh', -Values=>['none', '60', '120', '240', '480', '960', '1920', '3840', ], -Labels=>{'none'=>$corpus->translate('none'), '60' =>'1 min', '120'=>'2 min', '240'=>'4 min', '480'=>'8 min', '960'=>'16 min', '1920'=>'24 min', '3840'=>'48 min', }, -default=>$preferences{'refresh'} ), " | ", popup_menu(-name=>'language', -Values=>['Francais', 'English', ], -default=>$preferences{'language'} ), " | ",
checkbox(-Name=>'infos',
-Value=>'yes',
-Label=>$corpus->translate($conf{'infosTitle'})
),
" ", checkbox(-Name=>'Status', -Value=>'yes', -Label=>$corpus->translate($conf{'statusTitle'}) ), " ", checkbox(-Name=>'aliases', -Value=>'yes', -Label=>$corpus->translate($conf{'aliasTitle'}) ), " ", checkbox(-Name=>'historic', -Value=>'yes', -Label=>$corpus->translate($conf{'historicTitle'}) ), " |
| ", $corpus->translate('Login'), " | ||
| ",
"\n ",
$corpus->translate('User'),
"\n",
textfield(
-name=>'user',
-default=>$preferences{'user'},
-size=>9,
-maxlength=>25
),
"\n",
$corpus->translate('Password'),
"\n",
password_field(
-name=>'password',
-default=>$preferences{'password'},
-size=>9,
-maxlength=>25
),
" \n", checkbox(-Name=>'memorizeUserPassword', -Value=>'yes', -Label=>$corpus->translate(" Memorize User and Password") ), " | ||
", @submitCancel, "
| ", $corpus->translate('Host') , " | ", $corpus->translate('Group') , " | ", $corpus->translate('Members') , " | ", $corpus->translate('Service') , " | ", $corpus->translate('Last at') , " | ", $corpus->translate('Next in') , " | ", $corpus->translate('Status'); push @statusTable, " |
|---|---|---|---|---|---|---|
| ",
CGI::scrolling_list(-name=>"Enable_Host_CompleteListe",
-Values=>[sort {
$hostList{$a} cmp $hostList{$b}
or
$a cmp $b
}(keys(%hostList))],
-Default=>[@hostListDisable],
-Multiple=>'true',
-Size=>min(max($preferences{'scrollHostLength'}, $totalNumberOfServices),
scalar(keys(%hostList))),
),
;
#print dump();
foreach $group (sort {
# first a failure
$Watch{$b}{'order'}{'failed'} <=> $Watch{$a}{'order'}{'failed'}
or
# a disabled watch
$Watch{$b}{'function'} cmp $Watch{$a}{'function'}
or
# disabled services
$Watch{$b}{'order'}{'disabled'} <=> $Watch{$a}{'order'}{'disabled'}
or
# Alphabetic
$a cmp $b
}
keys(%Watch) ) {
$numberOfServices = scalar(keys(%{$Watch{$group}{'service'}}));
if ($Watch{$group}{'function'}){
$groupColor = "bgcolor=".$conf{'blue'};
}elsif($Watch{$group}{'order'}{'failed'}){
$groupColor = "bgcolor=".$conf{'red'};
}else{
$groupColor = "";
};
# "-w" flag obliges. An other way (cleaner).
@groupValues = (
defined(@{$Watch{$group}{'disable'}})
? sort {$a cmp $b} (@ { $Watch{$group}{'disable'} })
: (),
defined(@ { $Watch{$group}{'enable'} })
? sort {$a cmp $b}(@ { $Watch{$group}{'enable'} })
: ()
);
@groupValuesDisable = (
@{$Watch{$group}{'disable'}}
? sort {$a cmp $b} (@ { $Watch{$group}{'disable'} })
: ()
);
#print "groupValues:[@groupValues]", scalar(@groupValues)," \n"; #print "groupValuesDisable:[@groupValuesDisable]", scalar(@groupValuesDisable) ," \n"; push @statusTable, " | ", $group, " | ", CGI::scrolling_list(-Name=>"Enable_Host_In_Group_$group", -Values=>[@groupValues], -default=>[@groupValuesDisable], -Multiple=>'true', -Size=>min($preferences{'scrollGroupLength'}, scalar(@groupValues)) ); foreach $service ( sort { $Watch{$group}{'service'}{$b}{'order'}{'failed'} <=> $Watch{$group}{'service'}{$a}{'order'}{'failed'} or $Watch{$group}{'service'}{$b}{'order'}{'disabled'} <=> $Watch{$group}{'service'}{$a}{'order'}{'disabled'} or $a cmp $b }keys(%{$Watch{$group}{'service'}})) { my( $statusService, $timeStringLast, $timeStringNext, $ServiceColor ); $statusService = $Watch{$group}{'service'}{$service}{'status'}; if($Watch{$group}{'function'} eq 'disabled'){ $ServiceColor = "bgcolor=".$conf{'blue'}; }elsif($Watch{$group}{'service'}{$service}{'function'} eq 'disabled'){ $ServiceColor = "bgcolor=".$conf{'blue'}; }elsif($Watch{$group}{'service'}{$service}{'order'}{'failed'}){ $ServiceColor = "bgcolor=".$conf{'red'}; }elsif($Watch{$group}{'service'}{$service}{'opstatus'} == 7){ #$ServiceColor = ($groupColor) ? "bgcolor=".$conf{'yellow'} : ""; $ServiceColor = "bgcolor=".$conf{'yellow'}; }else{ $ServiceColor = ($groupColor) ? "bgcolor=".$conf{'green'} : ""; }; $timeLast = $Watch{$group}{'service'}{$service}{'last'}; ($ls,$lm,$lh) = (localtime ($timeLast))[0,1,2]; ($ns,$nm,$nh,$nyear) = (gmtime ($Watch{$group}{'service'}{$service}{'next'}))[0,1,2,7]; $nyear = ($nyear == 0) ? "" : $nyear . "d"; unless ($timeLast) { $timeStringLast = $corpus->translate("none"); }else{ $timeStringLast = sprintf("%02d:%02d:%02d", $lh, $lm, $ls); } $timeStringNext = sprintf("%s %02d:%02d:%02d", $nyear, $nh, $nm, $ns); $checkboxTest = join("::", "Test", $group, $service); my $checkboxEnable = join("::", "Enable_Service", $group, $service); push @statusTable, " | ", $service, br, checkbox(-Name=>$checkboxEnable, -Value=>'yes', -Label=>" ".$corpus->translate('HS') ), " | $timeStringLast", " | $timeStringNext", br, checkbox(-Name=>$checkboxTest, -Value=>'yes', -Label=>" ".$corpus->translate('Now') ), " | ", $statusService, " |
| ", $corpus->translate("Length "), textfield(-name=>'scrollHostLength', -default=>$preferences{'scrollHostLength'}, -override=>1, -size=>length($preferences{'scrollHostLength'})+1, ), " | ", $corpus->translate('Group'), " | ", $corpus->translate("Length "), textfield(-name=>'scrollGroupLength', -default=>$preferences{'scrollGroupLength'}, -override=>1, -size=>length($preferences{'scrollGroupLength'})+1, ), " | ", $corpus->translate('Service'), " | ", $corpus->translate('(H:M:S)'), " | ", $corpus->translate('(H:M:S)'), " | ", $corpus->translate('Status'), "\n |
\n";
unless (open(CONF,$configurationFile)) {
warn "Can not open $configurationFile : $!";
return "Can not open $configurationFile : $!";
}
while () {
next if /^#/;
next if /^\s*$/;
if (/^[ \t]*(\w+)[ \t]+:(.*)$/){
$paramConf{$1}=$2;
$debugConf and push @debug, sprintf("--> %-22s: [%s]\n", $1, $2);
} else {
warn "Syntax error in the configuration File : $configurationFile",
" line $INPUT_LINE_NUMBER\n",
"You have to use only alphanumeric terms\n",
"A correct syntax example :\n",
" ResultLengthMax :500 \n";
}
}
close(CONF);
$debugConf and push @debug, " \nleaving readTheConfigurationFile| ", $corpus->translate('Service'), " | ", $corpus->translate('Group'), " | ", $corpus->translate('No'), " | ", $corpus->translate('Date'), "", ' ' x 5, $corpus->translate("jj/mm/aaaa"), "", " | ", $corpus->translate('Status'), " | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| ", CGI::scrolling_list(-name=>"historicServices", -Values=>[sort (keys(%everyServices))], -Multiple=>'true', -Size=>min(5, scalar(keys(%everyServices))), ), " | ", CGI::scrolling_list(-name=>"historicGroups", -Values=>[sort (keys(%everyGroup))], -Multiple=>'true', -Size=>min(5, scalar(keys(%everyGroup))), ), " | ", textfield(-name=>'historicLength', -default=>$preferences{'historicLength'}, -override=>1, -size=>length($preferences{'historicLength'})+1, ), " | ",
"
| ", " ", " | ", "\n"; @alertHistoric = reverse(@alertHistoricFiltered); unless ($preferences{'historicLength'}){ @alertHistoricTroncated = splice(@alertHistoric, 0); }else{ @alertHistoricTroncated = splice(@alertHistoric, 0, $preferences{'historicLength'}); } # I do not understand why splice(reverse(@alertHistoric)) does not work. foreach $ligne (@alertHistoricTroncated) { my($groupName, $serviceName, $timeNumeric, $alertFile, $argList, $hostList, $timeString, $sec, $min, $hour, $day, $month, $year); chomp($ligne); $ligne =~ /\A(\d+)\s+(alert|upalert|startupalert)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\S+)\s+\((.*?)\)\s+(.*)\Z/; ($number, $alertType, $groupName, $serviceName, $timeNumeric, $alertFile, $argList, $hostList) = ($1, $2, $3, $4, $5, $6, $7, $8); @hostList = split(/\s+/,$hostList); $nowItIs = $serverTime; $diffTime = $nowItIs - $timeNumeric; if (defined($preferences{'historicFilter'})) { unless ($diffTime > $preferences{'historicFilter'}){ $colorBack = " bgcolor=".$conf{'brokenWhite'}; }else{ $colorBack = " "; } }else{ $colorBack = " "; } ($min,$hour,$day,$month,$year) = (localtime ($timeNumeric))[1,2,3,4,5]; $timeString = sprintf ("%02d/%02d/%04d %02d:%02d", $day,$month +1,$year +1900,$hour,$min); print("\n||||||
| $serviceName | \n"); }elsif ($alertType eq 'startupalert') { print("$serviceName | \n"); }elsif ($alertType eq 'alert') { print("$serviceName | \n"); }else { print("$serviceName | \n"); } print "$groupName", " | $number", " | $timeString"; if ($alertType eq 'upalert') { print(" | OK"); }elsif ($alertType eq 'startupalert') { print(" | reloading config"); }elsif ($alertType eq 'alert') { print(" | ");
foreach $hostElement (@hostList){
print("$hostElement "); } }else{ print(" | ");
foreach $hostElement (@hostList){
print("$hostElement "); } } } print " |
", "
| ", radio_group( -name=>'aliasSelection', -Values=>['all','none','selection'], -Default=>'selection', -Labels=>{ 'none'=>" ".$corpus->translate('none'), 'all'=>" ".$corpus->translate('all'), 'selection'=>" ".$corpus->translate('selection') } ), " | ", $corpus->translate($conf{'aliasTitle'}), " | ", $corpus->translate('Description'), " | ", $corpus->translate('Service'), " | ", $corpus->translate('Status'), "\n", " |
|---|---|---|---|---|
| ", CGI::scrolling_list(-name=>"aliasWanted", -Values=>[sort (keys(%aliasesHash))], -Multiple=>'true', -Size=>min(max($preferences{'scrollAliasLength'}, $numberOfAliasServices), scalar(keys(%aliasesHash))), ); unless (@aliasWanted) { push @aliasOutput, " | ||||
| ", $alias, " | ", $aliasesHash{$alias}{'declaration'}; foreach $service (sort { $a cmp $b } keys(%{$aliasesHash{$alias}{'service'}})){ my(@status, $serviceColor); if (defined(@{ $aliasesHash{$alias}{'service'}{$service}{'failed'} })) { @status = @{ $aliasesHash{$alias}{'service'}{$service}{'failed'} }; $serviceColor = "bgcolor=".$conf{'red'}; }else{ @status = ("OK"); $serviceColor = ""; } if(defined($aliasesHash{$alias}{'service'}{$service}{'url'})){ $url = $aliasesHash{$alias}{'service'}{$service}{'url'}; push @aliasOutput, " | ", "$service"; }else{ push @aliasOutput, " | ", $service; } push @aliasOutput, " | ", @status, " |
| ", $corpus->translate('List'), " | ", $corpus->translate($conf{'aliasTitle'}), " | ", $corpus->translate('Description'), " | ", $corpus->translate('Service'), " | ", $corpus->translate('Status'), " |
";
# What the user want to disable ?
# Just looking.
# Make a hash to simplify the search.
foreach $host (param('Enable_Host_CompleteListe')) {
$hostToDisable{$host} = 1;
$debugDisable and print "want disabling $host\n";
}
# Which are disabled ?
# Enable the hosts that the user wants to be
foreach $group (keys %{$d{"hosts"}}) {
foreach $host (keys %{$d{"hosts"}{$group}}) {
$debugDisable and print "host $group/$host disabled\n";
if (not defined($hostToDisable{$host})) {
# User want to enable this host
$debugDisable and print "host $group/$host have to be enabled\n";
$cl->enable_host($host);
}else{
# User want to leave this host disabled
$hostAlreadyDisabled{$host} = 1;
$debugDisable and print "host $group/$host already disabled\n";
}
}
}
# Now we can disable if necessary
foreach $host (param('Enable_Host_CompleteListe')) {
if (defined($hostAlreadyDisabled{$host})) {
$debugDisable and print "disabling $host already done\n";
}else{
$debugDisable and print "disabling $host\n";
$cl->disable_host($host);
}
}
}else{
# Nothing to disable or enable
foreach $group (keys %{$d{"hosts"}}) {
foreach $host (keys %{$d{"hosts"}{$group}}) {
$debugDisable and print "host $group/$host disabled\n";
}
}
}
if ($definedParam
and (param(-Name=>'Status') eq 'yes')
and ($cookie{'Status'} eq 'yes')
) {
foreach my $param (@allParamreters) {
my($group, $service);
if ($param =~ /\AEnable_Service::(.+)::(.+)\Z/) {
($group,$service) = ($1,$2);
CGI::delete($param);
$debugDisable and print "Wanna change $service service on group $group\n";
if ($d{"services"}{$group}{$service}) {
$cl->enable_service($group, $service);
}else{
$cl->disable_service($group, $service);
}
if (defined($cl->error)) {
$debugDisable and print b($corpus->translate("ERROR")), " : ", $cl->error, "\n";
}
}
}
%d = $cl->list_disabled;
}
foreach $watch (keys %{$d{"services"}}) {
foreach $service (keys %{$d{"services"}{$watch}}) {
$debugDisable and print "service $watch/$service disabled\n";
$service{$watch}{$service} = 1;
$Watch{$watch}{'service'}{$service}{'function'}="disabled";
}
}
foreach $watch (keys %{$d{"watches"}}) {
$debugDisable and print "watch $_ disabled\n";
$watch{$watch} = 1;
$Watch{$watch}{'function'} = "disabled";
}
print "";
}
sub testServicesNow {
foreach $param (@allParamreters) {
my($group, $service);
if ($param =~ /\ATest::(.+)::(.+)\Z/) {
($group,$service)=($1,$2);
CGI::delete($param);
print "Asking server to test service $service on group $group";
foreach $key (keys(%preferences)) {
$debug and push @debug,
sprintf("--> cookie: %-22s: [%s]\n", $key, $cookie{$key}),
sprintf("--> prefer: %-22s: [%s]\n\n", $key, $preferences{$key});
}
$debug and push @debug, "diff terminated";
# Flush mode.
$| = 1;
$the_cookie = cookie(-Name=>$cookieName,
-Value=>\%preferences,
-Expires=>$preferences{'cookieExpiration'}
);
$corpus = load($conf{'messagesFile'});
$corpus->language($preferences{'language'});
# The submit and cancel buttons are in several places
push @submitCancel,
submit(-Name=>'Go',
-Value=>$corpus->translate("Submit")
),
" ",
reset(-Value=>$corpus->translate("Cancel")
),
" ",
submit(-Name=>'Defaults',
-Value=>$corpus->translate("Defaults")
)
;
# do we have to send the refresh time ?
if ($preferences{'refresh'} eq "none"){
#$expirePage="now";
$expirePage="+60s";
# do we need to refresh the cookie
if ($diff){
print header(
#-Expires=>$expirePage,
-Cookie=>$the_cookie);
}else{
print header(
#-Expires=>$expirePage
);
}
}else{
$expirePage = "+".$preferences{'refresh'}."s";
#$expirePage="now";
if ($diff){
print
header(
#-Expires=>$expirePage,
-Refresh=>$preferences{'refresh'},
-Cookie=>$the_cookie);
}else{
print
header(
#-Expires=>$expirePage,
-Refresh=>$preferences{'refresh'});
}
}
$debug and print @debug;
}
sub beginTheOutput {
print start_html(
-Title=>$corpus->translate('Minotaur from ')
. $conf{'monserver'}
. ":"
. $conf{'monport'}
. $corpus->translate(' on ')
. $formatedDate,
-Author=>'lamiral@mail.dotcom.fr',
-Meta=>{
'keywords'=>$corpus->translate('monitoring, Minotaur, MON, HTTP, FTP, NNTP, LDAP, POP3, SMTP, IMAP4'),
'copyright'=>"Gnu Public Licence, copyleft September 1998 Jim Trocki, Gilles Lamiral"
},
-BGCOLOR=>$conf{'pagebgColor'},
),
"\n";
}
sub tryToMakeThingsClear {
# Try to make all things clear...
# There are :
# @group
# %Watch # this W have to be downcased
# $allGroups
# %servicesInOneString
# First : What are the groups ?
@group = keys(%Watch);
$allGroups = join(" ", @group);
$debug and print scalar(@group), " groups : ", "@group", "