Annotation of loncom/lonManage, revision 1.29

1.1       foxr        1: #!/usr/bin/perl
                      2: # The LearningOnline Network with CAPA
                      3: #
                      4: #  lonManage supports remote management of nodes in a LonCAPA cluster.
                      5: #
1.29    ! foxr        6: #  $Id: lonManage,v 1.28 2003/12/30 11:40:09 foxr Exp $
1.1       foxr        7: #
1.29    ! foxr        8: # $Id: lonManage,v 1.28 2003/12/30 11:40:09 foxr Exp $
1.1       foxr        9: #
                     10: # Copyright Michigan State University Board of Trustees
                     11: #
                     12: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                     13: ## LON-CAPA is free software; you can redistribute it and/or modify
                     14: # it under the terms of the GNU General Public License as published by
                     15: # the Free Software Foundation; either version 2 of the License, or
                     16: # (at your option) any later version.
                     17: #
                     18: # LON-CAPA is distributed in the hope that it will be useful,
                     19: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     20: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     21: # GNU General Public License for more details.
                     22: #
                     23: # You should have received a copy of the GNU General Public License
                     24: # along with LON-CAPA; if not, write to the Free Software
                     25: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     26: #
                     27: # /home/httpd/html/adm/gpl.txt
                     28: #
                     29: # http://www.lon-capa.org/
                     30: #
                     31: #
                     32: #   lonManage supports management of remot nodes in a lonCAPA cluster.
                     33: #   it is a command line tool.  The following command line syntax (usage)
                     34: #   is supported:
                     35: #
1.16      foxr       36: #    lonManage  -push   <tablename>  newfile  [host]
1.1       foxr       37: #        Push <tablename> to the lonTabs directory.  Note that
                     38: #        <tablename> must be one of:
1.28      foxr       39: #           hosts  (hosts.tab)
1.1       foxr       40: #           domain (domain.tab)
                     41: #
1.16      foxr       42: #    lonManage  -reinit lonc [host]
1.1       foxr       43: #           Sends a HUP signal to the remote systems's lond.
                     44: #
1.16      foxr       45: #    lonmanage  -reinit lond [host]
1.1       foxr       46: #          Requests the remote system's lond perform the same action as if
                     47: #          it had received a HUP signal.
                     48: #
                     49: #    In the above syntax, the host above is the hosts.tab name of a host,
1.16      foxr       50: #    not the IP address of the host
                     51: #  
                     52: #   If [host] is not supplied, every host in the client's hosts.tab
                     53: #   table is iterated through and procesed..
1.1       foxr       54: #
1.3       foxr       55: #
1.10      foxr       56: 
1.14      foxr       57: 
1.13      foxr       58: 
1.10      foxr       59: # Modules required:
                     60: 
1.17      foxr       61: use lib ".";
                     62: 
1.7       foxr       63: use strict;			# Because it's good practice.
                     64: use English;			# Cause I like meaningful names.
1.3       foxr       65: use Getopt::Long;
1.17      foxr       66: use LondConnection;
1.23      foxr       67: use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP POLLOUT);
1.28      foxr       68: use IO::File;
1.10      foxr       69: 
                     70: # File scoped variables:
                     71: 
                     72: my %perlvar;			# Perl variable defs from apache config.
                     73: my %hostshash;			# Host table as a host indexed hash.
1.2       foxr       74: 
1.19      foxr       75: my $MyHost="";			# Host name to use as me.
                     76: my $ForeignHostTab="";		# Name of foreign hosts table.
1.23      foxr       77: 
                     78: my $DefaultServerPort =  5663;	# Default server port if standalone.
1.21      foxr       79: my $ServerPort;			# Port used to connect to lond.
1.18      foxr       80: 
1.23      foxr       81: my $TransitionTimeout = 5;	# Poll timeout in seconds.
                     82: 
                     83: 
1.24      foxr       84: # LondConnection::SetDebug(10);
1.23      foxr       85: 
                     86: 
1.13      foxr       87: #
                     88: #   prints out utility's command usage info.
                     89: #
