Annotation of loncom/cgi/clusterstatus.pl, revision 1.10
1.1 www 1: #!/usr/bin/perl
2: $|=1;
3: # The LearningOnline Network with CAPA
4: # Cluster Status
1.9 www 5: #
1.10 ! www 6: # $Id: clusterstatus.pl,v 1.9 2003/07/31 15:35:02 www Exp $
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}}
1.10 ! www 181: </font></th></tr><tr><td bgcolor="#DDDDBB"><font color="#225522">
1.9 www 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.10 ! 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.10 ! www 327: print "<img src='/adm/lonIcons/lonlogos.gif' align='right' /><h1>LON-CAPA Cluster Status ".localtime()."</h1>";
1.8 www 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: }
1.10 ! www 427: } elsif ($mode eq 'connections') {
! 428: print
! 429: "<table cellspacing='3' cellpadding='3' border='0' bgcolor='#225522'>".
! 430: "<tr><td bgcolor='#225522'> </td>";
! 431: foreach (sort keys %hostname) {
! 432: my $remote=$_;
! 433: print '<th bgcolor="#DDDDBB">'.$remote.'</th>';
! 434: }
! 435: print "</tr>\n";
! 436: # connection matrix
! 437: foreach (sort keys %hostname) {
! 438: my $local=$_;
! 439: print '<tr><th bgcolor="#DDDDBB">'.$local.'</th>';
! 440: foreach (sort keys %hostname) {
! 441: my $remote=$_;
! 442: if ($connectionstatus{$local.'_TO_'.$remote} eq 'not_yet') {
! 443: print '<td bgcolor="#FFFFFF"> </td>';
! 444: } elsif ($connectionstatus{$local.'_TO_'.$remote} eq 'ok') {
! 445: print
! 446: '<td bgcolor="#BBDDBB"><font color="#225522" face="arial"><b>ok</b></td>';
! 447: } else {
! 448: print
! 449: '<td bgcolor="#DDBBBB"><font color="#552222" size="-2">'.
! 450: $connectionstatus{$local.'_TO_'.$remote}.'<br />';
! 451: &lonc($local); &lond($remote);
! 452: print '</td>';
! 453: }
! 454: }
! 455: print "</tr>\n";
! 456: }
1.9 www 457: }
1.10 ! www 458: print "</table>";
1.9 www 459: # ============================================================== Close, refresh
1.8 www 460: print "</form><script>";
461: $runtime=time-$starttime;
462: if ($runtime>=$refresh) {
463: print 'document.status.submit();';
464: } else {
465: $refreshtime=int(1000*($refresh-$runtime));
466: print "setTimeout('document.status.submit()',$refreshtime);";
1.2 www 467: }
1.8 www 468: print "</script></body></html>";
469: exit 0;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>