[LON-CAPA-cvs] cvs: loncom /auth migrateuser.pm switchserver.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Wed Nov 28 00:05:37 EST 2018


raeburn		Wed Nov 28 05:05:37 2018 EDT

  Modified files:              
    /loncom/auth	migrateuser.pm switchserver.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Bug 6876
    If node switched to from balancer can't connect to lond on user's 
    homeserver, then session is switched to another node in the original list
    of usable nodes sent by the balancer. 
  
  
-------------- next part --------------
Index: loncom/auth/migrateuser.pm
diff -u loncom/auth/migrateuser.pm:1.35 loncom/auth/migrateuser.pm:1.36
--- loncom/auth/migrateuser.pm:1.35	Sat Nov 24 16:19:04 2018
+++ loncom/auth/migrateuser.pm	Wed Nov 28 05:05:30 2018
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Starts a user off based of an existing token.
 #
-# $Id: migrateuser.pm,v 1.35 2018/11/24 16:19:04 raeburn Exp $
+# $Id: migrateuser.pm,v 1.36 2018/11/28 05:05:30 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -301,6 +301,7 @@
         %user_info=('ip'       => $ENV{'REMOTE_ADDR'},
                     'domain'   => $data->{'domain'},
                     'username' => $data->{'username'},
+                    'home'     => $data->{'home'},
                     'role'     => $data->{'role'},
                     'origurl'  => $data->{'origurl'},
                     'symb'     => $data->{'symb'},
@@ -319,6 +320,98 @@
     return;
 }
 
+sub conlost_userhome {
+    my ($r,$idsref,$dataref) = @_;
+    return unless ((ref($idsref) eq 'ARRAY') && (ref($dataref) eq 'HASH'));
+    my @ids = @{$idsref};
+    my %data = %{$dataref};
+    my (%conlost,%posstargets);
+    my $lonhost = $r->dir_config('lonHostID');
+    $conlost{$lonhost} = 1;
+    if ($data{'conlost'} ne '') {
+        map { $conlost{$_} = 1; } split(/,/,$data{'conlost'});
+    }
+    my ($lowest_load,$otherserver);
+    $lowest_load = 30000;
+    if ($data{'offloadto'} =~ /\&/) {
+        my @items = split(/\&/,$data{'offloadto'});
+        foreach my $item (@items) {
+            my ($type,$targets) = split(/\=/,$item);
+            @{$posstargets{$type}} = split(/,/,$targets);
+        }
+    } elsif ($data{'offloadto'} =~ /=/) {
+        my ($type,$targets) = split(/\=/,$data{'offloadto'});
+        @{$posstargets{$type}} = split(/,/,$targets);
+    } else {
+        @{$posstargets{'default'}} = split(/,/,$data{'offloadto'});
+    }
+    if (ref($posstargets{'primary'}) eq 'ARRAY') {
+        foreach my $try_server (@{$posstargets{'primary'}}) {
+            next if (grep(/^\Q$try_server\E$/, at ids));
+            next if ($conlost{$try_server});
+            ($otherserver,$lowest_load) =
+                &Apache::lonnet::compare_server_load($try_server,
+                                                     $otherserver,
+                                                     $lowest_load);
+        }
+    }
+    my $found_server = ($otherserver ne '' && $lowest_load < 100);
+    if (!$found_server) {
+        if (ref($posstargets{'default'}) eq 'ARRAY') {
+            foreach my $try_server (@{$posstargets{'default'}}) {
+                ($otherserver,$lowest_load) =
+                &Apache::lonnet::compare_server_load($try_server,
+                                                     $otherserver,
+                                                     $lowest_load);
+            }
+        }
+    }
+    if ($otherserver ne '') {
+        my $switchto = &Apache::lonnet::hostname($otherserver);
+        if ($switchto ne '') {
+            my $protocol = $Apache::lonnet::protocol{$switchto};
+            $protocol = 'http' if ($protocol ne 'https');
+            my $url = $protocol.'://'.$switchto.'/adm/login?'.
+                                    'domain='.$env{'user.domain'}.
+                                    '&username='.$env{'user.name'};
+            $data{'conlost'} = join(',',sort(keys(%conlost)));
+            $data{'server'} = $lonhost;
+            if (grep(/^\Q$otherserver\E$/,split(/,/,$data{'dom_balancers'}))) {
+                $data{'noloadbalance'} = $otherserver; 
+            }
+            my $token = &Apache::lonnet::tmpput(\%data,$otherserver);
+            $url .= '&token='.$token;
+            $r->send_http_header;
+            $r->print(
+                &Apache::loncommon::start_page('Switching Server ...',undef,
+                                               {'redirect'       => [0.1,$url]}).
+                                                &Apache::loncommon::end_page());
+            return $otherserver;
+        }
+    }
+}
+
+sub log_switch {
+    my ($r,$data,$lti_env) = @_;
+    my $lonhost = $r->dir_config('lonHostID');
+    return unless ((ref($data) eq 'HASH') && (ref($lti_env) eq 'HASH'));
+    my $now = time;
+    my %temp=('switchserver' => $now.':'.$lonhost,$data->{'role'});
+    &Apache::lonnet::put('email_status',\%temp);
+    my $logmsg = "Switch Server to $lonhost";
+    if ($data->{'role'}) {
+        $logmsg .= " with role: ".$data->{'role'};
+    } elsif (($lti_env->{'reqcrs'}) && ($lti_env->{'reqrole'} eq 'cc')) {
+        $logmsg .= " to create new LTI course";
+    } elsif ($lti_env->{'selfenrollrole'}) {
+        $logmsg .= " to selfenroll with role: ".$lti_env->{'selfenrollrole'};
+    } else {
+        $logmsg .= " (no role)";
+    }
+    $logmsg .= ' '.$ENV{'REMOTE_ADDR'};
+    &Apache::lonnet::log($data->{'domain'},$data->{'username'},$data->{'home'},$logmsg);
+}
+
 sub flush_course_logs {
     &Apache::lonnet::flushcourselogs();
     return OK;
@@ -349,13 +442,41 @@
 	return &ip_changed($r,$data{'domain'},$data{'server'},\%data);
     }
 
