--- loncom/Attic/lonManage 2003/08/18 10:25:46 1.9 +++ loncom/Attic/lonManage 2003/11/03 10:18:13 1.19 @@ -3,9 +3,9 @@ # # lonManage supports remote management of nodes in a LonCAPA cluster. # -# $Id: lonManage,v 1.9 2003/08/18 10:25:46 foxr Exp $ +# $Id: lonManage,v 1.19 2003/11/03 10:18:13 foxr Exp $ # -# $Id: lonManage,v 1.9 2003/08/18 10:25:46 foxr Exp $ +# $Id: lonManage,v 1.19 2003/11/03 10:18:13 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,80 +33,107 @@ # it is a command line tool. The following command line syntax (usage) # is supported: # -# lonManage -push newfile host +# lonManage -push newfile [host] # Push to the lonTabs directory. Note that # must be one of: -# hosts (hosts.tab) +# host (hosts.tab) # domain (domain.tab) # -# lonManage -reinit lonc host +# lonManage -reinit lonc [host] # Sends a HUP signal to the remote systems's lond. # -# lonmanage -reinit lond host +# lonmanage -reinit lond [host] # Requests the remote system's lond perform the same action as if # it had received a HUP signal. # # In the above syntax, the host above is the hosts.tab name of a host, -# not the IP address of the host. -# -# $Log: lonManage,v $ -# Revision 1.9 2003/08/18 10:25:46 foxr -# Write ReinitProcess function in terms of ValidHost and Transact. -# -# Revision 1.8 2003/08/18 10:18:21 foxr -# Completed PushFile function in terms of -# - ValidHost - Determines if target host is valid. -# - Transact - Performs one of the valid transactions with the -# appropriate lonc<-->lond client/server pairs. -# -# Revision 1.7 2003/08/18 09:56:01 foxr -# 1. Require to be run as root. -# 2. Catch case where no operation switch is supplied and put out usage. -# 3. skeleton/comments for PushFile function. -# -# Revision 1.6 2003/08/12 11:02:59 foxr -# Implement command switch dispatching. -# -# Revision 1.5 2003/08/12 10:55:42 foxr -# Complete command line parsing (tested) -# -# Revision 1.4 2003/08/12 10:40:44 foxr -# Get switch parsing right. -# -# Revision 1.3 2003/08/12 10:22:35 foxr -# Put in parameter parsing infrastructure -# -# Revision 1.2 2003/08/12 09:58:49 foxr -# Add usage and skeleton documentation. +# not the IP address of the host +# +# If [host] is not supplied, every host in the client's hosts.tab +# table is iterated through and procesed.. # # + + + +# Modules required: + +use lib "."; + use strict; # Because it's good practice. use English; # Cause I like meaningful names. use Getopt::Long; +use IO::Socket::UNIX; # To communicate with lonc. +use LondConnection; + +# File scoped variables: + +my %perlvar; # Perl variable defs from apache config. +my %hostshash; # Host table as a host indexed hash. +my $MyHost=""; # Host name to use as me. +my $ForeignHostTab=""; # Name of foreign hosts table. + +# +# prints out utility's command usage info. +# sub Usage { print "Usage:"; print < newfile host + lonManage [--myname=host --hosts=table] --push= newfile [host] Push to the lonTabs directory. Note that must be one of: - hosts (hosts.tab) + host (hosts.tab) domain (domain.tab) - lonManage --reinit=lonc host - Sends a HUP signal to the remote systems's lond. - - lonManage --reinit=lond host - Requests the remote system's lond perform the same action as if - it had received a HUP signal. + lonManage [--myname=host --hosts=table] --reinit=lonc [host] + Causes lonc in the remote system to reread hosts.tab and + adjust the set of clients that are being maintained to match + the new file. + + + lonManage [--myname=host --hosts=table] --reinit=lond [host] + Causes lond in the remote system to reread the hosts.tab file + and adjust the set of servers to match changes in that file. In the above syntax, the host above is the hosts.tab name of a host, not the IP address of the host. + + If [host] is omitted, all hosts in the hosts.tab file are iterated + over. + + For all of the above syntaxes if --myname=host and --hosts=table are + supplied (both must be present), the utility runs in standalone mode + presenting itself to the world as 'host' and using the hosts.tab file + specified in the --hosts switch. USAGE } - +# +# Lifted from lonnet.pm - and we need to figure out a way to get it back in. +# Performas a transaction with lond via the lonc proxy server. +# Parameter: +# cmd - The text of the request. +# host - The host to which the request ultimately goes. +# Returns: +# The text of the reply from the lond or con_lost if not able to contact +# lond/lonc etc. +# +sub subreply { + my ($cmd,$server)=@_; + my $peerfile="$perlvar{'lonSockDir'}/$server"; + my $client=IO::Socket::UNIX->new(Peer =>"$peerfile", + Type => SOCK_STREAM, + Timeout => 10) + or return "con_lost"; + print $client "$cmd\n"; + my $answer=<$client>; + if (!$answer) { $answer="con_lost"; } + chomp($answer); + return $answer; +} +# >>> BUGBUG <<< # # Use Getopt::Long to parse the parameters of the program. # @@ -130,12 +157,24 @@ USAGE # returns an empty list if the parse fails. # + sub ParseArgs { my $pushing = ''; my $reinitting = ''; if(!GetOptions('push=s' => \$pushing, - 'reinit=s' => \$reinitting)) { + 'reinit=s' => \$reinitting, + 'myname=s' => \$MyHost, + 'hosts=s' => \$ForeignHostTab)) { + return (); + } + # The --myname and --hosts switch must have values and + # most both appear if either appears: + + if(($MyHost ne "") && ($ForeignHostTab eq "")) { + return (); + } + if(($ForeignHostTab ne "") && ($MyHost eq "")) { return (); } @@ -148,9 +187,9 @@ sub ParseArgs { if($pushing ne '') { - # --push takes in addition a table, and a host: + # --push takes in addition a table, and an optional host: # - if($paramcount != 2) { + if(($paramcount != 2) && ($paramcount != 1)) { return (); # Invalid parameter count. } if($command ne '') { @@ -164,9 +203,9 @@ sub ParseArgs { if ($reinitting ne '') { - # --reinit takes in addition just a host name + # --reinit takes in addition just an optional host name - if($paramcount != 1) { + if($paramcount > 1) { return (); } if($command ne '') { @@ -187,10 +226,96 @@ sub ParseArgs { return @result; } +# +# Read the loncapa configuration stuff. If ForeignHostTab is empty, +# assume we are part of a loncapa cluster and read the hosts.tab +# file from the config directory. Otherwise, ForeignHossTab +# is the name of an alternate configuration file to read in +# standalone mode. +# +sub ReadConfig { + + if($ForeignHostTab eq "") { + my $perlvarref = LondConnection::read_conf('loncapa.conf'); + %perlvar = %{$perlvarref}; + my $hoststab = LondConnection::read_hosts( + "$perlvar{'lonTabDir'}/hosts.tab"); + %hostshash = %{$hoststab}; + } else { + my $hoststab = LondConnection::read_hosts($ForeignHostTab); + %hostshash = %{$hoststab}; + $perlvar{londPort} = 5663; + $perlvar{lonSockDir} = "/home/httpd/sockets"; + } + +} +# +# Determine if the target host is valid. +# This is done by reading the current hosts.tab file. +# For the host to be valid, it must be inthe file. +# +# Parameters: +# host - Name of host to check on. +# Returns: +# true if host is valid. +# false if host is invalid. +# sub ValidHost { - return 1; + my $host = shift; + + + return defined $hostshash{$host}; + } + + + +# +# Performs a transaction with lonc. +# By the time this is called, the transaction has already been +# validated by the caller. +# +# Parameters: +# +# host - hosts.tab name of the host whose lonc we'll be talking to. +# command - The base command we'll be asking lond to execute. +# body - [optional] If supplied, this is a command body that is a ref. +# to an array of lines that will be appended to the +# command. +# +# NOTE: +# The command will be done as an encrypted operation. +# sub Transact { + my $host = shift; + my $command = shift; + my $haveBody= 0; + my $body; + my $i; + + if(scalar @ARG) { + $body = shift; + $haveBody = 1; + } + # Construct the command to send to the server: + + my $request = "encrypt\:"; # All requests are encrypted. + $request .= $command; + if($haveBody) { + $request .= "\:"; + my $bodylines = scalar @$body; + for($i = 0; $i < $bodylines; $i++) { + $request .= $$body[$i]; + } + } else { + $request .= "\n"; + } + # Body is now built... transact with lond.. + + my $answer = subreply($request, $host); + + print "$answer\n"; + } # # Called to push a file to the remote system. @@ -208,6 +333,8 @@ sub Transact { # tablefile - name of the file containing the table to push. # host - name of the host to push this file to. # +# >>>BUGBUG<<< This belongs in lonnet.pm. +# sub PushFile { my $tablename = shift; my $tablefile = shift; @@ -231,7 +358,8 @@ sub PushFile { if( ($tablename eq "host") || ($tablename eq "domain")) { - Transact($host, "pushfile:$tablename:",\@table); + print("Pushing $tablename to $host\n"); + Transact($host, "pushfile:$tablename",\@table); } else { die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain"; } @@ -249,6 +377,8 @@ sub PushFile { # process - The name of the process to reinit (lonc or lond). # host - The host in which this reinit will happen. # +# >>>BUGBUG<<<< This belongs in lonnet.pm +# sub ReinitProcess { my $process = shift; my $host = shift; @@ -262,6 +392,7 @@ sub ReinitProcess { if(($process eq "lonc") || ($process eq "lond")) { + print("Reinitializing $process in $host\n"); Transact($host, "reinit:$process"); } else { die "EINVAL -Invalid parameter. Process $process must be lonc or lond"; @@ -269,6 +400,8 @@ sub ReinitProcess { } #--------------------------- Entry point: -------------------------- + + # Parse the parameters # If command parsing failed, then print usage: @@ -286,6 +419,11 @@ if ($EUID != 0) { die "ENOPRIV - No privilege for requested operation" } +# +# Read the configuration file. +# + +ReadConfig; # Read the configuration info (incl.hosts). # Based on the operation requested invoke the appropriate function: @@ -295,13 +433,25 @@ if($operation eq "push") { # push table my $tablename = shift @params; my $tablefile = shift @params; my $host = shift @params; - PushFile($tablename, $tablefile, $host); + if($host) { + PushFile($tablename, $tablefile, $host); + } else { # Push to whole cluster. + foreach my $host (keys %hostshash) { + PushFile($tablename, $tablefile, $host); + } + } } elsif($operation eq "reinit") { # reinit processname host. my $process = shift @params; my $host = shift @params; - ReinitProcess($process, $host); -} + if ($host) { + ReinitProcess($process, $host); + } else { # Reinit whole cluster. + foreach my $host (keys %hostshash) { + ReinitProcess($process,$host); + } + } +} else { Usage; } @@ -338,6 +488,9 @@ Usage: =item strict =item Getopt::Long =item English +=item IO::Socket::UNIX + +=head1 KEY Subroutines. =head1 CATEGORIES Command line utility