--- loncom/cgi/clusterstatus.pl 2003/08/01 14:47:44 1.13 +++ loncom/cgi/clusterstatus.pl 2003/08/05 18:33:08 1.16 @@ -3,10 +3,11 @@ $|=1; # The LearningOnline Network with CAPA # Cluster Status # -# $Id: clusterstatus.pl,v 1.13 2003/08/01 14:47:44 www Exp $ +# $Id: clusterstatus.pl,v 1.16 2003/08/05 18:33:08 www Exp $ use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; +use strict; use LWP::UserAgent(); use HTTP::Headers; @@ -19,6 +20,28 @@ my %connectionstatus=(); my %perlvar=(); my $mode; +my $concount=0; +my $fromcache; + +my %domaindescription = (); +my %domain_auth_def = (); +my %domain_auth_arg_def = (); + +my %hostname=(); +my %hostip=(); +my %hostdom=(); +my %hostrole=(); +my %libserv=(); + +my $maxusers=0; +my $maxload=0; +my $totalusers=0; + +my %FORM=(); + +my $stat_total=0; +my $stat_notyet=0; +my $stat_fromcache=0; sub select_form { my ($def,$name,%hash) = @_; @@ -50,11 +73,23 @@ sub request { $cachetime*=(0.5+rand); my $key=&key($local,$url); my $reply=''; + $stat_total++; +# if fromcache flag is set, only return cached values + if ($fromcache) { + if ($FORM{$key.'_time'}) { + return $FORM{$key}; + $stat_fromcache++; + } else { + return 'not_yet'; + $stat_notyet++; + } + } +# normal mode, refresh when expired or not yet present if ($FORM{$key.'_time'}) { if ((time-$FORM{$key.'_time'})<$cachetime) { $reply=$FORM{$key}; &hidden($key.'_time',$FORM{$key.'_time'}); - &hidden($key.'_fromcache',1); + $stat_fromcache++; } } unless ($reply) { @@ -62,7 +97,7 @@ sub request { $reply='local_unknown'; } else { - my $ua=new LWP::UserAgent(timeout => 15); + my $ua=new LWP::UserAgent(timeout => 10); my $request=new HTTP::Request('GET', "http://".$hostname{$local}.$url); @@ -92,10 +127,17 @@ sub connected { unless ($hostname{$remote}) { return 'remote_unknown'; } my $url='/cgi-bin/ping.pl?'.$remote; # -# Slowly phase this in: if not cached, only do 10 percent of the cases +# Slowly phase this in: if not cached, only do 5 percent of the cases, +# but always do the first five. # unless ($FORM{&key($local,$url)}) { - unless (rand>0.95) { return 'not_yet'; } + unless (($concount<=5) || (rand>0.95)) { + $stat_total++; + $stat_notyet++; + return 'not_yet'; + } else { + $concount++; + } } # # Actually do the query @@ -200,6 +242,10 @@ ENDHEADER print ("$trouble"); } print ""; +# version + if ($host{$local.'_version'}) { + print "
Version: ".$host{$local.'_version'} + } # load if (($host{$local.'_load_doomed'}>0.5) || ($mode eq 'load_doomed')) { print "
Load: ".$host{$local.'_load'} @@ -250,125 +296,23 @@ sub doomedness { return sort { $alldoomed{$b} <=> $alldoomed{$a} } @allhosts; } -# ====================================================================== Status -sub statuslist { - my ($local,$what)=@_; - print -"\n"; -} - -# -# Main program -# -# ========================================================= Get form parameters -my $buffer; - -read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); -my @pairs=split(/&/,$buffer); -my $pair; my $name; my $value; -undef %FORM; -%FORM=(); -foreach $pair (@pairs) { - ($name,$value) = split(/=/,$pair); - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; - $FORM{$name}=$value; -} - -$buffer=$ENV{'QUERY_STRING'}; -@pairs=split(/&/,$buffer); -foreach $pair (@pairs) { - ($name,$value) = split(/=/,$pair); - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; - $FORM{$name}=$value; -} - -# ====================================================== Determine refresh rate - -my $refresh=(($FORM{'refresh'}=~/^\d+$/)?$FORM{'refresh'}:120); -if ($refresh<30) { $refresh=30; } -my $starttime=time; - -# ============================================================== Determine mode +sub resetvars { + $maxusers=0; + $maxload=0; + $totalusers=0; + $stat_total=0; + $stat_notyet=0; + $stat_fromcache=0; -my %modes=('trouble' => 'Trouble', - 'users_doomed' => 'Doomed: Users', - 'loncron_doomed' => 'Doomed: General (loncron)', - 'mysql_doomed' => 'Doomed: Database (mysql)', - 'notconnected_doomed' => 'Doomed: Connections', - 'checkrpms_doomed' => 'Doomed: RPMs', - 'load_doomed' => 'Doomed: Load', - 'unresponsive_doomed' => 'Doomed: Status could not be determined', - 'users' => 'User Report', - 'load' => 'Load Report', - 'connections' => 'Connections Matrix'); - -$mode=$FORM{'mode'}; -unless ($modes{$mode}) { $mode='trouble'; } -# ================================================================ Send Headers -print "Content-type: text/html\n\n". - "\n"; -# -------------------- Read loncapa.conf (and by default, loncapa_apache.conf). -my $perlvarref=LONCAPA::Configuration::read_conf('loncapa.conf'); -%perlvar=%{$perlvarref}; -undef $perlvarref; # remove since sensitive and not needed -delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed -delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed - -# ------------------------------------------------------------- Read hosts file -{ - my $config=IO::File->new("$perlvar{'lonTabDir'}/hosts.tab"); - - $total=0; - while (my $configline=<$config>) { - $configline=~s/#.*$//; - unless ($configline=~/\w/) { next; } - my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); - $hostname{$id}=$name; - $hostdom{$id}=$domain; - $hostrole{$id}=$role; - $hostip{$id}=$ip; - $total++; - if (($role eq 'library') && ($id ne $perlvar{'lonHostID'})) { - $libserv{$id}=$name; - } - } + undef %host; + %host=(); } -# ------------------------------------------------------------ Read domain file -{ - my $fh=IO::File->new($perlvar{'lonTabDir'}.'/domain.tab'); - %domaindescription = (); - %domain_auth_def = (); - %domain_auth_arg_def = (); - if ($fh) { - while (<$fh>) { - next if (/^(\#|\s*$)/); - chomp; - my ($domain, $domain_description, $def_auth, $def_auth_arg) - = split(/:/,$_,4); - $domain_auth_def{$domain}=$def_auth; - $domain_auth_arg_def{$domain}=$def_auth_arg; - $domaindescription{$domain}=$domain_description; - } - } -} - -print "

