[LON-CAPA-cvs] cvs: loncom(version_2_10_X) /lonnet/perl lonnet.pm

raeburn raeburn@source.lon-capa.org
Tue, 17 Aug 2010 00:19:24 -0000


This is a MIME encoded message

--raeburn1282004364
Content-Type: text/plain

raeburn		Tue Aug 17 00:19:24 2010 EDT

  Modified files:              (Branch: version_2_10_X)
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Backport 1.1071, 1.1072, 1.1073, 1.1074, 1.1076, 1.1077, 1.1078.
  
  
--raeburn1282004364
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20100817001924.txt"

Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1056.4.2 loncom/lonnet/perl/lonnet.pm:1.1056.4.3
--- loncom/lonnet/perl/lonnet.pm:1.1056.4.2	Wed May 26 17:14:43 2010
+++ loncom/lonnet/perl/lonnet.pm	Tue Aug 17 00:19:24 2010
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1056.4.2 2010/05/26 17:14:43 raeburn Exp $
+# $Id: lonnet.pm,v 1.1056.4.3 2010/08/17 00:19:24 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -76,7 +76,7 @@
 use Image::Magick;
 
 use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir
-            $_64bit %env %protocol);
+            $_64bit %env %protocol %loncaparevs %serverhomeIDs);
 
 my (%badServerCache, $memcache, %courselogs, %accesshash, %domainrolehash,
     %userrolehash, $processmarker, $dumpcount, %coursedombuf,
@@ -196,7 +196,7 @@
 }
 
 sub get_server_loncaparev {
-    my ($dom,$lonhost) = @_;
+    my ($dom,$lonhost,$ignore_cache,$caller) = @_;
     if (defined($lonhost)) {
         if (!defined(&hostname($lonhost))) {
             undef($lonhost);
@@ -211,15 +211,74 @@
         }
     }
     if (defined($lonhost)) {
-        my $cachetime = 24*3600;
-        my ($loncaparev,$cached)=&is_cached_new('serverloncaparev',$lonhost);
+        my $cachetime = 12*3600;
+        if (!$ignore_cache) {
+            my ($loncaparev,$cached)=&is_cached_new('serverloncaparev',$lonhost);
+            if (defined($cached)) {
+                return $loncaparev;
+            }
+        }
+        my ($answer,$loncaparev);
+        my @ids=&current_machine_ids();
+        if (grep(/^\Q$lonhost\E$/,@ids)) {
+            $answer = $perlvar{'lonVersion'};
+            if ($answer =~ /^[\'\"]?([\d.\-]+)[\'\"]?$/) {
+                $loncaparev = $1;
+            }
+        } else {
+            $answer = &reply('serverloncaparev',$lonhost);
+            if (($answer eq 'unknown_cmd') || ($answer eq 'con_lost')) {
+                if ($caller eq 'loncron') {
+                    my $ua=new LWP::UserAgent;
+                    $ua->timeout(20);
+                    my $protocol = $protocol{$lonhost};
+                    $protocol = 'http' if ($protocol ne 'https');
+                    my $url = $protocol.'://'.&hostname($lonhost).'/adm/about.html';
+                    my $request=new HTTP::Request('GET',$url);
+                    my $response=$ua->request($request);
+                    unless ($response->is_error()) {
+                        my $content = $response->content;
+                        if ($content =~ /<p>VERSION\:\s*([\d.\-]+)<\/p>/) {
+                            $loncaparev = $1;
+                        }
+                    }
+                } else {
+                    $loncaparev = $loncaparevs{$lonhost};
+                }
+            } elsif ($answer =~ /^[\'\"]?([\d.\-]+)[\'\"]?$/) {
+                $loncaparev = $1;
+            }
+        }
+        return &do_cache_new('serverloncaparev',$lonhost,$loncaparev,$cachetime);
+    }
+}
+
+sub get_server_homeID {
+    my ($hostname,$ignore_cache,$caller) = @_;
+    unless ($ignore_cache) {
+        my ($serverhomeID,$cached)=&is_cached_new('serverhomeID',$hostname);
         if (defined($cached)) {
-            return $loncaparev;
-        } else {
-            my $loncaparev = &reply('serverloncaparev',$lonhost);
-            return &do_cache_new('serverloncaparev',$lonhost,$loncaparev,$cachetime);
+            return $serverhomeID;
+        }
+    }
+    my $cachetime = 12*3600;
+    my $serverhomeID;
+    if ($caller eq 'loncron') {
+        my @machine_ids = &machine_ids($hostname);
+        foreach my $id (@machine_ids) {
+            my $response = &reply('serverhomeID',$id);
+            unless (($response eq 'unknown_cmd') || ($response eq 'con_lost')) {
+                $serverhomeID = $response;
+                last;
+            }
         }
+        if ($serverhomeID eq '') {
+            $serverhomeID = $machine_ids[-1];
+        }
+    } else {
+        $serverhomeID = $serverhomeIDs{$hostname};
     }
+    return &do_cache_new('serverhomeID',$hostname,$serverhomeID,$cachetime);
 }
 
 # -------------------------------------------------- Non-critical communication
@@ -734,7 +793,7 @@
     my $userloadans = &reply('userload',$try_server);
 
     if ($loadans !~ /\d/ && $userloadans !~ /\d/) {
-	next; #didn't get a number from the server
+        return; #didn't get a number from the server
     }
 
     my $load;
@@ -777,6 +836,27 @@
     return 0;
 }
 
+# --------- determine least loaded server in a user's domain which allows login
+
+sub choose_server {
+    my ($udom) = @_;
+    my %domconfhash = &Apache::loncommon::get_domainconf($udom);
+    my %servers = &get_servers($udom);
+    my $lowest_load = 30000;
+    my ($login_host,$hostname);
+    foreach my $lonhost (keys(%servers)) {
+        my $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost};
+        if ($loginvia eq '') {
+            ($login_host, $lowest_load) =
+            &compare_server_load($lonhost, $login_host, $lowest_load);
+        }
+    }
+    if ($login_host ne '') {
+        $hostname = $servers{$login_host};
+    }
+    return ($login_host,$hostname);
+}
+
 # --------------------------------------------- Try to change a user's password
 
 sub changepass {
@@ -835,7 +915,7 @@
 # --------- Try to authenticate user from domain's lib servers (first this one)
 
 sub authenticate {
-    my ($uname,$upass,$udom,$checkdefauth)=@_;
+    my ($uname,$upass,$udom,$checkdefauth,$clientcancheckhost)=@_;
     $upass=&escape($upass);
     $uname= &LONCAPA::clean_username($uname);
     my $uhome=&homeserver($uname,$udom,1);
@@ -858,7 +938,7 @@
 	    return 'no_host';
         }
     }