1.3       foxr       90: sub Usage  {
1.2       foxr       91:     print "Usage:";
                     92:     print <<USAGE;
1.18      foxr       93:  lonManage  [--myname=host --hosts=table] --push=<tablename>  newfile  [host]
1.2       foxr       94:         Push <tablename> to the lonTabs directory.  Note that
                     95:         <tablename> must be one of:
1.28      foxr       96:            hosts  (hosts.tab)
1.2       foxr       97:            domain (domain.tab)
                     98: 
1.18      foxr       99:  lonManage [--myname=host --hosts=table] --reinit=lonc [host]
1.15      foxr      100:        Causes lonc in the remote system to reread hosts.tab and
                    101:        adjust the set of clients that are being maintained to match
                    102:        the new file.
                    103:        
1.2       foxr      104: 
1.18      foxr      105:  lonManage [--myname=host --hosts=table] --reinit=lond [host]
1.15      foxr      106:        Causes lond in the remote system to reread the hosts.tab file
                    107:        and adjust the set of servers to match changes in that file.
1.2       foxr      108: 
                    109:     In the above syntax, the host above is the hosts.tab name of a host,
                    110:     not the IP address of the host.
1.16      foxr      111: 
                    112:     If [host] is omitted, all hosts in the hosts.tab file are iterated
                    113:     over.
                    114: 
1.26      foxr      115: lonManage [--myname=host --hosts=table] --edit=<tablename> editscript [host]
                    116:      Requests lond edit the hosts or domain table (selected by
                    117:      tablename) with the editing command in editscript.  If
                    118:      host is supplied the individual host is operated on,
                    119:      otherwise, the entire cluster is operated on.
                    120:      The edit file has edit request, one per line of the form:
                    121:      append|newline
                    122:      replace|key|newline
                    123:      delete|key
                    124:      The key is a loncapa hostname if editing the host file
                    125:      or a domain name if editing the domain table file.
                    126: 
1.18      foxr      127:  For all of the above syntaxes if --myname=host and --hosts=table are
                    128:  supplied (both must be present), the utility runs in standalone mode
                    129:  presenting itself to the world as 'host' and using the hosts.tab file
                    130:  specified in the --hosts switch.
1.2       foxr      131: USAGE
                    132: 
                    133: 
                    134: }
1.21      foxr      135: 
1.23      foxr      136: #
                    137: #  Make a direct connection to the lond in 'host'.  The port is 
                    138: #  gotten from the global variable:  ServerPort.
                    139: #  Returns:
                    140: #    The connection or undef if one could not be formed.
                    141: #
1.21      foxr      142: sub MakeLondConnection {
                    143:     my $host = shift;
1.22      foxr      144: 
                    145:     my $Connection = LondConnection->new($host, $ServerPort);
                    146:     return return $Connection;
1.21      foxr      147: }
1.23      foxr      148: #
1.25      foxr      149: #   Process the connection state machine until the connection
                    150: #   becomes idle. This is used both to negotiate the initial
                    151: #   connection, during which the LondConnection sequences a rather 
                    152: #   complex state machine and during the transaction itself
                    153: #   for a simpler set of transitions.
                    154: #   All we really need to be concerned with is whether or not
                    155: #   we're readable or writable and the final state:
                    156: #
                    157: #   Parameter:
                    158: #       connection   - Represents the LondConnection to be sequenced.
                    159: #       timeout      - Maximum time to wait for readable/writable sockets.
                    160: #                      in seconds. < 0 waits forever.
                    161: #   Return:
                    162: #       'ok'         - We got to idle ok.
                    163: #       'error:msg'  - An error occured. msg describes the error.
                    164: #
                    165: sub SequenceStateMachine {
                    166:     my $connection   = shift;
                    167:     my $timeout      = shift;
                    168: 
                    169:     my $Socket       = $connection->GetSocket;
                    170:     my $returnstatus = "ok";	              # optimist!!!
                    171:     my $error        = 0;	              # Used to force early loop termination
                    172:                                               # damned perl has no break!!.
                    173:     my $state        = $connection->GetState;
                    174: 
                    175:     while(($connection->GetState ne "Idle") && (!$error)) {
1.26      foxr      176:       #
                    177:       # Figure out what the connection wants. read/write and wait for it
                    178:       # or for the timeout.
                    179:       #
1.25      foxr      180: 	my $wantread = $connection->WantReadable;
                    181: 	my $poll     = new IO::Poll;
                    182: 	$poll->mask($Socket, => $wantread ? POLLIN : POLLOUT);
1.26      foxr      183: 	my $handlecount = $poll->poll($timeout);
                    184: 	if($handlecount == 0) {            # no handles ready... timeout!!
1.25      foxr      185: 	    $returnstatus  = "error:";
                    186: 	    $returnstatus .= "Timeout in state $state\n";
                    187: 	    $error         = 1;
                    188: 	} else {
1.26      foxr      189: 	    my $done     = $poll->handles();
1.25      foxr      190: 	    my $status;
                    191: 	    $status        = $wantread ? $connection->Readable :
1.26      foxr      192: 		$connection->Writable;
1.25      foxr      193: 	    if($status != 0) {
                    194: 		$returnstatus  =  "error:";
                    195: 		$returnstatus .=  " I/O failed in state $state\n";
                    196: 		$error = 1;
                    197: 	    }
                    198: 	}
                    199: 	$state = $connection->GetState;
                    200:     }
                    201:     return $returnstatus;
                    202: }
                    203: 
                    204: #