LON-CAPA Cluster Status ".localtime()."

"; -print "
\n". -"
". -"
\n";; -print "
\n"; -print 'Choose next report: '.&select_form($mode,'mode',%modes).'
'; -&hidden('refresh',$refresh); +sub mainloop { + &resetvars(); # ==================================================== Main Loop over all Hosts -my $maxusers=0; -my $maxload=0; -my $totalusers=0; - -foreach $local (sort keys %hostname) { +foreach my $local (sort keys %hostname) { $host{$local.'_unresponsive_doomed'}=0; # -- Check general status &statuslist($local,'General'); @@ -387,6 +331,15 @@ foreach $local (sort keys %hostname) { $host{$local.'_errors'}=$loncron{'errors'}; } } +# -- Check version + &statuslist($local,'Version'); + my $version=&request($local,'/lon-status/version.txt',7200); + if ($version eq 'local_error') { + $host{$local.'_version'}='Could not determine.'; + $host{$local.'_unresponsive_doomed'}++; + } else { + $host{$local.'_version'}=$version; + } # -- Check user status &statuslist($local,'Users'); my %userstatus=&replyhash($local,'/cgi-bin/userstatus.pl?simple',600); @@ -453,7 +406,7 @@ foreach $local (sort keys %hostname) { &statuslist($local,'Connections'); $host{$local.'_notconnected'}=''; $host{$local.'_notconnected_doomed'}=0; - foreach $remote (sort keys %hostname) { + foreach my $remote (sort keys %hostname) { my $status=&connected($local,$remote); $connectionstatus{$local.'_TO_'.$remote}=$status; unless (($status eq 'ok') || ($status eq 'not_yet')) { @@ -461,9 +414,12 @@ foreach $local (sort keys %hostname) { $host{$local.'_notconnected_doomed'}++; } } -# =============================================================== End Mail Loop +# =============================================================== End Main Loop } -&statuslist('Done.'); + +} + +sub reports { # ====================================================================== Output if ($mode=~/\_doomed$/) { # Output by doomedness @@ -483,13 +439,27 @@ foreach $local (sort keys %hostname) { print ''.$local.''; foreach my $remote (sort keys %hostname) { if ($connectionstatus{$local.'_TO_'.$remote} eq 'not_yet') { - print 'not yet tested'; + my $cellcolor='#FFFFFF'; + if ($local eq $remote) { $cellcolor='#DDDDDD'; } + print 'not yet tested'; } elsif ($connectionstatus{$local.'_TO_'.$remote} eq 'ok') { + my $cellcolor='#BBDDBB'; + if ($local eq $remote) { $cellcolor='#99DD99'; } print -'ok'; +'ok'; } else { + my $cellcolor='#DDBBBB'; + if ($connectionstatus{$local.'_TO_'.$remote} eq 'local_error') { + if ($local eq $remote) { + $cellcolor='#DD88AA'; + } else { + $cellcolor='#DDAACC'; + } + } else { + if ($local eq $remote) { $cellcolor='#DD9999'; } + } print - ''. + ''. $connectionstatus{$local.'_TO_'.$remote}.'
'; &lonc($local); &lond($remote); print ''; @@ -505,11 +475,13 @@ foreach $local (sort keys %hostname) { print "

Total active user(s): $totalusers