-    my $answer=reply("encrypt:auth:$udom:$uname:$upass:$checkdefauth",$uhome);
+    my $answer=reply("encrypt:auth:$udom:$uname:$upass:$checkdefauth:$clientcancheckhost",$uhome);
     if ($answer eq 'authorized') {
         if ($newhome) {
             &logthis("User $uname at $udom authorized by $uhome, but needs account");
@@ -876,6 +956,64 @@
     return 'no_host';
 }
 
+sub can_host_session {
+    my ($udom,$lonhost,$remoterev,$remotesessions,$hostedsessions) = @_;
+    my $canhost = 1;
+    my $host_idn = &Apache::lonnet::internet_dom($lonhost);
+    if (ref($remotesessions) eq 'HASH') {
+        if (ref($remotesessions->{'excludedomain'}) eq 'ARRAY') {
+            if (grep(/^\Q$host_idn\E$/,@{$remotesessions->{'excludedomain'}})) {
+                $canhost = 0;
+            } else {
+                $canhost = 1;
+            }
+        }
+        if (ref($remotesessions->{'includedomain'}) eq 'ARRAY') {
+            if (grep(/^\Q$host_idn\E$/,@{$remotesessions->{'includedomain'}})) {
+                $canhost = 1;
+            } else {
+                $canhost = 0;
+            }
+        }
+        if ($canhost) {
+            if ($remotesessions->{'version'} ne '') {
+                my ($reqmajor,$reqminor) = ($remotesessions->{'version'} =~ /^(\d+)\.(\d+)$/);
+                if ($reqmajor ne '' && $reqminor ne '') {
+                    if ($remoterev =~ /^\'?(\d+)\.(\d+)/) {
+                        my $major = $1;
+                        my $minor = $2;
+                        if (($major < $reqmajor ) ||
+                            (($major == $reqmajor) && ($minor < $reqminor))) {
+                            $canhost = 0;
+                        }
+                    } else {
+                        $canhost = 0;
+                    }
+                }
+            }
+        }
+    }
+    if ($canhost) {
+        if (ref($hostedsessions) eq 'HASH') {
+            if (ref($hostedsessions->{'excludedomain'}) eq 'ARRAY') {
+                if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'excludedomain'}})) {
+                    $canhost = 0;
+                } else {
+                    $canhost = 1;
+                }
+            }
+            if (ref($hostedsessions->{'includedomain'}) eq 'ARRAY') {
+                if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'includedomain'}})) {
+                    $canhost = 1;
+                } else {
+                    $canhost = 0;
+                }
+            }
+        }
+    }
+    return $canhost;
+}
+
 # ---------------------- Find the homebase for a user from domain's lib servers
 
 my %homecache;
