Diff for /loncom/Attic/lonManage between versions 1.5 and 1.18

version 1.5, 2003/08/12 10:55:42 version 1.18, 2003/10/28 11:55:58
Line 33 Line 33
 #   it is a command line tool.  The following command line syntax (usage)  #   it is a command line tool.  The following command line syntax (usage)
 #   is supported:  #   is supported:
 #  #
 #    lonManage  -push   <tablename>  newfile  host  #    lonManage  -push   <tablename>  newfile  [host]
 #        Push <tablename> to the lonTabs directory.  Note that  #        Push <tablename> to the lonTabs directory.  Note that
 #        <tablename> must be one of:  #        <tablename> must be one of:
 #           hosts  (hosts.tab)  #           host  (hosts.tab)
 #           domain (domain.tab)  #           domain (domain.tab)
 #  #
 #    lonManage  -reinit lonc host  #    lonManage  -reinit lonc [host]
 #           Sends a HUP signal to the remote systems's lond.  #           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  #          Requests the remote system's lond perform the same action as if
 #          it had received a HUP signal.  #          it had received a HUP signal.
 #  #
 #    In the above syntax, the host above is the hosts.tab name of a host,  #    In the above syntax, the host above is the hosts.tab name of a host,
 #    not the IP address of the host.  #    not the IP address of the host
 #  #  
 #  $Log$  #   If [host] is not supplied, every host in the client's hosts.tab
 #  Revision 1.5  2003/08/12 10:55:42  foxr  #   table is iterated through and procesed..
 #  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.  
 #  #
 #  #
   
   
   
   # Modules required:
   
   use lib ".";
   
   use strict; # Because it's good practice.
   use English; # Cause I like meaningful names.
 use Getopt::Long;  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  {  sub Usage  {
     print "Usage:";      print "Usage:";
     print <<USAGE;      print <<USAGE;
     lonManage  --push=<tablename>  newfile  host   lonManage  [--myname=host --hosts=table] --push=<tablename>  newfile  [host]
         Push <tablename> to the lonTabs directory.  Note that          Push <tablename> to the lonTabs directory.  Note that
         <tablename> must be one of:          <tablename> must be one of:
            hosts  (hosts.tab)             host  (hosts.tab)
            domain (domain.tab)             domain (domain.tab)
   
     lonManage  --reinit=lonc host   lonManage [--myname=host --hosts=table] --reinit=lonc [host]
            Sends a HUP signal to the remote systems's lond.         Causes lonc in the remote system to reread hosts.tab and
          adjust the set of clients that are being maintained to match
     lonmanage  --reinit=lond host         the new file.
           Requests the remote system's lond perform the same action as if         
           it had received a HUP signal.  
    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,      In the above syntax, the host above is the hosts.tab name of a host,
     not the IP address of the 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  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.  #  Use Getopt::Long to parse the parameters of the program.
 #  #
Line 111  USAGE Line 157  USAGE
 #   returns an empty list if the parse fails.  #   returns an empty list if the parse fails.
 #  #
   
   
 sub ParseArgs {  sub ParseArgs {
     my $pushing   = '';      my $pushing   = '';
     my $reiniting = '';      my $reinitting = '';
   
     if(!GetOptions('push=s'    => \$pushing,      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 ();   return ();
     }      }
   
Line 129  sub ParseArgs { Line 187  sub ParseArgs {
   
     if($pushing ne '') {      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)) {
     print "Bad count $paramcount\n";  
     return (); # Invalid parameter count.      return (); # Invalid parameter count.
  }   }
  if($command ne '') {   if($command ne '') {
Line 146  sub ParseArgs { Line 203  sub ParseArgs {
   
     if ($reinitting ne '') {      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) {
     print "Bad count $paramcount\n";  
     return ();      return ();
  }   }
  if($command ne '') {   if($command ne '') {
Line 170  sub ParseArgs { Line 226  sub ParseArgs {
           
     return @result;      return @result;
 }  }
   #
   #  Read the loncapa configuration stuff.
   #
   sub ReadConfig {
       my $perlvarref = LondConnection::read_conf('loncapa.conf');
       %perlvar       = %{$perlvarref};
       my $hoststab   = LondConnection::read_hosts(
    "$perlvar{'lonTabDir'}/hosts.tab");
       %hostshash     = %{$hoststab};
   
   }
   #
   #  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 {
       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.
   #   The only legal files to push are hosts.tab and domain.tab.
   #   Security is somewhat improved by
   #   
   #   - Requiring the user run as root.
   #   - Connecting with lonc rather than lond directly ensuring this is a loncapa
   #     host
   #   - We must appear in the remote host's hosts.tab file.
   #   - The host must appear in our hosts.tab file.
   #
   #  Parameters:
   #     tablename - must be one of hosts or domain.
   #     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;
       my $host      = shift;
       
       # Open the table file:
   
       if(!open(TABLEFILE, "<$tablefile")) {
    die "ENOENT - No such file or directory $tablefile";
       }
     
       # Require that the host be valid:
   
       if(!ValidHost($host)) {
    die "EHOSTINVAL - Invalid host $host"; # Ok so I invented this 'errno'.
       }
       # Read in the file.  If the table name is valid, push it.
   
       my @table = <TABLEFILE>; #  These files are pretty small.
       close TABLEFILE;
   
       if( ($tablename eq "host")    ||
    ($tablename eq "domain")) {
    print("Pushing $tablename to $host\n");
    Transact($host, "pushfile:$tablename",\@table);
       } else {
    die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain";
       }
   }
 #  #
 #    If command parsing failed, then print usage:  #   This function is called to reinitialize a server in a remote host.
   #   The servers that can be reinitialized are:
   #   - lonc   - The lonc client process.
   #   - lond   - The lond daemon.
   #  NOTE:
   #    Reinitialization in this case means re-scanning the hosts table,
   #    starting new lond/lonc's as approprate and stopping existing lonc/lond's.
   #
   #  Parameters:
   #     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;
   
       #  Ensure the host is valid:
       
       if(!ValidHost($host)) {
    die "EHOSTINVAL - Invalid host $host";
       }
       # Ensure target process selector is valid:
   
       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";
       }
   }
   #--------------------------- Entry point: --------------------------
   
   ReadConfig; # Read the configuration info (incl.hosts).
   
   
 @status = ParseArgs;  #  Parse the parameters
 $nparam   = @status;  #  If command parsing failed, then print usage:
   
   my @params   = ParseArgs;
   my $nparam   = @params;
   
 if($nparam == 0) {  if($nparam == 0) {
     Usage;      Usage;
     exit -1;      exit -1;
 }  }
   #
 print "---- params ---\n";  #   Next, ensure we are running as EID root.
 for($i = 0; $i < $nparam; $i++) {  #
     print "Param[$i] = $status[$i]\n";  if ($EUID != 0) {
       die "ENOPRIV - No privilege for requested operation"
 }  }
   
   
   #   Based on the operation requested invoke the appropriate function:
   
   my $operation = shift @params;
   
   if($operation eq "push") {  # push tablename filename host
       my $tablename = shift @params;
       my $tablefile = shift @params;
       my $host      = shift @params;
       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;
       if ($host) {
    ReinitProcess($process, $host);
       } else { # Reinit whole cluster.
    foreach my $host (keys %hostshash) {
       ReinitProcess($process,$host);
    }
       }
   } 
   else {
       Usage;
   }
 exit 0;  exit 0;
   
 =head1 NAME  =head1 NAME
Line 217  Usage: Line 469  Usage:
   
 =head1 PREREQUISITES  =head1 PREREQUISITES
   
   =item strict
 =item Getopt::Long  =item Getopt::Long
   =item English
   =item IO::Socket::UNIX
   
   =head1 KEY Subroutines.
   
 =head1  CATEGORIES  =head1  CATEGORIES
     Command line utility      Command line utility

Removed from v.1.5  
changed lines
  Added in v.1.18


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