xcat-core/xCAT-server/lib/xcat/plugins/kit.pm
2014-01-07 03:06:30 -05:00

4926 lines
173 KiB
Perl

# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
=head1
xCAT plugin package to handle Kit management
=cut
#-------------------------------------------------------
package xCAT_plugin::kit;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use xCAT::Table;
use xCAT::Utils;
use xCAT::MsgUtils;
use Getopt::Long;
#use Data::Dumper;
use File::Basename;
use File::Path;
use Cwd;
my $kitconf = "kit.conf";
# kit framework version for this xcat.
$::KITFRAMEWORK ="2";
# this code is compatible with other kits that are at framework 0 or 1.
$::COMPATIBLE_KITFRAMEWORKS = "0,1,2";
#-------------------------------------------------------
=head3 handled_commands
Return list of commands handled by this plugin
=cut
#-------------------------------------------------------
sub handled_commands
{
return {
lskit => "kit",
addkit => "kit",
rmkit => "kit",
lskitcomp => "kit",
addkitcomp => "kit",
rmkitcomp => "kit",
chkkitcomp => "kit",
lskitdeployparam => "kit",
};
}
#-------------------------------------------------------
=head3 process_request
Process the command
=cut
#-------------------------------------------------------
sub process_request
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
$::CALLBACK = $callback;
$::args = $request->{arg};
my $lock;
my $locked = xCAT::Utils->is_locked("kit", 1);
if ( !locked ) {
$lock = xCAT::Utils->acquire_lock("kit", 1);
unless ($lock){
$callback->({error=>["Can not acquire lock."],errorcode=>[1]});
return 1;
}
} else {
if ( $::PID and $::PID != $$ ) {
$callback->({error=>["Can not acquire lock, another process is running."],errorcode=>[1]});
return 1;
}
$::PID = $$;
}
my $command = $request->{command}->[0];
my $rc;
if ($command eq "lskit"){
$rc = lskit($request, $callback, $request_command);
} elsif ($command eq "addkit"){
$rc = addkit($request, $callback, $request_command);
} elsif ($command eq "rmkit"){
$rc = rmkit($request, $callback, $request_command);
} elsif ($command eq "lskitcomp"){
$rc = lskitcomp($request, $callback, $request_command);
} elsif ($command eq "addkitcomp"){
$rc = addkitcomp($request, $callback, $request_command);
} elsif ($command eq "rmkitcomp"){
$rc = rmkitcomp($request, $callback, $request_command);
} elsif ($command eq "chkkitcomp"){
$rc = chkkitcomp($request, $callback, $request_command);
} elsif ($command eq "lskitdeployparam"){
$rc = lskitdeployparam($request, $callback, $request_command);
} else{
$callback->({error=>["Error: $command not found in this module."],errorcode=>[1]});
xCAT::Utils->release_lock($lock, 1);
return 1;
}
if ( $lock ) {
xCAT::Utils->release_lock($lock, 1);
}
return $rc;
}
#-------------------------------------------------------
=head3 get_highest_version
Return the highest version and release for a list of
kit, kitrepo, or kitcomponent names.
Input: @entries: the arrary contains all the data
$key: the key name in entries hash.
$version: compare version nums.
$release: compare release nums.
=cut
#-------------------------------------------------------
sub get_highest_version
{
my $key = shift;
my $version = shift;
my $release = shift;
my @entries = @_;
my $highest;
foreach my $entry ( @entries ) {
$highest=$entry if (!$highest);
my $rc = compare_version($highest,$entry,$key,$version,$release);
if ( $rc == 1 ) {
$highest = $entry;
}
}
return $highest->{$key};
}
#-------------------------------------------------------
=head3 compare_version
Compare the version and release between two kit/kitrepo/kitcomp
Input: $highest: the current highest version or release
$entry: the new entry
$key: the key name in entries hash.
$version: compare version nums.
$release: compare release nums.
=cut
#-------------------------------------------------------
sub compare_version
{
my $highest = shift;
my $entry = shift;
my $key = shift;
my $version = shift;
my $release = shift;
my @a1 = split(/\./, $highest->{$version});
my @a2 = split(/\./, $entry->{$version});
my ($len,$num1,$num2);
if (($release = 'release') &&
(defined $highest->{$release}) && (defined $entry->{$release})){
$len = (scalar(@a1) > scalar(@a2) ? scalar(@a1) : scalar(@a2));
}else{
$len = (scalar(@a1) < scalar(@a2) ? scalar(@a1) : scalar(@a2));
}
$#a1 = $len - 1; # make the arrays the same length before appending release
$#a2 = $len - 1;
if ($release = 'release') {
push @a1, split(/\./, $highest->{$release});
push @a2, split(/\./, $entry->{$release});
}
$len = (scalar(@a1) < scalar(@a2) ? scalar(@a1) : scalar(@a2));
$num1 = '';
$num2 = '';
for (my $i = 0 ; $i < $len ; $i++)
{
my ($d1,$w1) = $a1[$i] =~ /^(\d*)(\w*)/;
my ($d2,$w2) = $a2[$i] =~ /^(\d*)(\w*)/;
my $diff = length($d1) - length($d2);
if ($diff > 0) # pad d2
{
$num1 .= $d1;
$num2 .= ('0' x $diff) . $d2;
}
elsif ($diff < 0) # pad d1
{
$num1 .= ('0' x abs($diff)) . $d1;
$num2 .= $d2;
}
else # they are the same length
{
$num1 .= $d1;
$num2 .= $d2;
}
if ( $w1 && $w2)
{
my ($w_to_d1, $w_to_d2) = comp_word( $w1, $w2);
$num1 .= $w_to_d1;
$num2 .= $w_to_d2;
}
}
# Remove the leading 0s or perl will interpret the numbers as octal
$num1 =~ s/^0+//;
$num2 =~ s/^0+//;
#SuSE Changes
# if $num1="", the "eval '$num1 $operator $num2'" will fail. So MUSTBE be sure that $num1 is not a "".
if (length($num1) == 0) { $num1 = 0; }
if (length($num2) == 0) { $num2 = 0; }
return 1 if ( $num2 > $num1 );
return 0 if ( $num2 == $num1 );
return -1;
}
#--------------------------------------------------------------------------------
=head3 comp_word
Compare version1 word and version2 word. This subroutine can only be used to compare
one section in version number, and this section cannot start with number.
Arguments:
$w1:
$w2
Returns:
if $w1 > $w2, return (1,0)
if $w1 < $w2, return (0,1)
if $w1 == $w2, return (undef, undef)
Globals:
none
Example:
if ($self->comp_word ( "adfadsfa","acc2")
return (0,1)
Comments:
the version word cannot contain ".", and cannot start with number.
For examples, following version words cannot be compared by this subroutine:
(123.321, 123.322) You need use subroutine testVersion to do the version comparision
(123abc,12bcd) You need use subroutine testVersion to do the version comparision
=cut
#--------------------------------------------------------------------------------
sub comp_word
{
my $self = shift;
my ($w1,$w2) = @_;
return (undef,undef) if (!$w1 || !$w2);
my @strList1 = unpack "C*", $w1;
my @strList2 = unpack "C*", $w2;
my $len = scalar(@strList1) < scalar(@strList2) ? scalar(@strList1) : scalar(@strList2);
for ( my $i = 0; $i < $len; $i++)
{
next if ( $strList1[$i] == $strList2[$i]);
return ( 0, 1) if ( $strList1[$i] < $strList2[$i]);
return ( 1, 0);
}
return (undef,undef);
}
#-------------------------------------------------------
=head3 check_newinstall
Check if the given kitcomp list are in NEW_INSTALL_LIST
or not. If so, set $::noupgrade all other kitcomp
depending on this list will be put into NEW_INSTALL_LIST
also
=cut
#-------------------------------------------------------
sub check_newinstall
{
my $kitcomponents = shift;
my @lines = @_;
my @kitcomps = split /,/, $kitcomponents;
foreach my $kitcomp ( @kitcomps ) {
last if ( $::noupgrade );
my $match_newinstall = 0;
foreach my $line ( @lines ) {
chomp($line);
if ( $line =~ /^#NEW_INSTALL_LIST#$/ ) {
$match_newinstall = 1;
}
if ( $line =~ /\/$kitcomp$/ ) {
if ( $match_newinstall ) {
$::noupgrade = 1;
}
last;
}
}
}
}
#-------------------------------------------------------
=head3 assign_to_osimage
Assign a kit component to osimage
=cut
#-------------------------------------------------------
sub assign_to_osimage
{
my $osimage = shift;
my $kitcomp = shift;
my $callback = shift;
my $tabs = shift;
(my $kitcomptable) = $tabs->{kitcomponent}->getAttribs({kitcompname=> $kitcomp}, 'kitname', 'kitreponame', 'basename', 'kitcompdeps', 'kitpkgdeps', 'prerequisite', 'exlist', 'genimage_postinstall','postbootscripts', 'driverpacks');
(my $osimagetable) = $tabs->{osimage}->getAttribs({imagename=> $osimage}, 'provmethod', 'osarch', 'postbootscripts', 'kitcomponents');
(my $linuximagetable) = $tabs->{linuximage}->getAttribs({imagename=> $osimage}, 'rootimgdir', 'exlist', 'postinstall', 'otherpkglist', 'otherpkgdir', 'driverupdatesrc');
# Reading installdir.
my $installdir = xCAT::TableUtils->getInstallDir();
unless($installdir){
$installdir = '/install';
}
$installdir =~ s/\/$//;
# Reading kitdir
my $kittable;
if ( $kitcomptable and $kitcomptable->{kitname} ) {
($kittable) = $tabs->{kit}->getAttribs({kitname=> $kitcomptable->{kitname}}, 'kitdir', 'kitdeployparams');
}
# Create osimage direcotry to save kit tmp files
mkpath("$installdir/osimages/$osimage/kits/");
# Adding genimage_postinstall script to linuximage.postintall attribute for diskless image or osimage.postbootscripts for diskfull image.
if ( $kitcomptable and $kitcomptable->{genimage_postinstall} ){
my @kitcompscripts = split ',', $kitcomptable->{genimage_postinstall};
foreach my $kitcompscript ( @kitcompscripts ) {
if ( $osimagetable ) {
my $otherpkgdir;
my $rootimgdir;
if ( $linuximagetable and $linuximagetable->{otherpkgdir} ) {
$otherpkgdir = $linuximagetable->{otherpkgdir};
} else {
$callback->({error => ["Could not read otherpkgdir from osimage $osimage"],errorcode=>[1]});
return 1;
}
if ( $osimagetable->{provmethod} =~ /install/ ) {
# for diskfull node
my $match = 0;
my @scripts = split ',', $osimagetable->{postbootscripts};
foreach my $script ( @scripts ) {
if ( $script =~ /^KIT_$osimage.postbootscripts/ ) {
$match = 1;
last;
}
}
if ( !-e "$installdir/postscripts/KIT_$osimage.postbootscripts" ) {
if (open(FILE, ">", "$installdir/postscripts/KIT_$osimage.postbootscripts")) {
print FILE "#!/bin/sh\n\n";
close(FILE);
chmod(0755,"$installdir/postscripts/KIT_$osimage.postbootscripts");
}
}
my @postbootlines;
if (open(POSTBOOTSCRIPTS, "<", "$installdir/postscripts/KIT_$osimage.postbootscripts")) {
@postbootlines = <POSTBOOTSCRIPTS>;
close(POSTBOOTSCRIPTS);
if($::VERBOSE){
$callback->({data=>["\nCreating osimage postbootscripts file $installdir/postscripts/KIT_$osimage.postbootscripts"]});
}
}
unless ( grep(/$kitcompscript/ , @postbootlines ) ) {
if (open(NEWLIST, ">>", "$installdir/postscripts/KIT_$osimage.postbootscripts")) {
print NEWLIST "otherpkgdir=$otherpkgdir $kitcompscript\n";
close(NEWLIST);
}
}
if ( !$match ) {
$osimagetable->{postbootscripts} = "KIT_$osimage.postbootscripts," . $osimagetable->{postbootscripts};
$osimagetable->{postbootscripts} =~ s/^,//;
}
} else {
# for diskless node
if ( $linuximagetable and $linuximagetable->{rootimgdir} ) {
$rootimgdir = $linuximagetable->{rootimgdir}."/rootimg";
} else {
$callback->({error => ["Could not read rootimgdir from osimage $osimage"],errorcode=>[1]});
return 1;
}
if ( !-e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall" ) {
if (open(FILE, ">", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall")) {
print FILE "#!/bin/sh\n\n";
close(FILE);
chmod(0755,"$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall");
}
}
my @postinstalllines;
if (open(POSTINSTALL, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall")) {
@postinstalllines = <POSTINSTALL>;
close(POSTINSTALL);
if($::VERBOSE){
$callback->({data=>["\nReading osimage postinstall scripts file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall"]});
}
}
unless ( grep(/$kitcompscript/ , @postinstalllines ) ) {
my $deployparams;
my @ls;
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
if (open(DEPLOYPARAM, "<", "$kittable->{kitdir}/other_files/$kittable->{kitdeployparams}")) {
@ls = <DEPLOYPARAM>;
close(DEPLOYPARAM);
}
}
my @newlines;
foreach my $line (@ls) {
if ($line =~ /^#ENV:.+=.+#$/) {
chomp($line);
$line =~ s/^#ENV://;
$line =~ s/#$//;
push @newlines, $line;
}
}
$deployparams = join ' ', @newlines;
if (open(NEWLIST, ">>", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall")) {
if ($deployparams) {
print NEWLIST "installroot=$rootimgdir otherpkgdir=$otherpkgdir $deployparams $installdir/postscripts/$kitcompscript\n";
} else {
print NEWLIST "installroot=$rootimgdir otherpkgdir=$otherpkgdir $installdir/postscripts/$kitcompscript\n";
}
close(NEWLIST);
}
}
my $match = 0;
my @scripts = split ',', $linuximagetable->{postinstall};
foreach my $script ( @scripts ) {
if ( $script =~ /KIT_COMPONENTS.postinstall/ ) {
$match = 1;
last;
}
}
if ( !$match ) {
$linuximagetable->{postinstall} = $linuximagetable->{postinstall} . ",$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall";
}
$linuximagetable->{postinstall} =~ s/^,//;
}
}
}
}
# Adding postbootscrits to osimage.postbootscripts
if ( !$::noscripts and $kitcomptable and $kitcomptable->{postbootscripts} ){
my @kitcompscripts = split ',', $kitcomptable->{postbootscripts};
foreach my $kitcompscript ( @kitcompscripts ) {
my $formatedkitcomp = $kitcompscript;
if ( $osimagetable ) {
if ( $osimagetable->{postbootscripts} ){
my $match = 0;
my $added = 0;
my @newscripts;
my @scripts = split ',', $osimagetable->{postbootscripts};
foreach my $script ( @scripts ) {
if ( $script =~ /^$formatedkitcomp$/ ) {
$match = 1;
last;
}
if ( $script !~ /^BASEXCAT_/ and $script !~ /^KIT_/ ) {
unless ( $added ) {
push @newscripts, $formatedkitcomp;
$added = 1;
}
}
push @newscripts, $script;
}
if ( $match ) {
next;
} elsif ( !$added ) {
push @newscripts, $formatedkitcomp;
}
my $osimagescripts = join ',', @newscripts;
$osimagetable->{postbootscripts} = $osimagescripts;
} else {
$osimagetable->{postbootscripts} = $formatedkitcomp;
}
}
}
}
# Adding kit component's repodir to osimage.otherpkgdir
if ( $kitcomptable and $kitcomptable->{kitreponame} ) {
(my $kitrepotable) = $tabs->{kitrepo}->getAttribs({kitreponame=> $kitcomptable->{kitreponame}}, 'kitrepodir');
if ( $kitrepotable and $kitrepotable->{kitrepodir} ) {
if ( $linuximagetable and $linuximagetable->{otherpkgdir} ) {
my $otherpkgdir = $linuximagetable->{otherpkgdir};
my $kitrepodir = $kitrepotable->{kitrepodir};
# Create otherpkgdir if it doesn't exist
unless ( -d "$otherpkgdir" ) {
mkpath("$otherpkgdir");
}
# Create symlink if doesn't exist
unless ( -d "$otherpkgdir/$kitcomptable->{kitreponame}" ) {
system("ln -sf $kitrepodir $otherpkgdir/$kitcomptable->{kitreponame} ");
}
} else {
$callback->({error => ["Cannot open linuximage table or otherpkgdir do not exist"],errorcode=>[1]});
return 1;
}
} else {
$callback->({error => ["Cannot open kit table or kitdir do not exist"],errorcode=>[1]});
return 1;
}
}
# Adding kitcomponent.exlist to osimage.exlist
if ( $kitcomptable and $kitcomptable->{exlist} and $kittable and $kittable->{kitdir} ) {
my @lines;
my $exlistfile = $kitcomptable->{exlist};
my $kitdir = $kittable->{kitdir};
# Adding kit component exlist file to KIT_COMPONENTS.exlist file
mkpath("$installdir/osimages/$osimage/kits/");
if ( -e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist" ) {
if (open(EXLIST, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist")) {
@lines = <EXLIST>;
close(EXLIST);
if($::VERBOSE){
$callback->({data=>["\nReading kit component exlist file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist\n"]});
}
} else {
$callback->({error => ["Could not open kit component exlist file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist"],errorcode=>[1]});
return 1;
}
}
unless ( grep(/^#INCLUDE:$kitdir\/other_files\/$exlistfile#$/ , @lines) ) {
if (open(NEWEXLIST, ">>", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist")) {
print NEWEXLIST "#INCLUDE:$kitdir/other_files/$exlistfile#\n";
close(NEWEXLIST);
}
}
# Adding KIT_COMPONENTS.exlist file to osimage.exlist if not existing.
if ( $linuximagetable ) {
if ( $linuximagetable->{exlist} ) {
my $match = 0;
my @exlists= split ',', $linuximagetable->{exlist};
foreach my $exlist ( @exlists ) {
if ( $exlist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_COMPONENTS.exlist$/ ) {
$match = 1;
last;
}
}
unless ( $match ) {
$linuximagetable->{exlist} = $linuximagetable->{exlist} . ',' . "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist";
}
} else {
$linuximagetable->{exlist} = "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist";
}
}
}
# Adding kitdeployparams to a otherpkglist file in osimage
my @kitdeployparams;
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
# Creating kit deployparams file
my @lines;
mkpath("$installdir/osimages/$osimage/kits/");
if ( -e "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist" ) {
if (open(DEPLOYPARAM, "<", "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist")) {
@lines = <DEPLOYPARAM>;
close(DEPLOYPARAM);
if($::VERBOSE){
$callback->({data=>["\nReading kit deployparams file $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist\n"]});
}
} else {
$callback->({error => ["Could not open kit deployparams file $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist"],errorcode=>[1]});
return 1;
}
}
# Checking if the kit deployparams have been written in the generated kit deployparams file.
my @l;
my $matched = 0;
foreach my $line ( @lines ) {
chomp $line;
if ( $line =~ m!$kittable->{kitdir}/other_files/$kittable->{kitdeployparams}! ) {
$matched = 1;
last;
}
}
unless ( $matched ) {
push @l, "#INCLUDE:$kittable->{kitdir}/other_files/$kittable->{kitdeployparams}#\n";
}
# Write the missing lines to kit deployparams file
if (open(NEWDEPLOYPARAM, ">>", "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist")) {
print NEWDEPLOYPARAM @l;
close(NEWDEPLOYPARAM);
}
# Write this kit deployparams to osimage.otherpkglist if not existing.
if ( $linuximagetable ) {
if ( $linuximagetable->{otherpkglist} ) {
my $match = 0;
my @otherpkglists= split ',', $linuximagetable->{otherpkglist};
foreach my $otherpkglist ( @otherpkglists ) {
if ( $otherpkglist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_DEPLOY_PARAMS.otherpkgs.pkglist$/ ) {
$match = 1;
last;
}
}
unless ( $match ) {
$linuximagetable->{otherpkglist} = "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist" . ',' . "$linuximagetable->{otherpkglist}";
}
} else {
$linuximagetable->{otherpkglist} = "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist";
}
}
}
# Adding kit component basename to osimage.otherpkgs.pkglist
if ( $kitcomptable and $kitcomptable->{basename} and $kitcomptable->{kitreponame} ) {
my @lines;
my $basename = $kitcomptable->{basename};
my $kitreponame = $kitcomptable->{kitreponame};
# Adding kit component basename to KIT_COMPONENTS.otherpkgs.pkglist file
mkpath("$installdir/osimages/$osimage/kits");
if ( -e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist" ) {
if (open(OTHERPKGLIST, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist")) {
@lines = <OTHERPKGLIST>;
close(OTHERPKGLIST);
if($::VERBOSE){
$callback->({data=>["\nReading kit component otherpkg file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist\n"]});
}
} else {
$callback->({error => ["Could not open kit component otherpkg file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist"],errorcode=>[1]});
return 1;
}
}
unless ( grep(/^$kitreponame\/$basename$/, @lines) ) {
if (open(NEWOTHERPKGLIST, ">", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist")) {
if ( $kitcomptable and $kitcomptable->{prerequisite} ) {
push @lines, "#NEW_INSTALL_LIST#\n";
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
push @lines, "#INCLUDE:$kittable->{kitdir}/other_files/$kittable->{kitdeployparams}#\n";
}
push @lines, "$kitreponame/$kitcomptable->{prerequisite}\n";
$::noupgrade = 1;
}
# Check if this kitcomponent's kitcompdeps are in NEW_INSTALL_LIST or not.
# If so, set $::noupgrade to put this kitcomp in a new NEW_INSTALL_LIST
if ( $kitcomptable and $kitcomptable->{kitcompdeps} ) {
check_newinstall($kitcomptable->{kitcompdeps}, @lines);
}
if ( $::noupgrade ) {
push @lines, "#NEW_INSTALL_LIST#\n";
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
push @lines, "#INCLUDE:$kittable->{kitdir}/other_files/$kittable->{kitdeployparams}#\n";
}
push @lines, "$kitreponame/$basename\n";
print NEWOTHERPKGLIST @lines;
} else {
print NEWOTHERPKGLIST "$kitreponame/$basename\n";
print NEWOTHERPKGLIST @lines;
}
close(NEWOTHERPKGLIST);
}
}
# Write this kit component otherpkgs pkgfile to osimage.otherpkglist if not existing.
if ( $linuximagetable ) {
if ( $linuximagetable->{otherpkglist} ) {
my $match = 0;
my @otherpkglists= split ',', $linuximagetable->{otherpkglist};
foreach my $otherpkglist ( @otherpkglists ) {
if ( $otherpkglist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_COMPONENTS.otherpkgs.pkglist$/ ) {
$match = 1;
last;
}
}
unless ( $match ) {
$linuximagetable->{otherpkglist} = $linuximagetable->{otherpkglist} . ',' . "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist";
}
} else {
$linuximagetable->{otherpkglist} = "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist";
}
}
# Remove this component basename and pkgnames from KIT_RMPKGS.otherpkg.pkglist
my @lines = ();
my @kitpkgdeps = split ',', $kitcomptable->{kitpkgdeps};
# Remove prerequisite from KIT_RMPKGS.otherpkg.pkglist
if ( $kitcomptable and $kitcomptable->{prerequisite} ) {
my @kitpreps = split /,/, $kitcomptable->{prerequisite};
foreach my $kitprep ( @kitpreps ) {
push @kitpkgdeps, $kitprep;
}
}
push @kitpkgdeps, $basename;
my @l = ();
if ( -e "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist" ) {
if (open(RMOTHERPKGLIST, "<", "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist")) {
@lines = <RMOTHERPKGLIST>;
close(RMOTHERPKGLIST);
if($::VERBOSE){
$callback->({data=>["\nReading kit component rmpkgs file $installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist\n"]});
}
} else {
$callback->({error => ["Could not open kit component rmpkgs file $installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist"],errorcode=>[1]});
return 1;
}
}
my $changed = 0;
foreach my $line ( @lines ) {
chomp $line;
my $matched = 0;
foreach my $kitpkgdep ( @kitpkgdeps ) {
if ( $line =~ /^-$kitpkgdep$/ ) {
$matched = 1;
$changed = 1;
last;
}
}
if ( $line =~ /^-prep_$basename$/ ) {
$matched = 1;
$changed = 1;
}
unless ( $matched ) {
push @l, "$line\n";
}
my $lastline = pop @l;
while ( $lastline =~ /^#NEW_INSTALL_LIST#$/ ) {
$lastline = pop @l;
}
push @l, $lastline if ( $lastline );
}
if ( $changed ) {
if (open(RMPKGLIST, ">", "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist")) {
print RMPKGLIST @l;
close(RMPKGLIST);
}
}
} else {
$callback->({error => ["Could not open kit component table and read basename for kit component $kitcomp"],errorcode=>[1]});
return 1;
}
# Now writing kit component to osimage.kitcomponents
if($::VERBOSE){
$callback->({data=>["\nAdding this kitcomponent to osimage.kitcomponents\n"]});
}
if ( $osimagetable ) {
if ( $osimagetable->{kitcomponents} ){
$osimagetable->{kitcomponents} = join( ',', $osimagetable->{kitcomponents}, $kitcomp);
} else {
$osimagetable->{kitcomponents} = $kitcomp;
}
}
# Adding driverpacks
if ( $linuximagetable and $linuximagetable->{driverupdatesrc} ) {
if ( $kitcomptable and $kitcomptable->{driverpacks} ) {
my @driverpacks = split ',', $kitcomptable->{driverpacks};
my @driverupdatesrcs = split ',', $linuximagetable->{driverupdatesrc};
my @newdriverupdatesrcs = @driverupdatesrcs;
foreach my $driverpack ( @driverpacks ) {
my $matched = 0;
foreach my $driverupdatesrc ( @driverupdatesrcs ) {
if ( $driverpack eq $driverupdatesrc ) {
$matched = 1;
last;
}
}
unless ( $matched ) {
push @newdriverupdatesrcs, $driverpack;
}
}
my $newdriverupdatesrc = join ',', @newdriverupdatesrcs;
$linuximagetable->{driverupdatesrc} = $newdriverupdatesrc;
}
}
# Write linuximage table with all the above udpates.
$tabs->{linuximage}->setAttribs({imagename => $osimage }, \%{$linuximagetable} );
# Write osimage table with all the above udpates.
$tabs->{osimage}->setAttribs({imagename => $osimage }, \%{$osimagetable} );
}
#-------------------------------------------------------
=head3 check_kit_config
Check if this kit is suitable to add
=cut
#-------------------------------------------------------
sub check_kit_config
{
my $tabs = shift;
my $kit = shift;
my $kithash = shift;
my $kitrepohash = shift;
my $kitcomphash = shift;
#TODO: add check to see the the attributes name are acceptable by xCAT DB.
#TODO: need to check if the files are existing or not, like exlist,
unless (keys %{$kithash}) {
my %rsp;
push@{ $rsp{data} }, "Failed to add kit $kit because kit.conf is invalid";
xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $::INSPECTION ) {
my %rsp;
push@{ $rsp{data} }, "kitname=$kithash->{kitname}";
push@{ $rsp{data} }, " description=$kithash->{description}";
push@{ $rsp{data} }, " version=$kithash->{version}";
push@{ $rsp{data} }, " ostype=$kithash->{ostype}";
xCAT::MsgUtils->message( "I", \%rsp, $::CALLBACK );
next;
}
(my $ref1) = $tabs->{kit}->getAttribs({kitname => $kithash->{kitname}}, 'basename');
if ( $ref1 and $ref1->{'basename'}){
my %rsp;
push@{ $rsp{data} }, "Failed to add kit $kithash->{kitname} because it is already existing";
xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
# Check if the kitcomponent is existing
my @kitcomps = $tabs->{kitcomponent}->getAllAttribs( 'kitcompname' );
foreach my $kitcomp (@kitcomps) {
if ( $kitcomp->{kitcompname} ) {
foreach my $kitcompid (keys %{$kitcomphash}) {
if ( $kitcomphash->{$kitcompid}->{kitcompname} and $kitcomphash->{$kitcompid}->{kitcompname} =~ /$kitcomp->{kitcompname}/ ) {
my %rsp;
push@{ $rsp{data} }, "Failed to add kitcomponent $kitcomp->{kitcompname} because it is already existing";
xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
}
}
}
}
#-------------------------------------------------------
=head3 read_kit_config
Read kit configuration file
=cut
#-------------------------------------------------------
sub read_kit_config
{
my $fn = shift;
my @lines = @$fn;
my $sec;
my $kitname;
my $kitreponame;
my $kitcompname;
my $scripts;
my $kitrepoid = 0;
my $kitcompid = 0;
my %kithash;
my %kitrepohash;
my %kitcomphash;
foreach my $line (@lines) {
# Read through each line of kit.conf.
my $key, $value;
chomp $line;
next if ($line =~ /^$/);
next if ($line =~ /^\s*#/);
# Split the kit.conf to different parts: kit, kitrepo, kitcomponent.
if ($line =~ /kit:/) {
$sec = "KIT";
next;
} elsif ($line =~ /kitrepo:/) {
$sec = "KITREPO";
$kitrepoid = $kitrepoid + 1;
next;
} elsif ($line =~ /kitcomponent:/) {
$sec = "KITCOMPONENT";
$kitcompid = $kitcompid + 1;
next;
} else {
if ( $line =~ /kitcompdeps/ ) {
$key = $line;
$value = $line;
$key =~ s/\s+(\w+)\s+=.*$/$1/;
$key =~ s/\s+//g;
$value =~ s/$key\s+=(.*)$/$1/;
$key =~ s/\s+//g;
$value =~ s/\s+//g;
} else {
($key,$value) = split /=/, $line;
}
}
# Remove spaces in each lines.
$key =~s/^\s+|\s+$//g;
$value =~s/^\s+|\s+$//g;
# Add each attribute to different hash.
if ( $sec =~ /KIT$/) {
$kithash{$key} = $value;
} elsif ( $sec =~ /KITREPO$/ ) {
$kitrepohash{$kitrepoid}{$key} = $value;
} elsif ( $sec =~ /KITCOMPONENT$/ ) {
if ( $key =~ /postbootscripts/ or $key =~ /genimage_postinstall/ ) {
$scripts = $scripts . ',' . $value;
$kitcomphash{$kitcompid}{$key} = $value;
} else {
$kitcomphash{$kitcompid}{$key} = $value;
}
}
}
return(\%kithash,\%kitrepohash,\%kitcomphash,$scripts);
}
#-------------------------------------------------------
=head3 addkit
Add Kits into xCAT
=cut
#-------------------------------------------------------
sub addkit
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $path;
my $rc;
my $xusage = sub {
my %rsp;
push@{ $rsp{data} }, "Usage: addkit - Adds product software Kits to an xCAT cluster environment.";
push@{ $rsp{data} }, "\taddkit [-h|--help]";
push@{ $rsp{data} }, "\taddkit [-v|--version]";
push@{ $rsp{data} }, "\taddkit [-i|--inspection] <kitlist>]";
push@{ $rsp{data} }, "\taddkit [-V|--verbose] [-p|--path <path>] <kitlist>]";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
};
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The addkit command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
unless(defined($request->{arg})){ $xusage->(1); return; }
@ARGV = @{$request->{arg}};
if($#ARGV eq -1){
$xusage->(1);
return;
}
GetOptions(
'h|help' => \$help,
'V|verbose' => \$::VERBOSE,
'v|version' => \$vers,
'i|inspection' => \$::INSPECTION,
'p|path=s' => \$path,
);
if($help){
$xusage->(0);
return;
}
# Option -v for version
if ( defined($vers) ) {
create_version_response('addkit');
return 1; # no usage - just exit
}
my %tabs = ();
my @tables = qw(kit kitrepo kitcomponent);
foreach my $t ( @tables ) {
$tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1);
if ( !exists( $tabs{$t} )) {
my %rsp;
push@{ $rsp{data} }, "Could not open xCAT table $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
my $basename;
my $des = shift @ARGV;
my @kits = split ',', $des;
my @kitnames;
my $hasplugin = 0;
foreach my $kit (@kits) {
my $kitdir = '';
my $kittmpdir = '';
if ( $kit =~ /NEED_PRODUCT_PKGS/ ) {
my %rsp;
push@{ $rsp{data} }, "Not allowed to add partial kit $kit";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# extract the Kit to kitdir
my $installdir = xCAT::TableUtils->getInstallDir();
unless($installdir){
$installdir = '/install';
}
$installdir =~ s/\/$//;
my $dir = $request->{cwd}; #getcwd;
$dir = $dir->[0];
unless(-r $kit){
$kit = "$dir/$kit";
}
unless (-r $kit) {
my %rsp;
push@{ $rsp{data} }, "Can not find $kit";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if(-d "$kit") {
# This is a directory.
# TODO: check if this is a valid kit directory.
$kittmpdir = $kit;
} else {
# should be a tar.bz2 file
system("rm -rf /tmp/tmpkit/");
mkpath("/tmp/tmpkit/");
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Extract Kit $kit to /tmp";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
$rc = system("tar jxvf $kit -C /tmp/tmpkit/ --wildcards */kit.conf");
} else {
$rc = system("tar jxf $kit -C /tmp/tmpkit/ --wildcards */kit.conf");
}
opendir($dir,"/tmp/tmpkit/");
my @files = readdir($dir);
foreach my $file ( @files ) {
next if ( $file eq '.' || $file eq '..' );
$kittmpdir = "/tmp/tmpkit/$file";
last;
}
if ( !$kittmpdir ) {
my %rsp;
push@{ $rsp{data} }, "Could not find extracted kit.conf in /tmp/tmpkit";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to extract kit.conf from $kit, (Maybe there was no space left?)";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Read kit info from kit.conf
my @lines;
if (open(KITCONF, "<$kittmpdir/$kitconf")) {
@lines = <KITCONF>;
close(KITCONF);
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit configuration file $kittmpdir/$kitconf";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit configuration file $kittmpdir/$kitconf";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
#
# check contents of kit.conf to make sure the framework
# is compatible with this codes framework
if (&check_framework(\@lines)) {
return 1;
}
# Read kit configuration file
my ($kithash,$kitrepohash,$kitcomphash, $scripts) = read_kit_config(\@lines);
# Check if this kit is allowed to add.
if ( &check_kit_config(\%tabs,$kit,$kithash,$kitrepohash,$kitcomphash) ) {
return 1;
}
if( !-d "$kit") {
# should be a tar.bz2 file
system("rm -rf /tmp/tmpkit/");
mkpath("/tmp/tmpkit/");
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Extract Kit $kit to /tmp";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
$rc = system("tar jxvf $kit -C /tmp/tmpkit/");
} else {
$rc = system("tar jxf $kit -C /tmp/tmpkit/");
}
opendir($dir,"/tmp/tmpkit/");
my @files = readdir($dir);
foreach my $file ( @files ) {
next if ( $file eq '.' || $file eq '..' );
$kittmpdir = "/tmp/tmpkit/$file";
last;
}
if ( !$kittmpdir ) {
my %rsp;
push@{ $rsp{data} }, "Could not find extracted kit in /tmp/tmpkit";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
my %rsp;
push@{ $rsp{data} }, "Adding Kit $kithash->{kitname}";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
# Moving kits from tmp directory to kitdir
if (!$path) {
$kitdir = $installdir . "/kits";
} else {
$kitdir = $path;
}
$kitdir =~ s/\/$//;
$kitdir = $kitdir . "/" . $kithash->{kitname};
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Create Kit directory $kitdir";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
mkpath($kitdir);
# Set kitdir and kitrepodir
$kithash->{kitdir} = $kitdir;
foreach my $kitrepoid ( keys %{$kitrepohash} ) {
$kitrepohash->{$kitrepoid}->{kitrepodir} = $kitdir."/repos/".$kitrepohash->{$kitrepoid}->{kitreponame};
}
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Copying Kit from $kittmpdir to $kitdir";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
$rc = system("cp -rfv $kittmpdir/* $kitdir");
} else {
$rc = system("cp -rf $kittmpdir/* $kitdir");
}
# Coying scripts to /installdir/postscripts/
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Copying kit scripts from $kitdir/other_files/ to $installdir/postscripts";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
my @script = split ',', $scripts;
foreach (@script) {
next unless ($_);
if($::VERBOSE){
$rc = system("cp -rfv $kitdir/other_files/$_ $installdir/postscripts/");
} else {
$rc = system("cp -rf $kitdir/other_files/$_ $installdir/postscripts/");
}
chmod(0755,"$installdir/postscripts/$_");
}
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to copy scripts from $kitdir/scripts/ to $installdir/postscripts";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Copying plugins to /opt/xcat/lib/perl/xCAT_plugin/
if ( -d "$kitdir/plugins/" ) {
chmod(644, "$kitdir/plugins/*");
opendir($dir,"$kitdir/plugins/");
if ( grep { ($_ ne '.') && ($_ ne '..') } readdir($dir) ) {
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Copying kit plugins from $kitdir/plugins/ to $::XCATROOT/lib/perl/xCAT_plugin";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
$rc = system("cp -rfv $kitdir/plugins/* $::XCATROOT/lib/perl/xCAT_plugin/");
} else {
$rc = system("cp -rf $kitdir/plugins/* $::XCATROOT/lib/perl/xCAT_plugin/");
}
$hasplugin = 1;
}
}
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to copy plugins from $kitdir/plugins/ to $::XCATROOT/lib/perl/xCAT_plugin";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Write to DB
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Writing kit configuration into xCAT DB";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
$rc = $tabs{kit}->setAttribs({kitname => $kithash->{kitname} }, $kithash );
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to write kit object into xCAT DB";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
foreach my $kitrepoid (keys %{$kitrepohash}) {
$rc = $tabs{kitrepo}->setAttribs({kitreponame => $kitrepohash->{$kitrepoid}->{kitreponame} }, \%{$kitrepohash->{$kitrepoid}} );
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to write kitrepo $kitrepohash->{$kitrepoid}->{kitreponame} into xCAT DB";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
foreach my $kitcompid (keys %{$kitcomphash}) {
$rc = $tabs{kitcomponent}->setAttribs({kitcompname => $kitcomphash->{$kitcompid}->{kitcompname} }, \%{$kitcomphash->{$kitcompid}} );
if($rc){
my %rsp;
push@{ $rsp{data} }, "Failed to write kitcomponent $kitcomphash->{$kitcompid}->{kitcompname} xCAT DB";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
push @kitnames, $kithash->{kitname};
}
unless ( $::INSPECTION ) {
my $kitlist = join ',', @kitnames;
my %rsp;
push@{ $rsp{data} }, "Kit $kitlist was successfully added.";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
if ( $hasplugin ) {
# Issue xcatd reload to load the new plugins
system("/etc/init.d/xcatd reload");
}
}
}
#-------------------------------------------------------
=head3 rmkit
Remove Kits from xCAT
=cut
#-------------------------------------------------------
sub rmkit
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $kitdir;
my $rc;
my $xusage = sub {
my %rsp;
push@{ $rsp{data} }, "Usage: rmkit - Remove Kits from xCAT.";
push@{ $rsp{data} }, "\trmkit [-h|--help]";
push@{ $rsp{data} }, "\trmkit [-v|--version]";
push@{ $rsp{data} }, "\trmkit [-V|--verbose] [-f|--force] [-t|--test] <kitlist>] [-V]";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
};
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The rmkit command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
unless(defined($request->{arg})){ $xusage->(1); return; }
@ARGV = @{$request->{arg}};
if($#ARGV eq -1){
$xusage->(1);
return;
}
GetOptions(
'h|help' => \$help,
'V|verbose' => \$::VERBOSE,
'v|version' => \$vers,
't|test' => \$test,
'f|force' => \$force
);
# Option -v for version
if ( defined($vers) ) {
create_version_response('rmkit');
return 1; # no usage - just exit
}
if($help){
$xusage->(0);
return;
}
my %tabs = ();
my @tables = qw(kit kitrepo kitcomponent osimage);
foreach my $t ( @tables ) {
$tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1);
if ( !exists( $tabs{$t} )) {
my %rsp;
push@{ $rsp{data} }, "Could not open xCAT table $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
# Convert to kitname if input is a basename
my %kitnames;
my $des = shift @ARGV;
my @kits = split ',', $des;
foreach my $kit (@kits) {
# Check if it is a kitname or basename
(my $ref1) = $tabs{kit}->getAttribs({kitname => $kit}, 'basename', 'isinternal');
if ( $ref1 and $ref1->{'basename'}){
if ( $ref1->{'isinternal'} and !$force ) {
my %rsp;
push@{ $rsp{data} }, "Kit $kit with isinterval attribute cannot be removed";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
$kitnames{$kit} = 1;
} else {
my @entries = $tabs{kit}->getAllAttribsWhere( "basename = '$kit'", 'kitname', 'isinternal');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "Kit $kit could not be found in DB $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
foreach my $entry (@entries) {
if ( $entry->{'isinternal'} and !$force ) {
my %rsp;
push@{ $rsp{data} }, "Kit $entry->{kitname} with isinterval attribute cannot be remoed";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
$kitnames{$entry->{kitname}} = 1;
}
}
}
# Remove each kit
my @entries = $tabs{'osimage'}->getAllAttribs( 'imagename', 'kitcomponents' );
my @kitlist;
my $hasplugin;
my @kpinuse;
foreach my $kitname (keys %kitnames) {
if ( !$test ) {
my %rsp;
push@{ $rsp{data} }, "Removing kit $kitname";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
# Remove osimage.kitcomponents.
# Find all the components in this kit.
my $kitcompnames;
my @kitcomphash = $tabs{kitcomponent}->getAllAttribsWhere( "kitname = '$kitname'", 'kitcompname', 'postbootscripts', 'genimage_postinstall');
if (@entries && (@entries > 0)) {
if($::VERBOSE and !$test){
my %rsp;
push@{ $rsp{data} }, "Removing kit components from osimage.kitcomponents";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
foreach my $entry (@entries) {
# Check osimage.kitcomponents
my @kitcomponents = split ',', $entry->{kitcomponents};
foreach my $kitcomponent ( @kitcomponents ) {
chomp $kitcomponent;
# Compare with each component in osimage.kitcomponents list.
foreach my $kitcomp ( @kitcomphash ) {
my $kitcompname = $kitcomp->{kitcompname};
# Remove this component from osimage.kitcomponents if -f option.
if ("$kitcompname" =~ /^$kitcomponent$/) {
if ( $test ) {
push @kpinuse, $kitcomponent;
my %rsp;
push@{ $rsp{data} }, "$kitcomponent is being used by osimage $entry->{imagename}";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
next;
}
unless ($force) {
my %rsp;
push@{ $rsp{data} }, "Failed to remove kit component $kitcomponent because:$kitcomponent is being used by osimage $entry->{imagename}";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Remove this component from osimage.kitcomponents. Mark here.
my $ret = xCAT::Utils->runxcmd({ command => ['rmkitcomp'], arg => ['-f','-i',$entry->{imagename}, $kitcompname] }, $request_command, 0, 1);
if ( $::RUNCMD_RC ) {
my %rsp;
push@{ $rsp{data} }, "Failed to remove kit component $kitcomponent from $entry->{imagename}";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
}
}
}
}
if ( $test ) {
next;
}
my $kitdir;
(my $ref1) = $tabs{kit}->getAttribs({kitname => $kitname }, 'kitdir');
if ( $ref1 and $ref1->{'kitdir'}){
$kitdir = $ref1->{'kitdir'};
chomp $kitdir;
# remove kit plugins from /opt/xcat/lib/perl/xCAT_plugin
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Removing kit plugins from $::XCATROOT/lib/perl/xCAT_plugin/";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
opendir($dir, $kitdir."/plugins");
my @files = readdir($dir);
if ( grep { ($_ ne '.') && ($_ ne '..') } @files ) {
$hasplugin = 1;
}
foreach my $file (@files) {
if ($file eq '.' or $file eq '..') { next; }
if ( -e "$::XCATROOT/lib/perl/xCAT_plugin/$file" ) {
if($::VERBOSE){
system("rm -rfv $::XCATROOT/lib/perl/xCAT_plugin/$file");
} else {
system("rm -rf $::XCATROOT/lib/perl/xCAT_plugin/$file");
}
}
}
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Removing kit scripts from /install/postscripts/";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
# remove kit scripts from /install/postscripts/
my $installdir = xCAT::TableUtils->getInstallDir();
unless($installdir){
$installdir = '/install';
}
$installdir =~ s/\/$//;
my $scripts;
foreach my $kitcomp ( @kitcomphash ) {
$scripts = $scripts.",".$kitcomp->{postbootscripts} if ( $kitcomp->{postbootscripts} );
$scripts = $scripts.",".$kitcomp->{genimage_postinstall} if ( $kitcomp->{genimage_postinstall} );
}
$scripts =~ s/^,//;
my @files = split /,/, $scripts;
foreach my $file (@files) {
if ($file eq '.' or $file eq '..') { next; }
if ( -e "$installdir/postscripts/$file" ) {
if($::VERBOSE){
system("rm -rfv $installdir/postscripts/$file");
} else {
system("rm -rf $installdir/postscripts/$file");
}
}
}
# remove kitdir from /install/kits/
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Removing kitdir from installdir";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
system("rm -rfv $kitdir");
} else {
system("rm -rf $kitdir");
}
}
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Removing kit from xCAT DB";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
# Remove kitcomponent
foreach my $kitcomp ( @kitcomphash ) {
my $kitcompname = $kitcomp->{kitcompname};
$tabs{kitcomponent}->delEntries({kitcompname => $kitcompname});
}
# Remove kitrepo
my @kitrepohash = $tabs{kitrepo}->getAllAttribsWhere( "kitname = '$kitname'", 'kitreponame');
foreach my $kitrepo ( @kitrepohash ) {
my $kitreponame = $kitrepo->{kitreponame};
$tabs{kitrepo}->delEntries({kitreponame => $kitreponame});
}
# Remove kit
$tabs{kit}->delEntries({kitname => $kitname});
push @kitlist, $kitname;
}
if ( $test ) {
if ( scalar(@kpinuse) ) {
my $kp = join ',', @kpinuse;
my %rsp;
push @{ $rsp{data} }, "Following kitcomponents are in use: $kp";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
} else {
my %rsp;
push @{ $rsp{data} }, "No kitcomponents are in use";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
return 0;
}
my $kits = join ',', @kitlist;
my %rsp;
push@{ $rsp{data} }, "Kit $kits was successfully removed.";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
if ( $hasplugin ) {
# Issue xcatd reload to load the new plugins
system("/etc/init.d/xcatd reload");
}
}
#-------------------------------------------------------
=head3 validate_os
Validate if the input OS fit to the osimage or not.
=cut
#-----------------------------------------------------
sub validate_os{
my $os = shift;
my $osimage = shift;
my $kitcomp = shift;
# Validate each attribute in kitcomp.
my $catched = 0;
my @osbasename = split ',', $kitcomp->{osbasename};
foreach (@osbasename) {
if ( $osimage->{basename} eq $_ ) {
$catched = 1;
}
}
unless ( $catched ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute OS";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $osimage->{majorversion} ne $kitcomp->{osmajorversion} ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute majorversion";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $kitcomp->{osminorversion} and ($osimage->{minorversion} ne $kitcomp->{osminorversion}) ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute minorversion";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $osimage->{arch} ne $kitcomp->{osarch} && $kitcomp->{osarch} ne 'noarch' ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute arch";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $osimage->{type} ne $kitcomp->{ostype} ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute type";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
if ( $osimage->{serverrole} ) {
my $match = 0;
my @os_serverroles = split /,/, $osimage->{serverrole};
my @kitcomp_serverroles = split /,/, $kitcomp->{serverroles};
foreach my $os_serverrole (@os_serverroles) {
foreach my $kitcomp_serverrole (@kitcomp_serverroles) {
if ( $os_serverrole eq $kitcomp_serverrole ) {
$match = 1;
last;
}
}
if ( $match ) {
last;
}
}
if ( !$match ) {
# my %rsp;
# push@{ $rsp{data} }, "osimage $os is not compatible with kit component $kitcomp->{kitcompname} with attribute serverrole";
# xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}
}
return 0;
}
#-------------------------------------------------------
=head3 addkitcomp
Assign Kit component to osimage
=cut
#-------------------------------------------------------
sub addkitcomp
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $kitdir;
my $rc;
my $xusage = sub {
my $ret = shift;
my %rsp;
push@{ $rsp{data} }, "Usage: addkitcomp - Add a Kit component to an xCAT osimage.";
push@{ $rsp{data} }, "\taddkitcomp [-h|--help]";
push@{ $rsp{data} }, "\taddkitcomp [-v|--version]";
push@{ $rsp{data} }, "\taddkitcomp [-V|--verbose] [-a|--adddeps] [-f|--force] \n\t\t[-n|--noupgrade] [--noscripts] -i <osimage> <kitcompname_list>";
xCAT::MsgUtils->message( "I", \%rsp, $callback, $ret );
};
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The addkitcomp command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
unless(defined($request->{arg})){ $xusage->(1); return; }
@ARGV = @{$request->{arg}};
if($#ARGV eq -1){
$xusage->(1);
return;
}
GetOptions(
'h|help' => \$help,
'V|verbose' => \$::VERBOSE,
'v|version' => \$vers,
'a|adddeps' => \$adddeps,
'f|force' => \$force,
'n|noupgrade' => \$::noupgrade,
'noscripts' => \$::noscripts,
'i=s' => \$osimage
);
if($help){
$xusage->(0);
return;
}
# Option -v for version
if ( defined($vers) ) {
create_version_response('addkitcomp');
return 1; # no usage - just exit
}
unless(scalar @ARGV)
{
$xusage->(1);
return 1;
}
my %tabs = ();
my @tables = qw(kit kitrepo kitcomponent osimage osdistro linuximage);
foreach my $t ( @tables ) {
$tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1);
if ( !exists( $tabs{$t} )) {
my %rsp;
push@{ $rsp{data} }, "Could not open xCAT table $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
# Check if all the kitcomponents are existing before processing
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Checking if kitcomponents are valid";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
my %kitcomps;
my $des = shift @ARGV;
my @kitcomponents = split ',', $des;
foreach my $kitcomponent (@kitcomponents) {
# Check if it is a kitcompname or basename
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomponent}, 'kitname', 'basename');
if ( $kitcomptable and $kitcomptable->{'basename'}){
$kitcomps{$kitcomponent}{name} = $kitcomponent;
$kitcomps{$kitcomponent}{basename} = $kitcomptable->{'basename'};
} else {
my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcomponent'", 'kitcompname' , 'version', 'release');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "$kitcomponent kitcomponent does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my $highest = get_highest_version('kitcompname', 'version', 'release', @entries);
$kitcomps{$highest}{name} = $highest;
$kitcomps{$highest}{basename} = $kitcomponent;
}
}
# Verify if the kitcomponents fitting to the osimage or not.
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Verifying if kitcomponents fit to osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
my %os;
my $osdistrotable;
(my $osimagetable) = $tabs{osimage}->getAttribs({imagename=> $osimage}, 'osdistroname', 'serverrole', 'kitcomponents', 'osname', 'osvers', 'osarch');
if ( $osimagetable and $osimagetable->{'osdistroname'}){
($osdistrotable) = $tabs{osdistro}->getAttribs({osdistroname=> $osimagetable->{'osdistroname'}}, 'basename', 'majorversion', 'minorversion', 'arch', 'type');
if ( !$osdistrotable or !$osdistrotable->{basename} ) {
my %rsp;
push @{ $rsp{data} }, "$osdistroname osdistro does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Read basename,majorversion,minorversion,arch,type, from osdistro table
$os{$osimage}{basename} = lc($osdistrotable->{basename});
$os{$osimage}{majorversion} = lc($osdistrotable->{majorversion});
$os{$osimage}{minorversion} = lc($osdistrotable->{minorversion});
$os{$osimage}{arch} = lc($osdistrotable->{arch});
$os{$osimage}{type} = lc($osdistrotable->{type});
# Read serverrole from osimage.
$os{$osimage}{serverrole} = lc($osimagetable->{'serverrole'});
} elsif ( !$osimagetable or !$osimagetable->{'osname'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osname' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} elsif ( !$osimagetable->{'osvers'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osvers' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} elsif ( !$osimagetable->{'osarch'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osarch' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} else {
$os{$osimage}{type} = lc($osimagetable->{'osname'});
$os{$osimage}{arch} = lc($osimagetable->{'osarch'});
$os{$osimage}{serverrole} = lc($osimagetable->{'serverrole'});
my ($basename, $majorversion, $minorversion) = $osimagetable->{'osvers'} =~ /^(\D+)(\d+)\W+(\d+)/;
$os{$osimage}{basename} = lc($basename);
$os{$osimage}{majorversion} = lc($majorversion);
$os{$osimage}{minorversion} = lc($minorversion);
}
foreach my $kitcomp ( keys %kitcomps ) {
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomp}, 'kitname', 'kitreponame', 'serverroles', 'kitcompdeps');
if ( $kitcomptable and $kitcomptable->{'kitname'} and $kitcomptable->{'kitreponame'}) {
# Read serverroles from kitcomponent table
$kitcomps{$kitcomp}{serverroles} = lc($kitcomptable->{'serverroles'});
# Read ostype from kit table
(my $kittable) = $tabs{kit}->getAttribs({kitname => $kitcomptable->{'kitname'}}, 'ostype');
if ( $kittable and $kittable->{ostype} ) {
$kitcomps{$kitcomp}{ostype} = lc($kittable->{ostype});
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomptable->{'kitname'} ostype does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Read osbasename, osmajorversion,osminorversion,osarch,compat_osbasenames from kitrepo table
(my $kitrepotable) = $tabs{kitrepo}->getAttribs({kitreponame => $kitcomptable->{'kitreponame'}}, 'osbasename', 'osmajorversion', 'osminorversion', 'osarch', 'compat_osbasenames');
if ($kitrepotable and $kitrepotable->{osbasename} and $kitrepotable->{osmajorversion} and $kitrepotable->{osarch}) {
if ($kitrepotable->{compat_osbasenames}) {
$kitcomps{$kitcomp}{osbasename} = lc($kitrepotable->{osbasename}) . ',' . lc($kitrepotable->{compat_osbasenames});
} else {
$kitcomps{$kitcomp}{osbasename} = lc($kitrepotable->{osbasename});
}
$kitcomps{$kitcomp}{osmajorversion} = lc($kitrepotable->{osmajorversion});
$kitcomps{$kitcomp}{osminorversion} = lc($kitrepotable->{osminorversion});
$kitcomps{$kitcomp}{osarch} = lc($kitrepotable->{osarch});
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomp osbasename,osmajorversion,osminorversion or osarch does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomp kitname or kitrepo name does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( !$force ) {
# Validate each attribute in kitcomp.
my $catched = 0;
my @osbasename = split ',', $kitcomps{$kitcomp}{osbasename};
foreach (@osbasename) {
if ( $os{$osimage}{basename} eq $_ ) {
$catched = 1;
}
}
unless ( $catched ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute OS";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{majorversion} ne $kitcomps{$kitcomp}{osmajorversion} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute majorversion";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $kitcomps{$kitcomp}{osminorversion} and ($os{$osimage}{minorversion} ne $kitcomps{$kitcomp}{osminorversion}) ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute minorversion";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{arch} ne $kitcomps{$kitcomp}{osarch} && $kitcomps{$kitcomp}{osarch} ne 'noarch' ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute arch";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{type} ne $kitcomps{$kitcomp}{ostype} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute type";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{serverrole} ) {
my $match = 0;
my @os_serverroles = split /,/, $os{$osimage}{serverrole};
my @kitcomp_serverroles = split /,/, $kitcomps{$kitcomp}{serverroles};
foreach my $os_serverrole (@os_serverroles) {
foreach my $kitcomp_serverrole (@kitcomp_serverroles) {
if ( $os_serverrole eq $kitcomp_serverrole ) {
$match = 1;
last;
}
}
if ( $match ) {
last;
}
}
if ( !$match ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute serverrole";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
if ( $kitcomptable and $kitcomptable->{'kitcompdeps'} ) {
my @kitcompdeps = split ',', $kitcomptable->{'kitcompdeps'};
foreach my $kitcompdependency ( @kitcompdeps ) {
my ($kitcompdep, $vers) = split /<=|>=|=|<|>/, $kitcompdependency;
my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcompdep'", 'kitreponame', 'kitname', 'kitcompname' , 'serverroles', 'kitcompdeps', 'version', 'prerequisite', 'release');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "Cannot find any matched kit component for kit component $kitcomp dependency $kitcompdep";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my $highest;
if ( $vers ) {
my @valid_kitcomp;
my $tmpkitcomp;
my ($vers, $rel) = split /-/, $vers;
$tmpkitcomp->{version} = $vers;
$tmpkitcomp->{release} = $rel;
foreach my $entry ( @entries ) {
my $rc = &compare_version($entry, $tmpkitcomp, 'kitcompname', 'version', 'release');
if ( ($rc == -1 and $kitcompdependency =~ />/ )
|| ($rc == 1 and $kitcompdependency =~ /</)
|| ($rc == 0 and $kitcompdependency =~ /=/) ) {
# Check if this kitcomp fits to the osimage
(my $krtable) = $tabs{kitrepo}->getAttribs({kitreponame => $entry->{'kitreponame'}}, 'osbasename', 'osmajorversion', 'osminorversion', 'osarch', 'compat_osbasenames');
if ($krtable->{compat_osbasenames}) {
$entry->{osbasename} = lc($krtable->{osbasename}) . ',' . lc($krtable->{compat_osbasenames});
} else {
$entry->{osbasename} = lc($krtable->{osbasename});
}
$entry->{osmajorversion} = lc($krtable->{osmajorversion});
$entry->{osminorversion} = lc($krtable->{osminorversion});
$entry->{osarch} = lc($krtable->{osarch});
(my $ktable) = $tabs{kit}->getAttribs({kitname => $entry->{'kitname'}}, 'ostype');
$entry->{ostype} = lc($ktable->{ostype});
unless ( &validate_os($osimage, $os{$osimage}, $entry) ) {
push @valid_kitcomp, $entry;
}
}
}
if ( scalar(@valid_kitcomp) ) {
$highest = get_highest_version('kitcompname', 'version', 'release', @valid_kitcomp);
} else {
my %rsp;
push@{ $rsp{data} }, "Cannot find any kit component could match for kit component $kitcomp dependency $kitcompdep";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
}
} else {
my @valid_kitcomp;
foreach my $entry ( @entries ) {
# Check if this kitcomp fits to the osimage
(my $krtable) = $tabs{kitrepo}->getAttribs({kitreponame => $entry->{'kitreponame'}}, 'osbasename', 'osmajorversion', 'osminorversion', 'osarch', 'compat_osbasenames');
if ($krtable->{compat_osbasenames}) {
$entry->{osbasename} = lc($krtable->{osbasename}) . ',' . lc($krtable->{compat_osbasenames});
} else {
$entry->{osbasename} = lc($krtable->{osbasename});
}
$entry->{osmajorversion} = lc($krtable->{osmajorversion});
$entry->{osminorversion} = lc($krtable->{osminorversion});
$entry->{osarch} = lc($krtable->{osarch});
(my $ktable) = $tabs{kit}->getAttribs({kitname => $entry->{'kitname'}}, 'ostype');
$entry->{ostype} = lc($ktable->{ostype});
unless ( &validate_os($osimage, $os{$osimage}, $entry) ) {
push @valid_kitcomp, $entry;
}
}
$highest = get_highest_version('kitcompname', 'version', 'release', @valid_kitcomp);
}
if ( $adddeps and $highest ) {
my $catched = 0;
if ( $osimagetable and $osimagetable->{'kitcomponents'}) {
my @oskitcomps = split ',', $osimagetable->{'kitcomponents'};
foreach my $oskitcomp ( @oskitcomps ) {
if ( $highest eq $oskitcomp ) {
$catched = 1;
last;
}
}
}
if ( !$catched ) {
# Add dependencies recursive
my $ret = xCAT::Utils->runxcmd({ command => ['addkitcomp'], arg => ['-a','-i',$osimage, $highest] }, $request_command, 0, 1);
if ( $::RUNCMD_RC ) {
my %rsp;
push@{ $rsp{data} }, "Failed to add dependency $highest to osimage $osimage";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
} else {
my $catched = 0;
if ( $osimagetable and $osimagetable->{'kitcomponents'}) {
my @oskitcomps = split ',', $osimagetable->{'kitcomponents'};
foreach my $oskitcomp ( @oskitcomps ) {
if ( $highest eq $oskitcomp ) {
$catched = 1;
last;
}
}
}
foreach my $k ( keys %kitcomps ) {
if ( $kitcomps{$k}{basename} and $kitcompdep eq $kitcomps{$k}{basename} ) {
$catched = 1;
last;
}
}
if ( !$catched ) {
my %rsp;
push@{ $rsp{data} }, "kit component dependency $highest for kit component $kitcomp is not existing in osimage or specified in command line";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
}
}
}
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "kitcomponent $kitcomp fits to osimage $osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
}
# Now assign each component to the osimage
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Assigning kitcomponent to osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
my @kitcomps;
my @oskitcomps;
my $catched = 0;
my @kitlist;
if ( $osimagetable and $osimagetable->{'kitcomponents'}) {
@oskitcomps = split ',', $osimagetable->{'kitcomponents'};
}
my @newkitcomps = keys %kitcomps;
foreach ( keys %kitcomps ) {
my $kitcomp = shift @newkitcomps;
my %rsp;
push@{ $rsp{data} }, "Assigning kit component $kitcomp to osimage $osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
# Check if this component is existing in osimage.kitcomponents
foreach my $oskitcomp ( @oskitcomps ) {
if ( $kitcomp eq $oskitcomp ) {
my %rsp;
push@{ $rsp{data} }, "$kitcomp kit component is already in osimage $osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
$catched = 1;
}
}
# No matching kitcomponent name in osimage.kitcomponents, now checking their basenames.
if ( !$catched ) {
my $add = 0;
foreach my $oskitcomp ( @oskitcomps ) {
# Compare this kit component's basename with basenames in osimage.kitcomponents
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomp}, 'basename', 'version', 'release');
if ( !$kitcomptable or !$kitcomptable->{'basename'} ) {
my %rsp;
push@{ $rsp{data} }, "$kitcomp kit component does not have basename";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
(my $oskitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $oskitcomp}, 'basename', 'version', 'release');
if ( !$oskitcomptable or !$oskitcomptable->{'basename'} ) {
my %rsp;
push@{ $rsp{data} }, "$oskitcomp kit component does not have basename";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
next;
}
if ( $kitcomptable->{'basename'} eq $oskitcomptable->{'basename'} ) {
my $rc = compare_version($oskitcomptable,$kitcomptable,'kitcompname', 'version', 'release');
if ( $rc == 1 and !$::noupgrade ) {
my %rsp;
push@{ $rsp{data} }, "Upgrading kit component $oskitcomp to $kitcomp";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
my $ret = xCAT::Utils->runxcmd({ command => ['rmkitcomp'], arg => ['-f','-i',$osimage, $oskitcomp] }, $request_command, -2, 1);
if ( !$ret ) {
my %rsp;
push@{ $rsp{data} }, "Failed to remove kit component $kitcomp from $osimage";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
$add = 1;
} elsif ( $rc == 0 ) {
my %rsp;
push@{ $rsp{data} }, "Do nothing since kit component $oskitcomp in osimage $osimage has the same basename/version and release with kit component $kitcomp";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
next;
} elsif ( !$::noupgrade ) {
my %rsp;
push@{ $rsp{data} }, "kit component $oskitcomp is already in osimage $osimage, and has a newer release/version than $kitcomp. Downgrading kit component is not supported";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
}
# Now assign this component to osimage
my $rc = assign_to_osimage( $osimage, $kitcomp, $callback, \%tabs);
}
push @kitlist, $kitcomp;
}
my $kitnames = join ',', @kitlist;
my %rsp;
push@{ $rsp{data} }, "Kit components $kitnames were added to osimage $osimage successfully";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
return;
}
#-------------------------------------------------------
=head3 rmkitcomp
Remove Kit component from osimage
=cut
#-------------------------------------------------------
sub rmkitcomp
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $kitdir;
my $rc;
my $xusage = sub {
my $ret = shift;
my %rsp;
push@{ $rsp{data} }, "Usage: rmkitcomp - Remove Kit components from an xCAT osimage.";
push@{ $rsp{data} }, "\trmkitcomp [-h|--help]";
push@{ $rsp{data} }, "\trmkitcomp [-v|--version]";
push@{ $rsp{data} }, "\trmkitcomp [-V|--verbose] [-u|--uninstall] [-f|--force] \n\t\t-i <osimage> <kitcompname_list>";
xCAT::MsgUtils->message( "I", \%rsp, $callback, $ret );
};
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The rmkitcomp command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
unless(defined($request->{arg})){ $xusage->(1); return; }
@ARGV = @{$request->{arg}};
if($#ARGV eq -1){
$xusage->(1);
return;
}
GetOptions(
'h|help' => \$help,
'V|verbose' => \$::VERBOSE,
'v|version' => \$vers,
'u|uninstall' => \$uninstall,
'f|force' => \$force,
'noscripts' => \$noscripts,
'i=s' => \$osimage
);
if($help){
$xusage->(0);
return;
}
# Option -v for version
if ( defined($vers) ) {
create_version_response('rmkitcomp');
return 1; # no usage - just exit
}
unless(scalar @ARGV)
{
$xusage->(1);
return 1;
}
my %tabs = ();
my @tables = qw(kit kitrepo kitcomponent osimage osdistro linuximage);
foreach my $t ( @tables ) {
$tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1);
if ( !exists( $tabs{$t} )) {
my %rsp;
push@{ $rsp{data} }, "Could not open xCAT table $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
return 1;
}
}
# Check if all the kitcomponents are existing before processing
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Checking if kitcomponents are valid";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
my %kitcomps;
my $des = shift @ARGV;
my @kitcomponents = split ',', $des;
foreach my $kitcomponent (@kitcomponents) {
# Check if it is a kitcompname or basename
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomponent}, 'kitname', 'kitpkgdeps', 'prerequisite', 'postbootscripts', 'genimage_postinstall', 'kitreponame', 'exlist', 'basename', 'driverpacks');
if ( $kitcomptable and $kitcomptable->{'kitname'}){
$kitcomps{$kitcomponent}{name} = $kitcomponent;
$kitcomps{$kitcomponent}{kitname} = $kitcomptable->{kitname};
$kitcomps{$kitcomponent}{kitpkgdeps} = $kitcomptable->{kitpkgdeps};
$kitcomps{$kitcomponent}{prerequisite} = $kitcomptable->{prerequisite};
$kitcomps{$kitcomponent}{basename} = $kitcomptable->{basename};
$kitcomps{$kitcomponent}{exlist} = $kitcomptable->{exlist};
$kitcomps{$kitcomponent}{postbootscripts} = $kitcomptable->{postbootscripts};
$kitcomps{$kitcomponent}{kitreponame} = $kitcomptable->{kitreponame};
$kitcomps{$kitcomponent}{driverpacks} = $kitcomptable->{driverpacks};
$kitcomps{$kitcomponent}{genimage_postinstall} = $kitcomptable->{genimage_postinstall};
} else {
my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcomponent'", 'kitcompname' , 'version', 'release');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "$kitcomponent kitcomponent does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my $highest = get_highest_version('kitcompname', 'version', 'release', @entries);
$kitcomps{$highest}{name} = $highest;
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $highest}, 'kitname', 'kitpkgdeps', 'prerequisite', 'postbootscripts', 'genimage_postinstall', 'kitreponame', 'exlist', 'basename', 'driverpacks');
$kitcomps{$highest}{kitname} = $kitcomptable->{kitname};
$kitcomps{$highest}{kitpkgdeps} = $kitcomptable->{kitpkgdeps};
$kitcomps{$highest}{prerequisite} = $kitcomptable->{prerequisite};
$kitcomps{$highest}{basename} = $kitcomptable->{basename};
$kitcomps{$highest}{exlist} = $kitcomptable->{exlist};
$kitcomps{$highest}{postbootscripts} = $kitcomptable->{postbootscripts};
$kitcomps{$highest}{kitreponame} = $kitcomptable->{kitreponame};
$kitcomps{$highest}{driverpacks} = $kitcomptable->{driverpacks};
$kitcomps{$highest}{genimage_postinstall} = $kitcomptable->{genimage_postinstall};
}
}
# Check if the kitcomponents are existing in osimage.kitcomponents attribute.
(my $osimagetable) = $tabs{osimage}->getAttribs({imagename => $osimage}, 'kitcomponents', 'postbootscripts', 'provmethod');
if ( !$osimagetable or !$osimagetable->{'kitcomponents'} ){
my %rsp;
push@{ $rsp{data} }, "$osimage osimage does not exist or not includes any kit components";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( !$osimagetable->{'provmethod'} ){
my %rsp;
push@{ $rsp{data} }, "$osimage osimage is missing provmethod";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my @osikitcomps = split ',', $osimagetable->{'kitcomponents'};
foreach my $osikitcomp ( @osikitcomps ) {
if ( exists($kitcomps{$osikitcomp}) ) {
$kitcomps{$osikitcomp}{matched} = 1;
}
}
my $invalidkitcomp = '';
foreach my $kitcomp ( keys %kitcomps) {
if ( !$kitcomps{$kitcomp}{matched} ) {
if ( !$invalidkitcomp ) {
$invalidkitcomp = $kitcomp;
} else {
$invalidkitcomp = join(',', $invalidkitcomp, $kitcomp);
}
}
}
if ( $invalidkitcomp ) {
my %rsp;
push@{ $rsp{data} }, "$invalidkitcomp kit components are not assigned to osimage $osimage";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Now check if there is any other kitcomponent depending on this one.
foreach my $kitcomponent (keys %kitcomps) {
foreach my $osikitcomp ( @osikitcomps ) {
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $osikitcomp}, 'kitcompdeps');
if ( $kitcomptable and $kitcomptable->{'kitcompdeps'} ) {
my @kitcompdeps = split(',', $kitcomptable->{'kitcompdeps'});
foreach my $kitcompdependency (@kitcompdeps) {
my ($kitcompdep, $vers) = split /<=|>=|=|<|>/, $kitcompdependency;
# Get the kit component full name from basename.
my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcompdep'", 'kitcompname' , 'version', 'release');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "kitcomponent $kitcompdep basename does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
}
my $kitcompdepname = get_highest_version('kitcompname', 'version', 'release', @entries);
if ( ($kitcomponent eq $kitcompdepname) and !$force and !exists($kitcomps{$osikitcomp}) ) {
# There is other kitcomponent depending on this one and there is no --force option
my %rsp;
push@{ $rsp{data} }, "Failed to remove kitcomponent $kitcomponent because $osikitcomp is still depending on it. Use -f option to remove it anyway";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
}
}
}
# Reading installdir
my $installdir = xCAT::TableUtils->getInstallDir();
unless($installdir){
$installdir = '/install';
}
$installdir =~ s/\/$//;
# Remove each kitcomponent from osimage.
my @newosikitcomps;
foreach my $osikitcomp ( @osikitcomps ) {
my $match = 0;
foreach my $kitcomponent (keys %kitcomps) {
if ( $kitcomponent eq $osikitcomp ) {
$match = 1;
last;
}
}
if (!$match) {
push @newosikitcomps, $osikitcomp;
}
}
my $newosikitcomp = join ',', @newosikitcomps;
$osimagetable->{'kitcomponents'} = $newosikitcomp;
# Remove kitcomponent.postbootscripts and kitcomponent.genimage_postinstall from osimage.postbootscripts.
my @osimagescripts;
my @newosimagescripts;
if ( $osimagetable and $osimagetable->{'postbootscripts'} ){
@osimagescripts = split( ',', $osimagetable->{'postbootscripts'} );
}
foreach my $osimagescript (@osimagescripts) {
my $match = 0;
foreach my $kitcomponent (keys %kitcomps) {
my @kitcompscripts = split( ',', $kitcomps{$kitcomponent}{postbootscripts} );
foreach my $kitcompscript ( @kitcompscripts ) {
if ( $osimagescript =~ /^$kitcompscript/ ) {
$match = 1;
last;
}
}
last if ($match);
}
if (!$match or $noscripts) {
push @newosimagescripts, $osimagescript;
}
#Remove genimage_postinstall from osimage.postbootscripts
if ( $osimagescript =~ /KIT_$osimage.postbootscripts/ and -e "$installdir/postscripts/KIT_$osimage.postbootscripts" ) {
foreach my $kitcomponent (keys %kitcomps) {
my @postbootlines;
my @newlines;
if (open(POSTBOOTSCRIPTS, "<", "$installdir/postscripts/KIT_$osimage.postbootscripts")) {
@postbootlines = <POSTBOOTSCRIPTS>;
close(POSTBOOTSCRIPTS);
}
my $match = 0;
my @kitcompscripts = split( ',', $kitcomps{$kitcomponent}{genimage_postinstall} );
foreach my $line ( @postbootlines ) {
chomp $line;
foreach my $kitcompscript ( @kitcompscripts ) {
if ( grep(/$kitcompscript/, $line) ) {
$match = 1;
}
}
if ( !$match ) {
push @newlines, $line."\n";
}
}
# Now write the new postbootscripts file.
if (open(NEWEXLIST, ">", "$installdir/postscripts/KIT_$osimage.postbootscripts")) {
print NEWEXLIST @newlines;
close(NEWEXLIST);
}
}
}
}
my $newosimagescript = join ',', @newosimagescripts;
$osimagetable->{'postbootscripts'} = $newosimagescript;
# Remove symlink from osimage.otherpkgdir.
# Read all the kitcomponents assigned to all the osimage to make sure the repo used by other osimage
# will not be deleted.
my @allosikitcomps = $tabs{osimage}->getAllAttribs( 'imagename', 'kitcomponents' );
(my $linuximagetable) = $tabs{linuximage}->getAttribs({imagename=> $osimage}, 'postinstall', 'exlist', 'otherpkglist', 'otherpkgdir', 'driverupdatesrc');
if ( $linuximagetable and $linuximagetable->{otherpkgdir} ) {
my $otherpkgdir = $linuximagetable->{otherpkgdir};
foreach my $kitcomponent (keys %kitcomps) {
my %newosikitcomponents;
foreach my $allosikitcomp (@allosikitcomps) {
if ( $allosikitcomp->{kitcomponents} and $allosikitcomp->{imagename} ) {
my @allkitcomps = split /,/, $allosikitcomp->{kitcomponents};
foreach my $allkitcomp ( @allkitcomps ) {
if ( $allosikitcomp->{imagename} ne $osimage or $allkitcomp ne $kitcomponent ) {
$newosikitcomponents{$allkitcomp} = 1;
}
}
}
}
if ( $kitcomps{$kitcomponent}{kitreponame} ) {
if ( -d "$otherpkgdir/$kitcomps{$kitcomponent}{kitreponame}" ) {
# Check if this repo is used by other kitcomponent before removing the link
my $match = 0;
foreach my $osikitcomp ( keys %newosikitcomponents ) {
my $depkitrepodir;
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $osikitcomp}, 'kitreponame');
if ( $kitcomptable and $kitcomptable->{kitreponame} ) {
$depkitrepodir = "$otherpkgdir/$kitcomptable->{kitreponame}";
}
if ( $depkitrepodir =~ /^$otherpkgdir\/$kitcomps{$kitcomponent}{kitreponame}$/) {
$match = 1;
}
}
if ( !$match ) {
system("rm -rf $otherpkgdir/$kitcomps{$kitcomponent}{kitreponame}");
}
}
}
}
}
# Remove genimage_postinstall from linuximage table
if ( $linuximagetable->{postinstall} ) {
my @scripts = split ',', $linuximagetable->{postinstall};
foreach my $script ( @scripts ) {
if ( $script =~ /KIT_COMPONENTS.postinstall/ and -e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall" ) {
foreach my $kitcomponent (keys %kitcomps) {
my @postinstalllines;
my @newlines;
if (open(POSTINSTALLSCRIPTS, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall") ) {
@postinstalllines = <POSTINSTALLSCRIPTS>;
close(POSTINSTALLSCRIPTS);
}
my @kitcompscripts = split( ',', $kitcomps{$kitcomponent}{genimage_postinstall} );
foreach my $line ( @postinstalllines ) {
chomp $line;
my $match = 0;
foreach my $kitcompscript ( @kitcompscripts ) {
if ( grep(/$kitcompscript/, $line) ) {
$match = 1;
last;
}
}
if ( !$match ) {
push @newlines, $line."\n";
}
}
# Now write the new postbootscripts file.
if (open(NEWEXLIST, ">", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.postinstall")) {
print NEWEXLIST @newlines;
close(NEWEXLIST);
}
}
}
}
}
# Remove kitcomponent exlist,otherpkglist and deploy_params from osimage
my @kitlist;
foreach my $kitcomponent (keys %kitcomps) {
my %rsp;
push@{ $rsp{data} }, "Removing kitcomponent $kitcomponent from osimage $osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
if ( !exists($kitcomps{$kitcomponent}{kitname}) ) {
my %rsp;
push@{ $rsp{data} }, "Could not find kit object for kitcomponent $kitcomponent";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Reading kitdir
my $kitdir = '';
my $exlistfile = '';
my $kitname = $kitcomps{$kitcomponent}{kitname};
(my $kittable) = $tabs{kit}->getAttribs({kitname=> $kitname}, 'kitdir', 'kitdeployparams');
# Removing exlist
if ( $linuximagetable and $linuximagetable->{exlist} ) {
my $match = 0;
my @exlists= split ',', $linuximagetable->{exlist};
foreach my $exlist ( @exlists ) {
if ( $exlist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_COMPONENTS.exlist$/ ) {
$match = 1;
last;
}
}
my @lines = ();
if ( $match and -e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist" ) {
if (open(EXLIST, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist")) {
@lines = <EXLIST>;
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit component exlist file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit component exlist file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $kittable and $kittable->{kitdir} ) {
$kitdir = $kittable->{kitdir};
}
if ( exists($kitcomps{$kitcomponent}{exlist}) ) {
$exlistfile = $kitcomps{$kitcomponent}{exlist};
}
my @newlines = ();
foreach my $line ( @lines ) {
chomp $line;
if ( $line =~ /^#INCLUDE:$kitdir\/other_files\/$exlistfile#$/ ) {
next;
}
push @newlines, $line . "\n";
}
if (open(NEWEXLIST, ">", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist")) {
print NEWEXLIST @newlines;
close(NEWEXLIST);
}
}
}
# Removing otherpkglist
if ( $linuximagetable and $linuximagetable->{otherpkglist} ) {
my $match = 0;
my @lines = ();
my @otherpkglists = split ',', $linuximagetable->{otherpkglist};
foreach my $otherpkglist ( @otherpkglists ) {
if ( $otherpkglist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_COMPONENTS.otherpkgs.pkglist$/ ) {
$match = 1;
last;
}
}
if ( $match and -e "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist" ) {
if (open(OTHERPKGLIST, "<", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist")) {
@lines = <OTHERPKGLIST>;
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit component otherpkg pkglist $installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit component exlist file $installdir/osimages/$osimage/kits/KIT_COMPONENTS.exlist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my $basename = '';
if ( exists($kitcomps{$kitcomponent}{basename}) and exists($kitcomps{$kitcomponent}{kitreponame})) {
$basename = $kitcomps{$kitcomponent}{basename};
my $kitreponame = $kitcomps{$kitcomponent}{kitreponame};
my @newlines = ();
my $num = 0;
my $inlist = 0;
foreach my $line ( @lines ) {
chomp $line;
if ( $line =~ /^#NEW_INSTALL_LIST#/ ) {
$num = 1;
$inlist = 1;
}
if ( $kitcomps{$kitcomponent}{prerequisite} ) {
if ( $line =~ /^$kitreponame\/prep_$basename$/ ) {
if ( $inlist ) {
$num--;
foreach ( 1..$num ) {
pop @newlines;
}
}
next;
}
}
if ( $line =~ /^$kitreponame\/$basename$/ ) {
if ( $inlist ) {
$num--;
foreach ( 1..$num ) {
pop @newlines;
}
}
next;
}
push @newlines, $line . "\n";
$num++;
}
if (open(NEWOTHERPKGLIST, ">", "$installdir/osimages/$osimage/kits/KIT_COMPONENTS.otherpkgs.pkglist")) {
print NEWOTHERPKGLIST @newlines;
close(NEWOTHERPKGLIST);
}
}
}
# Add this component basename and pkgnames to KIT_RMPKGS.otherpkg.pkglist
if ( $uninstall ) {
my @lines = ();
mkpath("$installdir/osimages/$osimage/kits/");
if ( -e "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist" ) {
if (open(RMOTHERPKGLIST, "<", "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist")) {
@lines = <RMOTHERPKGLIST>;
close(RMOTHERPKGLIST);
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit component rmpkgs file $installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit component rmpkgs file $installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
my @l = @lines;
my $basename = '';
my $kitreponame = '';
my @kitpkgdeps = ();
if ( exists($kitcomps{$kitcomponent}{basename}) and exists($kitcomps{$kitcomponent}{kitreponame}) ) {
$basename = $kitcomps{$kitcomponent}{basename};
$kitreponame = $kitcomps{$kitcomponent}{kitreponame};
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit component table and read basename for kit component $kitcomp";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( exists($kitcomps{$kitcomponent}{kitpkgdeps}) ) {
@kitpkgdeps = split ',', $kitcomps{$kitcomponent}{kitpkgdeps};
}
# Add prerequisite to KIT_RMPKGS.otherpkg.pkglist
if ( $kitcomps{$kitcomponent}{prerequisite} ) {
my @kitpreps = split /,/, $kitcomps{$kitcomponent}{prerequisite};
foreach my $kitprep ( @kitpreps ) {
push @kitpkgdeps, $kitprep;
}
}
push @kitpkgdeps, $basename;
my $update = 0;
foreach my $kitpkgdep ( @kitpkgdeps ) {
next if ( $kitpkgdep =~ /^$/ );
my $matched = 0;
foreach my $line ( @lines ) {
chomp $line;
if ( $line =~ /^-$kitpkgdep$/ ) {
$matched = 1;
last;
}
}
unless ( $matched ) {
unshift @l, "-$kitpkgdep\n";
$update = 1;
}
}
if ( $update and open(RMPKGLIST, ">", "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist") ) {
print RMPKGLIST @l;
close(RMPKGLIST);
}
if ( $linuximagetable and $linuximagetable->{otherpkglist} ) {
my $match = 0;
my @otherpkglists= split ',', $linuximagetable->{otherpkglist};
foreach my $otherpkglist ( @otherpkglists ) {
if ( $otherpkglist =~ /^$installdir\/osimages\/$osimage\/kits\/KIT_RMPKGS.otherpkgs.pkglist$/ ) {
$match = 1;
last;
}
}
if ( !$match and -e "$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist" ) {
$linuximagetable->{otherpkglist} = $linuximagetable->{otherpkglist} . ",$installdir/osimages/$osimage/kits/KIT_RMPKGS.otherpkgs.pkglist"
}
}
}
}
# Removing deploy parameters
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
my $kitdir = $kittable->{kitdir};
my $kitdeployfile = $kittable->{kitdeployparams};
# Check if there is other kitcomponent in the same kit.
my $match = 0;
if ( exists($kitcomps{$kitcomponent}{kitname}) ) {
my $kitname = $kitcomps{$kitcomponent}{kitname};
foreach my $osikitcomp ( @osikitcomps ) {
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname=> $osikitcomp}, 'kitname');
if ( $kitcomptable and $kitcomptable->{kitname} and $kitcomptable->{kitname} eq $kitname and !exists($kitcomps{$osikitcomp}{name}) ) {
$match = 1;
last;
}
}
unless ( $match ) {
my @contents = ();;
if ( -e "$kitdir/other_files/$kitdeployfile" ) {
if (open(KITDEPLOY, "<", "$kitdir/other_files/$kitdeployfile") ) {
@contents = <KITDEPLOY>;
close(KITDEPLOY);
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit deployparams from $kitdir/other_files/$kitdeployfile";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit deployparams file $kitdir/other_files/$kitdeployfile";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
push @contents, "#INCLUDE:$kitdir/other_files/$kitdeployfile#";
}
my @lines = ();
if ( -e "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist" ) {
system("cp $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist.orig");
if (open(DEPLOYPARAM, "<", "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist")) {
@lines = <DEPLOYPARAM>;
close(DEPLOYPARAM);
if($::VERBOSE){
my %rsp;
push@{ $rsp{data} }, "Reading kit deployparams file $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
}
} else {
my %rsp;
push@{ $rsp{data} }, "Could not open kit deployparams file $installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
# Check if each deploy parameter is used by other kitcomponent.
my @otherlines = ();
foreach my $osikitcomp ( @osikitcomps ) {
next if ( exists($kitcomps{$osikitcomp}{name}) );
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname=> $osikitcomp}, 'kitname');
if ( $kitcomptable and $kitcomptable->{kitname} ) {
(my $kittable) = $tabs{kit}->getAttribs({kitname=> $kitcomptable->{kitname}}, 'kitdir', 'kitdeployparams');
if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) {
my @otherdeployparams;
my $deployparam_file = $kittable->{kitdir}."/other_files/".$kittable->{kitdeployparams};
if ( -e "$deployparam_file" ) {
if (open(OTHERDEPLOYPARAM, "<", "$deployparam_file" )) {
@otherdeployparams = <OTHERDEPLOYPARAM>;
close(OTHERDEPLOYPARAM);
}
foreach ( @otherdeployparams ) {
push @otherlines, $_;
}
push @otherlines, "#INCLUDE:$deployparam_file#";
}
}
}
}
my @newcontents = ();
foreach my $line ( @lines ) {
chomp $line;
my $found = 0;
#check if the parameter is used by other kitcomponent
foreach my $otherline ( @otherlines ) {
chomp $otherline;
if ( $line =~ m!$otherline! ) {
$found = 1;
last;
}
}
if ( $found ) {
push @newcontents, $line . "\n";
} else {
foreach my $content ( @contents ) {
chomp $content;
if ( $line =~ m!$content! ) {
$found = 1;
last;
}
}
unless ( $found ) {
push @newcontents, $line . "\n";
}
}
}
# Write the updated lines to kit deployparams file
if (open(NEWDEPLOYPARAM, ">", "$installdir/osimages/$osimage/kits/KIT_DEPLOY_PARAMS.otherpkgs.pkglist")) {
print NEWDEPLOYPARAM @newcontents;
close(NEWDEPLOYPARAM);
}
}
}
}
# Remove driverpacks from linuximage
if ( $linuximagetable and $linuximagetable->{driverupdatesrc} ) {
if ( exists($kitcomps{$kitcomponent}{driverpacks}) ) {
my @driverpacks = split ',', $kitcomps{$kitcomponent}{driverpacks};
my @driverupdatesrcs = split ',', $linuximagetable->{driverupdatesrc};
my @newdriverupdatesrcs = ();
foreach my $driverupdatesrc ( @driverupdatesrcs ) {
my $matched = 0;
foreach my $driverpack ( @driverpacks ) {
if ( $driverpack eq $driverupdatesrc ) {
$matched = 1;
last;
}
}
unless ( $matched ) {
push @newdriverupdatesrcs, $driverupdatesrc;
}
}
my $newdriverupdatesrc = join ',', @newdriverupdatesrcs;
$linuximagetable->{driverupdatesrc} = $newdriverupdatesrc;
}
}
push @kitlist, $kitcomponent;
}
my $kitcompnames = join ',', @kitlist;
my %rsp;
push@{ $rsp{data} }, "kitcomponents $kitcompnames were removed from osimage $osimage successfully";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
# Write linuximage table with all the above udpates.
$tabs{linuximage}->setAttribs({imagename => $osimage }, \%{$linuximagetable} );
# Write osimage table with all the above udpates.
$tabs{osimage}->setAttribs({imagename => $osimage }, \%{$osimagetable} );
return;
}
#-------------------------------------------------------
=head3 chkkitcomp
Check if the kit components fits to osimage
=cut
#-------------------------------------------------------
sub chkkitcomp
{
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $xusage = sub {
my %rsp;
push@{ $rsp{data} }, "Usage: chkkitcomp - Check if a Kit component is compatible with an xCAT osimage.";
push@{ $rsp{data} }, "\tchkkitcomp [-h|--help]";
push@{ $rsp{data} }, "\tchkkitcomp [-v|--version]";
push@{ $rsp{data} }, "\tchkkitcomp [-V|--verbose] -i <osimage> <kitcompname_list>";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
};
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The chkkitcomp command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
unless(defined($request->{arg})){ $xusage->(1); return; }
@ARGV = @{$request->{arg}};
if($#ARGV eq -1){
$xusage->(1);
return;
}
GetOptions(
'h|help' => \$help,
'V|verbose' => \$::VERBOSE,
'v|version' => \$vers,
'i=s' => \$osimage
);
if($help){
$xusage->(0);
return;
}
# Option -v for version
if ( defined($vers) ) {
create_version_response('chkkitcomp');
return 1; # no usage - just exit
}
my %tabs = ();
my @tables = qw(kit kitrepo kitcomponent osimage osdistro linuximage);
foreach my $t ( @tables ) {
$tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1);
if ( !exists( $tabs{$t} )) {
my %rsp;
push@{ $rsp{data} }, "Could not open xCAT table $t";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
# Check if all the kitcomponents are existing before processing
my %kitcomps;
my %kitcompbasename;
my $des = shift @ARGV;
my @kitcomponents = split ',', $des;
foreach my $kitcomponent (@kitcomponents) {
# Check if it is a kitcompname or basename
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomponent}, 'kitname', 'kitcompdeps', 'kitpkgdeps', 'kitreponame', 'basename', 'serverroles');
if ( $kitcomptable and $kitcomptable->{'kitname'}){
$kitcomps{$kitcomponent}{name} = $kitcomponent;
$kitcomps{$kitcomponent}{kitname} = $kitcomptable->{kitname};
$kitcomps{$kitcomponent}{kitpkgdeps} = $kitcomptable->{kitpkgdeps};
$kitcomps{$kitcomponent}{kitcompdeps} = $kitcomptable->{kitcompdeps};
$kitcomps{$kitcomponent}{basename} = $kitcomptable->{basename};
$kitcomps{$kitcomponent}{kitreponame} = $kitcomptable->{kitreponame};
$kitcomps{$kitcomponent}{serverroles} = $kitcomptable->{serverroles};
$kitcompbasename{$kitcomptable->{basename}} = 1;
} else {
my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcomponent'", 'kitcompname' , 'version', 'release');
unless (@entries) {
my %rsp;
push@{ $rsp{data} }, "$kitcomponent kitcomponent does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
my $highest = get_highest_version('kitcompname', 'version', 'release', @entries);
$kitcomps{$highest}{name} = $highest;
(my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $highest}, 'kitname', 'kitpkgdeps', 'kitcompdeps', 'kitreponame', 'basename', 'serverroles');
$kitcomps{$highest}{kitname} = $kitcomptable->{kitname};
$kitcomps{$highest}{kitpkgdeps} = $kitcomptable->{kitpkgdeps};
$kitcomps{$highest}{kitcompdeps} = $kitcomptable->{kitcompdeps};
$kitcomps{$highest}{basename} = $kitcomptable->{basename};
$kitcomps{$highest}{kitreponame} = $kitcomptable->{kitreponame};
$kitcomps{$highest}{serverroles} = $kitcomptable->{serverroles};
$kitcompbasename{$kitcomponent} = 1;
}
}
# Verify if the kitcomponents fitting to the osimage or not.
my %os;
my $osdistrotable;
(my $osimagetable) = $tabs{osimage}->getAttribs({imagename=> $osimage}, 'osdistroname', 'serverrole', 'kitcomponents', 'osname', 'osvers', 'osarch');
if ( $osimagetable and $osimagetable->{'osdistroname'}){
($osdistrotable) = $tabs{osdistro}->getAttribs({osdistroname=> $osimagetable->{'osdistroname'}}, 'basename', 'majorversion', 'minorversion', 'arch', 'type');
if ( !$osdistrotable or !$osdistrotable->{basename} ) {
my %rsp;
push @{ $rsp{data} }, "$osdistroname osdistro does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Read basename,majorversion,minorversion,arch,type, from osdistro table
$os{$osimage}{basename} = lc($osdistrotable->{basename});
$os{$osimage}{majorversion} = lc($osdistrotable->{majorversion});
$os{$osimage}{minorversion} = lc($osdistrotable->{minorversion});
$os{$osimage}{arch} = lc($osdistrotable->{arch});
$os{$osimage}{type} = lc($osdistrotable->{type});
# Read serverrole from osimage.
$os{$osimage}{serverrole} = lc($osimagetable->{'serverrole'});
} elsif ( !$osimagetable or !$osimagetable->{'osname'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osname' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} elsif ( !$osimagetable->{'osvers'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osvers' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} elsif ( !$osimagetable->{'osarch'} ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage does not contains a valid 'osarch' attribute";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
} else {
$os{$osimage}{type} = lc($osimagetable->{'osname'});
$os{$osimage}{arch} = lc($osimagetable->{'osarch'});
$os{$osimage}{serverrole} = lc($osimagetable->{'serverrole'});
my ($basename, $majorversion, $minorversion) = $osimagetable->{'osvers'} =~ /^(\D+)(\d+)\W+(\d+)/;
$os{$osimage}{basename} = lc($basename);
$os{$osimage}{majorversion} = lc($majorversion);
$os{$osimage}{minorversion} = lc($minorversion);
}
my @kitcompnames;
foreach my $kitcomp ( keys %kitcomps ) {
if ( $kitcomps{$kitcomp}{kitname} and $kitcomps{$kitcomp}{kitreponame}) {
# Read ostype from kit table
(my $kittable) = $tabs{kit}->getAttribs({kitname => $kitcomps{$kitcomp}{kitname}}, 'ostype');
if ( $kittable and $kittable->{ostype} ) {
$kitcomps{$kitcomp}{ostype} = lc($kittable->{ostype});
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomp ostype does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Read osbasename, osmajorversion,osminorversion,osarch,compat_osbasenames from kitrepo table
(my $kitrepotable) = $tabs{kitrepo}->getAttribs({kitreponame => $kitcomps{$kitcomp}{kitreponame}}, 'osbasename', 'osmajorversion', 'osminorversion', 'osarch', 'compat_osbasenames');
if ($kitrepotable and $kitrepotable->{osbasename} and $kitrepotable->{osmajorversion} and $kitrepotable->{osarch}) {
if ($kitrepotable->{compat_osbasenames}) {
$kitcomps{$kitcomp}{osbasename} = lc($kitrepotable->{osbasename}) . ',' . lc($kitrepotable->{compat_osbasenames});
} else {
$kitcomps{$kitcomp}{osbasename} = lc($kitrepotable->{osbasename});
}
$kitcomps{$kitcomp}{osmajorversion} = lc($kitrepotable->{osmajorversion});
$kitcomps{$kitcomp}{osminorversion} = lc($kitrepotable->{osminorversion});
$kitcomps{$kitcomp}{osarch} = lc($kitrepotable->{osarch});
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomp osbasename,osmajorversion,osminorversion or osarch does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
} else {
my %rsp;
push@{ $rsp{data} }, "$kitcomp kitname $kitcomptable->{'kitname'} or kitrepo name $kitcomptable->{'kitreponame'} or serverroles $kitcomps{$kitcomp}{serverroles} does not exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
# Validate each attribute in kitcomp.
my $catched = 0;
my @osbasename = split ',', $kitcomps{$kitcomp}{osbasename};
foreach (@osbasename) {
if ( $os{$osimage}{basename} eq $_ ) {
$catched = 1;
}
}
unless ( $catched ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp is not compatible with osimage $osimage with attribute OS";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{majorversion} ne $kitcomps{$kitcomp}{osmajorversion} ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp is not compatible with osimage $osimage with attribute majorversion";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $kitcomps{$kitcomp}{osminorversion} and ($os{$osimage}{minorversion} ne $kitcomps{$kitcomp}{osminorversion}) ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp is not compatible with osimage $osimage with attribute minorversion";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{arch} ne $kitcomps{$kitcomp}{osarch} && $kitcomps{$kitcomp}{osarch} ne 'noarch' ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp is not compatible with osimage $osimage with attribute arch";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{type} ne $kitcomps{$kitcomp}{ostype} ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp is not compatible with osimage $osimage with attribute type";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
if ( $os{$osimage}{serverrole} ) {
my $match = 0;
my @os_serverroles = split /,/, $os{$osimage}{serverrole};
my @kitcomp_serverroles = split /,/, $kitcomps{$kitcomp}{serverroles};
foreach my $os_serverrole (@os_serverroles) {
foreach my $kitcomp_serverrole (@kitcomp_serverroles) {
if ( $os_serverrole eq $kitcomp_serverrole ) {
$match = 1;
last;
}
}
if ( $match ) {
last;
}
}
if ( !$match ) {
my %rsp;
push@{ $rsp{data} }, "osimage $osimage is not compatible with kit component $kitcomp with attribute serverrole";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
# Check if this kit component's dependencies are in the kitcomponent list.
if ( $kitcomps{$kitcomp}{kitcompdeps} ) {
my ($kitcompdep, $vers) = split /<=|>=|=|<|>/, $kitcomps{$kitcomp}{kitcompdeps};
if ( !exists( $kitcompbasename{ $kitcompdep } ) ) {
my %rsp;
push@{ $rsp{data} }, "kit component $kitcomp dependency $kitcomps{$kitcomp}{kitcompdeps} doesn't exist";
xCAT::MsgUtils->message( "E", \%rsp, $callback );
return 1;
}
}
push @kitcompnames, $kitcomp;
}
my $kitcompnamelist = join ',', @kitcompnames;
my %rsp;
push@{ $rsp{data} }, "Kit components $kitcompnamelist are compatible with osimage $osimage";
xCAT::MsgUtils->message( "I", \%rsp, $callback );
return;
}
#----------------------------------------------------------------------------
=head3 lskit_usage
Display the lskit usage
=cut
#-----------------------------------------------------------------------------
sub lskit_usage {
my $rsp;
push @{ $rsp->{data} },
"\nUsage: lskit - List infomation for one or more kits.\n";
push @{ $rsp->{data} },
"\tlskit [-V|--verbose] [-x|--xml|--XML] [-K|--kitattr kitattr_names]\n\t[-R|--repoattr repoattr_names] [-C|--compattr compattr_names]\n\t[kit_names]\n ";
push @{ $rsp->{data} }, "\tlskit [-h|--help|-?]\n";
push @{ $rsp->{data} }, "\tlskit [-v|--version]\n ";
push @{ $rsp->{data} }, "\tlskit [-F|--framework] kit_path_name\n ";
xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK );
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitcomp_usage
Display the lskitcomp usage
=cut
#-----------------------------------------------------------------------------
sub lskitcomp_usage {
my $rsp;
push @{ $rsp->{data} },
"\nUsage: lskitcomp - List information for one or more Kit components.";
push @{ $rsp->{data} }, "\tlskitcomp [-h|--help|-?]";
push @{ $rsp->{data} }, "\tlskitcomp [-v|--version]";
push @{ $rsp->{data} }, "\tlskitcomp [-V|--verbose] [-x|--xml|--XML] \n\t\t[-C|--compattr compattr_names] [-O|--osdistro os_distro]\n\t\t[-S|--serverrole server_role] [kitcomp_names]\n ";
xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK );
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitdeployparam_usage
Display the lskitdeployparam usage
=cut
#-----------------------------------------------------------------------------
sub lskitdeployparam_usage {
my $rsp;
push @{ $rsp->{data} }, "\nUsage: lskitdeployparam - List the kit deployment parameters for full Kits or Kit components.";
push @{ $rsp->{data} }, "\tlskitdeployparam [-h|--help|-?]";
push @{ $rsp->{data} }, "\tlskitdeployparam [-v|--version]";
push @{ $rsp->{data} }, "\tlskitdeployparam [-V|--verbose] [-x|--xml|--XML] \n\t\t[-k|--kitname kit_names] [-c|--compname comp_names]\n";
xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK );
return 0;
}
#----------------------------------------------------------------------------
=head3 create_version_response
Create a response containing the command name and version
=cut
#-----------------------------------------------------------------------------
sub create_version_response {
my $command = shift;
my $rsp;
my $version = xCAT::Utils->Version();
push @{ $rsp->{data} }, "$command - xCAT $version";
push @{ $rsp->{data} }, "\tkitframework = $::KITFRAMEWORK";
push @{ $rsp->{data} }, "\tcompatible_frameworks = $::COMPATIBLE_KITFRAMEWORKS\n";
xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK );
}
#----------------------------------------------------------------------------
=head3 create_error_response
Create a response containing a single error message
Arguments: error message
=cut
#-----------------------------------------------------------------------------
sub create_error_response {
my $error_msg = shift;
my $rsp;
push @{ $rsp->{data} }, $error_msg;
xCAT::MsgUtils->message( "E", $rsp, $::CALLBACK );
}
#----------------------------------------------------------------------------
=head3 lskit_processargs
Process the lskit command line
Returns:
0 - OK
1 - just print version
2 - just print help
3 - error
=cut
#-----------------------------------------------------------------------------
sub lskit_processargs {
if ( defined( @{$::args} ) ) {
@ARGV = @{$::args};
}
# parse the options
# options can be bundled up like -vV, flag unsupported options
Getopt::Long::Configure( "bundling", "no_ignore_case", "no_pass_through" );
my $getopt_success = Getopt::Long::GetOptions(
'help|h|?' => \$::opt_h,
'kitattr|K=s' => \$::opt_K,
'repoattr|R=s' => \$::opt_R,
'compattr|C=s' => \$::opt_C,
'framework|F=s' => \$::opt_F,
'verbose|V' => \$::opt_V,
'version|v' => \$::opt_v,
'xml|XML|x' => \$::opt_x,
);
if (!$getopt_success) {
return 3;
}
# Option -h for Help
if ( defined($::opt_h) ) {
return 2;
}
# Option -v for version
if ( defined($::opt_v) ) {
create_version_response('lskit');
return 1; # no usage - just exit
}
# Option -V for verbose output
if ( defined($::opt_V) ) {
$::VERBOSE = 1;
}
# Option -K for kit attributes
if ( defined($::opt_K) ) {
$::kitattrs = split_comma_delim_str($::opt_K);
ensure_kitname_attr_in_list($::kitattrs);
if (check_attr_names_exist('kit', $::kitattrs) != 0) {
return 3;
}
}
# Option -R for kit repo attributes
if ( defined($::opt_R) ) {
$::kitrepoattrs = split_comma_delim_str($::opt_R);
ensure_kitname_attr_in_list($::kitrepoattrs);
if (check_attr_names_exist('kitrepo', $::kitrepoattrs) != 0) {
return 3;
}
}
# Option -C for kit component attributes
if ( defined($::opt_C)) {
$::kitcompattrs = split_comma_delim_str($::opt_C);
ensure_kitname_attr_in_list($::kitcompattrs);
if (check_attr_names_exist('kitcomponent', $::kitcompattrs) != 0) {
return 3;
}
}
# Kit names
my $kitnames_str = shift(@ARGV);
if ( defined($kitnames_str) ) {
my @tmp = split(/,/, $kitnames_str);
$::kitnames = \@tmp;
if (check_attr_values_exist('kit', 'kitname', 'kit names', $::kitnames) != 0) {
return 3;
}
}
# Other attributes are not allowed
my $more_input = shift(@ARGV);
if ( defined($more_input) ) {
create_error_response("Invalid input: $more_input \n");
return 3;
}
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitcomp_processargs
Process the lskitcomp command line
Returns:
0 - OK
1 - just print version
2 - just print help
3 - error
=cut
#-----------------------------------------------------------------------------
sub lskitcomp_processargs {
if ( defined( @{$::args} ) ) {
@ARGV = @{$::args};
}
# parse the options
# options can be bundled up like -vV, flag unsupported options
Getopt::Long::Configure( "bundling", "no_ignore_case", "no_pass_through" );
my $getopt_success = Getopt::Long::GetOptions(
'help|h|?' => \$::opt_h,
'compattr|C=s' => \$::opt_C,
'osdistro|O=s' => \$::opt_O,
'serverrole|S=s' => \$::opt_S,
'verbose|V' => \$::opt_V,
'version|v' => \$::opt_v,
'xml|XML|x' => \$::opt_x,
);
if (!$getopt_success) {
return 3;
}
# Option -h for Help
if ( defined($::opt_h) ) {
return 2;
}
# Option -v for version
if ( defined($::opt_v) ) {
create_version_response('lskitcomp');
return 1; # no usage - just exit
}
# Option -V for verbose output
if ( defined($::opt_V) ) {
$::VERBOSE = 1;
}
# Option -C for kit component attributes
if ( defined($::opt_C) ) {
$::kitcompattrs = split_comma_delim_str($::opt_C);
ensure_kitname_attr_in_list($::kitcompattrs);
if (check_attr_names_exist('kitcomponent', $::kitcompattrs) != 0) {
return 3;
}
}
# Option -O for osdistro name
$::osdistroname = $::opt_O;
if ( defined($::osdistroname) ) {
if (check_attr_values_exist('osdistro', 'osdistroname', 'os distro', [$::osdistroname]) != 0) {
return 3;
}
}
# Option -S for server role
$::serverrole = $::opt_S;
# Kit component names
my $kitcompnames_str = shift(@ARGV);
if ( defined($kitcompnames_str) ) {
my @tmp = split(/,/, $kitcompnames_str);
$::kitcompnames = \@tmp;
if (check_attr_values_exist('kitcomponent', 'kitcompname', 'kit component names', $::kitcompnames) != 0) {
return 3;
}
}
# Other attributes are not allowed
my $more_input = shift(@ARGV);
if ( defined($more_input) ) {
create_error_response("Invalid input: $more_input \n");
return 3;
}
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitdeployparam_processargs
Process the lskitdeployparam command line
Returns:
0 - OK
1 - just print version
2 - just print help
3 - error
=cut
#-----------------------------------------------------------------------------
sub lskitdeployparam_processargs {
if ( defined( @{$::args} ) ) {
@ARGV = @{$::args};
}
# parse the options
# options can be bundled up like -vV, flag unsupported options
Getopt::Long::Configure( "bundling", "no_ignore_case", "no_pass_through" );
my $getopt_success = Getopt::Long::GetOptions(
'help|h|?' => \$::opt_h,
'kitname|k=s' => \$::opt_k,
'compname|c=s' => \$::opt_c,
'verbose|V' => \$::opt_V,
'version|v' => \$::opt_v,
'xml|XML|x' => \$::opt_x,
);
if (!$getopt_success) {
return 3;
}
# Option -h for Help
if ( defined($::opt_h) ) {
return 2;
}
# Option -v for version
if ( defined($::opt_v) ) {
create_version_response('lskitdeployparam');
return 1; # no usage - just exit
}
# Option -V for verbose output
if ( defined($::opt_V) ) {
$::VERBOSE = 1;
}
# Ensure -k and -c option not used together
if (defined($::opt_k) && defined($::opt_c)) {
create_error_response("The -k and -c options cannot be used together.");
return 3;
}
# Ensure -k or -c option are specified
if (!defined($::opt_k) && !defined($::opt_c)) {
create_error_response("The -k or -c option must be specified.");
return 3;
}
# Option -k for kit names
if ( defined($::opt_k) ) {
$::kitnames = split_comma_delim_str($::opt_k);
if (check_attr_values_exist('kit', 'kitname', 'kit names', $::kitnames) != 0) {
return 3;
}
}
# Option -c for kitocmponent names
if ( defined($::opt_c) ) {
$::kitcompnames = split_comma_delim_str($::opt_c);
if (check_attr_values_exist('kitcomponent', 'kitcompname', 'kit component names', $::kitcompnames) != 0) {
return 3;
}
}
# Other attributes are not allowed
my $more_input = shift(@ARGV);
if ( defined($more_input) ) {
create_error_response("Invalid input: $more_input \n");
return 3;
}
return 0;
}
#----------------------------------------------------------------------------
=head3 split_comma_delim_str
Split comma-delimited list of strings into an array.
Arguments: comma-delimited string
Returns: Returns list of strings (ref)
=cut
#-----------------------------------------------------------------------------
sub split_comma_delim_str {
my $input_str = shift;
my @result = split(/,/, $input_str);
return \@result;
}
#----------------------------------------------------------------------------
=head3 ensure_kitname_attr_in_list
Checks if 'kitname' attribute is in specified attribute list.
If not, then add it.
Arguments: list of attribute names (ref)
=cut
#-----------------------------------------------------------------------------
sub ensure_kitname_attr_in_list {
my $attrs = shift;
if (defined($attrs)) {
if (! grep(/^kitname$/, @$attrs)) {
push(@$attrs, "kitname");
}
}
}
#----------------------------------------------------------------------------
=head3 check_attr_names_exist
Check if list of DB attribute names exist in a table
Arguments: a table name
a list of attribute names to check (ref)
Returns:
0 - OK
1 - error
=cut
#-----------------------------------------------------------------------------
sub check_attr_names_exist {
my $tablename = shift;
my $attrs = shift;
my @badattrs = ();
if (defined($attrs)) {
my $schema = xCAT::Table->getTableSchema($tablename);
my @cols = @{$schema->{cols}};
foreach my $attr (@{$attrs}) {
if (! grep {$_ eq $attr} @cols ) {
push(@badattrs, $attr);
}
}
}
if (scalar @badattrs > 0) {
my $error = sprintf("The following %s attributes are not valid: %s.",
$tablename, join(",",@badattrs));
create_error_response($error);
return 1;
}
return 0;
}
#----------------------------------------------------------------------------
=head3 check_attr_values_exist
Check if a list of DB attribute values exist
Arguments:
table name
table attribute
table attribute desc (e.g. kit names), this string is added to error message
list of values to check (ref)
Returns:
0 - OK
1 - error
=cut
#-----------------------------------------------------------------------------
sub check_attr_values_exist {
my $tablename = shift;
my $tableattr = shift;
my $tableattr_desc = shift;
my $values_to_check = shift;
my @badvalues = ();
my $filter_stmt = db_build_filter_stmt({$tableattr => $values_to_check});
my $rows = db_get_table_rows($tablename, [$tableattr], $filter_stmt);
my @values_in_DB = map {$_->{$tableattr}} @$rows;
foreach my $value_to_check (@{$values_to_check}) {
if (! grep {$_ eq $value_to_check} @values_in_DB ) {
push(@badvalues, $value_to_check);
}
}
if (scalar @badvalues > 0) {
my $error;
if ($tableattr_desc =~ /s$/) {
$error = sprintf("The following %s are not valid: %s.", $tableattr_desc, join(",",@badvalues));
} else {
$error = sprintf("The following %s is not valid: %s.", $tableattr_desc, join(",",@badvalues));
}
create_error_response($error);
return 1;
}
return 0;
}
#----------------------------------------------------------------------------
=head3 lskit
Support for listing kits
Returns:
0 - OK
1 - help
2 - error
=cut
#-----------------------------------------------------------------------------
sub lskit {
my $request = shift;
my $callback = shift;
my $request_command = shift;
my $rc = 0;
# process the command line
# 0=success, 1=version, 2=help, 3=error
$rc = lskit_processargs(@_);
if ( $rc != 0 ) {
if ( $rc != 1) {
lskit_usage(@_);
}
return ( $rc - 1 );
}
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The lskit command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
if ( defined($::opt_F) ) {
if ( defined($::opt_x) || defined($::opt_K) || defined($::opt_R) || defined($::opt_C) ) {
my $rsp = {};
push @{ $rsp->{data}}, "\nThe \'-F\' option cannot be used with the x, R, K, or C options.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
lskit_usage(1);
return 1;
}
my $tarpathname = $::opt_F;
# check if full path
my $dir = $request->{cwd}; #getcwd;
my $cwd = $dir->[0];
if ($tarpathname !~ /^\//)
{
my $fullpath = xCAT::Utils->full_path($tarpathname, $cwd);
if ($fullpath)
{
$tarpathname = $fullpath;
}
}
unless (-e $tarpathname) {
my $rsp = {};
push @{ $rsp->{data} }, "Could not find $tarpathname.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
# create a unique /tmp dir name name
my $thisdate = `/bin/date +%s`;
my $tmp_dir_name = qq~/tmp/tmp_kit_$thisdate~;
$tmp_dir_name =~ s/\s*//g; #remove blanks
# extract the kit.conf file
my $rsp = {};
push @{ $rsp->{data} }, "\nExtracting the kit.conf file from $tarpathname. Please wait.\n";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
my $tcmd = qq~/bin/mkdir -p $tmp_dir_name;/bin/tar -C $tmp_dir_name -jxvf $tarpathname --wildcards */kit.conf~;
my $kitconffile = xCAT::Utils->runcmd("$tcmd", -1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "No kit.conf file was found.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
# get the framework from the file
my $fcmd = "/bin/cat $tmp_dir_name/$kitconffile | grep 'kitframework '";
my $fline = xCAT::Utils->runcmd("$fcmd", -1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "No kitframework value was found.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
my ($junk, $kitframework) = split(/=/, $fline);
$kitframework =~ s/\s*//g; #remove blanks
my $cfcmd = "/bin/cat $tmp_dir_name/$kitconffile | grep 'compatible_kitframeworks'";
my $cfline = xCAT::Utils->runcmd("$cfcmd", -1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "No compatible_kitframeworks value was found.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
my ($junk, $compatframework) = split(/=/, $cfline);
$compatframework =~ s/\s*//g; #remove blanks
my $rcmd = qq~/bin/rm -Rf $tmp_dir_name 2>/dev/null~;
my $out = xCAT::Utils->runcmd("$rcmd", -1);
if ($::RUNCMD_RC != 0) {
my $rsp = {};
push @{ $rsp->{data} }, "Could not remove $tmp_dir_name.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
}
if ($kitframework && $compatframework) {
my $rsp = {};
push @{ $rsp->{data} }, "\tkitframework=$kitframework\n\tcompatible_kitframeworks=$compatframework\n";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
} else {
my $rsp = {};
push @{ $rsp->{data} }, "Could not determine framework values for Kit $tarpathname.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
return 0;
}
# Prepare the hash tables to pass to the output routines
my $kit_hash = get_kit_hash($::kitnames, $::kitattrs);
my $kitrepo_hash = get_kitrepo_hash($::kitnames, $::kitrepoattrs);
my $kitcomp_hash = get_kitcomp_hash($::kitnames, $::kitcompattrs);
# Now display the output
my @kitnames = keys(%$kit_hash);
if (scalar @kitnames == 0) {
my $rsp = {};
push @{ $rsp->{data} }, "No kits were found.";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
}
if (defined($::opt_x)) {
create_lskit_xml_response($kit_hash, $kitrepo_hash, $kitcomp_hash);
} else {
create_lskit_stanza_response($kit_hash, $kitrepo_hash, $kitcomp_hash);
}
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitcomp
Support for listing kit components
Arguments:
Returns:
0 - OK
1 - help
2 - error
=cut
#-----------------------------------------------------------------------------
sub lskitcomp {
my $rc = 0;
# process the command line
# 0=success, 1=version, 2=help, 3=error
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The lskitcomp command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
$rc = lskitcomp_processargs(@_);
if ( $rc != 0 ) {
if ( $rc != 1) {
lskitcomp_usage(@_);
}
return ( $rc - 1 );
}
# Get the list of kitcomponents to display
## Build the initial kitcomponent list, filtering the kitcomponents whose:
## - name matches one of the user-specified names
## - AND, reponame refers to a repo that is compatible with the user-specified osdistro
my $compat_kitreponames = undef;
if (defined($::osdistroname)) {
$compat_kitreponames = get_compat_kitreponames($::osdistroname);
}
my $kitcomps = get_kitcomp_list($::kitcompnames, $compat_kitreponames, $::kitcompattrs);
## Filter the kitcomponent list by user-specified server role
if (defined($::serverrole)) {
my @tmplist = ();
foreach my $kitcomp (@$kitcomps) {
if (defined($kitcomp->{serverroles})) {
my @serverroles = split(/,/, $kitcomp->{serverroles});
if (grep {$_ eq $::serverrole } @serverroles) {
push(@tmplist, $kitcomp);
}
} else {
# If kit component doesn't have server roles, it means
# it supports any server role.
push(@tmplist, $kitcomp);
}
}
@$kitcomps = @tmplist;
}
# Check if kit component list is empty
if (scalar(@$kitcomps) == 0) {
my $rsp = {};
push @{ $rsp->{data} }, "No kit components were found.";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
return 0;
}
# Prepare the hash tables to pass to the output routines
## Kit hash table
my @kitnames = map {$_->{kitname}} @$kitcomps;
my $kit_hash = get_kit_hash(\@kitnames, ['kitname']);
## Kit component hash table
my $kitcomp_hash = create_hash_from_table_rows($kitcomps, 'kitname');
## Now display the output
if (defined($::opt_x)) {
create_lskit_xml_response($kit_hash, {}, $kitcomp_hash);
} else {
create_lskit_stanza_response($kit_hash, {}, $kitcomp_hash);
}
return 0;
}
#----------------------------------------------------------------------------
=head3 lskitdeployparam
Support for listing kit deployment parameters
Arguments:
Returns:
0 - OK
1 - help
2 - error
=cut
#-----------------------------------------------------------------------------
sub lskitdeployparam {
my $rc = 0;
# process the command line
# 0=success, 1=version, 2=help, 3=error
if ($^O ne 'linux') {
my $rsp = {};
push @{ $rsp->{data}}, "The lskitdeployparam command is only supported on Linux.\n";
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
return 1;
}
$rc = lskitdeployparam_processargs(@_);
if ( $rc != 0 ) {
if ( $rc != 1) {
lskitdeployparam_usage(@_);
}
return ( $rc - 1 );
}
# Get the kit deployment parameter files to read
## First get the list of kits
my $kitnames = undef;
if (defined($::kitnames)) {
$kitnames = $::kitnames;
} elsif (defined $::kitcompnames) {
my $kitcomps = get_kitcomp_list($::kitcompnames, undef, ['kitname','kitcompname']);
my @tmp = map {$_->{kitname}} @$kitcomps;
$kitnames = \@tmp;
} else {
# unreachable code
}
## Then get the kit deployment parameter file for each kit
my $kits = get_kit_list($kitnames, ['kitname','kitdir','kitdeployparams']);
# Read the kit deployment parameter files. The format is:
# #ENV:KIT_KIT1_PARAM1=value11#
# #ENV:KIT_KIT1_PARAM2=value12#
# #ENV:KIT_KIT2_PARAM1=value21#
my $deployparam_hash = {};
foreach my $kit (@$kits) {
my $deployparam_file = $kit->{kitdir}."/other_files/".$kit->{kitdeployparams};
if (defined($deployparam_file)) {
open(my $fh, "<", $deployparam_file) || die sprintf("Failed to open file %s because: %s", $deployparam_file, $!);
while (<$fh>) {
chomp $_;
if ($_ =~ /^#ENV:.+=.+#$/) {
my $tmp = $_;
$tmp =~ s/^#ENV://;
$tmp =~ s/#$//;
(my $name, my $value) = split(/=/, $tmp);
$deployparam_hash->{$name} = $value;
}
}
close($fh);
}
}
# Now display the output
my $rsp = {};
if (defined($::opt_x)) {
# Output XML format
foreach my $deployparam_key (sort(keys(%$deployparam_hash))) {
my $output_hash = {"kitdeployparam" => {"name" => "", "value" => ""}};
$output_hash->{kitdeployparam}->{name} = $deployparam_key;
$output_hash->{kitdeployparam}->{value} = $deployparam_hash->{$deployparam_key};
push @{ $rsp->{data} }, $output_hash;
}
} else {
# Output Stanza format
foreach my $deployparam_key (sort(keys(%$deployparam_hash))) {
my $output = "kitdeployparam:\n";
$output .= sprintf(" name=%s\n", $deployparam_key);
$output .= sprintf(" value=%s\n", $deployparam_hash->{$deployparam_key});
push @{ $rsp->{data} }, $output;
}
}
xCAT::MsgUtils->message("D", $rsp, $::CALLBACK);
return 0
}
1;
#----------------------------------------------------------------------------
=head3 get_kit_hash
Returns a hash table containing kit entries indexed by kit name.
Arguments:
list of kit names (ref)
list of kit attribute names (ref)
Returns: hash table (ref)
{ kitname1 => [{kitname1,basename1,...}],
kitname2 => [{kitname2,basename2,...}],
...
}
=cut
#-----------------------------------------------------------------------------
sub get_kit_hash {
my $tablename = 'kit';
my $kitnames = shift;
my $kitattrs = shift;
my $filter_hash = {};
if (defined($kitnames)) {
$filter_hash->{kitname} = $kitnames;
}
my $filter_stmt = undef;
if (scalar(keys(%$filter_hash)) > 0) {
$filter_stmt = db_build_filter_stmt($filter_hash);
}
my $rows = db_get_table_rows($tablename, $kitattrs, $filter_stmt);
return create_hash_from_table_rows($rows, 'kitname');
}
#----------------------------------------------------------------------------
=head3 get_kitrepo_hash
Returns a hash table containing lists of kit repository entries
indexed by kit name.
Arguments:
list of kit names (ref)
list of kit repo attribute names (ref)
Returns: hash table (ref)
{ kitname1 => [{kitrepo11,...},{kitrepo12,...}],
kitname2 => [{kitrepo21,...},{kitrepo22,...}],
...
}
=cut
#-----------------------------------------------------------------------------
sub get_kitrepo_hash {
my $tablename = 'kitrepo';
my $kitnames = shift;
my $kitrepoattrs = shift;
my $filter_hash = {};
if (defined($kitnames)) {
$filter_hash->{kitname} = $kitnames;
}
my $filter_stmt = undef;
if (scalar(keys(%$filter_hash)) > 0) {
$filter_stmt = db_build_filter_stmt($filter_hash);
}
my $rows = db_get_table_rows($tablename, $kitrepoattrs, $filter_stmt);
return create_hash_from_table_rows($rows, 'kitname');
}
#----------------------------------------------------------------------------
=head3 get_kitcomp_hash
Returns a hash table containing lists of kit component entries
indexed by kit name.
Arguments:
list of kit names (ref)
list of kit component attribute names (ref)
Returns: hash table (ref)
{ kitname1 => [{kitcomp11,...},{kitcomp12,...}],
kitname2 => [{kitcomp21,...},{kitcomp22,...}],
...
}
=cut
#-----------------------------------------------------------------------------
sub get_kitcomp_hash {
my $tablename = 'kitcomponent';
my $kitnames = shift;
my $kitcompattrs = shift;
my $filter_hash = {};
if (defined($kitnames)) {
$filter_hash->{kitname} = $kitnames;
}
my $filter_stmt = undef;
if (scalar(keys(%$filter_hash)) > 0) {
$filter_stmt = db_build_filter_stmt($filter_hash);
}
my $rows = db_get_table_rows($tablename, $kitcompattrs, $filter_stmt);
return create_hash_from_table_rows($rows, 'kitname');
}
#----------------------------------------------------------------------------
=head3 get_kit_list
Returns a list of kit, filtering the kits by:
- kit name
Arguments:
list of kit attributes to query (ref)
list of kit names for filtering (ref)
Returns a list of kit(ref)
=cut
#-----------------------------------------------------------------------------
sub get_kit_list {
my $kitnames = shift;
my $kitattrs = shift;
my $filter_hash = {};
if (defined($kitnames)) {
$filter_hash->{kitname} = $kitnames;
}
my $filter_stmt = undef;
if (scalar(keys(%$filter_hash)) > 0) {
$filter_stmt = db_build_filter_stmt($filter_hash);
}
return db_get_table_rows('kit', $kitattrs, $filter_stmt);
}
#----------------------------------------------------------------------------
=head3 get_kitcomp_list
Returns a list of kit components, filtering the kit components by:
- kit component name
- kit repository name
Arguments:
list of kit component names for filtering (ref)
list of kit repo names for filtering (ref)
list of kit component attributes to query (ref)
Returns a list of kit components (ref)
=cut
#-----------------------------------------------------------------------------
sub get_kitcomp_list {
my $kitcompnames = shift;
my $kitreponames = shift;
my $kitcompattrs = shift;
my $filter_hash = {};
if (defined($kitcompnames)) {
$filter_hash->{kitcompname} = $kitcompnames;
}
if (defined($kitreponames)) {
$filter_hash->{kitreponame} = $kitreponames;
}
my $filter_stmt = undef;
if (scalar(keys(%$filter_hash)) > 0) {
$filter_stmt = db_build_filter_stmt($filter_hash);
}
return db_get_table_rows('kitcomponent', $kitcompattrs, $filter_stmt);
}
#----------------------------------------------------------------------------
=head3 get_compat_kitreponames
Returns a list of kitreponames which are compatible with the specified
osdistroname.
Arguments:
osdistroname
Returns:
List of kitreponames (ref)
=cut
#-----------------------------------------------------------------------------
sub get_compat_kitreponames {
my $osdistroname = shift;
my @compat_kitrepos = ();
## Get the osdistro info
my $filter_stmt = db_build_filter_stmt({'osdistroname' => [$osdistroname]});
my $osdistros = db_get_table_rows('osdistro', undef, $filter_stmt);
my $osdistro = $osdistros->[0];
#print Dumper($osdistro);
## Get the kitrepos, which are compatible with the osdistro info
my $kitrepos = db_get_table_rows('kitrepo', undef, undef);
foreach my $kitrepo (@$kitrepos) {
## To check if kitrepo is compatible with an osdistro, the following 4 things
## must be true:
## 1) The kitrepo basename must be same as or compatible with osdistro basename.
## 2) The kitrepo major verison must be same as osdistro major version.
## 3) The kitrepo minor version must either:
## - Be same as osdistro minor version
## - OR, be empty which matches any osdistro minor version
## 4) The kitrepo arch must be same as osdistro arch.
if (defined($kitrepo->{osbasename})) {
my @kitrepo_compat_basenames = ();
if (defined($kitrepo->{compat_osbasenames})) {
@kitrepo_compat_basenames = split(/,/, $kitrepo->{compat_osbasenames});
}
if ($kitrepo->{osbasename} ne $osdistro->{basename} &&
! grep {$_ eq $osdistro->{basename}} @kitrepo_compat_basenames ) {
next;
}
}
if (defined($kitrepo->{osmajorversion}) && $kitrepo->{osmajorversion} ne $osdistro->{majorversion}) {
next;
}
if (defined($kitrepo->{osminorversion}) && $kitrepo->{osminorversion} ne $osdistro->{minorversion}) {
next;
}
if (defined($kitrepo->{osarch}) && $kitrepo->{osarch} ne $osdistro->{arch} && $kitrepo->{osarch} ne 'noarch') {
next;
}
push(@compat_kitrepos, $kitrepo);
}
#print Dumper(@compat_kitrepos);
my @compat_kitreponames = map {$_->{kitreponame}} @compat_kitrepos;
return \@compat_kitreponames;
}
#----------------------------------------------------------------------------
=head3 db_build_filter_stmt
Returns a SQL 'where' statement which is used to filter the
result of a kit, kit repository or kit component query.
Arguments:
hash table
- each entry represents a filter
- each entry has a key <keyN>, and a list of values <valuesN>.
- each entry is added to 'where' stmt as follows:
<key1> in (comma-separated list of <values1>)
<key2> in (comma-separated list of <values2>)
...
Returns: string containing SQL 'where' statement
=cut
#-----------------------------------------------------------------------------
sub db_build_filter_stmt {
my $filter_hash = shift;
my $filter_stmt = "";
for my $filter_key (keys(%$filter_hash)) {
my $filter_values = $filter_hash->{$filter_key};
my $values_str = join ",", map {'\''.$_.'\''} @$filter_values;
if ($filter_stmt eq "") {
$filter_stmt = sprintf("%s in (%s)", $filter_key, $values_str);
} else {
$filter_stmt .= sprintf(" AND %s in (%s)", $filter_key, $values_str);
}
}
return $filter_stmt;
}
#----------------------------------------------------------------------------
=head3 db_get_table_rows
Returns a list of table rows. Each table row is a hash table.
Arguments:
table name
attribute list
where statement
Returns: list of table rows (ref)
=cut
#-----------------------------------------------------------------------------
sub db_get_table_rows {
my $tablename = shift;
my $attrs = shift;
my $filter_stmt = shift;
if (!defined($attrs)) {
@{$attrs} = ();
my $schema = xCAT::Table->getTableSchema($tablename);
foreach my $c (@{$schema->{cols}}) {
push @{$attrs}, $c;
}
}
my $table = xCAT::Table->new($tablename);
my @table_rows = ();
if (defined($filter_stmt)) {
if (length($filter_stmt) > 0) {
@table_rows = $table->getAllAttribsWhere($filter_stmt, @{$attrs});
}
} else {
@table_rows = $table->getAllAttribs(@{$attrs});
}
return \@table_rows;
}
#----------------------------------------------------------------------------
=head3 create_hash_from_table_rows
Returns a hash table containing table rows indexed by specified
table attribute.
Arguments:
list of table rows (each row is a hash table)
table attribute
Returns: hash table (ref)
{ kitname1 => [row11,row12,...}],
kitname2 => [row21,row22,...}],
...
}
=cut
#-----------------------------------------------------------------------------
sub create_hash_from_table_rows {
my $table_rows = shift;
my $table_attr = shift;
my $result = {};
foreach my $row (@$table_rows) {
my $hash_key = $row->{$table_attr};
if (! defined($result->{$hash_key})) {
$result->{$hash_key} = [];
}
push(@{$result->{$hash_key}}, $row);
}
return $result;
}
#----------------------------------------------------------------------------
=head3 create_lskit_xml_response
Prepare a response that returns the kit, kit repository, and
kit component info in XML format.
Arguments:
kit hash table
kit repo hash table
kit component hash table
Note: Hash tables are created by create_hash_from_table_rows()
=cut
#-----------------------------------------------------------------------------
sub create_lskit_xml_response {
my $kit_hash = shift;
my $kitrepo_hash = shift;
my $kitcomp_hash = shift;
my $rsp = {};
for my $kitname (sort(keys(%$kit_hash))) {
my $output_hash = {"kitinfo" => {"kit" => [], "kitrepo" => [], "kitcomponent" => [] } };
# Kit info
if (defined($kit_hash->{$kitname})) {
my $kit = $kit_hash->{$kitname}->[0];
push(@{$output_hash->{kitinfo}->{kit}}, $kit);
}
# Kit repository info
if (defined($kitrepo_hash->{$kitname})) {
for my $kitrepo (@{$kitrepo_hash->{$kitname}}) {
push(@{$output_hash->{kitinfo}->{kitrepo}}, $kitrepo);
}
}
# Kit component info
if (defined($kitcomp_hash->{$kitname})) {
for my $kitcomp (@{$kitcomp_hash->{$kitname}}) {
push(@{$output_hash->{kitinfo}->{kitcomp}}, $kitcomp);
}
}
push @{ $rsp->{data} }, $output_hash;
}
xCAT::MsgUtils->message("D", $rsp, $::CALLBACK);
}
#----------------------------------------------------------------------------
=head3 create_lskit_stanza_response
Prepare a response that returns the kit, kit repository, and
kit component info in stanza-like format.
Arguments:
kit hash table
kit repo hash table
kit component hash table
Note: Hash tables are created by create_hash_from_table_rows()
=cut
#-----------------------------------------------------------------------------
sub create_lskit_stanza_response {
my $kit_hash = shift;
my $kitrepo_hash = shift;
my $kitcomp_hash = shift;
my $rsp = {};
my $count = 0;
for my $kitname (sort(keys(%$kit_hash))) {
my $output .= "\n----------------------------------------------------\n";
# Kit info
if (defined($kit_hash->{$kitname})) {
my $kit = $kit_hash->{$kitname}->[0];
$output .= "kit:\n";
for my $kit_attr (sort(keys(%$kit))) {
$output .= sprintf(" %s=%s\n", $kit_attr, $kit->{$kit_attr});
}
$output .= "\n";
}
# Kit repository info
if (defined($kitrepo_hash->{$kitname})) {
for my $kitrepo (@{$kitrepo_hash->{$kitname}}) {
$output .= "kitrepo:\n";
for my $kitrepo_attr (sort(keys(%$kitrepo))) {
$output .= sprintf(" %s=%s\n", $kitrepo_attr, $kitrepo->{$kitrepo_attr});
}
$output .= "\n";
}
}
# Kit component info
if (defined($kitcomp_hash->{$kitname})) {
for my $kitcomp (@{$kitcomp_hash->{$kitname}}) {
$output .= "kitcomponent:\n";
for my $kitcomp_attr (sort(keys(%$kitcomp))) {
$output .= sprintf(" %s=%s\n", $kitcomp_attr, $kitcomp->{$kitcomp_attr});
}
$output .= "\n";
}
}
push @{ $rsp->{data} }, $output;
}
xCAT::MsgUtils->message("D", $rsp, $::CALLBACK);
}
1;
#-----------------------------------------------------------------------------
=head3 check_framework
Check the compatible frameworks of the kit to see if it is
compatible with the running code.
If one of the compatible frameworks of the kit matches one of the
compatible frameworks of the running code then we're good.
NOTE: compatible_kitframeworks are the kitframeworks that I can add
and kit frameworks that I can be added to.
Returns:
0 - OK
1 - error
Example:
my $rc = &check_framework(\@lines);
=cut
#-----------------------------------------------------------------------------
sub check_framework
{
my $lines = shift;
my @kitconflines = @$lines;
my $kitbasename;
my $kitcompat;
my $section = '';
foreach my $l (@kitconflines) {
# skip blank and comment lines
if ( $l =~ /^\s*$/ || $l =~ /^\s*#/ ) {
next;
}
if ( $l =~ /^\s*(\w+)\s*:/ ) {
$section = $1;
next;
}
if ( $l =~ /^\s*(\w+)\s*=\s*(.*)\s*/ ) {
my $attr = $1;
my $val = $2;
$attr =~ s/^\s*//; # Remove any leading whitespace
$attr =~ s/\s*$//; # Remove any trailing whitespace
$attr =~ tr/A-Z/a-z/; # Convert to lowercase
$val =~ s/^\s*//;
$val =~ s/\s*$//;
if ($section eq 'kitbuildinfo') {
if ( $attr eq 'compatible_kitframeworks' ) {
$kitcompat = $val;
}
}
if ($section eq 'kit') {
if ( $attr eq 'basename' ) { $kitbasename = $val; }
}
}
}
if (!$kitcompat) {
my %rsp;
push @{ $rsp{data} }, "Could not determine the kit compatible framework values for \'$kitbasename\' from the kit.conf file. Continuing for now.";
xCAT::MsgUtils->message( "I", \%rsp, $::CALLBACK );
return 0;
}
my @kit_compat_list = split (',', $kitcompat);
my @my_compat_list = split (',', $::COMPATIBLE_KITFRAMEWORKS);
foreach my $myfw (@my_compat_list) {
chomp $myfw;
foreach my $kitfw (@kit_compat_list) {
chomp $kitfw;
if ($myfw eq $kitfw) {
return 0;
}
}
}
my %rsp;
push @{ $rsp{data} }, "The kit named \'$kitbasename\' is not compatible with this version of the buildkit command. \'$kitbasename\' is compatible with \'$kitcompat\' and the buildkit command is compatible with \'$::COMPATIBLE_KITFRAMEWORKS\'";
xCAT::MsgUtils->message( "E", \%rsp, $::CALLBACK );
return 1;
}