--- loncom/Attic/lonManage 2003/08/12 09:58:49 1.2 +++ loncom/Attic/lonManage 2003/08/18 10:43:31 1.10 @@ -3,9 +3,9 @@ # # lonManage supports remote management of nodes in a LonCAPA cluster. # -# $Id: lonManage,v 1.2 2003/08/12 09:58:49 foxr Exp $ +# $Id: lonManage,v 1.10 2003/08/18 10:43:31 foxr Exp $ # -# $Id: lonManage,v 1.2 2003/08/12 09:58:49 foxr Exp $ +# $Id: lonManage,v 1.10 2003/08/18 10:43:31 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -50,24 +50,67 @@ # not the IP address of the host. # # $Log: lonManage,v $ +# Revision 1.10 2003/08/18 10:43:31 foxr +# Code/test ValidHost. The hosts.tab and the perl variables are read in as +# global hashes as a side effect. May later want to clean this up by making +# a separate getconfig function and hoisting the config reads into that. +# +# 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. # # -sub Usage {} { +# Modules required: + +use strict; # Because it's good practice. +use English; # Cause I like meaningful names. +use Getopt::Long; +use LONCAPA::Configuration; # To handle configuration I/O. + +# File scoped variables: + +my %perlvar; # Perl variable defs from apache config. +my %hostshash; # Host table as a host indexed hash. + +sub Usage { print "Usage:"; print < newfile host + lonManage --push= newfile host Push to the lonTabs directory. Note that must be one of: hosts (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. @@ -79,11 +122,225 @@ USAGE } # -# If command parsing failed, then print usage: +# Use Getopt::Long to parse the parameters of the program. +# +# Return value is a list consisting of: +# A 'command' which is one of: +# push - table push requested. +# reinit - reinit requested. +# Additional parameters as follows: +# for push: Tablename, hostname +# for reinit: Appname hostname +# +# This function does not validation of the parameters of push and +# reinit. +# +# returns a list. The first element of the list is the operation name +# (e.g. reinit or push). The second element is the switch parameter. +# for push, this is the table name, for reinit, this is the process name. +# Additional elements of the list are the command argument. The count of +# command arguments is validated, but not their semantics. +# +# returns an empty list if the parse fails. +# + +sub ParseArgs { + my $pushing = ''; + my $reinitting = ''; + + if(!GetOptions('push=s' => \$pushing, + 'reinit=s' => \$reinitting)) { + return (); + } + + # Require exactly one of --push and --reinit + + my $command = ''; + my $commandarg = ''; + my $paramcount = @ARGV; # Number of additional arguments. + + + if($pushing ne '') { + + # --push takes in addition a table, and a host: + # + if($paramcount != 2) { + return (); # Invalid parameter count. + } + if($command ne '') { + return (); + } else { + + $command = 'push'; + $commandarg = $pushing; + } + } + + if ($reinitting ne '') { + + # --reinit takes in addition just a host name + + if($paramcount != 1) { + return (); + } + if($command ne '') { + return (); + } else { + $command = 'reinit'; + $commandarg = $reinitting; + } + } + + # Build the result list: + + my @result = ($command, $commandarg); + my $i; + for($i = 0; $i < $paramcount; $i++) { + push(@result, $ARGV[$i]); + } + + return @result; +} +# +# 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; + + my $perlvarref = LONCAPA::Configuration::read_conf('loncapa.conf'); + %perlvar = %{$perlvarref}; + my $hoststab = LONCAPA::Configuration::read_hosts( + "$perlvar{'lonTabDir'}/hosts.tab"); + %hostshash = %{$hoststab}; + + return defined $hostshash{$host}; + +} +sub Transact { -if(0) { +} +# +# 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. +# +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 = ; # These files are pretty small. + close TABLEFILE; + + if( ($tablename eq "host") || + ($tablename eq "domain")) { + Transact($host, "pushfile:$tablename:",\@table); + } else { + die "EINVAL - Invalid parameter. tablename: $tablename must be host or domain"; + } +} +# +# 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. +# +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")) { + Transact($host, "reinit:$process"); + } else { + die "EINVAL -Invalid parameter. Process $process must be lonc or lond"; + } +} +#--------------------------- Entry point: -------------------------- + +# Parse the parameters +# If command parsing failed, then print usage: + +my @params = ParseArgs; +my $nparam = @params; + +if($nparam == 0) { + Usage; + exit -1; +} +# +# Next, ensure we are running as EID root. +# +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; + PushFile($tablename, $tablefile, $host); + +} elsif($operation eq "reinit") { # reinit processname host. + my $process = shift @params; + my $host = shift @params; + ReinitProcess($process, $host); +} +else { Usage; } +exit 0; =head1 NAME lonManage - Command line utility for remote management of lonCAPA @@ -92,16 +349,16 @@ if(0) { =head1 SYNOPSIS Usage: - B newfile host> + B newfile host> Push to the lonTabs directory. Note that must be one of: hosts (hosts.tab) domain (domain.tab) - B + B Sends a HUP signal to the remote systems's lond. - B + B Requests the remote system's lond perform the same action as if it had received a HUP signal. @@ -113,6 +370,10 @@ Usage: =head1 PREREQUISITES +=item strict +=item Getopt::Long +=item English + =head1 CATEGORIES Command line utility