### ### Copyright 2000-2004 University of Illinois Board of Trustees ### All rights reserved. ### ### PSGConf::Action::PackageManager::Solaris - Solaris pkg action type for psgconf ### ### Campus Information Technologies and Educational Services ### University of Illinois at Urbana-Champaign ### package PSGConf::Action::PackageManager::Solaris; use strict; use PSGConf::Action::PackageManager::FTPArchive; use PSGConf::Data::String; use File::Basename; our @ISA = qw(PSGConf::Action::PackageManager::FTPArchive); ############################################################################### ### configuration constructor ############################################################################### sub conf { my ($class, $psgconf) = @_; my ($arch, $arch2); $arch = `/usr/bin/uname -m`; $arch2 = `/usr/bin/uname -p`; chomp $arch; chomp $arch2; if ( $arch eq "i86pc" ) { $arch = 'i'; ### Hacks to fix the mess from sunfreeware.com $arch2 = '((intel)|(i386)|(x86))'; } else { $arch =~ s/sun4//; } PSGConf::Action::PackageManager::FTPArchive->conf($psgconf); $psgconf->register_data( pkg_add_cmd => PSGConf::Data::String->new( value => "/usr/sbin/pkgadd" ), pkg_rm_cmd => PSGConf::Data::String->new( value => "/usr/sbin/pkgrm" ), pkg_info_cmd => PSGConf::Data::String->new( value => "/usr/bin/pkginfo" ), pkg_trans_cmd => PSGConf::Data::String->new( value => "/usr/bin/pkgtrans" ), pkg_gzip_cmd => PSGConf::Data::String->new( value => "/usr/bin/gzip" ), pkg_admin_file => PSGConf::Data::String->new( value => "dontask" ), pkg_dir => PSGConf::Data::String->new( value => "/var/sadm/pkg/" ), pkg_regex => PSGConf::Data::String->new( value => "\-sol[0-9]+\-${arch2}\-local\.gz" ), pkg_arch => PSGConf::Data::String->new( value => $arch ) ); } ############################################################################### ### pkg_get_installed() method ############################################################################### sub pkg_get_installed { my ($self, $psgconf) = @_; my (%pkg_installed_list); my ($cmd, $pkg, $ver); local *FP; $cmd = $psgconf->data_obj('pkg_info_cmd')->get(); $pkg = undef; $ver = undef; if (open (FP, "$cmd -l |")) { while () { chomp; if ( m/PKGINST: /o ) { s/^.*PKGINST: *//; $pkg = $_; } if ( m/VERSION: /o ) { s/^.*VERSION: *//; s/,REV=/_/; ### ### Hacks to clean up the version info from ### TSM and Emulex Packages ### s/^Release //; s/^Version //; s/ Release /./; s/ Level /./; $ver = $_; } if ( defined $pkg && defined $ver ) { push (@{$pkg_installed_list{$pkg}}, $ver); $ver = undef; $pkg = undef; } } close FP; } else { warn "\t!!! pkginfo failed: $!\n"; } return \%pkg_installed_list; } ############################################################################### ### pkg_get_latest_version() method ############################################################################### sub pkg_get_latest_version { my ($self, $psgconf, $pkg) = @_; my ($regex) = "(\Q${pkg}\E(\." . $psgconf->data_obj('pkg_arch')->get() . ")?\-[^-]+)" . $psgconf->data_obj('pkg_regex')->get(); return $self->get_latest_version ( $psgconf, $pkg, $psgconf->data_obj('env_vars')->find('SOL_PKG_UPDATE_PATH'), qr{$regex} ); } ############################################################################### ### pkg_get_dependencies() method ############################################################################### sub pkg_get_dependencies { my ($self, $psgconf, $pkg) = @_; my ($pkg2) = $self->Parse($pkg); my (@deps, $cmd, $file, $dir, @files); my ($regex) = "\Q${pkg}\E" . $psgconf->data_obj('pkg_regex')->get(); local *FP; ### ### IF we are working with a datastream package format covert ### to the directory format ### if ( ! -d $psgconf->data_obj('pkg_dir')->get() . $pkg2 ) { # Else find the package on the server # Need to escape the + and . in the package name, hence \Q and \E @files = $self->list_files_from_url( $psgconf, $psgconf->data_obj('env_vars')->find('SOL_PKG_UPDATE_PATH'), qr{$regex}); # we should have only found one entry if ( scalar @files == 1 ) { # See if we have the package tarball 'cached'. $file = &basename ($files[0]); $file = $self->get_file_from_url($psgconf, $files[0]) if ( ! -f "$psgconf->{tmpdir}/$file" ); if ( -f $file ) { $cmd = $psgconf->data_obj('pkg_gzip_cmd')->get(); $cmd .= ' -d ' . $psgconf->{tmpdir} . '/' . $file; &PSGConf::Util::RunCommand($cmd); $file =~ s/.gz$//; if ( -f $file ) { $cmd = $psgconf->data_obj('pkg_trans_cmd')->get(); $cmd .= ' ' . $file . ' . all'; &PSGConf::Util::RunCommand($cmd); $dir = $psgconf->{tmpdir} . '/' . $pkg2 . '/install'; } } } elsif ( ! scalar @files ) { warn "\tCould not find URL for ($pkg)\n"; } else { warn "\tFound too many URLs for ($pkg)\n"; } } else { $dir = $psgconf->data_obj('pkg_dir')->get() . $pkg2 . '/install'; } ### ### Now that we are in directory format (or it is already installed) ### read the depend file. ### if ( -f "$dir/depend" ) { if (open (FP, "$dir/depend" )) { grep (/^P ([^\s]*) /o && (push @deps, $1), ); close FP; } else { warn "\t!!! dependency file ($dir/depend) for ($pkg) could not be read\n"; } } return @deps; } ############################################################################### ### pkg_install() method ############################################################################### sub pkg_install { my ($self, $psgconf, $pkg) = @_; my ($cmd, $err, $file, @files); my ($regex) = "\Q${pkg}\E" . $psgconf->data_obj('pkg_regex')->get(); ### ### Find the location of the package ### @files = $self->list_files_from_url( $psgconf, $psgconf->data_obj('env_vars')->find('SOL_PKG_UPDATE_PATH'), qr{$regex}); # We must not have found any packages, so return right away return -1 if ( ! scalar @files ); ### ### Download it it in the tmp area. ### $file = &basename ($files[0]); $file = $self->get_file_from_url($psgconf, $files[0]) if ( ! -f "$psgconf->{tmpdir}/$file" ); # We must not have downloaded the file, so return right away. return -1 if ( ! -f "$psgconf->{tmpdir}/$file" ); ### ### Unpack it. ### $cmd = $psgconf->data_obj('pkg_gzip_cmd')->get(); $cmd .= ' -d ' . $psgconf->{tmpdir} . '/' . $file; return $err if (($err=&PSGConf::Util::RunCommand($cmd))); $file =~ s/.gz$//; ### ### Now that we have the package staged, install it. ### $cmd = $psgconf->data_obj('pkg_add_cmd')->get(); $cmd .= ' -na ' . $psgconf->data_obj('pkg_admin_file')->get(); $cmd .= ' -v ' if ($psgconf->{verbose}); $cmd .= ' -d ' . $psgconf->{tmpdir} . '/' . $file; $cmd .= ' all'; $err=&PSGConf::Util::RunCommand($cmd); print "\n" if ($psgconf->{verbose}); return $err; } ############################################################################### ### pkg_remove() method ############################################################################### sub pkg_remove { my ($self, $psgconf, $pkg, $force) = @_; my ($cmd, $err); ### ### Remove the version of the package if we have ### pkg_number_of_versions set to 1 ### ($pkg) = $self->Parse($pkg) if ( $self->{number_of_versions} <= 1 ); ### ### The force option is actually solved via the admin file. ### $cmd = $psgconf->data_obj('pkg_rm_cmd')->get(); $cmd .= ' -na ' . $psgconf->data_obj('pkg_admin_file')->get(); $cmd .= ' -v' if ($psgconf->{verbose}); $cmd .= ' ' . $pkg; $err=&PSGConf::Util::RunCommand($cmd); print "\n" if ($psgconf->{verbose}); return $err; } ############################################################################### ### documentation ############################################################################### 1; __END__ =head1 NAME PSGConf::Action::PackageManager::Solaris - install Solaris packages =head1 SYNOPSIS use PSGConf::Action::PackageManager::Solaris; $psgconf->register_actions( PSGConf::Action::PackageManager::Solaris->new( 'quiet' => 1 ), ... ); =head1 DESCRIPTION The B module provides a B action class for updating Solaris packages. The B class is derived from the B class, but it defines/overrides the following methods: =over 4 =item I A method that will assign values to the I, which will be all the packages currently installed. The I is a reference to a hash of arrays. The array is sorted to have versions in ascending order. Called from the B method. =item I A method that will return a B that contains the latest version of $pkg from the package repository. Called from the B method. =item I A method that will return a B that contains all the packages that $pkg will depend upon, regardless if they have been installed or not. This is for the package on the package repository and $pkg will have the version in it as well. Called from the B method. =item I A method that will install a $pkg on the system. Returns 0 for a successfull install, non-zero for a failure. Called from B method. =item I A method that will remove $pkg from the system, and may have to force the removal, depending on the value of $force, which will be a B. Returns 0 for a successfull install, non-zero for a failure. Called from B method. =back The constructor also registers the following data objects: =over 4 =item I A B object that determines where the F command is. The default is I. =item I A B object that determines where the F command is. The default is I. =item I A B object that determines where the F command is. The default is I. =item I A B object that determines where the F command is. The default is I. =item I A B object that determines where gzip is located. Used to unpack the data stream for installation. The default is I. =item I A B object that determines where the F and F command will use for the admin file, C<-a> option. The default is I. =item I A B object that determines where the information related to installed packages is stored. The default is I. =item I A B object that determines what the regex is to match against the FTPArchive listing. The default is I<\-sol[0-9]+\-(sparc|intel)\-local\.gz>. =item I A B object that determines the specific package architecture for installing SVR4 packages. Defaults to the output of C, sans F, on sparc platforms and I on x86. =back =head1 SEE ALSO L L L L L L Cpkgadd(1)E> Cpkginfo(1)E> Cpkgrm(1)E> =cut