File:  [LON-CAPA] / loncom / debugging_tools / unsubresources.pl
Revision 1.1: download - view: text, annotated - select for diffs
Wed May 13 01:49:55 2020 UTC (4 years ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- Script to remove replicated resources in /res/ directory and send unsub
  request to homeserver of resource author. For use when removing surplus
  access nodes in a domain.

    1: #!/usr/bin/perl
    2: #
    3: # The LearningOnline Network
    4: #
    5: # When an access node is being taken offline either permanently
    6: # or for a long period of time, it would be friendly to domains
    7: # which have library nodes from which resources have been replicated
    8: # to unsubscribe from the resources, to avoid accumulation of
    9: # delayed "update" transactions in lonnet.perm.log on the library
   10: # nodes which are the home servers for the authors of the replicated
   11: # resources, in the event that the author publishes updated version(s).
   12: #
   13: # $Id: unsubresources.pl,v 1.1 2020/05/13 01:49:55 raeburn Exp $
   14: #
   15: # Copyright Michigan State University Board of Trustees
   16: #
   17: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   18: #
   19: # LON-CAPA is free software; you can redistribute it and/or modify
   20: # it under the terms of the GNU General Public License as published by
   21: # the Free Software Foundation; either version 2 of the License, or
   22: # (at your option) any later version.
   23: #
   24: # LON-CAPA is distributed in the hope that it will be useful,
   25: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   26: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27: # GNU General Public License for more details.
   28: #
   29: # You should have received a copy of the GNU General Public License
   30: # along with LON-CAPA; if not, write to the Free Software
   31: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   32: #
   33: # /home/httpd/html/adm/gpl.txt
   34: #
   35: # http://www.lon-capa.org/
   36: #
   37: #################################################
   38: 
   39: use strict;
   40: use lib '/home/httpd/lib/perl/';
   41: use LONCAPA::Configuration;
   42: use LONCAPA qw(:DEFAULT :match);
   43: use Apache::lonlocal;
   44: use Apache::lonnet;
   45: 
   46: my ($londocroot,$londaemons);
   47: 
   48: BEGIN {
   49:     my $perlvar=&LONCAPA::Configuration::read_conf();
   50:     if (ref($perlvar) eq 'HASH') {
   51:         $londocroot = $perlvar->{'lonDocRoot'};
   52:         $londaemons = $perlvar->{'lonDaemons'};
   53:     }
   54:     undef($perlvar);
   55: }
   56: 
   57: my $lang = &Apache::lonlocal::choose_language();
   58: &Apache::lonlocal::get_language_handle(undef,$lang);
   59: 
   60: my $parameter=$ARGV[0];
   61: $parameter =~ s/^\s+//;
   62: $parameter =~ s/\s+$//;
   63: 
   64: if ((@ARGV > 1) || (($parameter ne '') && ($parameter ne 'execute'))) {
   65:     print &mt('usage: [_1]','unsubresources.pl [dryrun|execute]')."\n\n".
   66:           &mt('You should enter either no arguments, or just one argument: execute.')."\n".
   67:           &mt("execute - to unlink resources in [_1], and send unsub request to homeserver of resource author",
   68:               "$londocroot/res/'")."\n".
   69:           &mt('no argument to do a dry run, without actually unlinking or unsubscribing anything.')."\n";
   70:     exit;
   71: }
   72: 
   73: my $wwwid=getpwnam('www');
   74: if ($wwwid!=$<) {
   75:     print &mt('This must be run as user www in order to unsubscribe previously subscribed resources.')."\n".
   76:           &mt('Stopping')."\n";
   77:     exit;
   78: }
   79: 
   80: if ($londocroot eq '') {
   81:     print &mt('Could not determine location of [_1] directory.',"'lonDocRoot'")."\n".
   82:           &mt('Stopping')."\n";
   83:     exit;
   84: }
   85: if ($londaemons eq '') {
   86:     print &mt('Could not determine location of [_1] directory.',"'lonDaemons'")."\n".
   87:           &mt('Stopping')."\n";
   88:     exit;
   89: }
   90: 
   91: # Get machine IDs
   92: my @ids=&Apache::lonnet::current_machine_ids();
   93: 
   94: print "\n".&mt("Unlinking and unsubscribing resources in $londocroot/res/")."\n".
   95:       &mt('No changes will occur for resources for which this server is the homeserver of the author of the resource.')."\n".
   96:       "-----------------------------\n\n".
   97:       &mt('If run without an argument, the script will report what it would do when unlinking and unsubscribing resources in [_1].',
   98:           "'$londocroot/res/'")."\n\n";
   99: 
  100: my ($action) = ($parameter=~/^(execute)$/);
  101: if ($action eq '') {
  102:     $action = 'dryrun';
  103: }
  104: 
  105: if ($action eq 'dryrun') {
  106:     print "\n".
  107:           &mt('Running in exploratory mode ...')."\n\n".
  108:           &mt('Run with argument [_1] to actually unlink and unsubscribe resources in [_2], i.e., [_3]',
  109:               "'execute'","'$londocroot/res/'","\n\nperl unsubresources.pl execute")."\n\n\n".
  110:           &mt('Continue? ~[y/N~] ');
  111:     if (!&get_user_selection()) {
  112:         exit;
  113:     } else {
  114:         print "\n";
  115:     }
  116: } else {
  117:     print "\n *** ".&mt('Running in a mode where changes will be made.')." ***\n";
  118:     print "\n".
  119:           &mt('Mode is [_1] -- replicated resources in [_2] will be unlinked and unsubscribed.',
  120:               "'$action'","'$londocroot/res/'")."\n";
  121:     print &mt('Continue? ~[y/N~] ');
  122:     if (!&get_user_selection()) {
  123:         exit;
  124:     } else {
  125:         print "\n";
  126:     }
  127: }
  128: 
  129: my $dir = "$londocroot/res";
  130: my %alreadyseen;
  131: 
  132: my $logfh;
  133: unless ($action eq 'dryrun') {
  134:     if (!open($logfh,'>>',"$londaemons/logs/unsubresources.log")) {
  135:         print &mt('Could not open log file: [_1] for writing.',
  136:                   "'$londaemons/logs/unsubresources.log'")."\n".
  137:               &mt('Stopping.')."\n";
  138:         exit;
  139:     } else {
  140:         &start_logging($logfh,$action);
  141:     }
  142: }
  143: &check_directory($action,$dir,$logfh,\@ids,\%alreadyseen);
  144: unless ($action eq 'dryrun') {
  145:     &stop_logging($logfh);
  146: }
  147: print "\n".&mt('Done')."\n";
  148: exit;
  149: 
  150: sub check_directory {
  151:     my ($action,$dir,$fh,$idsref,$seenref,$currhome) = @_;
  152:     my $msg;
  153:     if (opendir(my $dirh,$dir)) {
  154:         while (my $item=readdir($dirh)) {
  155:             next if ($item =~ /^\./);
  156:             if (-d "$dir/$item") {
  157:                 if ($dir eq "$londocroot/res") {
  158:                     next if (($item eq 'adm') || ($item eq 'lib') || ($item eq 'res'));
  159:                     if (&Apache::lonnet::domain($item) ne '') {
  160:                         my %servers = &Apache::lonnet::get_unique_servers($item);
  161:                         my @libservers;
  162:                         foreach my $server (keys(%servers)) {
  163:                             if (&Apache::lonnet::is_library($server)) {
  164:                                 push(@libservers,$server); 
  165:                             }
  166:                         }
  167:                         if (@libservers == 1) {
  168:                             if ((ref($idsref) eq 'ARRAY') && (grep(/^\Q$libservers[0]\E$/,@{$idsref}))) {
  169:                                 $msg = &mt('Skipping directory for [_1] as [_2] is the single library node for the domain',
  170:                                            $item,$libservers[0])."\n";
  171:                                 if ($action eq 'execute') {
  172:                                     print $fh $msg;
  173:                                 } else {
  174:                                     print $msg;
  175:                                 }
  176:                                 next;
  177:                             }
  178:                         }
  179:                         &check_directory($action,"$dir/$item",$fh,$idsref,$seenref);
  180:                     } else {
  181:                         $msg = &mt('Domain [_1] in [_2] is unavailable',
  182:                                    $item,$dir)."\n";
  183:                         if ($action eq 'execute') {
  184:                             print $fh $msg;
  185:                         } else {
  186:                             print $msg;
  187:                         }
  188:                         next;
  189:                     }
  190:                 } elsif ($dir =~ m{^\Q$londocroot/res\E/($match_domain)$}) {
  191:                     my $udom = $1;
  192:                     if ($item =~ /^($match_username)$/) {
  193:                         my $uname = $1;
  194:                         $currhome = &Apache::lonnet::homeserver($uname,$udom,1);
  195:                         if ($currhome eq 'no_host') {
  196:                             $msg = &mt('No homeserver for user: [_1] domain: [_2]',
  197:                                        $uname,$udom)."\n";
  198:                             if ($action eq 'execute') {
  199:                                 print $fh $msg;
  200:                             } else {
  201:                                 print $msg;
  202:                             }
  203:                         } elsif ((ref($idsref) eq 'ARRAY') && (grep(/^\Q$currhome\E$/,@{$idsref}))) {
  204:                             $msg = &mt("Skipping user: [_1] in domain: [_2] as this is the user's homeserver.",
  205:                                        $uname,$udom)."\n"; 
  206:                             if ($action eq 'execute') {
  207:                                 print $fh $msg;
  208:                             } else {
  209:                                 print $msg;
  210:                             }
  211:                         } else {
  212:                             &check_directory($action,"$dir/$item",$fh,$idsref,$seenref,$currhome);
  213:                         }
  214:                     } else {
  215:                         $msg = &mt('Username: [_1] in domain: [_2] is invalid',
  216:                                    $item,$udom)."\n";
  217:                         if ($action eq 'execute') {
  218:                             print $fh $msg;
  219:                         } else {
  220:                             print $msg;
  221:                         }
  222:                     }
  223:                 } else {
  224:                     &check_directory($action,"$dir/$item",$fh,$idsref,$seenref,$currhome);
  225:                 }
  226:             } elsif (-f "$dir/$item") {
  227:                 if ($dir =~ m{^\Q$londocroot/res\E/$match_domain/$match_username}) {
  228:                     next if ($seenref->{"$dir/$item"});
  229:                     if ($action eq 'execute') {
  230:                         if (unlink("$dir/$item")) {
  231:                             if ($item =~ /\.meta$/) {
  232:                                 my $nonmeta = $item;
  233:                                 $nonmeta =~ s/\.meta$//;
  234:                                 next if ((-e "$dir/$nonmeta") || ($seenref->{"$dir/$nonmeta"}));
  235:                             } elsif (-e "$dir/$item.meta") {
  236:                                 unlink("$dir/$item.meta");
  237:                             }
  238:                             if ($currhome ne '') {
  239:                                 my $result = &Apache::lonnet::reply("unsub:$dir/$item",$currhome);
  240:                                 if ($result eq 'ok') {
  241:                                     print $fh &mt('Unsub complete for [_1] at [_2]',
  242:                                                      "$dir/$item",$currhome)."\n";
  243:                                 } else {
  244:                                     print $fh &mt('Result of unsub for [_1] at [_2] was: [_3]',
  245:                                                      "$dir/$item",$currhome,$result)."\n";
  246:                                 }
  247:                             }
  248:                             $seenref->{"$dir/$item"} = 1;
  249:                         } else {
  250:                             print $fh &mt('Failed to unlink [_1]',"$dir/$item")."\n"; 
  251:                         }
  252:                     } else {
  253:                         if ($item =~ /\.meta$/) {
  254:                             my $nonmeta = $item;
  255:                             $nonmeta =~ s/\.meta$//;
  256:                             next if (-e "$dir/$nonmeta");
  257:                             print &mt('Would unlink [_1] and send unsub to [_2]',
  258:                                       "$dir/$item",$currhome)."\n";
  259:                         } elsif (-e "$dir/$item.meta") {
  260:                             print &mt('Would unlink [_1] and [_2], and send unsub to [_3]',
  261:                                       "$dir/$item","$dir/$item.meta",$currhome)."\n";
  262:                             $seenref->{"$dir/$item.meta"} = 1;
  263:                         } else {
  264:                             print &mt('Would unlink [_1] and send unsub to [_2]',
  265:                                       "$dir/$item",$currhome)."\n";
  266:                         }
  267:                         $seenref->{"$dir/$item"} = 1;
  268:                     }
  269:                 } else {
  270:                     $msg = &mt('Invalid directory [_1]',$dir)."\n";
  271:                     if ($action eq 'execute') {
  272:                         print $fh $msg;
  273:                     } else {
  274:                         print $msg;
  275:                     }
  276:                 }
  277:             }
  278:         }
  279:         closedir($dirh);
  280:     } else {
  281:         $msg = &mt('Could not open directory: [_1]',$dir)."\n";
  282:         if ($action eq 'execute') {
  283:             print $fh $msg;
  284:         } else {
  285:             print $msg;
  286:         }
  287:     }
  288:     return;
  289: }
  290: 
  291: sub get_user_selection {
  292:     my ($defaultrun) = @_;
  293:     my $do_action = 0;
  294:     my $choice = <STDIN>;
  295:     chomp($choice);
  296:     $choice =~ s/(^\s+|\s+$)//g;
  297:     my $yes = &mt('y');
  298:     if ($defaultrun) {
  299:         if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) {
  300:             $do_action = 1;
  301:         }
  302:     } else {
  303:         if ($choice =~ /^\Q$yes\E/i) {
  304:             $do_action = 1;
  305:         }
  306:     }
  307:     return $do_action;
  308: }
  309: 
  310: sub start_logging {
  311:     my ($fh,$action) = @_;
  312:     my $start = localtime(time);
  313:     print $fh "*****************************************************\n".
  314:               &mt('[_1] - mode is [_2].',
  315:                   'unsubresources.pl',"'$action'")."\n".
  316:               &mt('Started -- time: [_1]',$start)."\n".
  317:               "*****************************************************\n\n";
  318:     return;
  319: }
  320: 
  321: sub stop_logging {
  322:     my ($fh) = @_;
  323:     my $end = localtime(time);
  324:     print $fh "*****************************************************\n".
  325:                &mt('Ended -- time: [_1]',$end)."\n".
  326:               "*****************************************************\n\n\n";
  327:     close($fh);
  328:     return;
  329: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>