Annotation of loncom/cgi/clusterstatus.pl, revision 1.25

1.1       www         1: #!/usr/bin/perl
                      2: $|=1;
1.25    ! raeburn     3: # Generates a html page showing various status reports about the domain or cluster
        !             4: # $Id: clusterstatus.pl,v 1.24 2005/04/13 18:30:46 albertel Exp $
1.21      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
1.9       www        27: #
1.3       harris41   28: 
1.25    ! raeburn    29: use strict;
        !            30: 
1.3       harris41   31: use lib '/home/httpd/lib/perl/';
1.25    ! raeburn    32: use Apache::lonnet;
        !            33: use Apache::lonlocal;
1.3       harris41   34: use LONCAPA::Configuration;
1.25    ! raeburn    35: use LONCAPA::loncgi;
1.1       www        36: use LWP::UserAgent();
                     37: use HTTP::Headers;
                     38: use IO::File;
                     39: 
1.25    ! raeburn    40: my $perlvar=&LONCAPA::Configuration::read_conf('loncapa.conf');
        !            41: 
1.8       www        42: my %host=();
                     43: my $oneday=60*60*24;
                     44: 
                     45: my %connectionstatus=();
1.9       www        46: my %perlvar=();
                     47: 
                     48: my $mode;
1.14      www        49: my $concount=0;
1.16      www        50: my $fromcache;
                     51: 
1.25    ! raeburn    52: my %domaininfo = &Apache::lonnet::domain_info();
        !            53: my %allhostname = &Apache::lonnet::all_hostnames();
        !            54: my (%hostname,%hostip);
        !            55: my %hostdom = &Apache::lonnet::all_host_domain();
        !            56: my %iphost = &Apache::lonnet::get_iphost();
        !            57: my %libserv= &Apache::lonnet::all_library();
        !            58: 
        !            59: foreach my $ip (keys(%iphost)) {
        !            60:     $hostip{$iphost{$ip}} = $ip;
        !            61: }
1.16      www        62: 
                     63: my $maxusers=0;
                     64: my $maxload=0;
                     65: my $totalusers=0;
                     66: 
                     67: my %FORM=();
                     68: 
                     69: my $stat_total=0;
                     70: my $stat_notyet=0;
                     71: my $stat_fromcache=0;
1.9       www        72: 
                     73: sub select_form {
                     74:     my ($def,$name,%hash) = @_;
                     75:     my $selectform = "<select name=\"$name\" size=\"1\">\n";
1.25    ! raeburn    76:     foreach my $key (sort(keys(%hash))) {
        !            77:         $selectform.="<option value=\"$key\" ".
        !            78:             ($key eq $def? 'selected' : '').
        !            79:                 ">".$hash{$key}."</option>\n";
1.9       www        80:     }
                     81:     $selectform.="</select>";
                     82:     return $selectform;
                     83: }
                     84: 
1.8       www        85: 
                     86: sub key {
                     87:     my ($local,$url)=@_;
                     88:     my $key=$local.'_'.$url;
                     89:     $key=~s/\W/\_/gs;
                     90:     return $key;
                     91: }
                     92: 
                     93: sub hidden {
                     94:     my ($name,$value)=@_;
1.25    ! raeburn    95:     print("\n<input type='hidden' name='$name' value='$value' />");
1.8       www        96: }
                     97: 
                     98: sub request {
                     99:     my ($local,$url,$cachetime)=@_;
1.13      www       100:     $cachetime*=(0.5+rand);
1.8       www       101:     my $key=&key($local,$url);
                    102:     my $reply='';
1.16      www       103:     $stat_total++;
                    104: # if fromcache flag is set, only return cached values
                    105:     if ($fromcache) {
                    106: 	if ($FORM{$key.'_time'}) {
1.25    ! raeburn   107:             $stat_fromcache++;
1.16      www       108: 	    return $FORM{$key};
                    109: 	} else {
1.25    ! raeburn   110:             $stat_notyet++;
1.16      www       111: 	    return 'not_yet';
                    112: 	}
                    113:     }
                    114: # normal mode, refresh when expired or not yet present
1.8       www       115:     if ($FORM{$key.'_time'}) {
                    116: 	if ((time-$FORM{$key.'_time'})<$cachetime) {
                    117: 	    $reply=$FORM{$key};
                    118: 	    &hidden($key.'_time',$FORM{$key.'_time'});
1.16      www       119: 	    $stat_fromcache++;
1.8       www       120: 	}
                    121:     }
                    122:     unless ($reply) {
1.25    ! raeburn   123:         if ($hostname{$local}) {
        !           124: 	    my $ua=new LWP::UserAgent(timeout => 20);
1.8       www       125: 	    my $request=new HTTP::Request('GET',
                    126: 					  "http://".$hostname{$local}.$url);
                    127: 	    my $response=$ua->request($request);
1.25    ! raeburn   128: 	    if ($response->is_success) {
        !           129:                 $reply=$response->content;
        !           130:                 chomp($reply);
        !           131:             } else {
1.8       www       132: 		$reply='local_error'; 
                    133: 	    }
1.25    ! raeburn   134: 	} else {
        !           135:             $reply='local_unknown';
        !           136:         }
1.8       www       137: 	&hidden($key.'_time',time);
                    138:     }
                    139:     &hidden($key,$reply);
                    140:     return $reply;
                    141: }
                    142: 
                    143: # ============================================= Are local and remote connected?