@@ -1352,7 +1490,7 @@
     my %domconfig =
          &Apache::lonnet::get_dom('configuration',['defaults','quotas',
                                   'requestcourses','inststatus',
-                                  'coursedefaults'],$domain);
+                                  'coursedefaults','usersessions'],$domain);
     if (ref($domconfig{'defaults'}) eq 'HASH') {
         $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'}; 
         $domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};
@@ -1392,6 +1530,14 @@
             $domdefaults{$item} = $domconfig{'coursedefaults'}{$item};
         }
     }
+    if (ref($domconfig{'usersessions'}) eq 'HASH') {
+        if (ref($domconfig{'usersessions'}{'remote'}) eq 'HASH') {
+            $domdefaults{'remotesessions'} = $domconfig{'usersessions'}{'remote'};
+        }
+        if (ref($domconfig{'usersessions'}{'hosted'}) eq 'HASH') {
+            $domdefaults{'hostedsessions'} = $domconfig{'usersessions'}{'hosted'};
+        }
+    }
     &Apache::lonnet::do_cache_new('domdefaults',$domain,\%domdefaults,
                                   $cachetime);
     return %domdefaults;
@@ -3059,7 +3205,7 @@
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,
         $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,
         $selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,
-        $cloneonly,$createdbefore,$createdafter,$creationcontext)=@_;
+        $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner)=@_;
     my $as_hash = 1;
     my %returnhash;
     if (!$domfilter) { $domfilter=''; }
@@ -3081,7 +3227,8 @@
                          $showhidden.':'.$caller.':'.&escape($cloner).':'.
                          &escape($cc_clone).':'.$cloneonly.':'.
                          &escape($createdbefore).':'.&escape($createdafter).':'.
-                         &escape($creationcontext),$tryserver);
+                         &escape($creationcontext).':'.$domcloner,
+                         $tryserver);
                 my @pairs=split(/\&/,$rep);
                 foreach my $item (@pairs) {
                     my ($key,$value)=split(/\=/,$item,2);
@@ -3905,9 +4052,10 @@
     my ($domain,$username,$authhost)=@_;
     my $now=time;
     my %userroles = ('user.login.time' => $now);
-    my $rolesdump=reply("dump:$domain:$username:roles",$authhost);
+    my $extra = &freeze_escape({'clientcheckrole' => 1});
+    my $rolesdump=reply("dump:$domain:$username:roles:.::$extra",$authhost);
     if (($rolesdump eq 'con_lost') || ($rolesdump eq '') || 
-        ($rolesdump =~ /^error:/)) { 
+        ($rolesdump =~ /^error:/)) {
         return \%userroles;
     }
     my %allroles=();
@@ -9861,6 +10009,14 @@
 	my @uniq = grep(!$seen{$_}++, values(%hostdom));
 	return @uniq;
     }
