#! perl use strict; use Carp; use Getopt::Long; use Cwd; use Config; # # Do a perl check for version >= 5.005. See 'gpt-translate-interpreter' should you # need to alter the invocation path to a valid perl interpreter in the GPT front-end # programs. # if ( ! ( defined eval "require 5.005" ) ) { die "GPT requires at least Perl version 5.005"; } # # dig the globus and gpt paths out of the user's environment variables # my $gpath; my $gpt_path = $ENV{GPT_LOCATION}; my $globus_path = $ENV{GLOBUS_LOCATION}; my $verbose; if ( !defined($gpt_path) && !defined($globus_path) ) { die("GPT_LOCATION and GLOBUS_LOCATION needs to be set before running this script"); } if ( defined($gpt_path) ) { $gpath = $gpt_path; } if ( defined($globus_path) && !defined($gpath) ) { $gpath = $globus_path; } if ( ! -d "$globus_path/etc/globus_packages" ) { die("Can't find a globus_packages directory to work on in your GLOBUS_LOCATION!\n"); } @INC = ("$gpath/lib/perl", "$gpath/lib/perl/$Config{'archname'}", @INC); if ( ! ( defined eval "require Grid::GPT::GPTObject" ) ) { die("$gpath does not appear to hold a valid GPT installation\n"); } require Pod::Usage; my($force, $error, $version, $help, $man, $location, $debug); # sub pod2usage { # my $ex = shift; # print "gpt-postinstall [-help -force -version]\n"; # exit $ex; # } GetOptions( 'force' => \$force, 'debug' => \$debug, 'verbose' => \$verbose, 'version' => \$version, 'help|?' => \$help, 'location=s' => \$globus_path, 'man' => \$man) or Pod::Usage::pod2usage(0); Pod::Usage::pod2usage(1) if $help; Pod::Usage::pod2usage(-verbose => 2) if $man; require Grid::GPT::GPTIdentity; Grid::GPT::GPTIdentity::print_gpt_version() if defined $version; require Grid::GPT::Installation; require Grid::GPT::SetupInstallation; require Grid::GPT::PackageFactory; require Grid::GPT::Algorithms; require Grid::GPT::PkgMngmt::Inform; my @pkg_queries = @ARGV; my $all = @pkg_queries < 1; my $log = new Grid::GPT::PkgMngmt::Inform( verbose => $verbose, debug => $debug ); my $locations = new Grid::GPT::Locations( installdir => $globus_path); my $list; my $installation = new Grid::GPT::Installation(locations => $locations, log => $log); if (! $all) { require Grid::GPT::Algorithms; my $checks = new Grid::GPT::Algorithms( log => $log, locations => $locations, ); $list = $checks->sort_input_patterns(inputs => \@pkg_queries); $list = find_pkgs($list); } else { $list = $installation->setup_pkgs(); } my $msg .= "The following setup packages were found:\n" if @$list; for my $p (@$list) { $msg .= "\t" .$p->label() ." ver: " . $p->version_label() . "\n"; } $log->debug($msg); my @postpkgs; my %postcommands; my $setupinstallation = new Grid::GPT::SetupInstallation(locations => $locations, log => $log); @$list = grep {$_->pkgtype() =~ m!pgm! } @$list; if ( !defined($force) ) { my $needs = $setupinstallation->check_for_setup_needs(pkgs => $list); if (defined $verbose or defined $debug or ! $all) { for my $p (@$list) { next if grep {$_->is_same($p)} @$needs; $log->inform($p->label() . " is already set up",1); } } $list = $needs; } $msg .= "The following packages need to be set up:\n" if @$list; for my $p (@$list) { $msg .= "\t" .$p->label() ." ver: " . $p->version_label() . "\n"; } $log->debug($msg); my @setupcommands; my $setupcmd; my $depnode; my $pkgset = new Grid::GPT::PkgSet; # # our first pass checks for collisions against the post install program. it # only adds packages to our package set that require post install programs which # we haven't seen yet be run. # for my $l (@$list) { # $l->printnode(); $setupcmd = trimSetupCommand($l->{'depnode'}->{'Post_Install_Program'}); if ( ! grep(/^$setupcmd$/, @setupcommands) ) { $depnode = $l->{'depnode'}; push(@setupcommands, $setupcmd); $pkgset->add_package(pkg => $depnode); } } # # print out the unsorted commands (for debugging) # # printf("\nunsorted commands\n"); # for my $s (@setupcommands) # { # printf("command = '%s'\n", $s); # } # # prep the package set and sort # $pkgset->set_depenv('Setup'); #open (OUT, ">./deptable.html"); #select(OUT); #print " # # # Globus Packages # # #

Installation Dependency Tree