1.1       www       144: sub connected {
                    145:     my ($local,$remote)=@_;
                    146:     $local=~s/\W//g;
                    147:     $remote=~s/\W//g;
                    148: 
                    149:     unless ($hostname{$remote}) { return 'remote_unknown'; }
1.8       www       150:     my $url='/cgi-bin/ping.pl?'.$remote;
                    151: #
1.14      www       152: # Slowly phase this in: if not cached, only do 5 percent of the cases,
                    153: # but always do the first five. 
1.8       www       154: #
                    155:     unless ($FORM{&key($local,$url)}) {
1.16      www       156: 	unless (($concount<=5) || (rand>0.95)) {
                    157: 	    $stat_total++;
                    158: 	    $stat_notyet++; 
1.14      www       159: 	    return 'not_yet'; 
                    160: 	} else {
                    161: 	    $concount++;
                    162: 	}
1.8       www       163:     }
                    164: #
                    165: # Actually do the query
                    166: #
                    167:     &statuslist($local,'connecting '.$remote);
1.9       www       168:     my $reply=&request($local,$url,3600);
1.8       www       169:     $reply=(split("\n",$reply))[0];
                    170:     $reply=~s/\W//g;
                    171:     if ($reply ne $remote) { return $reply; }
                    172:     return 'ok';
                    173: }
                    174: # ============================================================ Get a reply hash
                    175: 
                    176: sub replyhash {
                    177:     my %returnhash=();
                    178:     foreach (split(/\&/,&request(@_))) {
                    179: 	my ($name,$value)=split(/\=/,$_);
                    180: 	if ($name) {
                    181: 	    unless ($value) { $value=''; }
                    182: 	    $returnhash{$name}=$value;
                    183: 	}
                    184:     }
                    185:     return %returnhash;
                    186: }
1.1       www       187: 
1.9       www       188: # ================================================================ Link to host
1.1       www       189: 
1.8       www       190: sub otherwindow {
                    191:     my ($local,$url,$label)=@_;
                    192:     return
1.9       www       193:   " <a href='http://$hostname{$local}$url' target='newwin$local'>$label</a> ";
                    194: }
                    195: 
                    196: sub login {
                    197:     my $local=shift;
1.25    ! raeburn   198:     print(&otherwindow($local,'/adm/login?domain='.$perlvar{'lonDefDomain'},
        !           199: 		       'Login'));
1.9       www       200: }
                    201: 
                    202: sub runloncron {
                    203:     my $local=shift;
1.25    ! raeburn   204:     print(&otherwindow($local,'/cgi-bin/loncron.pl',&Apache::lonlocal::mt('Run loncron')));
1.9       www       205: }
                    206: 
                    207: sub loncron {
                    208:     my $local=shift;
1.25    ! raeburn   209:     print(&otherwindow($local,'/lon-status','loncron'));
1.9       www       210: }
                    211: 
                    212: sub lonc {
                    213:     my $local=shift;
1.25    ! raeburn   214:     print(&otherwindow($local,'/lon-status/loncstatus.txt','lonc'));
1.9       www       215: }
                    216: 
                    217: sub lond {
                    218:     my $local=shift;
1.25    ! raeburn   219:     print(&otherwindow($local,'/lon-status/londstatus.txt','lond'));
1.9       www       220: }
                    221: 
                    222: sub users {
                    223:     my $local=shift;
1.25    ! raeburn   224:     print(&otherwindow($local,'/cgi-bin/userstatus.pl',&Apache::lonlocal::mt('Users')));
1.9       www       225: }
                    226: 
                    227: sub versions {
                    228:     my $local=shift;
1.25    ! raeburn   229:     print(&otherwindow($local,'/cgi-bin/lonversions.pl',&Apache::lonlocal::mt('Versions')));
1.9       www       230: }
                    231: 
                    232: sub server {
                    233:     my $local=shift;
1.25    ! raeburn   234:     print(&otherwindow($local,'/server-status',&Apache::lonlocal::mt('Server Status')));
1.8       www       235: }
1.1       www       236: 
1.18      www       237: sub announcement {
                    238:     my $local=shift;
1.25    ! raeburn   239:     print(&otherwindow($local,'/announcement.txt',&Apache::lonlocal::mt('Announcement')));
1.18      www       240: }
                    241: 
1.22      www       242: sub takeonline {
                    243:     my $local=shift;
1.25    ! raeburn   244:     print(&otherwindow($local,'/cgi-bin/takeonline.pl',&Apache::lonlocal::mt('Take online')));
1.22      www       245: }
                    246: 