+
+    sub internet_dom {
+        &load_hosts_tab() if (!$loaded);
+
+        my ($lonid) = @_;
+        return $internetdom{$lonid};
+    }
+
 }
 
 { 
@@ -9978,6 +10134,40 @@
         return undef;
     }
 
+    sub get_internet_names {
+        my ($lonid) = @_;
+        return if ($lonid eq '');
+        my ($idnref,$cached)=
+            &Apache::lonnet::is_cached_new('internetnames',$lonid);
+        if ($cached) {
+            return $idnref;
+        }
+        my $ip = &get_host_ip($lonid);
+        my @hosts = &get_hosts_from_ip($ip);
+        my %iphost = &get_iphost();
+        my (@idns,%seen);
+        foreach my $id (@hosts) {
+            my $dom = &host_domain($id);
+            my $prim_id = &domain($dom,'primary');
+            my $prim_ip = &get_host_ip($prim_id);
+            next if ($seen{$prim_ip});
+            if (ref($iphost{$prim_ip}) eq 'ARRAY') {
+                foreach my $id (@{$iphost{$prim_ip}}) {
+                    my $intdom = &internet_dom($id);
+                    unless (grep(/^\Q$intdom\E$/,@idns)) {
+                        push(@idns,$intdom);
+                    }
+                }
+            }
+            $seen{$prim_ip} = 1;
+        }
+        return &Apache::lonnet::do_cache_new('internetnames',$lonid,\@idns,12*60*60);
+    }
+
+}
+
+sub all_loncaparevs {
+    return qw(1.1 1.2 1.3 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10);
 }
 
 BEGIN {
@@ -10055,6 +10245,34 @@
     close($config);
 }
 
+# ---------------------------------------------------------- Read loncaparev table
+{
+    if (-e "$perlvar{'lonTabDir'}/loncaparevs.tab") {
+        if (open(my $config,"<$perlvar{'lonTabDir'}/loncaparevs.tab")) {
+            while (my $configline=<$config>) {
+                chomp($configline);
+                my ($hostid,$loncaparev)=split(/:/,$configline);
+                $loncaparevs{$hostid}=$loncaparev;
+            }
+            close($config);
+        }
+    }
+}
+
+# ---------------------------------------------------------- Read serverhostID table
+{
+    if (-e "$perlvar{'lonTabDir'}/serverhomeIDs.tab") {
+        if (open(my $config,"<$perlvar{'lonTabDir'}/serverhomeIDs.tab")) {
+            while (my $configline=<$config>) {
+                chomp($configline);
+                my ($name,$id)=split(/:/,$configline);
+                $serverhomeIDs{$name}=$id;
+            }
+            close($config);
+        }
+    }
+}
+
 # ------------- set up temporary directory
 {
     $tmpdir = $perlvar{'lonDaemons'}.'/tmp/';
@@ -10285,9 +10503,14 @@
 
 =item *
 X<authenticate()>
-B<authenticate($uname,$upass,$udom)>: try to
+B<authenticate($uname,$upass,$udom,$checkdefauth,$clientcancheckhost)>: try to
 authenticate user from domain's lib servers (first use the current
 one). C<$upass> should be the users password.
+$checkdefauth is optional (value is 1 if a check should be made to
+   authenticate user using default authentication method, and allow
+   account creation if username does not have account in the domain).
+$clientcancheckhost is optional (value is 1 if checking whether the
+   server can host will occur on the client side in lonauth.pm).
 
 =item *
 X<homeserver()>

--raeburn1282004364--