1.23      foxr      205: #    This function runs through the section of the connection
                    206: #   state machine that has to do with negotiating the startup 
                    207: #   sequence with lond.  The general strategy is to loop
                    208: #   until the connection state becomes idle or disconnected.
                    209: #   Disconnected indicates an error or rejection of the
                    210: #   connection at some point in the negotiation.
                    211: #   idle indicates a connection ready for a request.
                    212: #   The main loop consults the object to determine if it
                    213: #   wants to be writeable or readable, waits for that
                    214: #   condition on the socket (with timeout) and  then issues
                    215: #   the appropriate LondConnection call. Note that
                    216: #   LondConnection is capable of doing everything necessary
                    217: #   to get to the initial idle state.
                    218: # 
                    219: #
                    220: #  Parameters:
                    221: #     connection - A connection that has been created with
                    222: #                  the remote lond.  This connection should
                    223: #                  be in the Connected state ready to send
                    224: #                  the init sequence.
                    225: #
1.21      foxr      226: sub NegotiateStartup {
                    227:     my $connection = shift;
1.23      foxr      228:     my $returnstatus = "ok";	# Optimistic!!.
                    229: 
                    230:     my $state      = $connection->GetState;
1.26      foxr      231:    if($state ne "Connected") {
                    232:       print "Error: Initial lond connection state: $state should be Connected\n";
                    233:       return "error";
                    234:    }
1.23      foxr      235: 
1.26      foxr      236:    return SequenceStateMachine($connection, $TransitionTimeout);
1.21      foxr      237: }
1.24      foxr      238: #
                    239: #   Perform a transaction with the remote lond.
                    240: #   Paramters:
                    241: #      connection - the connection object that represents
                    242: #                   a LondConnection to the remote lond.
                    243: #      command    - The request to send to the remote system.
                    244: #   Returns:
                    245: #       The 'reaction' of the lond to this command.
                    246: #       However if the connection to lond is lost during the transaction
                    247: #       or some other error occurs, the text "error:con_lost" is returned.
                    248: #    
