Annotation of loncom/cgi/clusterstatus.pl, revision 1.9
1.1 www 1: #!/usr/bin/perl
2: $|=1;
3: # The LearningOnline Network with CAPA
4: # Cluster Status
1.9 ! www 5: #
! 6: # $Id: $
1.3 harris41 7:
8: use lib '/home/httpd/lib/perl/';
9: use LONCAPA::Configuration;
10:
1.1 www 11: use LWP::UserAgent();
12: use HTTP::Headers;
13: use IO::File;
14:
1.8 www 15: my %host=();
16: my $oneday=60*60*24;
17:
18: my %connectionstatus=();
1.9 ! www 19: my %perlvar=();
! 20:
! 21: my $mode;
! 22:
! 23: sub select_form {
! 24: my ($def,$name,%hash) = @_;
! 25: my $selectform = "<select name=\"$name\" size=\"1\">\n";
! 26: foreach (sort keys %hash) {
! 27: $selectform.="<option value=\"$_\" ".
! 28: ($_ eq $def ? 'selected' : '').
! 29: ">".$hash{$_}."</option>\n";
! 30: }
! 31: $selectform.="</select>";
! 32: return $selectform;
! 33: }
! 34:
1.8 www 35:
36: sub key {
37: my ($local,$url)=@_;
38: my $key=$local.'_'.$url;
39: $key=~s/\W/\_/gs;
40: return $key;
41: }
42:
43: sub hidden {
44: my ($name,$value)=@_;
45: print "\n<input type='hidden' name='$name' value='$value' />";
46: }
47:
48: sub request {
49: my ($local,$url,$cachetime)=@_;
50: my $key=&key($local,$url);
51: my $reply='';
52: if ($FORM{$key.'_time'}) {
53: if ((time-$FORM{$key.'_time'})<$cachetime) {
54: $reply=$FORM{$key};
55: &hidden($key.'_time',$FORM{$key.'_time'});
56: &hidden($key.'_fromcache',1);
57: }
58: }
59: unless ($reply) {
60: unless ($hostname{$local}) {
61: $reply='local_unknown';
62: } else {
63:
64: my $ua=new LWP::UserAgent(timeout => 20);
65:
66: my $request=new HTTP::Request('GET',
67: "http://".$hostname{$local}.$url);
68: $request->authorization_basic('lonadm','litelite');
69:
70: my $response=$ua->request($request);
71:
72: unless ($response->is_success) {
73: $reply='local_error';
74: } else {
75: $reply=$response->content;
76: chomp($reply);
77: }
78: }
79: &hidden($key.'_time',time);
80: }
81: &hidden($key,$reply);
82: return $reply;
83: }
84:
85: # ============================================= Are local and remote connected?
1.1 www 86: sub connected {
87: my ($local,$remote)=@_;
88: $local=~s/\W//g;
89: $remote=~s/\W//g;
90:
91: unless ($hostname{$remote}) { return 'remote_unknown'; }
1.8 www 92: my $url='/cgi-bin/ping.pl?'.$remote;
93: #
94: # Slowly phase this in: if not cached, only do 10 percent of the cases
95: #
96: unless ($FORM{&key($local,$url)}) {
97: unless (rand>0.9) { return 'not_yet'; }
98: }
99: #
100: # Actually do the query
101: #
102: &statuslist($local,'connecting '.$remote);
1.9 ! www 103: my $reply=&request($local,$url,3600);
1.8 www 104: $reply=(split("\n",$reply))[0];
105: $reply=~s/\W//g;
106: if ($reply ne $remote) { return $reply; }
107: return 'ok';
108: }
109: # ============================================================ Get a reply hash
110:
111: sub replyhash {
112: my %returnhash=();
113: foreach (split(/\&/,&request(@_))) {
114: my ($name,$value)=split(/\=/,$_);
115: if ($name) {
116: unless ($value) { $value=''; }
117: $returnhash{$name}=$value;
118: }
119: }
120: return %returnhash;
121: }
1.1 www 122:
1.9 ! www 123: # ================================================================ Link to host
1.1 www 124:
1.8 www 125: sub otherwindow {
126: my ($local,$url,$label)=@_;
127: return
1.9 ! www 128: " <a href='http://$hostname{$local}$url' target='newwin$local'>$label</a> ";
! 129: }
! 130:
! 131: sub login {
! 132: my $local=shift;
! 133: print &otherwindow($local,'/adm/login?domain='.$perlvar{'lonDefDomain'},
! 134: 'Login');
! 135: }
! 136:
! 137: sub runloncron {
! 138: my $local=shift;
! 139: print &otherwindow($local,'/cgi-bin/loncron.pl','Run loncron');
! 140: }
! 141:
! 142: sub loncron {
! 143: my $local=shift;
! 144: print &otherwindow($local,'/lon-status','loncron');
! 145: }
! 146:
! 147: sub lonc {
! 148: my $local=shift;
! 149: print &otherwindow($local,'/lon-status/loncstatus.txt','lonc');
! 150: }
! 151:
! 152: sub lond {
! 153: my $local=shift;
! 154: print &otherwindow($local,'/lon-status/londstatus.txt','lond');
! 155: }
! 156:
! 157: sub users {
! 158: my $local=shift;
! 159: print &otherwindow($local,'/cgi-bin/userstatus.pl','Users');
! 160: }
! 161:
! 162: sub versions {
! 163: my $local=shift;
! 164: print &otherwindow($local,'/cgi-bin/lonversions.pl','Versions');
! 165: }
! 166:
! 167: sub server {
! 168: my $local=shift;
! 169: print &otherwindow($local,'/server-status','Server Status');
1.8 www 170: }
1.1 www 171:
1.9 ! www 172: # ========================================================== Show server status
! 173:
1.8 www 174: sub serverstatus {
175: my $local=shift;
1.9 ! www 176: print (<<ENDHEADER);
! 177: <table width="100%" bgcolor="#225522" cellspacing="2" cellpadding="2" border="0">
! 178: <tr><td bgcolor="#BBDDBB"><font color="#225522" face="arial"><b>
! 179: $local $hostdom{$local}</b> <tt>($hostname{$local}; $hostrole{$local})</tt>
! 180: <br />$domaindescription{$hostdom{$local}}
! 181: </font></th></tr><tr><td bgcolor="DDDDBB"><font color="#225522">
! 182: ENDHEADER
! 183: &login($local);&server($local);&users($local);&versions($local);
! 184: &loncron($local);&lond($local);&lonc($local);&runloncron($local);
! 185: print "</font></td></tr><tr><td bgcolor='#BBBBBB'>";
! 186: # load
! 187: if (($host{$local.'_load_doomed'}>0.5) || ($mode eq 'load_doomed')) {
! 188: print "<br />Load: ".$host{$local.'_load'}
! 189: }
! 190: # users
! 191: if (($host{$local.'_users_doomed'}>10) || ($mode eq 'users_doomed')) {
! 192: print "<br />Active Users: ".$host{$local.'_users'}
! 193: }
! 194:
1.8 www 195: # checkrpms
196: if ($host{$local.'_checkrpms'}) {
197: print "<br />RPMs: ".$host{$local.'_checkrpms'}
198: }
199: # mysql
200: if ($host{$local.'_mysql'}) {
201: print "<br />MySQL Database: ".$host{$local.'_mysql'}
202: }
1.9 ! www 203: print "</td></tr></table><br />";
! 204: }
! 205:
! 206: # =========================================================== Doomedness sorted
! 207:
! 208: sub doomedness {
! 209: my $crit=shift;
! 210: my %alldoomed=();
! 211: my @allhosts=();
! 212: foreach (keys %host) {
! 213: if ($_=~/^(\w+)\_$crit$/) {
! 214: if ($host{$_}) {
! 215: push (@allhosts,$1);
! 216: $alldoomed{$1}=$host{$_};
! 217: }
! 218: }
! 219: }
! 220: return sort { $alldoomed{$b} <=> $alldoomed{$a} } @allhosts;
1.8 www 221: }
1.1 www 222:
1.8 www 223: # ====================================================================== Status
224: sub statuslist {
225: my ($local,$what)=@_;
226: print
227: "<script>document.prgstat.progress.value='Testing $local ($hostname{$local}): $what';</script>\n";
1.1 www 228: }
229:
1.8 www 230: #
231: # Main program
232: #
233: # ========================================================= Get form parameters
234: my $buffer;
235:
236: read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
237: my @pairs=split(/&/,$buffer);
238: my $pair; my $name; my $value;
239: undef %FORM;
240: %FORM=();
241: foreach $pair (@pairs) {
242: ($name,$value) = split(/=/,$pair);
243: $value =~ tr/+/ /;
244: $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
245: $FORM{$name}=$value;
246: }
247:
248: $buffer=$ENV{'QUERY_STRING'};
249: @pairs=split(/&/,$buffer);
250: foreach $pair (@pairs) {
251: ($name,$value) = split(/=/,$pair);
252: $value =~ tr/+/ /;
253: $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
254: $FORM{$name}=$value;
255: }
256:
257: # ====================================================== Determine refresh rate
258:
259: my $refresh=(($FORM{'refresh'}=~/^\d+$/)?$FORM{'refresh'}:60);
260: if ($refresh<30) { $refresh=30; }
261: my $starttime=time;
1.9 ! www 262:
! 263: # ============================================================== Determine mode
! 264:
! 265: my %modes=('trouble' => 'Trouble',
! 266: 'users_doomed' => 'Doomed: Users',
! 267: 'loncron_doomed' => 'Doomed: General (loncron)',
! 268: 'mysql_doomed' => 'Doomed: Database (mysql)',
! 269: 'notconnected_doomed' => 'Doomed: Connections',
! 270: 'checkrpms_doomed' => 'Doomed: RPMs',
! 271: 'load_doomed' => 'Doomed: Load',
! 272: 'unresponsive_doomed' => 'Doomed: Status could not be determined',
! 273: 'users' => 'User Report',
! 274: 'connections' => 'Connections Matrix');
! 275:
! 276: $mode=$FORM{'mode'};
! 277: unless ($modes{$mode}) { $mode='trouble'; }
1.8 www 278: # ================================================================ Send Headers
1.1 www 279: print "Content-type: text/html\n\n".
1.8 www 280: "<html><body bgcolor=#FFFFFF>\n";
1.4 harris41 281: # -------------------- Read loncapa.conf (and by default, loncapa_apache.conf).
282: my $perlvarref=LONCAPA::Configuration::read_conf('loncapa.conf');
1.9 ! www 283: %perlvar=%{$perlvarref};
1.3 harris41 284: undef $perlvarref; # remove since sensitive and not needed
285: delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed
286: delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed
1.1 www 287:
288: # ------------------------------------------------------------- Read hosts file
289: {
290: my $config=IO::File->new("$perlvar{'lonTabDir'}/hosts.tab");
291:
1.2 www 292: $total=0;
1.1 www 293: while (my $configline=<$config>) {
1.7 www 294: $configline=~s/#.*$//;
295: unless ($configline=~/\w/) { next; }
1.1 www 296: my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
297: $hostname{$id}=$name;
298: $hostdom{$id}=$domain;
299: $hostrole{$id}=$role;
300: $hostip{$id}=$ip;
1.2 www 301: $total++;
1.1 www 302: if (($role eq 'library') && ($id ne $perlvar{'lonHostID'})) {
303: $libserv{$id}=$name;
304: }
305: }
306: }
1.9 ! www 307: # ------------------------------------------------------------ Read domain file
! 308: {
! 309: my $fh=IO::File->new($perlvar{'lonTabDir'}.'/domain.tab');
! 310: %domaindescription = ();
! 311: %domain_auth_def = ();
! 312: %domain_auth_arg_def = ();
! 313: if ($fh) {
! 314: while (<$fh>) {
! 315: next if (/^(\#|\s*$)/);
! 316: chomp;
! 317: my ($domain, $domain_description, $def_auth, $def_auth_arg)
! 318: = split(/:/,$_,4);
! 319: $domain_auth_def{$domain}=$def_auth;
! 320: $domain_auth_arg_def{$domain}=$def_auth_arg;
! 321: $domaindescription{$domain}=$domain_description;
! 322: }
! 323: }
! 324: }
! 325:
1.1 www 326:
1.8 www 327: print "<h1>Cluster Status ".localtime()."</h1>";
328: print "<form name='prgstat'>\n".
329: "<input type='text' name='progress' value='Starting ...' size='100' /><br />".
330: "</form>\n";;
331: print "<form name='status' method='post'>\n";
1.9 ! www 332: print 'Choose next report: '.&select_form($mode,'mode',%modes).'<hr />';
1.8 www 333: &hidden('refresh',$refresh);
334:
335: # ==================================================== Main Loop over all Hosts
336:
337: foreach $local (sort keys %hostname) {
1.9 ! www 338: $host{$local.'_unresponsive_doomed'}=0;
1.8 www 339: # -- Check general status
340: &statuslist($local,'General');
341: my %loncron=&replyhash($local,'/lon-status/loncron_simple.txt',1200);
342: if (defined($loncron{'local_error'})) {
343: $host{$local.'_loncron'}='Could not determine.';
1.9 ! www 344: $host{$local.'_unresponsive_doomed'}++;
1.8 www 345: } else {
346: if ((time-$loncron{'time'})>$oneday) {
347: $host{$local.'_loncron'}='Stale.';
1.9 ! www 348: $host{$local.'_unresponsive_doomed'}++;
1.8 www 349: } else {
350: }
351: }
352: # -- Check user status
353: &statuslist($local,'Users');
354: my %userstatus=&replyhash($local,'/cgi-bin/userstatus.pl?simple',600);
355: if (defined($userstatus{'local_error'})) {
356: $host{$local.'_userstatus'}='Could not determine.';
1.9 ! www 357: $host{$local.'_unresponsive_doomed'}++;
1.8 www 358: } else {
1.9 ! www 359: $host{$local.'_users_doomed'}=$userstatus{'Active'};
! 360: $host{$local.'_users'}=$userstatus{'Active'};
! 361: my ($sload,$mload,$lload)=split(/ /,$userstatus{'loadavg'});
! 362: $host{$local.'_load_doomed'}=$mload;
! 363: $host{$local.'_load'}=$userstatus{'loadavg'};
1.8 www 364: }
365: # -- Check mysql status
366: &statuslist($local,'Database');
1.9 ! www 367: my %mysql=&replyhash($local,'/lon-status/mysql.txt',3600);
1.8 www 368: if (defined($mysql{'local_error'})) {
369: $host{$local.'_mysql'}='Could not determine.';
1.9 ! www 370: $host{$local.'_unresponsive_doomed'}++;
1.8 www 371: } else {
372: if ((time-$mysql{'time'})>(7*$oneday)) {
373: if ($hostrole{$local} eq 'library') {
374: $host{$local.'_mysql'}='Stale.';
375: $host{$local.'_mysql_doomed'}=1;
376: }
377: if ($mysql{'mysql'} eq 'defunct') {
378: $host{$local.'_mysql'}='Defunct (maybe stale).';
379: $host{$local.'_mysql_doomed'}=2;
380: }
381: } elsif ($mysql{'mysql'} eq 'defunct') {
382: $host{$local.'_mysql'}='Defunct.';
383: $host{$local.'_mysql_doomed'}=3;
384: }
385: }
386: # -- Check rpm status
387: &statuslist($local,'RPMs');
1.9 ! www 388: my %checkrpms=&replyhash($local,'/lon-status/checkrpms.txt',7200);
1.8 www 389: if (defined($checkrpms{'local_error'})) {
390: $host{$local.'_checkrpms'}='Could not determine.';
1.9 ! www 391: $host{$local.'_unresponsive_doomed'}++;
1.8 www 392: } else {
393: if ((time-$checkrpms{'time'})>(4*$oneday)) {
394: $host{$local.'_checkrpms'}='Stale.';
395: $host{$local.'_checkrpms_doomed'}=50;
1.9 ! www 396: $host{$local.'_unresponsive_doomed'}++;
1.8 www 397: } elsif ($checkrpms{'status'} eq 'fail') {
398: $host{$local.'_checkrpms'}='Could not checked RPMs.';
399: $host{$local.'_checkrpms_doomed'}=100;
400: } elsif ($checkrpms{'rpmcount'}) {
401: $host{$local.'_checkrpms'}='Outdated RPMs: '.
402: $checkrpms{'rpmcount'};
403: $host{$local.'_checkrpms_doomed'}=$checkrpms{'rpmcount'};
404: }
405: }
406: # -- Check connections
407: &statuslist($local,'Connections');
408: $host{$local.'_notconnected'}='';
409: $host{$local.'_notconnected_doomed'}=0;
410: foreach $remote (sort keys %hostname) {
411: my $status=&connected($local,$remote);
412: $connectionstatus{$local.'_TO_'.$remote}=$status;
413: unless (($status eq 'ok') || ($status eq 'not_yet')) {
414: $host{$local.'_notconnected'}.=' '.$remote;
415: $host{$local.'_notconnected_doomed'}++;
416: }
417: }
1.9 ! www 418: # =============================================================== End Mail Loop
1.8 www 419: }
1.9 ! www 420: &statuslist('Done.');
! 421: # ====================================================================== Output
! 422: if ($mode=~/\_doomed$/) {
! 423: # Output by doomedness
! 424: foreach (&doomedness($mode)) {
! 425: &serverstatus($_);
! 426: }
! 427: }
! 428: # ============================================================== Close, refresh
1.8 www 429: print "</form><script>";
430: $runtime=time-$starttime;
431: if ($runtime>=$refresh) {
432: print 'document.status.submit();';
433: } else {
434: $refreshtime=int(1000*($refresh-$runtime));
435: print "setTimeout('document.status.submit()',$refreshtime);";
1.2 www 436: }
1.8 www 437: print "</script></body></html>";
438: exit 0;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>