1.23      www       247: sub takeoffline {
                    248:     my $local=shift;
1.25    ! raeburn   249:     print(&otherwindow($local,'/cgi-bin/takeoffline.pl',&Apache::lonlocal::mt('Take offline')));
1.23      www       250: }
                    251: 
                    252: sub reroute {
                    253:     my ($local,$remote)=@_;
1.25    ! raeburn   254:     print(&otherwindow($local,'/cgi-bin/takeoffline.pl?'.
1.23      www       255: 		       $hostname{$remote}.'&'.$hostdom{$local}
1.25    ! raeburn   256: 		       ,$remote)."\n");
1.23      www       257: }
                    258: 
                    259: sub allreroutes {
                    260:     my $local=shift;
                    261:     &takeoffline($local);
1.25    ! raeburn   262:     print(&Apache::lonlocal::mt('Reroute to:').' <font size="1">');
1.23      www       263:     foreach my $remote (sort keys %hostname) {
                    264: 	unless ($local eq $remote) {
                    265: 	    &reroute($local,$remote);
                    266: 	}
                    267:     }
1.25    ! raeburn   268:     print('</font>');
1.23      www       269: }
                    270: 
1.11      www       271: # ========================================================= Produce a green bar
                    272: sub bar {
                    273:     my $parm=shift;
                    274:     my $number=int($parm+0.5);
1.25    ! raeburn   275:     print('<table><tr><td bgcolor="#225522"><font color="#225522">');
1.11      www       276:     for (my $i=0;$i<$number;$i++) {
                    277: 	print "+";
                    278:     }
1.25    ! raeburn   279:     print("</font></table>");
1.11      www       280: }
                    281: 
1.9       www       282: # ========================================================== Show server status
                    283: 