1.21      foxr      249: sub PerformTransaction {
                    250:     my $connection  = shift;
                    251:     my $command     = shift;
1.24      foxr      252:     my $retval;                          # What we'll returnl.
1.25      foxr      253: 
1.24      foxr      254:    
                    255:     #  Set up the connection to do the transaction then
                    256:     #  do the I/O until idle or error.
                    257:     #
                    258:     $connection->InitiateTransaction($command);
                    259: 
1.25      foxr      260:     my $status = SequenceStateMachine($connection, $TransitionTimeout);
1.26      foxr      261:    if($status eq "ok") {
                    262:       $retval = $connection->GetReply;
                    263:    } else {
                    264:       $retval = $status;
                    265:    }
1.21      foxr      266: 
1.24      foxr      267:     return $retval;
1.21      foxr      268: }
1.13      foxr      269: #
1.21      foxr      270: # Performs a transaction direct to a remote lond.
1.13      foxr      271: #   Parameter:
                    272: #      cmd  - The text of the request.
                    273: #      host - The host to which the request ultimately goes.
                    274: #   Returns:
                    275: #      The text of the reply from the lond or con_lost if not able to contact
                    276: #      lond/lonc etc.
                    277: #
                    278: sub subreply {
1.21      foxr      279:     my $cmd = shift;
                    280:     my $host = shift;
                    281: 
                    282: 
1.26      foxr      283:    my $connection  = MakeLondConnection($host);
                    284:    if ($connection eq undef) {
                    285:       return "Connect Failed";
                    286:    }
                    287:    my $reply = NegotiateStartup($connection);
                    288:    if($reply ne "ok") {
                    289:       return "connection negotiation failed";
                    290:    }
                    291:    my $reply =  PerformTransaction($connection, $cmd);
                    292:    return $reply;
1.21      foxr      293: 
                    294: 
1.13      foxr      295: }
1.2       foxr      296: #
1.3       foxr      297: #  Use Getopt::Long to parse the parameters of the program.
                    298: #
                    299: #  Return value is a list consisting of:
                    300: #    A 'command' which is one of:
                    301: #       push   - table push requested.
                    302: #       reinit - reinit requested.
                    303: #   Additional parameters as follows:
                    304: #       for push: Tablename, hostname
                    305: #       for reinit: Appname  hostname
                    306: #
                    307: #   This function does not validation of the parameters of push and
                    308: #   reinit.
1.4       foxr      309: #
                    310: #   returns a list.  The first element of the list is the operation name
                    311: #   (e.g. reinit or push).  The second element is the switch parameter.
                    312: #   for push, this is the table name, for reinit, this is the process name.
                    313: #   Additional elements of the list are the command argument.  The count of
                    314: #   command arguments is validated, but not their semantics.
                    315: #
1.3       foxr      316: #   returns an empty list if the parse fails.
                    317: #
                    318: 