". ""; - foreach $local (sort keys %hostname) { + foreach my $local (sort keys %hostname) { if (defined($host{$local.'_users'})) { print -'
'.$local. - ''; +'
'.$local. + '
'. + $domaindescription{$hostdom{$local}}. + '
'; &users($local); print ''. @@ -528,12 +500,14 @@ foreach $local (sort keys %hostname) { my $factor=50/$maxload; print ""; - foreach $local (sort keys %hostname) { + foreach my $local (sort keys %hostname) { if (defined($host{$local.'_load_doomed'})) { print -'
'. +'
'. $local. - ''; + '
'. + $domaindescription{$hostdom{$local}}. + '
'; &server($local); print ''. @@ -548,8 +522,11 @@ foreach $local (sort keys %hostname) { } } elsif ($mode eq 'trouble') { my $count=0; - foreach $local (sort keys %hostname) { + foreach my $local (sort keys %hostname) { my $trouble=''; + if ($host{$local.'_unresponsive_doomed'}>3) { + $trouble='Does not respond to several queries.
'; + } if ($host{$local.'_errors'}) { $trouble='Has loncron errors.
'; } elsif ($host{$local.'_loncron_doomed'}>600) { @@ -571,14 +548,145 @@ foreach $local (sort keys %hostname) { } unless ($count) { print "No mayor trouble."; } } +} + +# ====================================================================== Status +sub statuslist { + my ($local,$what)=@_; + print +"\n"; +} + +# ============================================================================= +# ============================================================================= +# Main program +# +# ========================================================= Get form parameters +my $buffer; + +read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); +my @pairs=split(/&/,$buffer); +my $pair; my $name; my $value; +undef %FORM; +%FORM=(); +foreach $pair (@pairs) { + ($name,$value) = split(/=/,$pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; + $FORM{$name}=$value; +} + +$buffer=$ENV{'QUERY_STRING'}; +@pairs=split(/&/,$buffer); +foreach $pair (@pairs) { + ($name,$value) = split(/=/,$pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; + $FORM{$name}=$value; +} + +# ====================================================== Determine refresh rate + +my $refresh=(($FORM{'refresh'}=~/^\d+$/)?$FORM{'refresh'}:30); +if ($refresh<30) { $refresh=30; } +my $starttime=time; + +# ============================================================== Determine mode + +my %modes=('trouble' => 'Trouble', + 'users_doomed' => 'Doomed: Users', + 'loncron_doomed' => 'Doomed: General (loncron)', + 'mysql_doomed' => 'Doomed: Database (mysql)', + 'notconnected_doomed' => 'Doomed: Connections', + 'checkrpms_doomed' => 'Doomed: RPMs', + 'load_doomed' => 'Doomed: Load', + 'unresponsive_doomed' => 'Doomed: Status could not be determined', + 'users' => 'User Report', + 'load' => 'Load Report', + 'connections' => 'Connections Matrix'); + +$mode=$FORM{'mode'}; +unless ($modes{$mode}) { $mode='trouble'; } +# ================================================================ Send Headers +print "Content-type: text/html\n\n". + "\n"; +# -------------------- Read loncapa.conf (and by default, loncapa_apache.conf). +my $perlvarref=LONCAPA::Configuration::read_conf('loncapa.conf'); +%perlvar=%{$perlvarref}; +undef $perlvarref; # remove since sensitive and not needed +delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed +delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed + +# ------------------------------------------------------------- Read hosts file +{ + my $config=IO::File->new("$perlvar{'lonTabDir'}/hosts.tab"); + + while (my $configline=<$config>) { + $configline=~s/#.*$//; + unless ($configline=~/\w/) { next; } + my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); + $hostname{$id}=$name; + $hostdom{$id}=$domain; + $hostrole{$id}=$role; + $hostip{$id}=$ip; + if (($role eq 'library') && ($id ne $perlvar{'lonHostID'})) { + $libserv{$id}=$name; + } + } +} +# ------------------------------------------------------------ Read domain file +{ + my $fh=IO::File->new($perlvar{'lonTabDir'}.'/domain.tab'); + if ($fh) { + while (<$fh>) { + next if (/^(\#|\s*$)/); + chomp; + my ($domain, $domain_description, $def_auth, $def_auth_arg) + = split(/:/,$_,4); + $domain_auth_def{$domain}=$def_auth; + $domain_auth_arg_def{$domain}=$def_auth_arg; + $domaindescription{$domain}=$domain_description; + } + } +} + +print "

LON-CAPA Cluster Status ".localtime()."

"; +print "\n". +"
". +"\n";; +print "
\n"; +print 'Choose next report: '.&select_form($mode,'mode',%modes).'
'; +&hidden('refresh',$refresh); + + if (!$FORM{'runonetime'}) { + print + "

Gathering initial cluster data

This may take some time ...
"; + $fromcache=0; + &mainloop(); + &statuslist('Done initial run.'); + &reports(); + } else { + $fromcache=1; + &mainloop(); + &statuslist('Done gathering cached data'); + &reports(); + $fromcache=0; + &mainloop(); + } + &hidden('runonetime',1); +print '
Total number of queries: '.$stat_total. + '
Percent complete: '. + int(($stat_total-$stat_notyet)/$stat_total*100.). + '
Percent from cache: '. + int($stat_fromcache/$stat_total*100.).'
'; + # ============================================================== Close, refresh print "