1.8       www       284: sub serverstatus {
1.11      www       285:     my ($local,$trouble)=@_;
1.25    ! raeburn   286:     my $hostrole;
        !           287:     if (exists($libserv{$local})) {
        !           288:         $hostrole = 'library';
        !           289:     } else {
        !           290:         $hostrole = 'access';
        !           291:     }
        !           292:     my %lt = &Apache::lonlocal::texthash(
        !           293:                                           rero => 'Reroute:',
        !           294:                                           vers => 'Version:',
        !           295:                                           load => 'Load:',
        !           296:                                           acti => 'Active Users:',
        !           297:                                           rpms => 'RPMs',
        !           298:                                           mysq => 'MySQL Database:',
        !           299:                                           notc => 'Not connected',
        !           300:                                           lonc => 'loncron errors',
        !           301:                                          );
        !           302:    
        !           303:     print(<<ENDHEADER);
1.11      www       304: <a name="$local" />
1.9       www       305: <table width="100%" bgcolor="#225522" cellspacing="2" cellpadding="2" border="0">
                    306: <tr><td bgcolor="#BBDDBB"><font color="#225522" face="arial"><b>
1.25    ! raeburn   307: $local $hostdom{$local}</b> <tt>($hostname{$local}); $hostrole</tt>
        !           308: <br />$domaininfo{$hostdom{$local}}{'description'}
        !           309: $domaininfo{$hostdom{$local}}{'city'}
1.10      www       310: </font></th></tr><tr><td bgcolor="#DDDDBB"><font color="#225522">
1.9       www       311: ENDHEADER
                    312:     &login($local);&server($local);&users($local);&versions($local);
1.18      www       313:     &announcement($local);
1.9       www       314:     &loncron($local);&lond($local);&lonc($local);&runloncron($local);
1.25    ! raeburn   315:     print("</font></td></tr>");
1.11      www       316:     if ($trouble) {
1.25    ! raeburn   317: 	print("<tr><td bgcolor='#DDBBBB'><font color='#552222' size='+2'>$trouble</font></td></tr>");
1.11      www       318:     }
1.25    ! raeburn   319:     print("<tr><td bgcolor='#BBBBBB'>");
1.22      www       320: # re-routing
                    321:     if ($host{$local.'_reroute'}) {
1.25    ! raeburn   322: 	print('<br />'.$lt{'rero'}.' '.$host{$local.'_reroute'});
1.22      www       323: 	&takeonline($local);
                    324:     }
1.15      www       325: # version
                    326:     if ($host{$local.'_version'}) {
1.25    ! raeburn   327: 	print('<br />'.$lt{'vers'}.' '.$host{$local.'_version'});
1.15      www       328:     }
1.9       www       329: # load
                    330:     if (($host{$local.'_load_doomed'}>0.5) || ($mode eq 'load_doomed')) {
1.25    ! raeburn   331: 	print('<br />'.$lt{'load'}.' '.$host{$local.'_load'});
1.9       www       332:     }
                    333: # users
                    334:     if (($host{$local.'_users_doomed'}>10) || ($mode eq 'users_doomed')) {
1.25    ! raeburn   335: 	print('<br />'.$lt{'acti'}.' '.$host{$local.'_users'});
1.9       www       336:     }
                    337: 
1.8       www       338: # checkrpms
                    339:     if ($host{$local.'_checkrpms'}) {
1.25    ! raeburn   340: 	print('<br />'.$lt{'rpms'}.' '.$host{$local.'_checkrpms'});
1.8       www       341:     }
                    342: # mysql
                    343:     if ($host{$local.'_mysql'}) {
1.25    ! raeburn   344: 	print('<br />'.$lt{'mysq'}.' '.$host{$local.'_mysql'});
1.8       www       345:     }
1.11      www       346: # connections
                    347:     if ($host{$local.'_notconnected'}) {
1.25    ! raeburn   348: 	print('<br />'.$lt{'notc'}.' ');
        !           349: 	foreach my $item (split(/ /,$host{$local.'_notconnected'})) {
        !           350: 	    if ($item) {
        !           351: 		print(' <a href="#$item">'.$item.'</a>');
1.11      www       352: 	    }
                    353: 	}
                    354:     }
                    355: # errors
                    356:     if ($host{$local.'_errors'}) {
1.25    ! raeburn   357: 	print('<br />'.$lt{'lonc'}.' '.$host{$local.'_errors'});
1.11      www       358:     }
1.23      www       359:     print "</td></tr><tr><td bgcolor='#DDDDDD'>";
                    360:     &allreroutes($local);
1.9       www       361:     print "</td></tr></table><br />";
                    362: }
                    363: 
                    364: # =========================================================== Doomedness sorted
                    365: 
                    366: sub doomedness {
                    367:     my $crit=shift;
                    368:     my %alldoomed=();
                    369:     my @allhosts=();
                    370:     foreach (keys %host) {
                    371: 	if ($_=~/^(\w+)\_$crit$/) {
                    372: 	    if ($host{$_}) {
                    373: 		push (@allhosts,$1);
                    374: 		$alldoomed{$1}=$host{$_};
                    375: 	    }
                    376: 	}
                    377:     }
                    378:     return sort { $alldoomed{$b} <=> $alldoomed{$a} } @allhosts;
1.8       www       379: }
1.1       www       380: 
1.16      www       381: sub resetvars {
                    382:    $maxusers=0;
                    383:    $maxload=0;
                    384:    $totalusers=0;
                    385:    $stat_total=0;
                    386:    $stat_notyet=0;
                    387:    $stat_fromcache=0;
1.17      www       388:    $concount=0;
1.16      www       389:    undef %host;
                    390:    %host=();
1.1       www       391: }
1.8       www       392: 
1.16      www       393: sub mainloop {
                    394:     &resetvars();
1.8       www       395: # ==================================================== Main Loop over all Hosts
                    396: 
1.25    ! raeburn   397: foreach my $local (sort(keys(%hostname))) {
1.9       www       398:     $host{$local.'_unresponsive_doomed'}=0;
1.8       www       399: # -- Check general status
                    400:     &statuslist($local,'General');
                    401:     my %loncron=&replyhash($local,'/lon-status/loncron_simple.txt',1200);
                    402:     if (defined($loncron{'local_error'})) {
                    403: 	$host{$local.'_loncron'}='Could not determine.';
1.9       www       404: 	$host{$local.'_unresponsive_doomed'}++;
1.8       www       405:     } else {
                    406: 	if ((time-$loncron{'time'})>$oneday) {
                    407: 	    $host{$local.'_loncron'}='Stale.';
1.9       www       408: 	    $host{$local.'_unresponsive_doomed'}++;
1.8       www       409: 	} else {
1.11      www       410: 	    $host{$local.'_loncron_doomed'}=$loncron{'notices'}
                    411: 	                                 +4*$loncron{'warnings'}
                    412: 	                               +100*$loncron{'errors'};
                    413: 	    $host{$local.'_errors'}=$loncron{'errors'};
1.8       www       414: 	}
                    415:     }
1.15      www       416: # -- Check version
                    417:     &statuslist($local,'Version');
                    418:     my $version=&request($local,'/lon-status/version.txt',7200);
                    419:     if ($version eq 'local_error') {
                    420: 	$host{$local.'_version'}='Could not determine.';
                    421: 	$host{$local.'_unresponsive_doomed'}++;
                    422:     } else {
                    423: 	$host{$local.'_version'}=$version;
                    424:     }
1.8       www       425: # -- Check user status
                    426:     &statuslist($local,'Users');
                    427:     my %userstatus=&replyhash($local,'/cgi-bin/userstatus.pl?simple',600);
                    428:     if (defined($userstatus{'local_error'})) {
                    429: 	$host{$local.'_userstatus'}='Could not determine.';
1.9       www       430: 	$host{$local.'_unresponsive_doomed'}++;
1.8       www       431:     } else {
1.9       www       432: 	$host{$local.'_users_doomed'}=$userstatus{'Active'};
                    433: 	$host{$local.'_users'}=$userstatus{'Active'};
1.11      www       434: 	unless ($host{$local.'_users'}) { $host{$local.'_users'}=0; }
                    435: 	if ($host{$local.'_users'}>$maxusers) { 
                    436: 	    $maxusers=$host{$local.'_users'};
                    437: 	}
                    438: 	$totalusers+=$host{$local.'_users'};
1.9       www       439: 	my ($sload,$mload,$lload)=split(/ /,$userstatus{'loadavg'});
                    440: 	$host{$local.'_load_doomed'}=$mload;
1.11      www       441: 	if ($mload>$maxload) { 
                    442: 	    $maxload=$mload;
                    443: 	}
1.9       www       444: 	$host{$local.'_load'}=$userstatus{'loadavg'};
1.8       www       445:     }
1.22      www       446: # -- Check reroute status
                    447:     &statuslist($local,'Reroute');
                    448:     my %reroute=&replyhash($local,'/lon-status/reroute.txt',1800);
                    449:     if ($reroute{'status'} eq 'rerouting') {
                    450: 	if ($reroute{'server'}) {
                    451: 	    $host{$local.'_reroute'}=
                    452: 		'Rerouting to <tt>'.$reroute{'server'}.
                    453:                    '</tt>, domain: '.$reroute{'domain'}.
                    454: 		 ' (since '.localtime($reroute{'time'}).')';
                    455: 	} else {
                    456: 	    $host{$local.'_reroute'}='offline';
                    457: 	}
                    458:     }
1.8       www       459: # -- Check mysql status
                    460:     &statuslist($local,'Database');
1.9       www       461:     my %mysql=&replyhash($local,'/lon-status/mysql.txt',3600);
1.8       www       462:     if (defined($mysql{'local_error'})) {
                    463: 	$host{$local.'_mysql'}='Could not determine.';
1.9       www       464: 	$host{$local.'_unresponsive_doomed'}++;
1.8       www       465:     } else {
                    466: 	if ((time-$mysql{'time'})>(7*$oneday)) {
1.25    ! raeburn   467: 	    if (exists($libserv{$local})) {
1.8       www       468: 		$host{$local.'_mysql'}='Stale.';
                    469: 		$host{$local.'_mysql_doomed'}=1;
                    470: 	    }
                    471: 	    if ($mysql{'mysql'} eq 'defunct') {
                    472: 		$host{$local.'_mysql'}='Defunct (maybe stale).';
                    473: 		$host{$local.'_mysql_doomed'}=2;
                    474: 	    }
                    475: 	} elsif ($mysql{'mysql'} eq 'defunct') {
                    476: 	    $host{$local.'_mysql'}='Defunct.';
                    477: 	    $host{$local.'_mysql_doomed'}=3;
                    478: 	}
                    479:     }
                    480: # -- Check rpm status
                    481:     &statuslist($local,'RPMs');
1.9       www       482:     my %checkrpms=&replyhash($local,'/lon-status/checkrpms.txt',7200);
1.8       www       483:     if (defined($checkrpms{'local_error'})) {
                    484: 	$host{$local.'_checkrpms'}='Could not determine.';
1.9       www       485: 	$host{$local.'_unresponsive_doomed'}++;
1.8       www       486:     } else {
                    487: 	if ((time-$checkrpms{'time'})>(4*$oneday)) {
                    488: 	    $host{$local.'_checkrpms'}='Stale.';
                    489: 	    $host{$local.'_checkrpms_doomed'}=50;
1.9       www       490: 	    $host{$local.'_unresponsive_doomed'}++;
1.8       www       491: 	} elsif ($checkrpms{'status'} eq 'fail') {
                    492: 	    $host{$local.'_checkrpms'}='Could not checked RPMs.';
                    493: 	    $host{$local.'_checkrpms_doomed'}=100;
                    494: 	} elsif ($checkrpms{'rpmcount'}) {
                    495: 	    $host{$local.'_checkrpms'}='Outdated RPMs: '.
                    496: 		$checkrpms{'rpmcount'};
                    497: 	    $host{$local.'_checkrpms_doomed'}=$checkrpms{'rpmcount'};
                    498: 	}
                    499:     }
                    500: # -- Check connections
                    501:     &statuslist($local,'Connections');
                    502:     $host{$local.'_notconnected'}='';
                    503:     $host{$local.'_notconnected_doomed'}=0;
1.16      www       504:     foreach my $remote (sort keys %hostname) {
1.8       www       505: 	my $status=&connected($local,$remote);
                    506: 	$connectionstatus{$local.'_TO_'.$remote}=$status;
                    507: 	unless (($status eq 'ok') || ($status eq 'not_yet')) {
                    508: 	    $host{$local.'_notconnected'}.=' '.$remote;
                    509: 	    $host{$local.'_notconnected_doomed'}++;
                    510: 	}
                    511:     }
1.16      www       512: # =============================================================== End Main Loop
                    513: }
                    514: 
1.8       www       515: }
1.16      www       516: 
                    517: sub reports {
1.9       www       518: # ====================================================================== Output
                    519:     if ($mode=~/\_doomed$/) {
                    520: # Output by doomedness
                    521: 	foreach (&doomedness($mode)) {
                    522: 	    &serverstatus($_);
                    523: 	}
1.10      www       524:     } elsif ($mode eq 'connections') {
                    525: 	print 
                    526:        "<table cellspacing='3' cellpadding='3' border='0' bgcolor='#225522'>".
                    527:        "<tr><td bgcolor='#225522'>&nbsp;</td>";
1.11      www       528: 	foreach my $remote (sort keys %hostname) {
1.17      www       529: 	    print '<td bgcolor="#DDDDBB">'.$remote.'</td>';
1.10      www       530: 	}
                    531: 	print "</tr>\n";
                    532: # connection matrix
1.11      www       533: 	foreach my $local (sort keys %hostname) {
1.17      www       534: 	    print '<tr><td bgcolor="#DDDDBB">'.$local.'</td>';
1.11      www       535: 	    foreach my $remote (sort keys %hostname) {
1.10      www       536: 		if ($connectionstatus{$local.'_TO_'.$remote} eq 'not_yet') {
1.14      www       537: 		    my $cellcolor='#FFFFFF';
                    538: 		    if ($local eq $remote) { $cellcolor='#DDDDDD'; }
                    539: 		    print '<td bgcolor="'.$cellcolor.'"><font color="#555522" size="-2">not yet tested</font></td>';
1.10      www       540: 		} elsif ($connectionstatus{$local.'_TO_'.$remote} eq 'ok') {
1.14      www       541: 		    my $cellcolor='#BBDDBB';
                    542: 		    if ($local eq $remote) { $cellcolor='#99DD99'; }
1.10      www       543: 		    print 
1.25    ! raeburn   544: '<td bgcolor="'.$cellcolor.'"><font color="#225522" face="arial"><b>'.&Apache::lonlocal::mt('ok').'</b></td>';
1.10      www       545: 		} else {
1.20      www       546: 		    my $cellcolor='#DDCCAA';
1.14      www       547: 		    if ($connectionstatus{$local.'_TO_'.$remote} eq 'local_error') {
                    548: 			if ($local eq $remote) { 
                    549: 			    $cellcolor='#DD88AA'; 
                    550: 			} else {
                    551: 			    $cellcolor='#DDAACC';
                    552: 			}
                    553: 		    } else {
1.20      www       554: 			if ($local eq $remote) { $cellcolor='#DDBB77'; }
1.14      www       555: 		    }
1.10      www       556: 		    print 
1.14      www       557: 		  '<td bgcolor="'.$cellcolor.'"><font color="#552222" size="-2">'.
1.10      www       558: 		  $connectionstatus{$local.'_TO_'.$remote}.'<br />';
                    559: 		    &lonc($local); &lond($remote);
                    560: 		    print '</td>';
                    561: 		}
                    562: 	    }
                    563: 	    print "</tr>\n";
                    564: 	}
1.11      www       565: 	print "</table>";
                    566:     } elsif ($mode eq 'users') {
                    567: # Users
                    568: 	if ($maxusers) {
                    569: 	    my $factor=50/$maxusers;
1.25    ! raeburn   570: 	    print '<h3>'.&Apache::lonlocal::mt('Total active user(s)').': '.$totalusers.'</h3>'. 
        !           571:                   '<table cellspacing="3" cellpadding="3" border="0" bgcolor="#225522">';
1.11      www       572: 
1.16      www       573: 	    foreach my $local (sort keys %hostname) {
1.11      www       574: 		if (defined($host{$local.'_users'})) {
                    575: 		    print 
1.16      www       576: '<tr><td bgcolor="#BBDDBB"><font face="arial" color="#225522" size="+1">'.$local.
                    577: 			'</font><br /><font size="-2">'.
1.25    ! raeburn   578: 			$domaininfo{$hostdom{$local}}{'description'}.
1.16      www       579: 		       '</font></td><td bgcolor="#DDDDBB">';
1.12      www       580: 		    &users($local);
1.11      www       581: 		    print 
                    582: 	      '</td><td bgcolor="#DDDDBB"><font face="arial" color="#225522">'.
                    583: 	      $host{$local.'_users'}.'</font></td><td bgcolor="#DDDDBB"';
                    584: 		    &bar($factor*$host{$local.'_users'});
1.25    ! raeburn   585: 		    print '</td></tr>'."\n";
1.11      www       586: 		}
                    587: 	    }
1.25    ! raeburn   588: 	    print '</table>';
1.11      www       589: 	} else {
1.25    ! raeburn   590: 	    print &Apache::lonlocal::mt('No active users logged in.');
1.11      www       591: 	}
                    592:     } elsif ($mode eq 'load') {
                    593: # Load
                    594: 	if ($maxload) {
                    595: 	    my $factor=50/$maxload; 
                    596: 	    print
                    597:        "<table cellspacing='3' cellpadding='3' border='0' bgcolor='#225522'>";
1.16      www       598: 	    foreach my $local (sort keys %hostname) {
1.11      www       599: 		if (defined($host{$local.'_load_doomed'})) {
                    600: 		    print 
1.16      www       601: '<tr><td bgcolor="#BBDDBB"><font face="arial" color="#225522" size="+1">'.
1.11      www       602:                         $local.
1.16      www       603: 			'</font><br /><font size="-2">'.
1.25    ! raeburn   604: 			$Apache::lonnet::domain{$hostdom{$local}}{'description'}.
1.16      www       605: 		       '</font></td><td bgcolor="#DDDDBB">';
1.12      www       606: 		    &server($local);
1.11      www       607: 		    print 
                    608: 	      '</td><td bgcolor="#DDDDBB"><font face="arial" color="#225522">'.
                    609: 	      $host{$local.'_load_doomed'}.'</font></td><td bgcolor="#DDDDBB"';
                    610: 		    &bar($factor*$host{$local.'_load_doomed'});
                    611: 		    print "</td></tr>\n";
                    612: 		}
                    613: 	    }
                    614: 	    print "</table>";
                    615: 	} else {
1.25    ! raeburn   616: 	    print &Apache::lonlocal::mt('No workload.');
1.11      www       617: 	}
                    618:     } elsif ($mode eq 'trouble') {
                    619: 	my $count=0;
1.16      www       620: 	foreach my $local (sort keys %hostname) {
1.11      www       621: 	    my $trouble='';
1.15      www       622: 	    if ($host{$local.'_unresponsive_doomed'}>3) {
1.25    ! raeburn   623: 		$trouble=&Apache::lonlocal::mt('Does not respond to several queries.').
        !           624:                          '<br />';
1.15      www       625: 	    }
1.11      www       626: 	    if ($host{$local.'_errors'}) {
1.25    ! raeburn   627: 		$trouble=&Apache::lonlocal::mt('Has loncron errors').'<br />';
1.24      albertel  628: 	    } elsif ($host{$local.'_loncron_doomed'}>2500) {
1.25    ! raeburn   629: 		$trouble=&Apache::lonlocal::mt('High loncron count.').'<br />';
1.11      www       630: 	    }
                    631: 	    if ($host{$local.'_load_doomed'}>5) {
1.25    ! raeburn   632: 		$trouble=&Apache::lonlocal::mt('High load.').'<br />';
1.11      www       633: 	    }
                    634: 	    if ($host{$local.'_users_doomed'}>200) {
1.25    ! raeburn   635: 		$trouble=&Apache::lonlocal::mt('High user volume.').'<br />';
1.11      www       636: 	    }
                    637: 	    if ($host{$local.'_mysql_doomed'}>1) {
1.25    ! raeburn   638: 		$trouble=&Apache::lonlocal::mt('MySQL database apparently offline.').'<br />';
1.11      www       639: 	    }
                    640: 	    if ($host{$local.'_checkrpms_doomed'}>100) {
1.25    ! raeburn   641: 		$trouble=&Apache::lonlocal::mt('RPMs outdated.').'<br />';
1.22      www       642: 	    }
                    643: 	    if ($host{$local.'_reroute'}) {
1.25    ! raeburn   644: 		$trouble=&Apache::lonlocal::&mt('Rerouting').'<br >';
1.11      www       645: 	    }
                    646: 	    if ($trouble) { $count++; &serverstatus($local,$trouble); }
                    647: 	}
1.25    ! raeburn   648: 	unless ($count) { print &Apache::lonlocal::mt('No major trouble.'); }
1.9       www       649:     }
1.16      www       650: }
                    651: 
                    652: # ====================================================================== Status
                    653: sub statuslist {
                    654:     my ($local,$what)=@_;
1.25    ! raeburn   655:     my $displaylocal;
        !           656:     if (defined($local)) {
        !           657:         $displaylocal = " $local ($hostname{$local})";
        !           658:     }
        !           659:     print '<script>document.prgstat.progress.value="'. 
        !           660:           &Apache::lonlocal::mt("Testing[_1]: $what",$displaylocal).'";</script>'."\n";
1.16      www       661: }
                    662: 
                    663: # =============================================================================
                    664: # =============================================================================
                    665: # Main program
                    666: #
                    667: # ========================================================= Get form parameters
                    668: my $buffer;
                    669: 
                    670: read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
                    671: my @pairs=split(/&/,$buffer);
                    672: my $pair; my $name; my $value;
                    673: undef %FORM;
                    674: %FORM=();
                    675: foreach $pair (@pairs) {
                    676:     ($name,$value) = split(/=/,$pair);
                    677:     $value =~ tr/+/ /;
                    678:     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
                    679:     $FORM{$name}=$value;
                    680: } 
                    681: 
                    682: $buffer=$ENV{'QUERY_STRING'};
                    683: @pairs=split(/&/,$buffer);
                    684: foreach $pair (@pairs) {
                    685:     ($name,$value) = split(/=/,$pair);
                    686:     $value =~ tr/+/ /;
                    687:     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
                    688:     $FORM{$name}=$value;
                    689: } 
                    690: 
                    691: # ====================================================== Determine refresh rate
                    692: 
                    693: my $refresh=(($FORM{'refresh'}=~/^\d+$/)?$FORM{'refresh'}:30);
                    694: if ($refresh<30) { $refresh=30; }
                    695: my $starttime=time;
                    696: 
                    697: # ============================================================== Determine mode
                    698: 