1.18      foxr      319: 
1.3       foxr      320: sub ParseArgs {
1.26      foxr      321:     my $pushing    = '';
1.7       foxr      322:     my $reinitting = '';
1.26      foxr      323:     my $editing    = '';
                    324:     
1.4       foxr      325:     if(!GetOptions('push=s'    => \$pushing,
1.26      foxr      326:                    'reinit=s'  => \$reinitting,
                    327:                    'edit=s'    => \$editing,
                    328: 		             'myname=s'  => \$MyHost,
                    329: 		             'hosts=s'   => \$ForeignHostTab)) {
                    330:       return ();
                    331:    }
1.18      foxr      332:     #  The --myname and --hosts switch must have values and
                    333:     #  most both appear if either appears:
                    334: 
1.26      foxr      335:    if(($MyHost ne "") && ($ForeignHostTab eq "")) {
                    336:       return ();
                    337:    }
                    338:    if(($ForeignHostTab ne "") && ($MyHost eq "")) {
                    339:       return ();
                    340:    }
                    341: 
                    342:     #  Require exactly   one of --push, --reinit, or --edit
                    343: 
                    344:    my $command    = '';
                    345:    my $commandarg = '';
                    346:    my $paramcount = @ARGV; 	# Number of additional arguments.
                    347: 
                    348:    my $commands = 0;           # Number of commands seen.
                    349: 
                    350:    if($pushing ne '') {
                    351: 
                    352:       # --push takes in addition a table, and an optional  host:
                    353:       #
                    354:         
                    355: 	   if(($paramcount != 2) && ($paramcount != 1)) {
                    356:          return ();		# Invalid parameter count.
                    357:       }
1.5       foxr      358: 	    
1.26      foxr      359:       $commands++;              # Count a command seen.
                    360:       $command    = 'push';
                    361:       $commandarg = $pushing;
1.4       foxr      362: 	}
1.5       foxr      363: 
1.26      foxr      364:    if ($reinitting ne '') {
1.5       foxr      365: 
1.16      foxr      366: 	# --reinit takes in addition just an optional  host name
1.5       foxr      367: 
1.26      foxr      368:       if($paramcount > 1) {
                    369:          return ();
                    370:       }
                    371:       $commands++;              #  Count a command seen.
                    372:       $command    = 'reinit';
                    373:       $commandarg = $reinitting; 
1.5       foxr      374: 	}
1.26      foxr      375: 
                    376:    # --edit takes a script file and optional host name.
                    377:    #
                    378:    if ($editing ne "") {
                    379:       if(($paramcount != 2) && ($paramcount != 1)) {
                    380:          return ();              # Invalid parameter count.
                    381:       }
                    382:       
                    383:       $commands++;               # Count a command seen.
                    384:       $command    = 'edit';
                    385:       $commandarg = $editing;
                    386:    }
                    387:    
                    388:    #  At this point, $commands must be 1 or else we've seen
                    389:    #  The wrong number of command switches:
                    390:    
                    391:    if($commands != 1) {
                    392:       return ();
                    393:    }
1.4       foxr      394: 
1.5       foxr      395:     #  Build the result list:
                    396: 
1.26      foxr      397:    my @result = ($command, $commandarg);
                    398:    my $i;
                    399:    for($i = 0; $i < $paramcount; $i++) {
                    400:       push(@result, $ARGV[$i]);
                    401:    }
1.5       foxr      402:     
                    403:     return @result;
1.3       foxr      404: }
1.10      foxr      405: #
1.26      foxr      406: #  Build the editor script.  This function:
                    407: #  - Opens the edit script file.
                    408: #  - Reads each line of the edit script file
                    409: #  - Replaces the ending \n with a /
                    410: #  - Appends it to the EditScript variable.
                    411: #  - Returns the contents of the EditScript variable.
                    412: #  Parameters:
                    413: #     tabletype   - The type of table being built:
                    414: #                   hosts or domain
                    415: #     scriptname  - The script input file.
                    416: #
                    417: sub BuildEditScript {
                    418:    my $TableType    = shift;
                    419:    my $ScriptName   = shift;
                    420:    
1.28      foxr      421:    my $fh  = new IO::File "< $ScriptName";
                    422:    if (! (defined $fh)) {
                    423:        print "Unable to open script file: $ScriptName \n";
                    424:        Usage;
                    425:        exit -1;
                    426:    }
1.26      foxr      427:    
1.28      foxr      428:    my @EditScript;
                    429:    my $scriptline = "$TableType\:"; # First leads with e.g. hosts:
                    430:    while (! $fh->eof()) {
                    431:        my $line = <$fh>;
                    432:        chomp $line;
                    433:        if($line ne "\n") {
                    434: 	   $scriptline .= "$line\n";
                    435: 	   push(@EditScript, $scriptline);
                    436: 	   $scriptline = "";
                    437:        }
                    438:    }
                    439: 
1.26      foxr      440:    return \@EditScript;
                    441: }
1.19      foxr      442: #  Read the loncapa configuration stuff.  If ForeignHostTab is empty,
                    443: #  assume we are part of a loncapa cluster and read the hosts.tab
                    444: #  file from the config directory.  Otherwise, ForeignHossTab
                    445: #  is the name of an alternate configuration file to read in 
                    446: #  standalone mode.
1.11      foxr      447: #
1.28      foxr      448: sub ReadConfig {  
1.19      foxr      449: 
1.26      foxr      450: 
                    451:    
                    452:    if($ForeignHostTab eq "") {
                    453:        my $perlvarref = LondConnection::read_conf('loncapa.conf');
                    454:        %perlvar    = %{$perlvarref};
                    455:        my $hoststab   = LondConnection::read_hosts(
                    456: 						   "$perlvar{lonTabDir}/hosts.tab");
                    457:       %hostshash     = %{$hoststab};
                    458:       $MyHost        = $perlvar{lonHostID}; # Set hostname from vars.
                    459:       $ServerPort    = $perlvar{londPort};
                    460:    } else {
1.23      foxr      461: 	
1.26      foxr      462:       LondConnection::ReadForeignConfig($MyHost, 
                    463:                                         $ForeignHostTab);
                    464:       my $hoststab = LondConnection::read_hosts($ForeignHostTab); #  we need to know too.
                    465: 	   %hostshash   = %{$hoststab};
                    466: 	   $ServerPort    = $DefaultServerPort;
                    467:    }
1.11      foxr      468: }
                    469: #