\n"; #$pkgset->printtablehtml(); #print " # #"; $pkgset->sort_pkgs(); # # zero out our list of setup commands # @setupcommands = (); # # grab the packages that have been sorted and add them onto setup commands # for my $p (@{$pkgset->sorted()}) { $setupcmd = trimSetupCommand($p->{'depnode'}->{'Post_Install_Program'}); $setupcmd = formatSetupCommand($setupcmd); if (length($setupcmd) > 0) { push(@setupcommands, $setupcmd); } } # printf("\nsorted commands\n"); # for my $s (@setupcommands) # { # printf("command = '%s'\n", $s); # } if ( (scalar(@setupcommands) == 0) && !defined($error) && $all) { printf("All of the packages in your GLOBUS_LOCATION are already set up.\n"); exit; } else { runSetupCommands(@setupcommands); } #verifying that scripts have completed. $setupinstallation = new Grid::GPT::SetupInstallation(locations => $locations, log => $log); $list = $setupinstallation->check_for_setup_needs(pkgs => $pkgset->{'pkgs'}); my @bad; for my $p (@$list) { next if ! grep {$_->is_same($p)} @{$pkgset->{'pkgs'}}; push @bad, $p->label(); } exit 0 if ! @bad; print "WARNING: The following packages were not set up correctly:\n"; for my $l (@bad) { print "\t$l\n"; } print "Check the package documentation or run postinstall -verbose to see what happened\n"; exit; ### getFileLocation( $entity ) # # given an entity in the form of a unix-style path, remove the trailing entry # and return its parent directory. # sub getFileLocation { my($entity) = @_; my($dir); $dir = $entity; $dir =~ s:/+:/:g; # remove consecutive slashes $dir =~ s:/$::g; # remove trailing slash (just in case) $dir =~ s:/[^/]*$::; # remove trailing filename return $dir; } ### runSetupCommands # # given a list of setup commands, run them (in order) # sub runSetupCommands { my (@setupcommands) = @_; my $olddir; for my $s (@setupcommands) { printf("running %s..", $s); print "\n" if defined $verbose or defined $debug; action($s, getFileLocation($s)); printf("..Done\n") if ! defined $verbose and ! defined $debug; } } ### formatSetupCommand( $setupcmd ) # # prepend the setup path to the setup command # sub formatSetupCommand { my($setupcmd) = @_; my($newcmd, $tmpcmd1, $tmpcmd2); # # first check in $GL/setup/globus/ to maintain backwards compatibility # $tmpcmd1 = $globus_path . "/setup/globus/" . $setupcmd; if ( -x $tmpcmd1 ) { $newcmd = $tmpcmd1; return $newcmd; } # # otherwise check in $GL/setup/ to support new-style paths # $tmpcmd2 = $globus_path . "/setup/" . $setupcmd; if ( -x $tmpcmd2 ) { $newcmd = $tmpcmd2; return $newcmd; } # # warn that we can't find a match for $setupcmd # printf("WARNING: cannot locate an executable file at either\n"); printf("\t'$tmpcmd1'\n"); printf("or\n"); printf("\t'$tmpcmd2'\n"); printf("...giving up.\n"); $error = 1; return ""; } ### trimSetupCommand( $setupcmd ) # # given a string, trim extraneous characters off of it # sub trimSetupCommand { my ($setupcmd) = @_; $setupcmd =~ s:\n+::g; $setupcmd =~ s:^[\s]+|[\s]+$::g; $setupcmd =~ s:\s+: :g; return $setupcmd; } ### action( $command, $dir ) # # perform some command and inform the user # sub action { my ($command, $dir) = @_; my $pwd; if (defined $dir) { $pwd = cwd(); $log->inform("[ Changing to $dir ]",1); chdir($dir); } my $result = system( "GLOBUS_LOCATION=$locations->{'installdir'}; \\ export GLOBUS_LOCATION; \\ GPT_LOCATION=$gpath; \\ export GPT_LOCATION; \\ $command 2>&1"); if ($result or $?) { # results are bad print them out. die("ERROR: Command failed\n"); } if (defined $dir) { $log->inform("[ Changing to $pwd ]"); chdir($pwd); } } sub find_pkgs { my ($queries) = @_; my @bad; my @pkgs; for my $q (@$queries) { my $cands = $installation->query(%$q); my $input = "$q->{'pkgname'}-$q->{'flavor'}-$q->{'pkgtype'}"; $input =~ s!ANY!*!g; # Complain about pattern if it does not come from a bundle. if (! defined $cands) { push @bad, $input; next; } my $msg = "Query: $input found the following setup packages:\n"; for my $c (@$cands) { next if ! defined $c->setupname(); $msg .= "\t" . $c->label() . "\n"; push @pkgs, $c; } $log->debug($msg); } if (@bad) { print "ERROR: The following does not match any packages:\n"; for my $b (@bad) { print "\t$b->{'pkgname'}-$b->{'flavor'}-$b->{'pkgtype'}\n"; } exit 1; } return \@pkgs; } =head1 NAME B - Searches for post install scripts and executes them =head1 SYNOPSIS gpt-postinstall [-help -force -version -man -location ] =head1 DESCRIPTION B Searches an installation for post-install scripts that have not been run yet and executes them. These scripts are installed by Setup packages and are designed to localize an installation. The I<-force> flag can be used to re-run all of the setup scripts. =head1 OPTIONS =over 8 =item B<-force> forces all action to be taken, regardless of state. =item B<-help> Print a brief help message and exits. =item B<-man> Prints the manual page and exits. =item B<-version> Prints the version of GPT and exits. =item B<-location> Location indicates the path to the Globus installation that will be used. =back =head1 SEE ALSO gpt-install(1) gpt-uninstall(1) gpt-verify(1) =head1 AUTHOR Michael Bletzinger Embletzin.ncsa.uiuc.eduE and Eric Blau Eeblau.ncsa.uiuc.eduE =cut