Diff for /loncom/Attic/lonManage between versions 1.25 and 1.26

version 1.25, 2003/11/04 11:52:06 version 1.26, 2003/12/22 11:02:36
Line 111  sub Usage  { Line 111  sub Usage  {
     If [host] is omitted, all hosts in the hosts.tab file are iterated      If [host] is omitted, all hosts in the hosts.tab file are iterated
     over.      over.
   
   lonManage [--myname=host --hosts=table] --edit=<tablename> editscript [host]
        Requests lond edit the hosts or domain table (selected by
        tablename) with the editing command in editscript.  If
        host is supplied the individual host is operated on,
        otherwise, the entire cluster is operated on.
        The edit file has edit request, one per line of the form:
        append|newline
        replace|key|newline
        delete|key
        The key is a loncapa hostname if editing the host file
        or a domain name if editing the domain table file.
   
  For all of the above syntaxes if --myname=host and --hosts=table are   For all of the above syntaxes if --myname=host and --hosts=table are
  supplied (both must be present), the utility runs in standalone mode   supplied (both must be present), the utility runs in standalone mode
  presenting itself to the world as 'host' and using the hosts.tab file   presenting itself to the world as 'host' and using the hosts.tab file
Line 160  sub SequenceStateMachine { Line 172  sub SequenceStateMachine {
     my $state        = $connection->GetState;      my $state        = $connection->GetState;
   
     while(($connection->GetState ne "Idle") && (!$error)) {      while(($connection->GetState ne "Idle") && (!$error)) {
  #        #
  # Figure out what the connection wants. read/write and wait for it        # Figure out what the connection wants. read/write and wait for it
  # or for the timeout.        # or for the timeout.
  #        #
  my $wantread = $connection->WantReadable;   my $wantread = $connection->WantReadable;
  my $poll     = new IO::Poll;   my $poll     = new IO::Poll;
  $poll->mask($Socket, => $wantread ? POLLIN : POLLOUT);   $poll->mask($Socket, => $wantread ? POLLIN : POLLOUT);
  $poll->poll($timeout);   my $handlecount = $poll->poll($timeout);
  my $done     = $poll->handles();   if($handlecount == 0) {            # no handles ready... timeout!!
  if(scalar($done) == 0) {            # no handles ready... timeout!!  
     $returnstatus  = "error:";      $returnstatus  = "error:";
     $returnstatus .= "Timeout in state $state\n";      $returnstatus .= "Timeout in state $state\n";
     $error         = 1;      $error         = 1;
  } else {   } else {
       my $done     = $poll->handles();
     my $status;      my $status;
     $status        = $wantread ? $connection->Readable :      $status        = $wantread ? $connection->Readable :
                          $connection->Writable;   $connection->Writable;
     if($status != 0) {      if($status != 0) {
  $returnstatus  =  "error:";   $returnstatus  =  "error:";
  $returnstatus .=  " I/O failed in state $state\n";   $returnstatus .=  " I/O failed in state $state\n";
Line 215  sub NegotiateStartup { Line 227  sub NegotiateStartup {
     my $returnstatus = "ok"; # Optimistic!!.      my $returnstatus = "ok"; # Optimistic!!.
   
     my $state      = $connection->GetState;      my $state      = $connection->GetState;
     if($state ne "Connected") {     if($state ne "Connected") {
  print "Error: Initial lond connection state: $state should be Connected\n";        print "Error: Initial lond connection state: $state should be Connected\n";
  return "error";        return "error";
     }     }
   
     return SequenceStateMachine($connection, $TransitionTimeout);     return SequenceStateMachine($connection, $TransitionTimeout);
 }  }
 #  #
 #   Perform a transaction with the remote lond.  #   Perform a transaction with the remote lond.
Line 245  sub PerformTransaction { Line 257  sub PerformTransaction {
     $connection->InitiateTransaction($command);      $connection->InitiateTransaction($command);
   
     my $status = SequenceStateMachine($connection, $TransitionTimeout);      my $status = SequenceStateMachine($connection, $TransitionTimeout);
     if($status eq "ok") {     if($status eq "ok") {
  $retval = $connection->GetReply;        $retval = $connection->GetReply;
     } else {     } else {
  $retval = $status;        $retval = $status;
     }     }
   
     return $retval;      return $retval;
 }  }
Line 267  sub subreply { Line 279  sub subreply {
     my $host = shift;      my $host = shift;
   
   
     my $connection  = MakeLondConnection($host);     my $connection  = MakeLondConnection($host);
     if ($connection eq undef) {     if ($connection eq undef) {
  return "Connect Failed";        return "Connect Failed";
     }     }
     my $reply = NegotiateStartup($connection);     my $reply = NegotiateStartup($connection);
     if($reply ne "ok") {     if($reply ne "ok") {
  return "connection negotiation failed";        return "connection negotiation failed";
     }     }
     my $reply =  PerformTransaction($connection, $cmd);     my $reply =  PerformTransaction($connection, $cmd);
     return $reply;     return $reply;
   
   
      #    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 317  sub subreply { Line 317  sub subreply {
   
   
 sub ParseArgs {  sub ParseArgs {
     my $pushing   = '';      my $pushing    = '';
     my $reinitting = '';      my $reinitting = '';
       my $editing    = '';
       
     if(!GetOptions('push=s'    => \$pushing,      if(!GetOptions('push=s'    => \$pushing,
            'reinit=s'  => \$reinitting,                     'reinit=s'  => \$reinitting,
    'myname=s' => \$MyHost,                     'edit=s'    => \$editing,
    'hosts=s' => \$ForeignHostTab)) {               'myname=s'  => \$MyHost,
  return ();               'hosts=s'   => \$ForeignHostTab)) {
     }        return ();
      }
     #  The --myname and --hosts switch must have values and      #  The --myname and --hosts switch must have values and
     #  most both appear if either appears:      #  most both appear if either appears:
   
     if(($MyHost ne "") && ($ForeignHostTab eq "")) {     if(($MyHost ne "") && ($ForeignHostTab eq "")) {
  return ();        return ();
     }     }
     if(($ForeignHostTab ne "") && ($MyHost eq "")) {     if(($ForeignHostTab ne "") && ($MyHost eq "")) {
  return ();        return ();
     }     }
   
     #  Require exactly   one of --push and --reinit      #  Require exactly   one of --push, --reinit, or --edit
   
     my $command    = '';     my $command    = '';
     my $commandarg = '';     my $commandarg = '';
     my $paramcount = @ARGV; # Number of additional arguments.     my $paramcount = @ARGV; # Number of additional arguments.
       
      my $commands = 0;           # Number of commands seen.
     if($pushing ne '') {  
      if($pushing ne '') {
         # --push takes in addition a table, and an optional  host:  
         #        # --push takes in addition a table, and an optional  host:
  if(($paramcount != 2) && ($paramcount != 1)) {        #
     return (); # Invalid parameter count.          
  }     if(($paramcount != 2) && ($paramcount != 1)) {
  if($command ne '') {           return (); # Invalid parameter count.
     return ();        }
  } else {  
           
     $command    = 'push';        $commands++;              # Count a command seen.
     $commandarg = $pushing;        $command    = 'push';
         $commandarg = $pushing;
  }   }
     }  
   
     if ($reinitting ne '') {     if ($reinitting ne '') {
   
  # --reinit takes in addition just an optional  host name   # --reinit takes in addition just an optional  host name
   
  if($paramcount > 1) {        if($paramcount > 1) {
     return ();           return ();
  }        }
  if($command ne '') {        $commands++;              #  Count a command seen.
     return ();        $command    = 'reinit';
  } else {        $commandarg = $reinitting; 
     $command    = 'reinit';  
     $commandarg = $reinitting;   
  }   }
     }  
      # --edit takes a script file and optional host name.
      #
      if ($editing ne "") {
         if(($paramcount != 2) && ($paramcount != 1)) {
            return ();              # Invalid parameter count.
         }
         
         $commands++;               # Count a command seen.
         $command    = 'edit';
         $commandarg = $editing;
      }
      
      #  At this point, $commands must be 1 or else we've seen
      #  The wrong number of command switches:
      
      if($commands != 1) {
         return ();
      }
   
     #  Build the result list:      #  Build the result list:
   
     my @result = ($command, $commandarg);     my @result = ($command, $commandarg);
     my $i;     my $i;
     for($i = 0; $i < $paramcount; $i++) {     for($i = 0; $i < $paramcount; $i++) {
  push(@result, $ARGV[$i]);        push(@result, $ARGV[$i]);
     }     }
           
     return @result;      return @result;
 }  }
 #  #
   #  Build the editor script.  This function:
   #  - Opens the edit script file.
   #  - Reads each line of the edit script file
   #  - Replaces the ending \n with a /
   #  - Appends it to the EditScript variable.
   #  - Returns the contents of the EditScript variable.
   #  Parameters:
   #     tabletype   - The type of table being built:
   #                   hosts or domain
   #     scriptname  - The script input file.
   #
   sub BuildEditScript {
      my $TableType    = shift;
      my $ScriptName   = shift;
      
      #Stub
      
      my @EditScript = (
         "$TableType\:append|".
            "nscll2\:nscl\:library\:lonkashy.nscl.msu.edu\:35.8.32.89"
         );
      return \@EditScript;
   }
 #  Read the loncapa configuration stuff.  If ForeignHostTab is empty,  #  Read the loncapa configuration stuff.  If ForeignHostTab is empty,
 #  assume we are part of a loncapa cluster and read the hosts.tab  #  assume we are part of a loncapa cluster and read the hosts.tab
 #  file from the config directory.  Otherwise, ForeignHossTab  #  file from the config directory.  Otherwise, ForeignHossTab
Line 393  sub ParseArgs { Line 433  sub ParseArgs {
 #  #
 sub ReadConfig {  sub ReadConfig {
   
     if($ForeignHostTab eq "") {  
  my $perlvarref = LondConnection::read_conf('loncapa.conf');     
  %perlvar       = %{$perlvarref};     if($ForeignHostTab eq "") {
  my $hoststab   = LondConnection::read_hosts(         my $perlvarref = LondConnection::read_conf('loncapa.conf');
     "$perlvar{'lonTabDir'}/hosts.tab");         %perlvar    = %{$perlvarref};
  %hostshash     = %{$hoststab};         my $hoststab   = LondConnection::read_hosts(
  $MyHost        = $perlvar{lonHostID}; # Set hostname from vars.     "$perlvar{lonTabDir}/hosts.tab");
  $ServerPort    = $perlvar{londPort};        %hostshash     = %{$hoststab};
     } else {        $MyHost        = $perlvar{lonHostID}; # Set hostname from vars.
         $ServerPort    = $perlvar{londPort};
      } else {
   
  LondConnection::ReadForeignConfig($MyHost, $ForeignHostTab);        LondConnection::ReadForeignConfig($MyHost, 
   my $hoststab = LondConnection::read_hosts($ForeignHostTab); #  we need to know too.                                          $ForeignHostTab);
   %hostshash   = %{$hoststab};        my $hoststab = LondConnection::read_hosts($ForeignHostTab); #  we need to know too.
   $ServerPort    = $DefaultServerPort;     %hostshash   = %{$hoststab};
       }     $ServerPort    = $DefaultServerPort;
          }
 }  }
 #  #
 #  Determine if the target host is valid.  #  Determine if the target host is valid.
Line 454  sub Transact { Line 496  sub Transact {
     my $body;      my $body;
     my $i;      my $i;
   
     if(scalar @ARG) {     if(scalar @ARG) {
  $body = shift;        $body = shift;
  $haveBody = 1;        $haveBody = 1;
     }     }
     #  Construct the command to send to the server:      #  Construct the command to send to the server:
           
     my $request = "encrypt\:"; # All requests are encrypted.     my $request = "encrypt\:"; # All requests are encrypted.
     $request   .= $command;     $request   .= $command;
     if($haveBody) {     if($haveBody) {
  $request .= "\:";        $request .= "\:";
  my $bodylines = scalar @$body;        my $bodylines = scalar @$body;
  for($i = 0; $i < $bodylines; $i++) {        for($i = 0; $i < $bodylines; $i++) {
     $request .= $$body[$i];           $request .= $$body[$i];
  }        }
     } else {     } else {
  $request .= "\n";        $request .= "\n";
     }     }
     # Body is now built... transact with lond..      # Body is now built... transact with lond..
           
     my $answer = subreply($request, $host);      my $answer = subreply($request, $host);
Line 494  sub Transact { Line 536  sub Transact {
 #     tablefile - name of the file containing the table to push.  #     tablefile - name of the file containing the table to push.
 #     host      - name of the host to push this file to.       #     host      - name of the host to push this file to.     
 #  #
 #    >>>BUGBUG<<< This belongs in lonnet.pm.  #    
 #  #
 sub PushFile {  sub PushFile {
     my $tablename = shift;      my $tablename = shift;
Line 503  sub PushFile { Line 545  sub PushFile {
           
     # Open the table file:      # Open the table file:
   
     if(!open(TABLEFILE, "<$tablefile")) {     if(!open(TABLEFILE, "<$tablefile")) {
  die "ENOENT - No such file or directory $tablefile";        die "ENOENT - No such file or directory $tablefile";
     }     }
       
     # Require that the host be valid:      # Require that the host be valid:
   
     if(!ValidHost($host)) {     if(!ValidHost($host)) {
  die "EHOSTINVAL - Invalid host $host"; # Ok so I invented this 'errno'.        die "EHOSTINVAL - Invalid host $host"; # Ok so I invented this 'errno'.
     }     }
     # Read in the file.  If the table name is valid, push it.      # Read in the file.  If the table name is valid, push it.
   
     my @table = <TABLEFILE>; #  These files are pretty small.     my @table = <TABLEFILE>; #  These files are pretty small.
     close TABLEFILE;     close TABLEFILE;
   
     if( ($tablename eq "host")    ||     if( ($tablename eq "host")    ||
  ($tablename eq "domain")) {         ($tablename eq "domain")) {
  print("Pushing $tablename to $host\n");        print("Pushing $tablename to $host\n");
  Transact($host, "pushfile:$tablename",\@table);        Transact($host, "pushfile:$tablename",\@table);
     } else {     } else {
  die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain";        die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain";
     }     }
 }  }
 #  #
   #   This function forms and executes an edit file with a
   #   remote lond server.  We build the full transaction string
   #   and use Transact to perform the transaction.
   #   Paramters:
   #      host     - loncapa name of host to operate on.
   #      body     - Body of the command.  We send:
   #                  edit:$body as the command request.
   #
   sub EditFile {
      my $host    = shift;
      my $body    = shift;
      
      if(!ValidHost($host)) {
         die "EHOSTINVAL - Invalid host $host";
      }
      Transact($host, "edit", $body);
   }
   
   #
 #   This function is called to reinitialize a server in a remote host.  #   This function is called to reinitialize a server in a remote host.
 #   The servers that can be reinitialized are:  #   The servers that can be reinitialized are:
 #   - lonc   - The lonc client process.  #   - lonc   - The lonc client process.
Line 541  sub PushFile { Line 602  sub PushFile {
 #   >>>BUGBUG<<<< This belongs  in lonnet.pm  #   >>>BUGBUG<<<< This belongs  in lonnet.pm
 #  #
 sub ReinitProcess {  sub ReinitProcess {
     my $process = shift;     my $process = shift;
     my $host    = shift;     my $host    = shift;
   
     #  Ensure the host is valid:      #  Ensure the host is valid:
           
     if(!ValidHost($host)) {     if(!ValidHost($host)) {
  die "EHOSTINVAL - Invalid host $host";        die "EHOSTINVAL - Invalid host $host";
     }     }
     # Ensure target process selector is valid:      # Ensure target process selector is valid:
   
     if(($process eq "lonc") ||     if(($process eq "lonc") ||
        ($process eq "lond")) {        ($process eq "lond")) {
  print("Reinitializing $process in $host\n");        print("Reinitializing $process in $host\n");
  Transact($host, "reinit:$process");        Transact($host, "reinit:$process");
     } else {     } else {
  die "EINVAL -Invalid parameter. Process $process must be lonc or lond";        die "EINVAL -Invalid parameter. Process $process must be lonc or lond";
     }     }
 }  }
 #--------------------------- Entry point: --------------------------  #--------------------------- Entry point: --------------------------
   
Line 595  if($operation eq "push") {  # push table Line 656  if($operation eq "push") {  # push table
     my $tablefile = shift @params;      my $tablefile = shift @params;
     my $host      = shift @params;      my $host      = shift @params;
     if($host) {      if($host) {
  PushFile($tablename, $tablefile, $host);        PushFile($tablename, $tablefile, $host);
     } else { # Push to whole cluster.      } else { # Push to whole cluster.
  foreach my $host (keys %hostshash) {        foreach my $host (keys %hostshash) {
     PushFile($tablename, $tablefile, $host);           PushFile($tablename, $tablefile, $host);
  }        }
     }      }
   
 } elsif($operation eq "reinit") { # reinit processname host.  } elsif($operation eq "reinit") { # reinit processname host.
Line 612  if($operation eq "push") {  # push table Line 673  if($operation eq "push") {  # push table
     ReinitProcess($process,$host);      ReinitProcess($process,$host);
  }   }
     }      }
 }   } elsif($operation eq "edit") {   # Edit a table.
      my $tablename     = shift @params;
      my $scriptfile    = shift @params;
      my $host          = shift @params;
      my $CommandBody   = BuildEditScript($tablename, $scriptfile);
      if ($host) {
         EditFile($host, $CommandBody);
      } else {
         foreach my $ClusterMember (keys %hostshash) {
            EditFile($ClusterMember, $CommandBody);
         }
      }
   }
 else {  else {
     Usage;     Usage;
 }  }
 exit 0;  exit 0;
   
Line 634  Usage: Line 707  Usage:
     B<lonManage  --reinit=lonc host>      B<lonManage  --reinit=lonc host>
            Sends a HUP signal to the remote systems's lond.             Sends a HUP signal to the remote systems's lond.
   
     B<lonmanage  --reinit=lond host>      B<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,      B<lonManage  --edit=<tablename> editscript host>
     not the IP address of the host.           Requests the remote system's lond perform an edit
            on <tablename>  editscript supplies a set of 
            editing commands.  Each edit command is one of :
            
            append|key|newline
            delete|key|
            replace|key|newline
            
            The key above is the value of the loncapa host name
            in the file.
            
   In the above syntax, the host above is the 
   hosts.tab name of a host,
   not the IP address of the host.
   
   
 =head1 DESCRIPTION  =head1 DESCRIPTION
Line 650  Usage: Line 736  Usage:
 =item Getopt::Long  =item Getopt::Long
 =item English  =item English
 =item IO::Socket::UNIX  =item IO::Socket::UNIX
   =item LONCAPA::LondConnection
   
 =head1 KEY Subroutines.  =head1 KEY Subroutines.
   

Removed from v.1.25  
changed lines
  Added in v.1.26


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