#!/usr/bin/perl # # The LearningOnline Network # # When an access node is being taken offline either permanently # or for a long period of time, it would be friendly to domains # which have library nodes from which resources have been replicated # to unsubscribe from the resources, to avoid accumulation of # delayed "update" transactions in lonnet.perm.log on the library # nodes which are the home servers for the authors of the replicated # resources, in the event that the author publishes updated version(s). # # $Id: unsubresources.pl,v 1.1 2020/05/13 01:49:55 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # ################################################# use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; use LONCAPA qw(:DEFAULT :match); use Apache::lonlocal; use Apache::lonnet; my ($londocroot,$londaemons); BEGIN { my $perlvar=&LONCAPA::Configuration::read_conf(); if (ref($perlvar) eq 'HASH') { $londocroot = $perlvar->{'lonDocRoot'}; $londaemons = $perlvar->{'lonDaemons'}; } undef($perlvar); } my $lang = &Apache::lonlocal::choose_language(); &Apache::lonlocal::get_language_handle(undef,$lang); my $parameter=$ARGV[0]; $parameter =~ s/^\s+//; $parameter =~ s/\s+$//; if ((@ARGV > 1) || (($parameter ne '') && ($parameter ne 'execute'))) { print &mt('usage: [_1]','unsubresources.pl [dryrun|execute]')."\n\n". &mt('You should enter either no arguments, or just one argument: execute.')."\n". &mt("execute - to unlink resources in [_1], and send unsub request to homeserver of resource author", "$londocroot/res/'")."\n". &mt('no argument to do a dry run, without actually unlinking or unsubscribing anything.')."\n"; exit; } my $wwwid=getpwnam('www'); if ($wwwid!=$<) { print &mt('This must be run as user www in order to unsubscribe previously subscribed resources.')."\n". &mt('Stopping')."\n"; exit; } if ($londocroot eq '') { print &mt('Could not determine location of [_1] directory.',"'lonDocRoot'")."\n". &mt('Stopping')."\n"; exit; } if ($londaemons eq '') { print &mt('Could not determine location of [_1] directory.',"'lonDaemons'")."\n". &mt('Stopping')."\n"; exit; } # Get machine IDs my @ids=&Apache::lonnet::current_machine_ids(); print "\n".&mt("Unlinking and unsubscribing resources in $londocroot/res/")."\n". &mt('No changes will occur for resources for which this server is the homeserver of the author of the resource.')."\n". "-----------------------------\n\n". &mt('If run without an argument, the script will report what it would do when unlinking and unsubscribing resources in [_1].', "'$londocroot/res/'")."\n\n"; my ($action) = ($parameter=~/^(execute)$/); if ($action eq '') { $action = 'dryrun'; } if ($action eq 'dryrun') { print "\n". &mt('Running in exploratory mode ...')."\n\n". &mt('Run with argument [_1] to actually unlink and unsubscribe resources in [_2], i.e., [_3]', "'execute'","'$londocroot/res/'","\n\nperl unsubresources.pl execute")."\n\n\n". &mt('Continue? ~[y/N~] '); if (!&get_user_selection()) { exit; } else { print "\n"; } } else { print "\n *** ".&mt('Running in a mode where changes will be made.')." ***\n"; print "\n". &mt('Mode is [_1] -- replicated resources in [_2] will be unlinked and unsubscribed.', "'$action'","'$londocroot/res/'")."\n"; print &mt('Continue? ~[y/N~] '); if (!&get_user_selection()) { exit; } else { print "\n"; } } my $dir = "$londocroot/res"; my %alreadyseen; my $logfh; unless ($action eq 'dryrun') { if (!open($logfh,'>>',"$londaemons/logs/unsubresources.log")) { print &mt('Could not open log file: [_1] for writing.', "'$londaemons/logs/unsubresources.log'")."\n". &mt('Stopping.')."\n"; exit; } else { &start_logging($logfh,$action); } } &check_directory($action,$dir,$logfh,\@ids,\%alreadyseen); unless ($action eq 'dryrun') { &stop_logging($logfh); } print "\n".&mt('Done')."\n"; exit; sub check_directory { my ($action,$dir,$fh,$idsref,$seenref,$currhome) = @_; my $msg; if (opendir(my $dirh,$dir)) { while (my $item=readdir($dirh)) { next if ($item =~ /^\./); if (-d "$dir/$item") { if ($dir eq "$londocroot/res") { next if (($item eq 'adm') || ($item eq 'lib') || ($item eq 'res')); if (&Apache::lonnet::domain($item) ne '') { my %servers = &Apache::lonnet::get_unique_servers($item); my @libservers; foreach my $server (keys(%servers)) { if (&Apache::lonnet::is_library($server)) { push(@libservers,$server); } } if (@libservers == 1) { if ((ref($idsref) eq 'ARRAY') && (grep(/^\Q$libservers[0]\E$/,@{$idsref}))) { $msg = &mt('Skipping directory for [_1] as [_2] is the single library node for the domain', $item,$libservers[0])."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } next; } } &check_directory($action,"$dir/$item",$fh,$idsref,$seenref); } else { $msg = &mt('Domain [_1] in [_2] is unavailable', $item,$dir)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } next; } } elsif ($dir =~ m{^\Q$londocroot/res\E/($match_domain)$}) { my $udom = $1; if ($item =~ /^($match_username)$/) { my $uname = $1; $currhome = &Apache::lonnet::homeserver($uname,$udom,1); if ($currhome eq 'no_host') { $msg = &mt('No homeserver for user: [_1] domain: [_2]', $uname,$udom)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } } elsif ((ref($idsref) eq 'ARRAY') && (grep(/^\Q$currhome\E$/,@{$idsref}))) { $msg = &mt("Skipping user: [_1] in domain: [_2] as this is the user's homeserver.", $uname,$udom)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } } else { &check_directory($action,"$dir/$item",$fh,$idsref,$seenref,$currhome); } } else { $msg = &mt('Username: [_1] in domain: [_2] is invalid', $item,$udom)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } } } else { &check_directory($action,"$dir/$item",$fh,$idsref,$seenref,$currhome); } } elsif (-f "$dir/$item") { if ($dir =~ m{^\Q$londocroot/res\E/$match_domain/$match_username}) { next if ($seenref->{"$dir/$item"}); if ($action eq 'execute') { if (unlink("$dir/$item")) { if ($item =~ /\.meta$/) { my $nonmeta = $item; $nonmeta =~ s/\.meta$//; next if ((-e "$dir/$nonmeta") || ($seenref->{"$dir/$nonmeta"})); } elsif (-e "$dir/$item.meta") { unlink("$dir/$item.meta"); } if ($currhome ne '') { my $result = &Apache::lonnet::reply("unsub:$dir/$item",$currhome); if ($result eq 'ok') { print $fh &mt('Unsub complete for [_1] at [_2]', "$dir/$item",$currhome)."\n"; } else { print $fh &mt('Result of unsub for [_1] at [_2] was: [_3]', "$dir/$item",$currhome,$result)."\n"; } } $seenref->{"$dir/$item"} = 1; } else { print $fh &mt('Failed to unlink [_1]',"$dir/$item")."\n"; } } else { if ($item =~ /\.meta$/) { my $nonmeta = $item; $nonmeta =~ s/\.meta$//; next if (-e "$dir/$nonmeta"); print &mt('Would unlink [_1] and send unsub to [_2]', "$dir/$item",$currhome)."\n"; } elsif (-e "$dir/$item.meta") { print &mt('Would unlink [_1] and [_2], and send unsub to [_3]', "$dir/$item","$dir/$item.meta",$currhome)."\n"; $seenref->{"$dir/$item.meta"} = 1; } else { print &mt('Would unlink [_1] and send unsub to [_2]', "$dir/$item",$currhome)."\n"; } $seenref->{"$dir/$item"} = 1; } } else { $msg = &mt('Invalid directory [_1]',$dir)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } } } } closedir($dirh); } else { $msg = &mt('Could not open directory: [_1]',$dir)."\n"; if ($action eq 'execute') { print $fh $msg; } else { print $msg; } } return; } sub get_user_selection { my ($defaultrun) = @_; my $do_action = 0; my $choice = ; chomp($choice); $choice =~ s/(^\s+|\s+$)//g; my $yes = &mt('y'); if ($defaultrun) { if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) { $do_action = 1; } } else { if ($choice =~ /^\Q$yes\E/i) { $do_action = 1; } } return $do_action; } sub start_logging { my ($fh,$action) = @_; my $start = localtime(time); print $fh "*****************************************************\n". &mt('[_1] - mode is [_2].', 'unsubresources.pl',"'$action'")."\n". &mt('Started -- time: [_1]',$start)."\n". "*****************************************************\n\n"; return; } sub stop_logging { my ($fh) = @_; my $end = localtime(time); print $fh "*****************************************************\n". &mt('Ended -- time: [_1]',$end)."\n". "*****************************************************\n\n\n"; close($fh); return; }