#! /usr/bin/perl -w
##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************


##*******************************************************************
## Creates a local directory structure for a condor installation.
## Possibly installs a previously create local dir structure from
## archives.  It writes the location of the local_dir directories
## to a configuration file.  This file can be dynamically bound
## in later to bind a release installation to a local installation.
##
## Author: Joe Meehean
## Date: 7/26/05
##*******************************************************************

#***
# Uses
#***
use strict;
use FindBin;
use Getopt::Long;
use File::Spec;
use File::Path;
use File::Basename;

#***
# Constant Static Variables
#***
my $USAGE = "Usage: condor_install_local <-localdir local_dir>\n".
    "[-logarchive log_archive] [-spoolarchive spool_archive]\n".
    "[-execarchive exec_archive]\n".
    "[-configfile config_name]\n".
    "[-wget] [-globuslocation globus_location]\n".
    "[-f][-help]\n";

my $INSTALL_CONFIG_COMMENT = 
    " ## This configuration file was generated by condor_install_local\n";
    
my $DEFAULT_CONFIG_NAME = 'condor_config.local_dir';

#  condor_install_release variables
my $INSTALL_PROGRAM = 'install_release';
my $BASEDIR_OPT = '-basedir';
my $LOG_OPT = '-log';
my $FORCE_OPT = '-f';
my $WGET_OPT = '-wget';
my $GLOBUS_LOC_OPT = '-globuslocation';

#  condor_config variables
my $LOG_DIR_ATTR = 'LOG';
my $SPOOL_DIR_ATTR = 'SPOOL';
my $EXEC_DIR_ATTR = 'EXECUTE';

#***
# Non-Constant Static Variables
#***
my $local_dir = 0;
my $log_archive = 0;
my $spool_archive = 0;
my $exec_archive = 0;
my $config_file = 0;
my $globus_location = 0;
my $wget_flag = 0;
my $force = 0;
my $help = 0;

#***
# Main Function
#***
GetOptions('localdir=s'=>\$local_dir,
	   'logarchive=s'=>\$log_archive,
	   'spoolarchive=s'=>\$spool_archive,
	   'execarchive=s'=>\$exec_archive,
	   'configfile=s'=>\$config_file,
	   'wget'=>\$wget_flag,
	   'globuslocation=s'=>\$globus_location,
	   'force'=>\$force,
	   'help'=>\$help,
	   );

# Check the parameters
die $USAGE if( !$local_dir || $help );

# Ensure that all of the files specified actually exist
# Using check files dissallows installing from archives stored on the web
#&CheckFiles();

#Convert local dir to an absolute path
$local_dir = File::Spec->rel2abs($local_dir);

# Create a log directory
my $log_path = &CreateDir('log', $log_archive);

# Create a spool directory
my $spool_path = &CreateDir('spool', $spool_archive);

# Create a execute directory
my $execute_path = &CreateDir('execute', $exec_archive);

# Write out a local config file detailing the local dir structure
&WriteConfig($log_path, $spool_path, $execute_path);

#*********************************************************************
# Ensures that all of the directories and files specified actually
# exist.
#*********************************************************************
sub CheckFiles(){
    # create lists of the files and directories to check
    my @files = ($log_archive, $spool_archive, $exec_archive);
    my @dirs = ($local_dir);

    # Ensure each file exists
    foreach(@files){
	die "FAILED: $_ does not exist" if( $_ && !-e $_ );
    }

    # Ensure each directory exists
    foreach(@dirs){
	die "FAILED: $_ does not exist" if( $_ && !-e $_ );
	die "FAILED: $_ is not a directory" if( $_ && !-d $_ );
    }
}

#*********************************************************************
# Creates a local directory director (spool, log, or execute) from
# scratch or from an archive.
#*********************************************************************
sub CreateDir(){
    my ($dir_name, $archive) = @_;  #Name the parameters

    # Create the full directory path name
    my $dir_path = File::Spec->catdir($local_dir, $dir_name);

    # determine if the directory already exists
    if( -e $dir_path && !$force ){
	warn "WARNING: $dir_path already exists (no clobber)\n";
	return $dir_path;
    }

    # remove it if neccessary
    elsif( -e $dir_path && $force ){
	rmtree($dir_path, 0, 0);
    }

    # determine whether to install from an archive
    if( $archive ){
	&CreateDirFromArchive($archive);
    } 
    # OR to make a fresh directory
    else{
	&CreateDirFromScratch($dir_path);
    }
    
    # return the directory name
    return $dir_path;
}

#*********************************************************************
# Creates the given empty directory in the local directory
#*********************************************************************
sub CreateDirFromScratch(){
    my ($dir_path) = @_;  #Name the parameters
    
    mkdir $dir_path, 0755
	or die "FAILED: Failed to created $dir_path: $!";
}

#*********************************************************************
# Creates a directory in the local directory from an archive file
#*********************************************************************
sub CreateDirFromArchive(){
    my ($archive) = @_;   #Name the parameters

    # Create an install log name
    my $install_log = basename $archive.'.install_log';

    # Create the arguments for the install program
    my @install_args = ($archive,
			$FORCE_OPT,
			$BASEDIR_OPT, $local_dir,
			$LOG_OPT, $install_log,
			);

    push @install_args, $WGET_OPT if( $wget_flag );
    push @install_args, ($GLOBUS_LOC_OPT, $globus_location) if( $globus_location );

    # Find the install program path
    my $install_program_path = File::Spec->catpath(0, $FindBin::Bin, $INSTALL_PROGRAM);

    # Execute the install program
    #condor_install_release $archive -basedir $local_dir -log $install_log
    !system $install_program_path, @install_args
	or die "FAILED: Failed to install $archive, see $install_log";
}

#*********************************************************************
# Writes the location of the local_dir directories to a configuration
# file.
#*********************************************************************
sub WriteConfig(){
    my ($log_path, $spool_path, $exec_path) = @_;  #Name the parameters

    # if the user didn't specify a place for the config file
    # write it to the local_dir
    if( !$config_file ){
	$config_file = File::Spec->catpath(0, $local_dir, $DEFAULT_CONFIG_NAME);
    }

    # open the config file
    open CONFIG, "> $config_file"
	or die "Failed to open $config_file: $!";

    # append the comment
    print CONFIG $INSTALL_CONFIG_COMMENT;

    # append the location of the local_dir directories
    print CONFIG $LOG_DIR_ATTR, ' = ', $log_path, "\n";
    print CONFIG $SPOOL_DIR_ATTR, ' = ', $spool_path, "\n";
    print CONFIG $EXEC_DIR_ATTR, ' = ', $exec_path, "\n";

    # close the configuration file
    close CONFIG;
}
