diff --git a/xCAT/postscripts/aixswupdate b/xCAT/postscripts/aixswupdate new file mode 100755 index 000000000..3ae249927 --- /dev/null +++ b/xCAT/postscripts/aixswupdate @@ -0,0 +1,680 @@ +#!/usr/bin/env perl -w +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +##################################################### +# +# xCAT post script for AIX nodes +# +# This script is used to update software on AIX +# standalone systems. +# - it is executed by the updatenode command +# +##################################################### + +use File::Basename; +use Getopt::Long; + +# MAIN +# +# Process the command line... +# +Getopt::Long::Configure("no_pass_through"); +Getopt::Long::Configure("bundling"); +$Getopt::Long::ignorecase = 0; +if ( + !GetOptions( + 'f=s' => \$::FILENAME, # software list file name (full) + 's=s' => \$::SERVER, + 'i=s' => \$::INSTP_FLAGS, # installp flags + 'r=s' => \$::RPM_FLAGS, # RPM flags + 'e=s' => \$::EMGR_FLAGS, # emgr flags + 'n|nfsv4' => \$::NFSV4, + 'd|altsrc' => \$::ALTSRC, + 'a|all' => \$::ALLSW + ) + ) +{ # Gather options + exit 1; +} + +# +# set the name of this nodes server +# +my $servnode; +if ($::SERVER) +{ + $servnode = $::SERVER; +} +elsif (-f "/etc/xcatinfo") +{ + my $cmd = "/bin/cat /etc/xcatinfo | /bin/grep 'XCATSERVER'"; + &runcmd($cmd); + my $SNline = $::outref; + my $junk; + ($junk, $servnode) = split(/=/, $SNline); + chomp $servnode; + $servnode =~ s/^\s*//; +} +elsif ($ENV{'MASTER'}) +{ + $servnode = $ENV{'MASTER'}; +} +else +{ + + # error no server provided + print "aixswupdate: Could not determine the xCAT server for this node.\n"; + exit 1; +} + +# pick a local mount point +my $localsrc = "/xcatswmnt"; + +#ex. FILENAME -> /install/nim/lpp_source/71H_image_lpp_source/pkglist.$img +# mntdir -> /install/nim/lpp_source/71H_image_lpp_source +my $mntdir = dirname($::FILENAME); +my $file = basename($::FILENAME); +my $listfile = "$localsrc/$file"; + +# +# mount the package source directory +# +my $mtcmd; +if ($::NFSV4) +{ + $mtcmd = + qq~/bin/mkdir -m 644 -p $localsrc; /usr/sbin/mount -o vers=4 $servnode:$mntdir $localsrc~; +} +else +{ + $mtcmd = + qq~/bin/mkdir -m 644 -p $localsrc; /usr/sbin/mount $servnode:$mntdir $localsrc~; +} + +$rc = &runcmd($mtcmd); +if ($rc != 0) +{ + print + "aixswupdate: Could not mount $mntdir source directory from $servnode.\n"; + exit 1; +} + +# if the software list file exists then try to install the software +if (-f $listfile) +{ + + # copy the file contents into a list + unless (open(LISTFILE, "<$listfile")) + { + + # error + } + my @pkglist = ; + close(LISTFILE); + + if (scalar(@pkglist)) + { + + # sort the list into diff packaging types + my ($instpfile, $emgrfile, $rpmstring) = &processpkglist(\@pkglist); + + # installp + if (-f $instpfile) + { + my $rc = &do_installp($instpfile, $::INSTP_FLAGS, $localsrc); + if ($rc != 0) + { + print "One or more errors from the installp command.\n"; + } + } + + # updtvpkg + my $upcmd = qq~/usr/sbin/updtvpkg~; + my $rc = &runcmd($upcmd); + if ($rc != 0) + { + print "Could not run updtvpkg.\n"; + } + + # rpm + if ($rpmstring) + { + my $rc = &do_rpms($rpmstring, $::RPM_FLAGS, $localsrc); + if ($rc != 0) + { + print "One or more errors from the rpm command.\n"; + } + } + + # emgr + if (-f $emgrfile) + { + my $rc = &do_emgr($emgrfile, $::EMGR_FLAGS, $localsrc); + if ($rc != 0) + { + print "One or more errors from the emgr command.\n"; + } + } + + # clean up tmp files + my $rmcmd = qq~/bin/rmdir -R $emgrfile $instpfile~; + + # unmount source dir + my $umtcmd = qq~/usr/sbin/umount /xcatswmnt~; + $rc = &runcmd($umtcmd); + if ($rc != 0) + { + + # "Could not unmount source directory.\n"; + } + } + +} +else +{ + + # return error + print "aixswupdate: Cannot locate software list file: $::FILENAME\n"; + exit 1; +} + +#------------------------------------------------------------------------------- + +=head3 do_rpms + + This subroutine is used to install a list of rpm packages + + Arguments: + Returns: + 0 - ok + 1 - error + Example: + my $rc = &do_rpm($rpmstring, $rpmflags, $localsrc); + +=cut + +#----------------------------------------------------------------------------- +sub do_rpms +{ + my $rpmstring = shift; + my $rpmflag = shift; + my $localsrc = shift; + + # set flags + my $rflags; + if ($rpmflag) + { + $rflags = $rpmflag; + } + else + { + + # default + $rflags = qq~ -Uvh --replacepkgs ~; + } + + # if a specific dir was provided then use it + # otherwise use the emgr dir in the lpp src + my $dir; + if ($::ALTSRC) + { + $dir = "$localsrc"; + } + else + { + $dir = "$localsrc/RPMS/ppc"; + } + + my $pkg_string = ""; + if ($::ALLSW) + { + $pkg_string = " *.rpm "; + } + else + { + $pkg_string = $rpmstring; + } + + # - need to test rpms to make sure all will install + # - add test to rpm cmd if not included in rpm_flags + # + my @doinstall = split /\s+/, $pkg_string; + my @dontinstall = (); + + if ( ($rflags =~ /\-i/) + || ($rflags =~ /install /) + || ($rflags =~ /U/) + || ($rflags =~ /update /)) + { + + # if so then do test + @doinstall = (); + + my $flags; + + # if the flags don't include test then add it + if (!($rflags =~ /\-test/)) + { + $flags = " $rflags --test "; + } + + $rpmcmd = qq~cd $dir; /usr/bin/rpm $flags $pkg_string ~; + my $rc = &runcmd($rpmcmd); + my @outpt = split /\n/, $::outref; + my @badrpms; + + foreach my $line (@outpt) + { + chomp $line; + $line =~ s/^\s+//; #remove leading spaces + my ($first, $second, $rest) = split /\s+/, $line; + chomp $first; + if ($first eq 'package') + { + push @badrpms, $second; + } + } + + my @origrpms = split /\s+/, $pkg_string; + foreach my $sr (@origrpms) + { + if ($sr) + { + my $r = $sr; + $r =~ s/\*$//g; + my $found = 0; + foreach my $b (@badrpms) + { + if ($r =~ /$b/) + { + push @dontinstall, $r; + $found++; + last; + } + } + + if (!$found) + { + push @doinstall, $sr; + } + } + } + + if (scalar(@doinstall)) + { + $pkg_string = join(' ', @doinstall); + + } + else + { + $pkg_string = ""; + } + } + + if (scalar(@doinstall)) + { + if ($pkg_string) + { + $rpmcmd = qq~cd $dir; /usr/bin/rpm $rflags $pkg_string ~; + } + else + { + $rpmcmd = qq~/usr/bin/rpm $rflags ~; + } + + my $rc = &runcmd($rpmcmd); + print "$::outref\n"; + if ($rc != 0) + { + + # "error from rpm.\n"; + return 1; + } + } + + if (scalar(@dontinstall)) + { + print + "The following RPM packages were already installed and were not reinstalled:\n"; + my @rpms; + foreach my $rpm (@dontinstall) + { + print "$rpm\n"; + } + print "\n\n"; + } + return 0; +} + +#------------------------------------------------------------------------------- + +=head3 do_emgr + + This subroutine is used to install a list of emgr packages + + Arguments: + Returns: + 0 - ok + 1 - error + Example: + my $rc = &do_emgr($emgrfile, $emgrflags, $localsrc); + +=cut + +#----------------------------------------------------------------------------- +sub do_emgr +{ + my $emgrfile = shift; + my $emgrflag = shift; + my $localsrc = shift; + + # set flags + my $eflags; + if ($emgrflag) + { + $eflags = $emgrflag; + } + + # if a specific dir was provided then use it + # otherwise use the emgr dir in the lpp src + my $dir; + if ($::ALTSRC) + { + $dir = "$localsrc"; + } + else + { + $dir = "$localsrc/emgr/ppc"; + } + + my $emgrcmd = qq~cd $dir; /usr/sbin/emgr~; + + if ($eflags) + { + $emgrcmd .= qq~ $eflags ~; + } + + if ($emgrfile) + { + $emgrcmd .= qq~ -f $emgrfile ~; + } + + my $rc = &runcmd($emgrcmd); + print "$::outref\n"; + if ($rc != 0) + { + + # "error from emgr.\n"; + return 1; + } + return 0; +} + +#------------------------------------------------------------------------------- + +=head3 do_installp + + This subroutine is used to install a list of installp packages + + Arguments: + Returns: + 0 - ok + 1 - error + Example: + my $rc = &do_installp($instpfile, $instpflags, $localsrc); + +=cut + +#----------------------------------------------------------------------------- +sub do_installp +{ + my $instpfile = shift; + my $instpflag = shift; + my $localsrc = shift; + + # set flags + my $iflags; + if ($instpflag) + { + $iflags = $instpflag; + } + else + { + + # use default + $iflags = " -abgQXY "; + } + + # put together the installp command + my $inpcmd = qq~/usr/sbin/installp ~; + + # these installp flags can be used with -d + if ($iflags =~ /l|L|i|A|a/) + { + + # if a specific dir was provided then use it + # otherwise use the installp dir in the lpp src + if ($::ALTSRC) + { + $inpcmd .= qq~ -d $localsrc ~; + } + else + { + $inpcmd .= qq~ -d $localsrc/installp/ppc ~; + } + } + + $inpcmd .= qq~$iflags ~; + + # don't provide a list of filesets with these flags + if ($iflags !~ /C|L|l/) + { + if ($::ALLSW) + { + + # we want all sw installed + $inpcmd .= qq~ all ~; + } + else + { + + # install what is in the tmp file + $inpcmd .= qq~ -f $instpfile ~; + } + } + + my $rc = &runcmd($inpcmd); + print "$::outref\n"; + if ($rc != 0) + { + + # "error from installp.\n"; + return 1; + } + return 0; +} + +#------------------------------------------------------------------------------- + +=head3 processpkglist + + This subroutine is used to sort a list of software package names into + separate lists for each software packaging tool. + + Arguments: + Returns: + - name of installp list file + - name of emgr list file + - ptr to list of rpms + Example: + my ($instpfile, $emgrfile, $rpmstring) = &processpkglist(\@pkglist); + +=cut + +#----------------------------------------------------------------------------- +sub processpkglist +{ + my $pkg = shift; + + my @pkglist = @$pkg; + + # process the package list + # - split into rpm, emgr, and installp + my @rpm_pkgs; + my @emgr_pkgs; + my @installp_pkgs; + + my $emgrfile; + my $instpfile; + my $rpmstring; + + # separate into lists for each type of software + if (scalar(@pkglist)) + { + foreach my $p (@pkglist) + { + next if ($p =~ /^\s*$/ || $p =~ /^\s*#/); + chomp $p; + + if (($p =~ /\.rpm/) || ($p =~ /^R:/)) + { + my ($junk, $pname); + if ($p =~ /:/) + { + + # remove leading prefix - if any + ($junk, $pname) = split(/:/, $p); + } + else + { + $pname = $p; + } + push @rpm_pkgs, $pname; + } + elsif (($p =~ /epkg\.Z/) || ($p =~ /^E:/)) + { + my ($junk, $pname); + if ($p =~ /:/) + { + ($junk, $pname) = split(/:/, $p); + } + else + { + $pname = $p; + } + push @emgr_pkgs, $pname; + } + else + { + my ($junk, $pname); + if ($p =~ /:/) + { + ($junk, $pname) = split(/:/, $p); + } + else + { + $pname = $p; + } + push @installp_pkgs, $pname; + } + } + } # end - separate into lists + + # + # create tmp file for containing a list of software for + # installp and emgr + # + # tmp file for installp + # + + my $random_number = int(rand(1000000)); + my $installp_file_name = "installp_file-" . $random_number; + chomp $installp_file_name; + + if (scalar(@installp_pkgs)) + { + if (!open(INSTPFILE, ">/tmp/$installp_file_name")) + { + + # error "Could not open $installp_file_name.\n"; + $instpfile = ""; + } + else + { + foreach (@installp_pkgs) + { + print INSTPFILE $_ . "\n"; + } + close(INSTPFILE); + $instpfile = qq~/tmp/$installp_file_name~; + } + } + else + { + $instpfile = ""; + } + + # + # create tmp file for interim fix packages + # + my $emgr_file_name = "emgr_file-" . $random_number; + chomp $emgr_file_name; + if (scalar(@emgr_pkgs)) + { + if (!open(EMGRFILE, ">/tmp/$emgr_file_name")) + { + + # error "Could not open $emgr_file_name.\n"; + $emgrfile = ""; + } + else + { + foreach (@emgr_pkgs) + { + + # print EMGRFILE "./$_" . "\n"; + print EMGRFILE "$_" . "\n"; + } + close(EMGRFILE); + $emgrfile = qq~/tmp/$emgr_file_name~; + } + } + else + { + $emgrfile = ""; + } + + # put rpm list in a string + if (scalar(@rpm_pkgs)) + { + foreach my $pkg (@rpm_pkgs) + { + $rpmstring .= " $pkg"; + } + } + else + { + $rpmstring = ""; + } + + return ($instpfile, $emgrfile, $rpmstring); +} + +# +# run the command +# +sub runcmd +{ + my ($cmd) = @_; + my $rc = 0; + $cmd .= ' 2>&1'; + $::outref = `$cmd`; + if ($?) + { + $rc = $? >> 8; + if ($rc > 0) + { + return 1; + } + } + return 0; +}