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