1.10      foxr      470: #  Determine if the target host is valid.
                    471: #  This is done by reading the current hosts.tab file.
                    472: #  For the host to be valid, it must be inthe file.
                    473: #
                    474: #  Parameters:
                    475: #     host   - Name of host to check on.
                    476: #  Returns:
                    477: #     true   if host is valid.
                    478: #     false  if host is invalid.
                    479: #
1.8       foxr      480: sub ValidHost {
1.10      foxr      481:     my $host       = shift;
1.11      foxr      482:    
1.10      foxr      483: 
                    484:     return defined $hostshash{$host};
                    485: 
1.8       foxr      486: }
1.13      foxr      487: 
                    488: 
                    489: 
1.12      foxr      490: #
                    491: #  Performs a transaction with lonc.
                    492: #  By the time this is called, the transaction has already been
                    493: #  validated by the caller.
                    494: #
                    495: #   Parameters:
                    496: #
                    497: #   host    - hosts.tab name of the host whose lonc we'll be talking to.
                    498: #   command - The base command we'll be asking lond to execute.
                    499: #   body    - [optional] If supplied, this is a command body that is a ref.
                    500: #             to an array of lines that will be appended to the 
                    501: #             command.
                    502: #
                    503: #  NOTE:
                    504: #    The command will be done as an encrypted operation.
                    505: #
1.8       foxr      506: sub Transact {
1.12      foxr      507:     my $host    = shift;
                    508:     my $command = shift;
                    509:     my $haveBody= 0;
                    510:     my $body;
                    511:     my $i;
                    512: 
1.26      foxr      513:    if(scalar @ARG) {
                    514:       $body = shift;
                    515:       $haveBody = 1;
                    516:    }
1.12      foxr      517:     #  Construct the command to send to the server:
                    518:     
1.26      foxr      519:    my $request = "encrypt\:";	# All requests are encrypted.
                    520:    $request   .= $command;
                    521:    if($haveBody) {
                    522:       $request .= "\:";
                    523:       my $bodylines = scalar @$body;
                    524:       for($i = 0; $i < $bodylines; $i++) {
                    525:          $request .= $$body[$i];
                    526:       }
                    527:    } else {
                    528:       $request .= "\n";
                    529:    }
1.13      foxr      530:     # Body is now built... transact with lond..
                    531:     
1.29    ! foxr      532: #    print "Final command: '$request'\n";
1.13      foxr      533:     my $answer = subreply($request, $host);
                    534: 
                    535:     print "$answer\n";
1.10      foxr      536: 
1.8       foxr      537: }
1.7       foxr      538: #
                    539: #   Called to push a file to the remote system.
                    540: #   The only legal files to push are hosts.tab and domain.tab.
                    541: #   Security is somewhat improved by
                    542: #   
                    543: #   - Requiring the user run as root.
                    544: #   - Connecting with lonc rather than lond directly ensuring this is a loncapa
                    545: #     host
                    546: #   - We must appear in the remote host's hosts.tab file.
                    547: #   - The host must appear in our hosts.tab file.
                    548: #
                    549: #  Parameters:
                    550: #     tablename - must be one of hosts or domain.
                    551: #     tablefile - name of the file containing the table to push.
                    552: #     host      - name of the host to push this file to.     
                    553: #