-    &Apache::lonnet::logthis("Allowing access for $data{'username'}:$data{'domain'} to $data{'role'}");
     my $home=&Apache::lonnet::homeserver($data{'username'},$data{'domain'});
+    if ($home eq 'no_host') {
+        if (($data{'home'} ne '') && (&Apache::lonnet::hostname($data{'home'}))) {
+            &Apache::lonnet::reconlonc($data{'home'});
+            $home=&Apache::lonnet::homeserver($data{'username'},$data{'domain'});
+            if ($home eq 'no_host') {
+                my @ids=&Apache::lonnet::current_machine_ids();
+                unless (grep(/^\Q$data{'home'}\E$/, at ids)) {
+                    if (&Apache::lonnet::reply('ping',$data{'home'}) eq 'con_lost') {
+                        my $otherserver = &conlost_userhome($r,\@ids,\%data);
+                        if ($otherserver ne '') {
+                            &Apache::lonnet::logthis("No connection to home server ($data{'home'}) for $data{'username'}:$data{'domain'}. Switching to $otherserver");
+                            return OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     my $udom;
     if (&Apache::lonnet::domain($data{'domain'})) {
         $udom=$data{'domain'};
     }
-    if ($home =~ /(con_lost|no_such_host)/) { return &goto_login($r,$udom,\%data); }
+    if ($home eq 'no_host') { return &goto_login($r,$udom,\%data); }
+    if (&Apache::lonnet::hostname($home) eq '') { return &goto_login($r,$udom,\%data); } 
+
+    my $rolemsg;
+    if ($data{'role'}) {
+        $rolemsg = "role: $data{'role'}"; 
+    } else {
+        $rolemsg = '(no role)';
+    }
+
+    &Apache::lonnet::logthis("Allowing access for $data{'username'}:$data{'domain'} $rolemsg");
 
     my $sso_env = &sso_check(\%data);
     my $lti_env = &lti_check(\%data);
@@ -378,6 +499,16 @@
         $form{'noloadbalance'} = $data{'noloadbalance'};
     }
 
+    if (($data{'conlost'}) && ($data{'server'})) {
+        my @conlosts = split(/,/,$data{'conlost'});
+        my $switchfrom = $data{'server'};
+        if (@conlosts) {
+            if (grep(/^\Q$switchfrom\E$/, at conlosts)) {
+                &log_switch($r,\%data,$extra_env);
+            }
+        }
+    }
+
     if (!$data{'role'}) {
 	my $handle = &Apache::lonnet::check_for_valid_session($r);
 	if ($handle) {
Index: loncom/auth/switchserver.pm
diff -u loncom/auth/switchserver.pm:1.42 loncom/auth/switchserver.pm:1.43
--- loncom/auth/switchserver.pm:1.42	Sat Nov 24 16:19:04 2018
+++ loncom/auth/switchserver.pm	Wed Nov 28 05:05:30 2018
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Switch Servers Handler
 #
-# $Id: switchserver.pm,v 1.42 2018/11/24 16:19:04 raeburn Exp $
+# $Id: switchserver.pm,v 1.43 2018/11/28 05:05:30 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -215,7 +215,7 @@
 # ---------------------------------------------------------------- Get handover
 
     my $newcookieid;
-    (my $is_balancer,undef,my $setcookie) =
+    my ($is_balancer,$posshost,$setcookie,$offloadto,$dom_balancers) =
         &Apache::lonnet::check_loadbalancing($env{'user.name'},$env{'user.domain'});
     if ($is_balancer && $setcookie && $env{'form.otherserver'}) {
 
@@ -241,12 +241,25 @@
         }
     }
 
-    my %info=('ip'       => $ENV{'REMOTE_ADDR'},
-	      'domain'   => $env{'user.domain'},
-	      'username' => $env{'user.name'},
-	      'role'     => $env{'form.role'},
-	      'server'   => $r->dir_config('lonHostID'),
-	      'balancer' => $is_balancer);
+    my %info=('ip'            => $ENV{'REMOTE_ADDR'},
+              'domain'        => $env{'user.domain'},
+              'username'      => $env{'user.name'},
+              'home'          => $env{'user.home'},
+              'role'          => $env{'form.role'},
+              'server'        => $r->dir_config('lonHostID'),
+              'balancer'      => $is_balancer,
+              'dom_balancers' => $dom_balancers,
+              'offloadto'     => '');
+    if (ref($offloadto) eq 'HASH') {
+        foreach my $key (keys(%{$offloadto})) {
+            if (ref($offloadto->{$key}) eq 'ARRAY') {
+                $info{'offloadto'} .= $key.'='.join(',',@{$offloadto->{$key}}).'&';
+            }
+        }
+        $info{'offloadto'} =~ s/\&$//;
+    } elsif (ref($offloadto) eq 'ARRAY') {
+        $info{'offloadto'} = join(',',@{$offloadto});
+    }
     if ($newcookieid) {
         $info{'balcookie'} = $newcookieid;
     }
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1390 loncom/lonnet/perl/lonnet.pm:1.1391
--- loncom/lonnet/perl/lonnet.pm:1.1390	Sun Nov 25 02:27:04 2018
+++ loncom/lonnet/perl/lonnet.pm	Wed Nov 28 05:05:36 2018
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1390 2018/11/25 02:27:04 raeburn Exp $
+# $Id: lonnet.pm,v 1.1391 2018/11/28 05:05:36 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1435,7 +1435,7 @@
 sub check_loadbalancing {
     my ($uname,$udom,$caller) = @_;
     my ($is_balancer,$currtargets,$currrules,$dom_in_use,$homeintdom,
-        $rule_in_effect,$offloadto,$otherserver,$setcookie);
+        $rule_in_effect,$offloadto,$otherserver,$setcookie,$dom_balancers);
     my $lonhost = $perlvar{'lonHostID'};
     my @hosts = &current_machine_ids();
     my $uprimary_id = &Apache::lonnet::domain($udom,'primary');
@@ -1462,7 +1462,7 @@
         }
     }
     if (ref($result) eq 'HASH') {
-        ($is_balancer,$currtargets,$currrules,$setcookie) =
+        ($is_balancer,$currtargets,$currrules,$setcookie,$dom_balancers) =
             &check_balancer_result($result, at hosts);
         if ($is_balancer) {
             if (ref($currrules) eq 'HASH') {
@@ -1523,7 +1523,7 @@
             }
         }
         if (ref($result) eq 'HASH') {
-            ($is_balancer,$currtargets,$currrules,$setcookie) =
+            ($is_balancer,$currtargets,$currrules,$setcookie,$dom_balancers) =
                 &check_balancer_result($result, at hosts);
             if ($is_balancer) {
                 if (ref($currrules) eq 'HASH') {
@@ -1599,12 +1599,12 @@
             undef($setcookie);
         }
     }
-    return ($is_balancer,$otherserver,$setcookie);
+    return ($is_balancer,$otherserver,$setcookie,$offloadto,$dom_balancers);
 }
 
 sub check_balancer_result {
     my ($result, at hosts) = @_;
-    my ($is_balancer,$currtargets,$currrules,$setcookie);
+    my ($is_balancer,$currtargets,$currrules,$setcookie,$dom_balancers);
     if (ref($result) eq 'HASH') {
         if ($result->{'lonhost'} ne '') {
             my $currbalancer = $result->{'lonhost'};
@@ -1612,21 +1612,26 @@
                 $is_balancer = 1;
                 $currtargets = $result->{'targets'};
                 $currrules = $result->{'rules'};
+                $dom_balancers = $currbalancer;
             }
+            $dom_balancers = $currbalancer;
         } else {
-            foreach my $key (keys(%{$result})) {
-                if (($key ne '') && (grep(/^\Q$key\E$/, at hosts)) &&
-                    (ref($result->{$key}) eq 'HASH')) {
-                    $is_balancer = 1;
-                    $currrules = $result->{$key}{'rules'};
-                    $currtargets = $result->{$key}{'targets'};
-                    $setcookie = $result->{$key}{'cookie'};
-                    last;
+            if (keys(%{$result})) {
+                foreach my $key (keys(%{$result})) {
+                    if (($key ne '') && (grep(/^\Q$key\E$/, at hosts)) &&
+                        (ref($result->{$key}) eq 'HASH')) {
+                        $is_balancer = 1;
+                        $currrules = $result->{$key}{'rules'};
+                        $currtargets = $result->{$key}{'targets'};
+                        $setcookie = $result->{$key}{'cookie'};
+                        last;
+                    }
                 }
+                $dom_balancers = join(',',sort(keys(%{$result})));
             }
         }
     }
-    return ($is_balancer,$currtargets,$currrules,$setcookie);
+    return ($is_balancer,$currtargets,$currrules,$setcookie,$dom_balancers);
 }
 
 sub get_loadbalancer_targets {


More information about the LON-CAPA-cvs mailing list