1.25    ! raeburn   699: my %modes= &Apache::lonlocal::texthash (
        !           700:                      'trouble' => 'Trouble',
        !           701: 	             'users_doomed' => 'Doomed: Users',
        !           702: 	             'loncron_doomed' => 'Doomed: General (loncron)',
        !           703: 	             'mysql_doomed' => 'Doomed: Database (mysql)',
        !           704: 	             'notconnected_doomed' => 'Doomed: Connections',
        !           705: 	             'checkrpms_doomed' => 'Doomed: RPMs',
        !           706: 	             'load_doomed' => 'Doomed: Load',
        !           707: 	             'unresponsive_doomed' => 'Doomed: Status could not be determined',
        !           708: 	             'users' => 'User Report',
        !           709: 	             'load' => 'Load Report',
        !           710: 	             'connections' => 'Connections Matrix');
1.16      www       711: $mode=$FORM{'mode'};
                    712: unless ($modes{$mode}) { $mode='trouble'; }
                    713: # ================================================================ Send Headers
1.25    ! raeburn   714: print("Content-type: text/html\n\n".
        !           715:       '<html><body bgcolor="#FFFFFF">'."\n");
1.16      www       716: # -------------------- Read loncapa.conf (and by default, loncapa_apache.conf).
                    717: my $perlvarref=LONCAPA::Configuration::read_conf('loncapa.conf');
                    718: %perlvar=%{$perlvarref};
                    719: undef $perlvarref; # remove since sensitive and not needed
                    720: delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed
                    721: delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed
                    722: 
