[Swift-commit] r3434 - usertools/swift/swiftconfig/bin

noreply at svn.ci.uchicago.edu noreply at svn.ci.uchicago.edu
Wed Jul 14 06:03:10 CDT 2010


Author: davidk
Date: 2010-07-14 06:03:10 -0500 (Wed, 14 Jul 2010)
New Revision: 3434

Modified:
   usertools/swift/swiftconfig/bin/swiftconfig
Log:
interactive editor, auths.default, new split directory structure, better error handling

Modified: usertools/swift/swiftconfig/bin/swiftconfig
===================================================================
--- usertools/swift/swiftconfig/bin/swiftconfig	2010-07-13 19:43:19 UTC (rev 3433)
+++ usertools/swift/swiftconfig/bin/swiftconfig	2010-07-14 11:03:10 UTC (rev 3434)
@@ -1,132 +1,257 @@
 #!/usr/bin/perl
 
-# Find swift configuration files and libraries
-if ( $ENV{'SWIFT_HOME'} ) {
+use Cwd;
+use Cwd qw(abs_path);
+use File::Copy;
+use File::Path qw(remove_tree);
+use 5.010;
+
+my $swifthome = '';
+if ( $ENV{'SWIFT_HOME'} && -e "$ENV{'SWIFT_HOME'}/bin/swift" ) {
     $swifthome = $ENV{'SWIFT_HOME'};
 }
-else {
-    @path = split( '/', which("swift") );
-    @path = splice( @path, 0, $#path - 1 );
-    $swifthome = join( '/', @path );
+
+my @path = split( '/', abs_path($0) );
+my @path = splice( @path, 0, $#path - 1 );
+my $parent_directory = join( '/', @path );
+
+if ( !$swifthome ) {
+    if ( -e "$parent_directory/bin/swift" ) {
+        $swifthome = $parent_directory;
+    }
+
+    else {
+        @path = split( '/', which("swift") );
+        @path = splice( @path, 0, $#path - 1 );
+        my $tmp = join( '/', @path );
+        if ( -e "$tmp/bin/swift" ) {
+            $swifthome = $tmp;
+        }
+    }
 }
 
-use FindBin;
+use FindBin qw($Bin);
 use lib "$FindBin::Bin/../lib/perl";    # Use libraries in $swifthome/lib/perl
 use Getopt::Long;
 use File::Which qw(which where);
 use XML::Simple;
+use Data::Dumper;
 
 # Variables used for translation catalog
-my $host     = 'localhost';                 # Host name
-my $name     = '';                          # Translation name
-my $path     = "/usr/bin/$name";            # Full path of executable location
-my $status   = 'INSTALLED';                 # Installation status (not used)
-my $platform = 'INTEL32::LINUX';            # Platform (not used)
-my $profile  = 'null';                      # Profile entries
-my $tcfile   = "$swifthome/etc/tc.data";    # Location of TC file
+my $host     = 'localhost';             # Host name
+my $name     = '';                      # Translation name
+my $path     = "/usr/bin/$name";        # Full path of executable location
+my $status   = 'INSTALLED';             # Installation status (not used)
+my $platform = 'INTEL32::LINUX';        # Platform (not used)
+my $profile  = 'null';                  # Profile entries
 
 # Variables used for sites.xml
-my $templatefile = "$swifthome/etc/sites-template.xml"; # Template file
-my $template     = '';                                  # Use template entry
-my $templates    = 0;                                   # List all templates
-my $sitesfile    = "$swifthome/etc/sites.xml";          # Working sites.xml file
-my $entry       = '';    # Name of new entry (pool handle)
-my $gridftp     = '';    # Specify gridftp URL
-my $jobuniverse = '';    # Specify jobmanager universe
-my $joburl      = '';    # Specify jobmanager URL
-my $jobmajor    = '';    # Jobmanager major value
-my $jobminor    = '';    # Jobmanager minor value
-my $directory   = '';    # Work directory
-my $exprovider  = '';    # Execution provider
-my $exmanager   = '';    # Execution job manager
-my $exurl       = '';    # Execution URL
-my $remove      = '';    # Remove entry from sites.xml
-my $modify      = '';    # Modify mode
+my $templates = 0;                      # List all templates
+my $remove    = '';                     # Remove entry from sites.xml
+my $modify    = '';                     # Modify mode
+my @validproviders = ( "gt4", "local", "pbs", "condor", "ssh", "coaster" );
+my $keyfile  = "$ENV{'HOME'}/.ssh/id_rsa";
 
 # Assign variables from command line options
 GetOptions(
-    'host=s'         => \$host,
-    'name=s'         => \$name,
-    'path=s'         => \$path,
-    'status=s'       => \$status,
-    'platform=s'     => \$platform,
-    'profile=s'      => \$profile,
-    'tcfile=s'       => \$tcfile,
-    'templatefile=s' => \$templatefile,
-    'add=s'          => \$add,
-    'sitesfile=s'    => \$sitesfile,
-    'gridftp=s'      => \$gridftp,
-    'jobuniverse=s'  => \$jobuniverse,
-    'joburl=s'       => \$joburl,
-    'jobmajor=i'     => \$jobmajor,
-    'jobminor=i'     => \$jobminor,
-    'directory=s'    => \$directory,
-    'exprovider=s'   => \$exprovider,
-    'exmanager=s'    => \$exmanager,
-    'exurl=s'        => \$exurl,
-    'remove=s'       => \$remove,
-    'templates'      => \$templates,
-    'modify=s'       => \$modify,
-    'key=s'          => \$key,
-    'namespace=s'    => \$namespace,
-    'value=s'        => \$value
+    'add=s'       => \$add,
+    'remove=s'    => \$remove,
+    'templates'   => \$templates,
+    'modify=s'    => \$modify,
+    'swifthome=s' => \$swifthome,
+    'sites'     => \$sites
 );
 
+# Create a new directory if it does not exist
+sub create_directory {
+    $directory = $_[0];
+    if ( !-d "$directory" ) {
+        mkdir "$directory", 0700
+          or die "Unable to create directory $directory\n";
+    }
+}
+
+# Process keyboard input
+sub getEntry {
+    my ($description, $value, @valid) = @_;
+
+    print "$description [$value]: ";
+    my $newvalue = "";
+    chomp($newvalue = <STDIN>);
+    if ($newvalue) { $value = $newvalue; }
+    my $isvalid = 0;
+
+    if(@valid) {
+        foreach(@valid) {
+            if($_ eq $value){ $isvalid = 1; }
+        }
+        if(!$isvalid) {
+            my $msg = "";
+	    foreach(@valid) { $msg .=  $_ . " "; }
+	    print "Invalid value selected. Please select from: $msg\n";
+            $value = getEntry($description, $value, @valid);
+        }
+    }
+
+    return $value;
+}
+
 # Prepare data
-$xml           = new XML::Simple();
-$template_data = $xml->XMLin(
-    "$templatefile",
-    ForceArray => [qw(workdirectory pool profile)],
-    KeyAttr    => []
-);
-$sites_data = $xml->XMLin(
-    "$sitesfile",
-    ForceArray => [qw(workdirectory pool profile)],
-    KeyAttr    => []
-);
-open( TCFILESTREAM, "$tcfile" ) or die("Unable to open tc file $tcfile!");
- at tcdata = <TCFILESTREAM>;
-close(TCFILESTREAM);
+my $xml = new XML::Simple();
 
+# Create all required directories
+my $dotswift = "$ENV{'HOME'}/.swift";
+create_directory("$ENV{'HOME'}/.ssh");
+create_directory("$dotswift");
+create_directory("$dotswift/sites");
+
+# Determine the template directory
+my @path = split( '/', abs_path($0) );
+my @path = splice( @path, 0, $#path - 1 );
+my $template_directory = join( '/', @path ) . "/etc/sites";
+
+# Add new entry to auths.default
+sub add_ssh_auth
+{
+    my ($entry, $site) = @_;
+
+    # Open authfile
+    my $authfile = "$dotswift/sites/$entry/auth.defaults";
+    create_directory("$dotswift/sites/$entry");
+    if ( -e "$authfile" ) { open( AUTHFILE, "$authfile" ) || die "Unable to open auth file $authfile for reading!\n"; }
+    else { open( AUTHFILE, ">$authfile" ) || die "Unable to open $authfile for writing!\n"; }
+    @authdata = <AUTHFILE>;
+    close(AUTHFILE);
+
+    # Create RSA keypair if needed
+    if ( !-e "$keyfile" ) {
+        system("ssh-keygen -t rsa -f $keyfile");
+    }
+
+    # Get existing username and passphrase values
+    my $username;
+    my $passphrase;
+    foreach (@authdata) {
+        if (/username/i) { (my $blah, $username) = split('=', $_); chomp($username); }
+        if (/passphrase/i) { (my $blah, $passphrase) = split('=', $_); chomp($passphrase); } 
+    }
+    if(!$username){ $username = getlogin(); }
+
+    $username = getEntry("Username", $username);
+    $passphrase = getEntry("Passphrase", $passphrase);
+
+    # Remove old auth.defaults if it already exists
+    if(-e "$authfile") { 
+        unlink($authfile) || die "Unable to remove $authfile\n"; 
+        @authdata = ();
+    }
+
+    # Add data to new auth.defaults
+    push( @authdata, "$site.type=key\n" );
+    push( @authdata, "$site.username=$username\n" );
+    push( @authdata, "$site.key=$keyfile\n" );
+    push( @authdata, "$site.passphrase=$passphrase\n" );
+    write_file( $authfile, @authdata );
+}
+
+# Update TC with correct hostname
+sub update_tc_hostname {
+    my ($filename, $host) = @_;
+    # Store TC data
+    open( TCFILESTREAM, "$filename" ) or die("Unable to open tc file $tcfile!");
+    @tcdata = <TCFILESTREAM>;
+    close(TCFILESTREAM);
+
+    foreach $line (@tcdata) {
+        # Ignore comments
+        if ( substr( $line, 0, 1 ) eq '#' ) {
+            next;
+        }
+
+	# Replace old entry with new entry
+        my ( $tmphost, $tmpname, $tmppath, $tmpstatus, $tmpplatform, $tmpprofile ) = split( /\s+/, $line );
+        $tmphost = $host;
+        $line    = "$tmphost\t$tmpname\t$tmppath\t$tmpstatus\t$tmpplatform\t$tmpprofile\n";
+   }
+
+   write_file( $filename, @tcdata);
+}
+
 # Update XML hash with values from command line
 sub update_xml_entry {
-    my $xml_data = @_[0];
-    my $name     = @_[1];
-    foreach my $e ( @{ $xml_data->{pool} } ) {
-        if ( $name eq $e->{handle} ) {
-            $e->{workdirectory}[0] =~ s/\$HOME/$ENV{'HOME'}/;
-            if ($gridftp)     { $e->{gridftp}{url}          = $gridftp; }
-            if ($jobuniverse) { $e->{jobmanager}{universe}  = $jobuniverse; }
-            if ($joburl)      { $e->{jobmanager}{url}       = $joburl; }
-            if ($jobmajor)    { $e->{jobmanager}{major}     = $jobmajor; }
-            if ($jobminor)    { $e->{jobmanager}{minor}     = $jobminor; }
-            if ($directory)   { $e->{workdirectory}         = [$directory]; }
-            if ($exprovider)  { $e->{execution}{provider}   = $exprovider; }
-            if ($exmanager)   { $e->{execution}{jobmanager} = $exmanager; }
-            if ($exurl)       { $e->{execution}{url}        = $exurl; }
 
-            if ( $key && $namespace && $value ) {
-                my $found = 0;
-                foreach my $profile ( @{ $e->{profile} } ) {
-                    if ( $profile->{key} eq $key ) {
-                        $profile->{key}       = $key;
-                        $profile->{namespace} = $namespace;
-                        $profile->{content}   = $value;
-                        $found                = 1;
-                    }
-                }
-                if ( !$found ) {
-                    push @{ $e->{profile} },
-                      {
-                        key       => $key,
-                        namespace => $namespace,
-                        content   => $value
-                      };
-                }
+    my ($filename) = @_;
+    if ( !-e $filename ) { return 0; }
+    my $entryname = "";
+    my $tcfile = "";
+
+    my $xml_data = $xml->XMLin(
+        $filename,
+        ForceArray => [qw(workdirectory profile)],
+        KeyAttr    => []
+    );
+
+    # Renaming
+    if($modify)
+    {
+	$entryname = getEntry("Site Entry Name", $modify);
+	$tcfile = "$dotswift/sites/$modify/tc.data";
+	print "tcfile: $tcfile\n";
+        if($entryname ne $modify) {
+            if(!-d "$dotswift/sites/$entryname" && -d "$dotswift/sites/$modify") {
+                move("$dotswift/sites/$modify", "$dotswift/sites/$entryname") || die "Unable to rename $dotswift/sites/$modify to $dotsite/sites/$entryname";
             }
-            return $e;
+    	    $xml_data = $xml->XMLin("$dotswift/sites/$entryname/sites.xml", ForceArray => [qw(workdirectory profile)], KeyAttr => []);
+            $tcfile = "$dotswift/sites/$entryname/tc.data";
         }
     }
+    
+    # Adding
+    if($add){ 
+        $entryname = getEntry("Site Entry Name", $add);
+        if( -e "$dotswift/sites/$entryname/sites.xml") {
+            die "Entry file for $entryname already exists. Use -modify to change settings\n";
+        }
+	create_directory("$dotswift/sites/$entryname");
+        if(-e "$template_directory/$add/tc.data") { $tcfile = "$template_directory/$add/tc.data"; } 
+        elsif (-e "$dotswift/sites/$add/tc.data") { $tcfile = "$dotswift/sites/$add/tc.data"; }
+	copy("$tcfile", "$dotswift/sites/$entryname") || die "Unable to copy $tcfile to $dotswift/sites/$entryname\n";
+    }
+
+    $xml_data->{pool}{handle} = $entryname;
+    if(!-d "$dotswift/sites/$entryname") {
+        create_directory("$dotswift/sites/$entryname");
+    }
+    $filename = "$dotswift/sites/$entryname/sites.xml";    
+
+    # Replace values if requested by user
+    $xml_data->{pool}{workdirectory}[0] =~ s/\$HOME/$ENV{'HOME'}/;
+    if ( $xml_data->{pool}{gridftp} ) { $xml_data->{pool}{gridftp} = getEntry( "GridFTP URL", $xml_data->{pool}{gridftp}{url} ); }
+    if ( $xml_data->{pool}{workdirectory} ) { $xml_data->{pool}{workdirectory} = [ getEntry( "Work Directory", $xml_data->{pool}{workdirectory}[0] ) ]; }
+    if ( $xml_data->{pool}{jobmanager} ) {
+        if ( $xml_data->{pool}{jobmanager}{universe} ) { $xml_data->{pool}{jobmanager}{universe} = getEntry( "Job Universe", $xml_data->{pool}{jobmanager}{universe} ); }
+        if ( $xml_data->{pool}{jobmanager}{url} ) { $xml_data->{pool}{jobmanager}{url} = getEntry( "Job Manager URL", $xml_data->{pool}{jobmanager}{url} ); }
+        if ( $xml_data->{pool}{jobmanager}{major} ) { $xml_data->{pool}{jobmanager}{major} = getEntry( "Job Major Number", $xml_data->{pool}{jobmanager}{major} ); }
+        if ( $xml_data->{pool}{jobmanager}{minor} ) { $xml_data->{pool}{jobmanager}{minor} = getEntry( "Job Minor Number", $xml_data->{pool}{jobmanager}{minor} ); }
+    }
+    if ( $xml_data->{pool}{execution} ) {
+        if ( $xml_data->{pool}{execution}{provider} ) { $xml_data->{pool}{execution}{provider} = getEntry( "Execution Provider", $xml_data->{pool}{execution}{provider}, @validproviders); }
+        if ( $xml_data->{pool}{execution}{jobmanager} ) { $xml_data->{pool}{execution}{jobmanager} = getEntry( "Execution Job Manager", $xml_data->{pool}{execution}{jobmanager} ); }
+        if ( $xml_data->{pool}{execution}{url} ) { 
+            my $previous_site = $xml_data->{pool}{execution}{url};
+            $xml_data->{pool}{execution}{url} = getEntry( "Execution URL", $xml_data->{pool}{execution}{url} );
+	    update_tc_hostname("$tcfile", $xml_data->{pool}{execution}{url});
+       }
+    }
+    if ( $xml_data->{pool}{filesystem} ) {
+        if ( $xml_data->{pool}{filesystem}{provider} ) { $xml_data->{pool}{filesystem}{provider} = getEntry( "Filesystem Provider", $xml_data->{pool}{filesystem}{provider}, @validproviders); }
+        if ( $xml_data->{pool}{filesystem}{url} ) { $xml_data->{pool}{filesystem}{url} = getEntry( "Filesystem URL", $xml_data->{pool}{filesystem}{url} ); }
+    }
+    if ( $xml_data->{pool}{execution}{provider} eq "ssh") {
+	add_ssh_auth($entryname, $xml_data->{pool}{execution}{url});
+    } 
+
+    write_file( $filename, $xml->XMLout( $xml_data, RootName => 'config', SuppressEmpty => 1 ) );
 }
 
 # Write a file given variable and filename
@@ -137,92 +262,56 @@
     close(TEMPFILESTREAM);
 }
 
+# Print all files in a directory
+sub print_directory {
+    my ($template_directory) = @_;
+    chdir($template_directory) || die "Unable to change directories to $template_directory\n";
+    my @files = <*>;
+    foreach $file(@files)
+    {
+	(my $basename, my $ext) = split(/\./, $file);
+	my @path = split( '/', $basename);
+	print "$basename\n";
+    }  
+}
+
 # If a template is specified, find the correct one and modify as needed
 if ($add) {
-    my $data = update_xml_entry( $template_data, $add );
-
-    # Modify existing entry
-    my $isfound = 0;
-    foreach my $e ( @{ $sites_data->{pool} } ) {
-        if ( $add eq $e->{handle} ) {
-            $e       = $data;
-            $isfound = 1;
-        }
-    }
-
-    # Add new entry
-    if ( !$isfound ) {
-        push @{ $sites_data->{pool} }, $data;
-    }
-
-    # Write to sites file
-    write_file( $sitesfile, $xml->XMLout( $sites_data, RootName => 'config' ) );
+    my $data = 0;
+    $data = update_xml_entry("$template_directory/$add/sites.xml");
+    if ( $data == 0 ) { $data = update_xml_entry("$dotswift/sites/$add/sites.xml"); }
+    if ( $data == 0 ) { die "Unable to find template for $add\n"; }
 }
 
 # Remove an entry
 if ($remove) {
 
-    # Look first for a site to remove
-    $isfound = 0;
+      if(!-d "$dotswift/sites/$remove") {
+          "Unable to find site entry for $remove\n";
+      }
 
-    foreach my $e ( @{ $sites_data->{pool} } ) {
-        if ( $remove eq $e->{handle} ) {
-            undef $e;
-            $isfound = 1;
-        }
-    }
-
-    # Write to sites file
-    if ($isfound) {
-        write_file(
-            $sitesfile,
-            $xml->XMLout(
-                $sites_data,
-                RootName      => 'config',
-                SuppressEmpty => 1
-            )
-        );
-    }
-
-    # If no site found, check for a TC entry
-    else {
-        foreach $line (@tcdata) {
-
-            # Ignore comments
-            if ( substr( $line, 0, 1 ) eq '#' ) {
-                next;
-            }
-            ( $tmphost, $tmpname, @junk ) = split( /\s+/, $line );
-
-            # Replace old entry with new entry
-            if ( $remove eq $tmpname ) {
-                $line = "";
-            }
-        }
-        write_file( $tcfile, @tcdata );
-    }
+      remove_tree("$dotswift/sites/$remove") || die "Unable to remove directory $dotswift/sites/$remove\n";
 }
 
 # List all available templates
 if ($templates) {
-    foreach my $e ( @{ $template_data->{pool} } ) {
-        print $e->{handle} . "\n";
-    }
+    print_directory($template_directory);
 }
 
+# List all user-added sites
+if($sites) {
+    print_directory("$dotswift/sites");
+}
+
 # Modify a site entry
 if ($modify) {
-    my $data = update_xml_entry( $sites_data, $modify );
 
-    # Modify entry if one already exists
-    foreach my $e ( @{ $sites_data->{pool} } ) {
-        if ( $modify eq $e->{handle} ) {
-            $e = $data;
-        }
+    if(!-e "$dotswift/sites/$modify/sites.xml") {
+        die "Unable to find entry for $modify\n";
     }
 
-    write_file( $sitesfile,
-        $xml->XMLout( $sites_data, RootName => 'config', SuppressEmpty => 1 ) );
+    my $data = update_xml_entry( "$dotswift/sites/$modify/sites.xml" );
+
 }
 
 # Add or modify a TC entry
@@ -252,6 +341,7 @@
 }
 
 __END__
+
 =head1 NAME
 
 swiftconfig - Utility for managing Swift configuration
@@ -269,35 +359,9 @@
 General operations:
    -add sitename		add a site from template
    -remove site		removes a site from sites.xml
-   -remove command		removes a command from the catalog
    -templates			display all available sites in template
    -modify site		Specifies the name of a site to modify
 
-Translation catalog settings:
-   -host hostname		hostname of the translation catalog entry
-   -name name			translation name
-   -path path			full pathname to location of program
-   -status status		installation status (deprecated)
-   -profile setting		define the profile value for an entry
-   -tcfile filename		explicitly specify a translation file
-
-Sites settings:
-   -templatefile file	explicitly set the template file to use
-   -sitesfile file		explicitly set the sites file to use
-   -gridftp GridFTPURL	GridFTP URL
-   -jobuniverse universe	job manager universe
-   -joburl URL			job manager URL
-   -jobmajor major		job mager number
-   -jobminor minor		job minor number
-   -directory dir		work directory
-   -exprovider name		execution provider
-   -exmanager name		execution job manager
-   -exurl URL			execution URL
-   -key key			profile key
-   -value value		profile value
-   -namespace name		profile namespace
-
-
 =head1 EXAMPLES
 
 List all templates available for adding
@@ -307,20 +371,11 @@
    swiftconfig -add teraport
 
 Modify the work directory of a site
-   swiftconfig -modify teraport -directory /var/tmp
+   swiftconfig -modify teraport
 
 Remove a site
    swiftconfig -remove teraport
 
-Add a new command to translation catalog
-   swiftconfig -name convert -path /usr/local/bin/convert
-
-Modify an existing command in the translation catalog
-   swiftconfig -name convert -path /usr/bin/convert
-
-Remove a command from the translation catalog
-   swiftconfig -remove convert
-
 =head1 CAVEATS
 
 Swiftconfig will attempt to automatically determine the location of swift configuration files. It first checks for an environment variable called $SWIFT_HOME. If that is not found, it will look for the location of "swift" in the path, and try to find the configuration files from there. This default behavior can be overwridden by manually specifying the location of files with -templatefile, -sitesfile, and -tcfile.




More information about the Swift-commit mailing list