Annotation of loncom/lonManage, revision 1.28
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.28 ! foxr 6: # $Id: lonManage,v 1.27 2003/12/22 12:02:19 foxr Exp $
1.1 foxr 7: #
1.28 ! foxr 8: # $Id: lonManage,v 1.27 2003/12/22 12:02:19 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.28 ! 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>