--- loncom/lond 2010/09/27 00:21:02 1.459 +++ loncom/lond 2011/06/11 21:10:03 1.475 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.459 2010/09/27 00:21:02 raeburn Exp $ +# $Id: lond,v 1.475 2011/06/11 21:10:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -15,6 +15,7 @@ # # LON-CAPA 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. # @@ -52,13 +53,14 @@ use LONCAPA::lonlocal; use LONCAPA::lonssl; use Fcntl qw(:flock); use Apache::lonnet; +use Mail::Send; my $DEBUG = 0; # Non zero to enable debug log entries. my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.459 $'; #' stupid emacs +my $VERSION='$Revision: 1.475 $'; #' stupid emacs my $remoteVERSION; my $currenthostid="default"; my $currentdomainid; @@ -419,8 +421,11 @@ sub ReadManagerTable { my $tablename = $perlvar{'lonTabDir'}."/managers.tab"; if (!open (MANAGERS, $tablename)) { - logthis('No manager table. Nobody can manage!!'); - return; + my $hostname = &Apache::lonnet::hostname($perlvar{'lonHostID'}); + if (&Apache::lonnet::is_LC_dns($hostname)) { + &logthis('No manager table. Nobody can manage!!'); + } + return; } while(my $host = ) { chomp($host); @@ -445,7 +450,7 @@ sub ReadManagerTable { } } else { logthis(' existing host'." $host\n"); - $managers{&Apache::lonnet::get_host_ip($host)} = $host; # Use info from cluster tab if clumemeber + $managers{&Apache::lonnet::get_host_ip($host)} = $host; # Use info from cluster tab if cluster memeber } } } @@ -507,7 +512,8 @@ sub AdjustHostContents { my $me = $perlvar{'lonHostID'}; foreach my $line (split(/\n/,$contents)) { - if(!(($line eq "") || ($line =~ /^ *\#/) || ($line =~ /^ *$/))) { + if(!(($line eq "") || ($line =~ /^ *\#/) || ($line =~ /^ *$/) || + ($line =~ /^\s*\^/))) { chomp($line); my ($id,$domain,$role,$name,$ip,$maxcon,$idleto,$mincon)=split(/:/,$line); if ($id eq $me) { @@ -595,11 +601,8 @@ sub InstallFile { # # ConfigFileFromSelector: converts a configuration file selector # into a configuration file pathname. -# It's probably no longer necessary to preserve -# special handling of hosts or domain as those -# files have been superceded by dns_hosts, dns_domain. -# The default action is just to prepend the directory -# and append .tab +# Supports the following file selectors: +# hosts, domain, dns_hosts, dns_domain # # # Parameters: @@ -612,15 +615,11 @@ sub ConfigFileFromSelector { my $tablefile; my $tabledir = $perlvar{'lonTabDir'}.'/'; - if ($selector eq "hosts") { - $tablefile = $tabledir."hosts.tab"; - } elsif ($selector eq "domain") { - $tablefile = $tabledir."domain.tab"; - } else { + if (($selector eq "hosts") || ($selector eq "domain") || + ($selector eq "dns_hosts") || ($selector eq "dns_domain")) { $tablefile = $tabledir.$selector.'.tab'; } return $tablefile; - } # # PushFile: Called to do an administrative push of a file. @@ -646,6 +645,8 @@ sub PushFile { # supported: # hosts.tab ($filename eq host). # domain.tab ($filename eq domain). + # dns_hosts.tab ($filename eq dns_host). + # dns_domain.tab ($filename eq dns_domain). # Construct the destination filename or reject the request. # # lonManage is supposed to ensure this, however this session could be @@ -677,11 +678,31 @@ sub PushFile { return "error:$!"; } else { &logthis(' Installed new '.$tablefile - .""); - + ." - transaction by: $clientname ($clientip)"); + my $adminmail = $perlvar{'lonAdmEMail'}; + my $admindom = &Apache::lonnet::host_domain($perlvar{'lonHostID'}); + if ($admindom ne '') { + my %domconfig = + &Apache::lonnet::get_dom('configuration',['contacts'],$admindom); + if (ref($domconfig{'contacts'}) eq 'HASH') { + if ($domconfig{'contacts'}{'adminemail'} ne '') { + $adminmail = $domconfig{'contacts'}{'adminemail'}; + } + } + } + if ($adminmail =~ /^[^\@]+\@[^\@]+$/) { + my $msg = new Mail::Send; + $msg->to($adminmail); + $msg->subject('LON-CAPA DNS update on '.$perlvar{'lonHostID'}); + $msg->add('Content-type','text/plain; charset=UTF-8'); + if (my $fh = $msg->open()) { + print $fh 'Update to '.$tablefile.' from Cluster Manager '. + "$clientname ($clientip)\n"; + $fh->close; + } + } } - # Indicate success: return "ok"; @@ -1121,6 +1142,8 @@ sub establish_key_handler { sub load_handler { my ($cmd, $tail, $replyfd) = @_; + + # Get the load average from /proc/loadavg and calculate it as a percentage of # the allowed load limit as set by the perl global variable lonLoadLim @@ -1666,6 +1689,15 @@ sub server_homeID_handler { } ®ister_handler("serverhomeID", \&server_homeID_handler, 0, 1, 0); +sub server_distarch_handler { + my ($cmd,$tail,$client) = @_; + my $userinput = "$cmd:$tail"; + my $reply = &distro_and_arch(); + &Reply($client,\$reply,$userinput); + return 1; +} +®ister_handler("serverdistarch", \&server_distarch_handler, 0, 1, 0); + # Process a reinit request. Reinit requests that either # lonc or lond be reinitialized so that an updated # host.tab or domain.tab can be processed. @@ -2422,7 +2454,6 @@ sub user_has_session_handler { my ($udom, $uname) = map { &unescape($_) } (split(/:/, $tail)); - &logthis("Looking for $udom $uname"); opendir(DIR,$perlvar{'lonIDsDir'}); my $filename; while ($filename=readdir(DIR)) { @@ -4278,6 +4309,7 @@ sub put_domain_handler { sub get_domain_handler { my ($cmd, $tail, $client) = @_; + my $userinput = "$client:$tail"; my ($udom,$namespace,$what)=split(/:/,$tail,3); @@ -4422,7 +4454,8 @@ sub get_id_handler { sub put_dcmail_handler { my ($cmd,$tail,$client) = @_; my $userinput = "$cmd:$tail"; - + + my ($udom,$what)=split(/:/,$tail); chomp($what); my $hashref = &tie_domain_hash($udom, "nohist_dcmail", &GDBM_WRCREAT()); @@ -5004,10 +5037,11 @@ sub get_sections_handler { sub validate_course_owner_handler { my ($cmd, $tail, $client) = @_; my $userinput = "$cmd:$tail"; - my ($inst_course_id, $owner, $cdom) = split(/:/, $tail); - + my ($inst_course_id, $owner, $cdom, $coowners) = split(/:/, $tail); + $owner = &unescape($owner); - my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom); + $coowners = &unescape($coowners); + my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom,$coowners); &Reply($client, \$outcome, $userinput); @@ -5995,7 +6029,7 @@ if (-e $pidfile) { $server = IO::Socket::INET->new(LocalPort => $perlvar{'londPort'}, Type => SOCK_STREAM, Proto => 'tcp', - Reuse => 1, + ReuseAddr => 1, Listen => 10 ) or die "making socket: $@\n"; @@ -6058,9 +6092,13 @@ sub HUPSMAN { # sig # a setuid perl script that can be root for us to do this job. # sub ReloadApache { - my $execdir = $perlvar{'lonDaemons'}; - my $script = $execdir."/apachereload"; - system($script); +# --------------------------- Handle case of another apachereload process (locking) + if (&LONCAPA::try_to_lock('/tmp/lock_apachereload')) { + my $execdir = $perlvar{'lonDaemons'}; + my $script = $execdir."/apachereload"; + system($script); + unlink('/tmp/lock_apachereload'); # Remove the lock file. + } } # @@ -6233,7 +6271,7 @@ sub logstatus { sub initnewstatus { my $docdir=$perlvar{'lonDocRoot'}; my $fh=IO::File->new(">$docdir/lon-status/londstatus.txt"); - my $now=time; + my $now=time(); my $local=localtime($now); print $fh "LOND status $local - parent $$\n\n"; opendir(DIR,"$docdir/lon-status/londchld"); @@ -6326,6 +6364,13 @@ my %iphost = &Apache::lonnet::get_iphost my $dist=`$perlvar{'lonDaemons'}/distprobe`; +my $arch = `uname -i`; +chomp($arch); +if ($arch eq 'unknown') { + $arch = `uname -m`; + chomp($arch); +} + # -------------------------------------------------------------- # Accept connections. When a connection comes in, it is validated # and if good, a child process is created to process transactions @@ -6383,6 +6428,7 @@ sub make_new_child { or die "Can't unblock SIGINT for fork: $!\n"; $children{$pid} = $clientip; &status('Started child '.$pid); + close($client); return; } else { # Child can *not* return from this subroutine. @@ -6391,6 +6437,13 @@ sub make_new_child { #don't get intercepted $SIG{USR1}= \&logstatus; $SIG{ALRM}= \&timeout; + # + # Block sigpipe as it gets thrownon socket disconnect and we want to + # deal with that as a read faiure instead. + # + my $blockset = POSIX::SigSet->new(SIGPIPE); + sigprocmask(SIG_BLOCK, $blockset); + $lastlog='Forked '; $status='Forked'; @@ -7346,6 +7399,8 @@ sub releasereqd_check { my ($reqdmajor,$reqdminor) = split(/\./,$courseinfo->{'releaserequired'}); return unless (&useable_role($reqdmajor,$reqdminor,$major,$minor)); } + } else { + return; } } return 1; @@ -7353,10 +7408,25 @@ sub releasereqd_check { sub get_courseinfo_hash { my ($cnum,$cdom,$home) = @_; - my $hashid = $cdom.':'.$cnum; - my %info = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,1,[$home],'.'); - if (ref($info{$cdom.'_'.$cnum}) eq 'HASH') { - return &Apache::lonnet::do_cache_new('courseinfo',$hashid,$info{$cdom.'_'.$cnum},600); + my %info; + eval { + local($SIG{ALRM}) = sub { die "timeout\n"; }; + local($SIG{__DIE__})='DEFAULT'; + alarm(3); + %info = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,1,[$home],'.'); + alarm(0); + }; + if ($@) { + if ($@ eq "timeout\n") { + &logthis("WARNING courseiddump for $cnum:$cdom from $home timedout"); + } else { + &logthis("WARNING unexpected error during eval of call for courseiddump from $home"); + } + } else { + if (ref($info{$cdom.'_'.$cnum}) eq 'HASH') { + my $hashid = $cdom.':'.$cnum; + return &Apache::lonnet::do_cache_new('courseinfo',$hashid,$info{$cdom.'_'.$cnum},600); + } } return; } @@ -7400,7 +7470,10 @@ sub check_homecourses { return; } foreach my $hashid (keys(%recent)) { - &Apache::lonnet::do_cache_new('courseinfo',$hashid,$courseinfo{$hashid},600); + my ($result,$cached)=&Apache::lonnet::is_cached_new('courseinfo',$hashid); + unless ($cached) { + &Apache::lonnet::do_cache_new('courseinfo',$hashid,$courseinfo{$hashid},600); + } } foreach my $hashid (keys(%{$homecourses})) { next if ($recent{$hashid}); @@ -7444,6 +7517,10 @@ sub useable_role { return 1; } +sub distro_and_arch { + return $dist.':'.$arch; +} + # ----------------------------------- POD (plain old documentation, CPAN style) =head1 NAME