1.25    ! raeburn   723: if (!&LONCAPA::loncgi::check_cookie_and_load_env()) {
        !           724:     &Apache::lonlocal::get_language_handle();
        !           725:     print(&LONCAPA::loncgi::missing_cookie_msg());
        !           726:     exit;
        !           727: }
        !           728: 
        !           729: if (!&LONCAPA::loncgi::can_view('clusterstatus')) {
        !           730:     &Apache::lonlocal::get_language_handle();
        !           731:     print &LONCAPA::loncgi::unauthorized_msg('clusterstatus');
        !           732:     exit;
        !           733: }
        !           734: 
        !           735: &Apache::lonlocal::get_language_handle();
        !           736: 
        !           737: my $scope = 'Domain';
        !           738: if ($Apache::lonnet::env{'request.role'} =~ m{^su\./}) {
        !           739:     %hostname = %allhostname;
        !           740:     $scope = 'Cluster';
        !           741: } else {
        !           742:     undef(%hostname);
        !           743:     my @poss_domains = &Apache::lonnet::current_machine_domains();
        !           744:     foreach my $host (keys(%allhostname)) {
        !           745:         if (grep(/^\Q$hostdom{$host}\E$/,@poss_domains)) {
        !           746:             $hostname{$host} = $allhostname{$host};
        !           747:         }
1.16      www       748:     }
                    749: }
                    750: 