1.26      foxr      554: #    
1.13      foxr      555: #
1.7       foxr      556: sub PushFile {
                    557:     my $tablename = shift;
                    558:     my $tablefile = shift;
                    559:     my $host      = shift;
                    560:     
1.8       foxr      561:     # Open the table file:
                    562: 
1.26      foxr      563:    if(!open(TABLEFILE, "<$tablefile")) {
                    564:       die "ENOENT - No such file or directory $tablefile";
                    565:    }
1.8       foxr      566:   
                    567:     # Require that the host be valid:
                    568: 
1.26      foxr      569:    if(!ValidHost($host)) {
                    570:       die "EHOSTINVAL - Invalid host $host"; # Ok so I invented this 'errno'.
                    571:    }
1.8       foxr      572:     # Read in the file.  If the table name is valid, push it.
                    573: 
1.26      foxr      574:    my @table = <TABLEFILE>;	#  These files are pretty small.
                    575:    close TABLEFILE;
1.8       foxr      576: 
1.28      foxr      577:    if( ($tablename eq "hosts")    ||
1.26      foxr      578:        ($tablename eq "domain")) {
                    579:       print("Pushing $tablename to $host\n");
                    580:       Transact($host, "pushfile:$tablename",\@table);
                    581:    } else {
                    582:       die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain";
                    583:    }
                    584: }
                    585: #
                    586: #   This function forms and executes an edit file with a
                    587: #   remote lond server.  We build the full transaction string
                    588: #   and use Transact to perform the transaction.
                    589: #   Paramters:
                    590: #      host     - loncapa name of host to operate on.
                    591: #      body     - Body of the command.  We send:
                    592: #                  edit:$body as the command request.
                    593: #
                    594: sub EditFile {
                    595:    my $host    = shift;
                    596:    my $body    = shift;
                    597:    
                    598:    if(!ValidHost($host)) {
                    599:       die "EHOSTINVAL - Invalid host $host";
                    600:    }
                    601:    Transact($host, "edit", $body);
1.7       foxr      602: }
1.26      foxr      603: 
1.9       foxr      604: #
                    605: #   This function is called to reinitialize a server in a remote host.
                    606: #   The servers that can be reinitialized are:
                    607: #   - lonc   - The lonc client process.
                    608: #   - lond   - The lond daemon.
                    609: #  NOTE:
                    610: #    Reinitialization in this case means re-scanning the hosts table,
                    611: #    starting new lond/lonc's as approprate and stopping existing lonc/lond's.
                    612: #
                    613: #  Parameters:
                    614: #     process - The name of the process to reinit (lonc or lond).
                    615: #     host    - The host in which this reinit will happen.
                    616: #
1.13      foxr      617: #   >>>BUGBUG<<<< This belongs  in lonnet.pm
                    618: #
1.9       foxr      619: sub ReinitProcess {
1.26      foxr      620:    my $process = shift;
                    621:    my $host    = shift;
1.3       foxr      622: 
1.9       foxr      623:     #  Ensure the host is valid:
                    624:     
1.26      foxr      625:    if(!ValidHost($host)) {
                    626:       die "EHOSTINVAL - Invalid host $host";
                    627:    }
1.9       foxr      628:     # Ensure target process selector is valid:
                    629: 
1.26      foxr      630:    if(($process eq "lonc") ||
                    631:       ($process eq "lond")) {
                    632:       print("Reinitializing $process in $host\n");
                    633:       Transact($host, "reinit:$process");
                    634:    } else {
                    635:       die "EINVAL -Invalid parameter. Process $process must be lonc or lond";
                    636:    }
1.7       foxr      637: }
1.6       foxr      638: #--------------------------- Entry point: --------------------------
                    639: 
1.16      foxr      640: 
                    641: 
1.6       foxr      642: #  Parse the parameters
                    643: #  If command parsing failed, then print usage:
1.2       foxr      644: 
1.7       foxr      645: my @params   = ParseArgs;
                    646: my $nparam   = @params;
1.3       foxr      647: 
                    648: if($nparam == 0) {
1.2       foxr      649:     Usage;
1.4       foxr      650:     exit -1;
1.2       foxr      651: }
1.7       foxr      652: #
                    653: #   Next, ensure we are running as EID root.
                    654: #
                    655: if ($EUID != 0) {
                    656:     die "ENOPRIV - No privilege for requested operation"
1.6       foxr      657: }
                    658: 
1.19      foxr      659: #
                    660: #   Read the configuration file.
                    661: #   
                    662: 
                    663: ReadConfig;			# Read the configuration info (incl.hosts).
