[LON-CAPA-cvs] cvs: loncom /auth migrateuser.pm
raeburn
raeburn at source.lon-capa.org
Sun Dec 2 09:41:19 EST 2018
raeburn Sun Dec 2 14:41:19 2018 EDT
Modified files:
/loncom/auth migrateuser.pm
Log:
- Bug 6876 In case of connection failures between lonc on offload node(s)
and other node(s) try switching to other offload nodes and balancer(s).
-------------- next part --------------
Index: loncom/auth/migrateuser.pm
diff -u loncom/auth/migrateuser.pm:1.36 loncom/auth/migrateuser.pm:1.37
--- loncom/auth/migrateuser.pm:1.36 Wed Nov 28 05:05:30 2018
+++ loncom/auth/migrateuser.pm Sun Dec 2 14:41:19 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Starts a user off based of an existing token.
#
-# $Id: migrateuser.pm,v 1.36 2018/11/28 05:05:30 raeburn Exp $
+# $Id: migrateuser.pm,v 1.37 2018/12/02 14:41:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,9 +33,11 @@
use Apache::Constants qw(:common :http :methods);
use Apache::lonauth;
use Apache::lonnet;
+use Apache::loncommon;
use Apache::lonlocal;
use Apache::lonlogin();
use Apache::ltiauth;
+use Apache::switchserver;
use CGI::Cookie;
sub goto_login {
@@ -118,7 +120,7 @@
}
sub ip_changed {
- my ($r,$udom,$camefrom,$dataref) = @_;
+ my ($r,$udom,$camefrom,$idsref,$dataref) = @_;
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
if (ref($dataref) eq 'HASH') {
@@ -167,8 +169,10 @@
my $lonhost= $r->dir_config('lonHostID');
my $switchto = $lonhost;
if ($rule_in_effect ne 'offloadedto') {
- my $hosthere;
- my @ids=&Apache::lonnet::current_machine_ids();
+ my ($hosthere, at ids);
+ if (ref($idsref) eq 'ARRAY') {
+ @ids=@{$idsref};
+ }
unless ($rule_in_effect eq 'balancer') {
if (grep(/^\Q$rule_in_effect\E$/, at ids)) {
$hosthere = 1;
@@ -325,17 +329,41 @@
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;
+ my ($lonhost,$lowest_load,$otherserver,$is_balancer,%conlost,%posstargets);
+ $lonhost = $r->dir_config('lonHostID');
+ if (grep(/^\Q$lonhost\E$/,split(/,/,$data{'dom_balancers'}))) {
+ $is_balancer = 1;
+ }
+ $lowest_load = 30000;
if ($data{'conlost'} ne '') {
map { $conlost{$_} = 1; } split(/,/,$data{'conlost'});
}
- my ($lowest_load,$otherserver);
- $lowest_load = 30000;
+ if ($data{'loncfail'}) {
+ if ($is_balancer) {
+ if ($lonhost ne $data{'from_balancer'}) {
+ my ($is_balancer,$posshost,$setcookie,$offloadto,$dom_balancers) =
+ &Apache::lonnet::check_loadbalancing($data{'username'},$data{'domain'});
+ if ($is_balancer) {
+ if (ref($offloadto) eq 'HASH') {
+ $data{'offloadto'} = '';
+ foreach my $key (keys(%{$offloadto})) {
+ if (ref($offloadto->{$key}) eq 'ARRAY') {
+ $data{'offloadto'} .= $key.'='.join(',',@{$offloadto->{$key}}).'&';
+ }
+ }
+ $data{'offloadto'} =~ s/\&$//;
+ } elsif (ref($offloadto) eq 'ARRAY') {
+ $data{'offloadto'} = join(',',@{$offloadto});
+ }
+ }
+ }
+ }
+ } else {
+ $conlost{$lonhost} = 1;
+ $data{'conlost'} = join(',',sort(keys(%conlost)));
+ }
if ($data{'offloadto'} =~ /\&/) {
- my @items = split(/\&/,$data{'offloadto'});
- foreach my $item (@items) {
+ foreach my $item (split(/\&/,$data{'offloadto'})) {
my ($type,$targets) = split(/\=/,$item);
@{$posstargets{$type}} = split(/,/,$targets);
}
@@ -347,8 +375,8 @@
}
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});
+ next if ((grep(/^\Q$try_server\E$/, at ids)) && !$data{'loncfail'});
($otherserver,$lowest_load) =
&Apache::lonnet::compare_server_load($try_server,
$otherserver,
@@ -359,36 +387,109 @@
if (!$found_server) {
if (ref($posstargets{'default'}) eq 'ARRAY') {
foreach my $try_server (@{$posstargets{'default'}}) {
+ next if ($conlost{$try_server});
+ next if ((grep(/^\Q$try_server\E$/, at ids)) && !$data{'loncfail'});
($otherserver,$lowest_load) =
- &Apache::lonnet::compare_server_load($try_server,
- $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 ($data{'loncfail'}) {
+ delete($data{'loncfail'});
+ }
if (grep(/^\Q$otherserver\E$/,split(/,/,$data{'dom_balancers'}))) {
- $data{'noloadbalance'} = $otherserver;
+ $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());
+ &do_server_switch($r,$otherserver,$switchto,$is_balancer,\%data);
return $otherserver;
+ } else {
+ #FIXME Contents of $data{offloadto} contains invalid hostID.
+ }
+ } else {
+ my (%poss_balancers,%tried_balancers);
+ map { $poss_balancers{$_} = 1; } split(/,/,$data{'dom_balancers'});
+ map { $tried_balancers{$_} = 1; } split(/,/,$data{'tried_balancers'});
+ if (keys(%poss_balancers)) {
+ foreach my $try_server (sort(keys(%poss_balancers))) {
+ next if (grep(/^\Q$try_server\E$/, at ids));
+ next if (($data{'loncfail'}) && ($tried_balancers{$try_server}));
+ my $alreadytried;
+ foreach my $key (keys(%posstargets)) {
+ if ((ref($posstargets{$key}) eq 'ARRAY') &&
+ (grep(/^\Q$try_server\E$/,@{$posstargets{$key}}))) {
+ $alreadytried = 1;
+ last;
+ }
+ }
+ unless ($alreadytried) {
+ if (&Apache::lonnet::reply('ping',$try_server) eq $try_server) {
+ $otherserver = $try_server;
+ last;
+ }
+ }
+ }
+ }
+ if ($otherserver ne '') {
+ my $switchto = &Apache::lonnet::hostname($otherserver);
+ if ($switchto ne '') {
+ $data{'server'} = $lonhost;
+ $data{'loncfail'} = $lonhost;
+ $tried_balancers{$otherserver} = 1;
+ $data{'tried_balancers'} = join(',',sort(keys(%tried_balancers)));
+ &do_server_switch($r,$otherserver,$switchto,$is_balancer,\%data);
+ return $otherserver;
+ } else {
+ #FIXME Contents of $data{'dom_balancers'} contains invalid hostID.
+ }
+ } else {
+ if ($data{'loncfail'}) {
+ #FIXME Nowhere to go.
+ } else {
+ # FIXME Send back to a balancer (no token); different balancer if this is a balancer.
+ # Send command to balancer to exclude this host using http instead on lonc/lond
+ }
}
}
+ return;
+}
+
+sub do_server_switch {
+ my ($r,$otherserver,$switchto,$is_balancer,$dataref) = @_;
+ if (ref($dataref) eq 'HASH') {
+ my $domain = $dataref->{'domain'};
+ my $username = $dataref->{'username'};
+ # If this is a balancer set a balancer cookie unless browser already sent
+ # LON-CAPA load balancer cookie which points at the target server.
+ if ($is_balancer) {
+ my $newcookieid;
+ my ($found_server,$balancer_cookie) = &Apache::lonnet::check_for_balancer_cookie($r,1);
+ unless (($found_server eq $otherserver) &&
+ ($balancer_cookie =~ /^\Q$domain\E_\Q$username\E_/)) {
+ $newcookieid =
+ &Apache::switchserver::balancer_cookieid($r,$otherserver,$username,$domain);
+ if ($newcookieid) {
+ $dataref->{'balcookie'} = $newcookieid;
+ }
+ }
+ }
+ my $token = &Apache::lonnet::tmpput($dataref,$otherserver);
+ my $protocol = $Apache::lonnet::protocol{$otherserver};
+ $protocol = 'http' if ($protocol ne 'https');
+ my $url = $protocol.'://'.$switchto.'/adm/login?domain='.$domain.
+ '&username='.$username.'&token='.$token;
+ $r->send_http_header;
+ $r->print(
+ &Apache::loncommon::start_page('Switching Server ...',undef,
+ {'redirect' => [0.1,$url]}).
+ &Apache::loncommon::end_page());
+ }
+ return;
}
sub log_switch {
@@ -436,24 +537,33 @@
if (!defined($data{'username'}) || !defined($data{'domain'})) {
return &goto_login($r,undef,\%data);
}
+ my ($home, at ids);
+ @ids=&Apache::lonnet::current_machine_ids();
if ($data{'ip'} ne $ENV{'REMOTE_ADDR'}) {
&Apache::lonnet::logthis('IP change when session migration requested -- was: '.
$data{'ip'}.'; now: '.$ENV{'REMOTE_ADDR'}.' for '.$data{'username'}.':'.$data{'domain'});
- return &ip_changed($r,$data{'domain'},$data{'server'},\%data);
+ return &ip_changed($r,$data{'domain'},$data{'server'},\@ids,\%data);
}
-
- 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");
+ if ($data{'loncfail'}) {
+ &Apache::lonnet::logthis('Returned from '.$data{'server'}.' -- no connection to library node or other access node(s)');
+ my $otherserver = &conlost_userhome($r,\@ids,\%data);
+ if ($otherserver ne '') {
+ &Apache::lonnet::logthis("Switching to $otherserver");
+ }
+ return OK;
+ } else {
+ $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') {
+ 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;
}
}
@@ -488,6 +598,16 @@
$extra_env = $lti_env;
}
+ 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);
+ }
+ }
+ }
+
my %form;
if ($data{'symb'} ne '') {
$form{'symb'} = $data{'symb'};
@@ -499,16 +619,6 @@
$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) {
More information about the LON-CAPA-cvs
mailing list