1.25    ! raeburn   751: print '<img src="/adm/lonIcons/lonlogos.gif" align="right" /><h1>'.&Apache::lonlocal::mt("LON-CAPA $scope Status").' '.localtime()."</h1>";
1.16      www       752: print "<form name='prgstat'>\n".
1.25    ! raeburn   753: '<input type="text" name="progress" value="'."'".&Apache::lonlocal::mt('Starting ...')."'".'" size="100" /><br />'.
        !           754: "</form>\n";
1.16      www       755: print "<form name='status' method='post'>\n";
1.25    ! raeburn   756: print &Apache::lonlocal::mt('Choose next report:').' '.&select_form($mode,'mode',%modes).'<input type="submit" name="getreport" value="'.&Apache::lonlocal::mt('Go').'" /><hr />';
1.16      www       757: &hidden('refresh',$refresh);
                    758: 
                    759:     if (!$FORM{'runonetime'}) {
1.25    ! raeburn   760:         my $lcscope = lc($scope);
        !           761: 	print '<h3>'.&Apache::lonlocal::mt("Gathering initial $lcscope data").'</h3>'.
        !           762:               &Apache::lonlocal::mt('This may take some time ..').'<br />';
1.16      www       763: 	$fromcache=0;
                    764: 	&mainloop();
1.25    ! raeburn   765: 	&statuslist(undef,'Done initial run.');
1.16      www       766: 	&reports();
                    767:     } else {
                    768: 	$fromcache=1;
                    769: 	&mainloop();
1.25    ! raeburn   770: 	&statuslist(undef,'Done gathering cached data');
1.16      www       771: 	&reports();
                    772: 	$fromcache=0;
                    773: 	&mainloop();
                    774:     }
                    775:     &hidden('runonetime',1);