1.4       foxr      664: 
1.6       foxr      665: #   Based on the operation requested invoke the appropriate function:
                    666: 
1.7       foxr      667: my $operation = shift @params;
1.6       foxr      668: 
                    669: if($operation eq "push") {  # push tablename filename host
1.7       foxr      670:     my $tablename = shift @params;
                    671:     my $tablefile = shift @params;
                    672:     my $host      = shift @params;
1.16      foxr      673:     if($host) {
1.26      foxr      674:       PushFile($tablename, $tablefile, $host);
1.16      foxr      675:     } else {			# Push to whole cluster.
1.26      foxr      676:       foreach my $host (keys %hostshash) {
                    677:          PushFile($tablename, $tablefile, $host);
                    678:       }
1.16      foxr      679:     }
1.6       foxr      680: 
1.7       foxr      681: } elsif($operation eq "reinit") {	# reinit processname host.
                    682:     my $process   = shift @params;
                    683:     my $host      = shift @params;
1.16      foxr      684:     if ($host) {
                    685: 	ReinitProcess($process, $host);
                    686:     } else {			# Reinit whole cluster.
                    687: 	foreach my $host (keys %hostshash) {
                    688: 	    ReinitProcess($process,$host);
                    689: 	}
                    690:     }
1.26      foxr      691: } elsif($operation eq "edit") {   # Edit a table.
                    692:    my $tablename     = shift @params;
                    693:    my $scriptfile    = shift @params;
                    694:    my $host          = shift @params;
                    695:    my $CommandBody   = BuildEditScript($tablename, $scriptfile);
                    696:    if ($host) {
                    697:       EditFile($host, $CommandBody);
                    698:    } else {
                    699:       foreach my $ClusterMember (keys %hostshash) {
                    700:          EditFile($ClusterMember, $CommandBody);
                    701:       }
                    702:    }
                    703: }
1.7       foxr      704: else {
1.26      foxr      705:    Usage;
1.6       foxr      706: }
1.4       foxr      707: exit 0;
1.2       foxr      708: 
                    709: =head1 NAME
                    710:     lonManage - Command line utility for remote management of lonCAPA
                    711:     cluster nodes.
                    712: 
                    713: =head1 SYNOPSIS
                    714: 
                    715: Usage:
1.3       foxr      716:     B<lonManage  --push=<tablename>  newfile  host>
1.2       foxr      717:         Push <tablename> to the lonTabs directory.  Note that
                    718:         <tablename> must be one of:
                    719:            hosts  (hosts.tab)
                    720:            domain (domain.tab)
                    721: 
1.3       foxr      722:     B<lonManage  --reinit=lonc host>
1.2       foxr      723:            Sends a HUP signal to the remote systems's lond.
                    724: 
1.26      foxr      725:     B<lonManage  --reinit=lond host>
1.2       foxr      726:           Requests the remote system's lond perform the same action as if
                    727:           it had received a HUP signal.
                    728: 
1.26      foxr      729:     B<lonManage  --edit=<tablename> editscript host>
                    730:          Requests the remote system's lond perform an edit
                    731:          on <tablename>  editscript supplies a set of 
                    732:          editing commands.  Each edit command is one of :
                    733:          
                    734:          append|key|newline
                    735:          delete|key|
                    736:          replace|key|newline
                    737:          
                    738:          The key above is the value of the loncapa host name
                    739:          in the file.
                    740:          
                    741: In the above syntax, the host above is the 
                    742: hosts.tab name of a host,
                    743: not the IP address of the host.
1.2       foxr      744: 
                    745: 
                    746: =head1 DESCRIPTION
                    747: 
                    748: =head1 PREREQUISITES
1.3       foxr      749: 
1.7       foxr      750: =item strict
1.3       foxr      751: =item Getopt::Long
1.7       foxr      752: =item English
1.13      foxr      753: =item IO::Socket::UNIX
1.26      foxr      754: =item LONCAPA::LondConnection
1.13      foxr      755: 
                    756: =head1 KEY Subroutines.
1.2       foxr      757: 
                    758: =head1  CATEGORIES
                    759:     Command line utility
                    760: 
                    761: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.