1.25    ! raeburn   776:     print '<tt><br />'.&Apache::lonlocal::mt('Total number of queries: [_1]',$stat_total);
        !           777:     if ($stat_total != 0) {
        !           778:         print '<br />'.&Apache::lonlocal::mt('Percent complete:').''.
        !           779: 	      int(($stat_total-$stat_notyet)/$stat_total*100.).
        !           780: 	      '<br />'.&Apache::lonlocal::mt('Percent from cache:').' '.
        !           781:               int($stat_fromcache/$stat_total*100.).'</tt>';
        !           782:     }
1.16      www       783: 
1.9       www       784: # ============================================================== Close, refresh
1.8       www       785: print "</form><script>";
1.16      www       786: my $runtime=time-$starttime;
                    787: if (($refresh-$runtime)<0) {
                    788:     print "document.status.submit();";
1.8       www       789: } else {
1.16      www       790:     my $refreshtime=int(1000*($refresh-$runtime));
1.25    ! raeburn   791:     my $refreshmsg = &Apache::lonlocal::mt('Will automatically refresh ([_1] secs refresh cycle)',$refresh);
1.11      www       792:     print "setTimeout('document.status.submit()',$refreshtime);\n".
1.25    ! raeburn   793:           "document.prgstat.progress.value='$refreshmsg'";
1.2       www       794: }
1.8       www       795: print "</script></body></html>";
                    796: exit 0;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>