diff --git a/xCAT-server/lib/xcat/plugins/kit.pm b/xCAT-server/lib/xcat/plugins/kit.pm index 3cc6b1b9a..d23dc4842 100644 --- a/xCAT-server/lib/xcat/plugins/kit.pm +++ b/xCAT-server/lib/xcat/plugins/kit.pm @@ -19,6 +19,7 @@ use xCAT::MsgUtils; use Getopt::Long; use Data::Dumper; use File::Basename; +use File::Path; my $kitconf = "kit.conf"; @@ -35,8 +36,10 @@ Return list of commands handled by this plugin sub handled_commands { return { - addkit => "kit", - rmkit => "kit", + addkit => "kit", + rmkit => "kit", + addkitcomp => "kit", + rmkitcomp => "kit", }; } @@ -58,10 +61,14 @@ sub process_request my $command = $request->{command}->[0]; if ($command eq "addkit"){ - return addkit($request, @args, $callback); - }elsif ($command eq "rmkit"){ - return rmkit($request, @args, $callback); - }else{ + return addkit($request, $callback); + } elsif ($command eq "rmkit"){ + return rmkit($request, $callback); + } elsif ($command eq "addkitcomp"){ + return addkitcomp($request, $callback); + } elsif ($command eq "rmkitcomp"){ + return rmkitcomp($request, $callback); + } else{ $callback->({error=>["Error: $command not found in this module."],errorcode=>[1]}); #return (1, "$command not found); } @@ -70,6 +77,513 @@ sub process_request } +#------------------------------------------------------- + +=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 addkit + + 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', 'kitpkgdeps', 'exlist', 'postbootscripts'); + (my $osimagetable) = $tabs->{osimage}->getAttribs({imagename=> $osimage}, 'postbootscripts', 'kitcomponents'); + + # Adding postbootscrits to osimage.postbootscripts + if ( $kitcomptable and $kitcomptable->{postbootscripts} ){ + if ( $osimagetable ){ + if ( $osimagetable->{postbootscripts} ) { + my $match = 0; + my @scripts = split ',', $osimagetable->{postbootscripts}; + foreach my $script ( @scripts ) { + if ( $kitcomptable->{postbootscripts} =~ /^$script$/ ) { + $match = 1; + last; + } + } + unless ( $match ) { + $osimagetable->{postbootscripts} = $osimagetable->{postbootscripts} . ',' . $kitcomptable->{postbootscripts}; + } + } else { + $osimagetable->{postbootscripts} = $kitcomptable->{postbootscripts}; + } + + } + } + + (my $linuximagetable) = $tabs->{linuximage}->getAttribs({imagename=> $osimage}, 'exlist', 'otherpkglist', 'otherpkgdir'); + + # 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 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; + } + } + + 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'); + } + + # 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/kits/custom/$osimage/"); + if ( -e "$installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist" ) { + if (open(EXLIST, "<", "$installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist")) { + @lines = ; + close(EXLIST); + if($::VERBOSE){ + $callback->({data=>["\nReading kit component exlist file $installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist\n"]}); + } + } else { + $callback->({error => ["Could not open kit component exlist file $installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist"],errorcode=>[1]}); + return 1; + } + } + unless ( grep(/^#INCLUDE:$kitdir\/other_files\/$exlistfile#$/ , @lines) ) { + if (open(NEWEXLIST, ">>", "$installdir/kits/custom/$osimage/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\/kits\/custom\/$osimage\/KIT_COMPONENTS.exlist$/ ) { + $match = 1; + last; + } + } + unless ( $match ) { + $linuximagetable->{exlist} = $linuximagetable->{exlist} . ',' . "$installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist"; + } + } else { + $linuximagetable->{exlist} = "$installdir/kits/custom/$osimage/KIT_COMPONENTS.exlist"; + } + + } + + } + + # Adding kitdeployparams to a otherpkglist file in osimage + if ( $kittable and $kittable->{kitdeployparams} and $kittable->{kitdir} ) { + + # Reading contents from kit.kitdeployparams file + my @contents; + my $kitdir = $kittable->{kitdir}; + my $kitdeployfile = $kittable->{kitdeployparams}; + if ( -e "$kitdir/other_files/$kitdeployfile" ) { + if (open(KITDEPLOY, "<", "$kitdir/other_files/$kitdeployfile") ) { + @contents = ; + close(KITDEPLOY); + if($::VERBOSE){ + $callback->({data=>["\nReading kit deployparams from $kitdir/other_files/$kitdeployfile\n"]}); + } + } else { + $callback->({error => ["Could not open kit deployparams file $kitdir/other_files/$kitdeployfile"],errorcode=>[1]}); + } + } + + # Creating kit deployparams file + my @lines; + mkpath("$installdir/kits/custom/$osimage/"); + if ( -e "$installdir/kits/custom/$osimage/KIT_DEPLOY_PARAMS.otherpkgs.pkglist" ) { + if (open(DEPLOYPARAM, "<", "$installdir/kits/custom/$osimage/KIT_DEPLOY_PARAMS.otherpkgs.pkglist")) { + @lines = ; + close(DEPLOYPARAM); + if($::VERBOSE){ + $callback->({data=>["\nReading kit deployparams file $installdir/kits/custom/$osimage/KIT_DEPLOY_PARAMS.otherpkgs.pkglist\n"]}); + } + } else { + $callback->({error => ["Could not open kit deployparams file $installdir/kits/custom/$osimage/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; + foreach my $content ( @contents ) { + my $matched = 0; + foreach my $line ( @lines ) { + if ( $line =~ /$content/ ) { + $matched = 1; + last; + } + } + + unless ( $matched ) { + push @l, $content; + } + } + + # Write the missing lines to kit deployparams file + if (open(NEWDEPLOYPARAM, ">>", "$installdir/kits/custom/$osimage/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\/kits\/custom\/$osimage\/KIT_DEPLOY_PARAMS.otherpkgs.pkglist$/ ) { + $match = 1; + last; + } + } + unless ( $match ) { + $linuximagetable->{otherpkglist} = $linuximagetable->{otherpkglist} . ',' . "$installdir/kits/custom/$osimage/KIT_DEPLOY_PARAMS.otherpkgs.pkglist"; + } + } else { + $linuximagetable->{otherpkglist} = "$installdir/kits/custom/$osimage/KIT_DEPLOY_PARAMS.otherpkgs.pkglist"; + } + } + + } + + # Adding kit component basename to osimage.otherpkgs.pkglist + if ( $kitcomptable and $kitcomptable->{basename} ) { + + my @lines; + my $basename = $kitcomptable->{basename}; + + # Adding kit component basename to KIT_COMPONENTS.otherpkgs.pkglist file + mkpath("$installdir/kits/custom/$osimage/"); + if ( -e "$installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist" ) { + if (open(OTHERPKGLIST, "<", "$installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist")) { + @lines = ; + close(OTHERPKGLIST); + if($::VERBOSE){ + $callback->({data=>["\nReading kit component otherpkg file $installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist\n"]}); + } + } else { + $callback->({error => ["Could not open kit component otherpkg file $installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist"],errorcode=>[1]}); + return 1; + } + } + unless ( grep(/^$basename$/, @lines) ) { + if (open(NEWOTHERPKGLIST, ">>", "$installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist")) { + + print NEWOTHERPKGLIST "$basename\n"; + 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\/kits\/custom\/$osimage\/KIT_COMPONENTS.otherpkgs.pkglist$/ ) { + $match = 1; + last; + } + } + unless ( $match ) { + $linuximagetable->{otherpkglist} = $linuximagetable->{otherpkglist} . ',' . "$installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist"; + } + } else { + $linuximagetable->{otherpkglist} = "$installdir/kits/custom/$osimage/KIT_COMPONENTS.otherpkgs.pkglist"; + } + + } + + # Remove this component basename and pkgnames from KIT_RMPKGS.otherpkg.pkglist + if ( $kitcomptable->{kitpkgdeps} ) { + my @lines; + if ( -e "$installdir/kits/custom/$osimage/KIT_RMPKGS.otherpkgs.pkglist" ) { + if (open(RMOTHERPKGLIST, "<", "$installdir/kits/custom/$osimage/KIT_RMPKGS.otherpkgs.pkglist")) { + @lines = ; + close(RMOTHERPKGLIST); + if($::VERBOSE){ + $callback->({data=>["\nReading kit component rmpkgs file $installdir/kits/custom/$osimage/KIT_RMPKGS.otherpkgs.pkglist\n"]}); + } + } else { + $callback->({error => ["Could not open kit component rmpkgs file $installdir/kits/custom/$osimage/KIT_RMPKGS.otherpkgs.pkglist"],errorcode=>[1]}); + return 1; + } + } + + my @l; + my @kitpkgdeps = split ',', $kitcomptable->{kitpkgdeps}; + 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 =~ /^-$basename$/ ) { + $matched = 1; + $changed = 1; + } + + unless ( $matched ) { + push @l, "$line\n"; + } + } + + if ( scalar(@l) and $changed ) { + if (open(RMPKGLIST, ">", "$installdir/kits/custom/$osimage/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; + } + + } else { + $callback->({error => ["Could not open kit component table and read basename for kit component $kitcomp"],errorcode=>[1]}); + return 1; + } + + #TODO: adding driverpacks + + + # 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 addkit @@ -92,12 +606,11 @@ sub addkit my %kitcomphash; my $xusage = sub { - my $ec = shift; + my %rsp; push@{ $rsp{data} }, "addkit: add Kits into xCAT from a list of tarball file or directory which have the same structure with tarball file"; push@{ $rsp{data} }, "Usage: "; push@{ $rsp{data} }, "\taddkit [-h|--help]"; push@{ $rsp{data} }, "\taddkit [-p|--path ] ] [-V]"; - if($ec){ $rsp{errorcode} = $ec; } $callback->(\%rsp); }; @@ -134,7 +647,7 @@ sub addkit my $basename; my $des = shift @ARGV; - my @kits = split /,/, $des; + my @kits = split ',', $des; foreach my $kit (@kits) { # extract the Kit to kitdir @@ -220,6 +733,7 @@ sub addkit my $kitname; my $kitreponame; my $kitcompname; + my $scripts; foreach my $line (@lines) { # Read through each line of kit.conf. my $key, $value; @@ -252,13 +766,15 @@ sub addkit } elsif ( $sec =~ /KITREPO$/ ) { if ( $key =~ /kitreponame/ ) { $kitreponame = $value; - $kitrepohash{$kitreponame}{kitrepodir} = $kitdir."/repos"; + $kitrepohash{$kitreponame}{kitrepodir} = $kitdir."/repos/".$kitreponame; } else { $kitrepohash{$kitreponame}{$key} = $value; } } elsif ( $sec =~ /KITCOMPONENT$/ ) { if ( $key =~ /kitcompname/ ) { $kitcompname = $value; + } elsif ( $key =~ /postboot/ ) { + $scripts = $scripts . ',' . $value; } else { $kitcomphash{$kitcompname}{$key} = $value; } @@ -266,6 +782,7 @@ sub addkit } #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, # Write to DB if($::VERBOSE){ $callback->({data=>["Writing kit configuration into xCAT DB\n"]}); @@ -289,13 +806,18 @@ sub addkit } # Coying scripts to /installdir/postscripts/ - chmod(0755,"$kitdir/scripts/*"); - if($::VERBOSE){ - $callback->({data=>["Copying kit scripts from $kitdir/scripts/ to $installdir/postscripts\n"]}); - $rc = system("cp -rfv $kitdir/scripts/* $installdir/postscripts/"); - } else { - $rc = system("cp -rf $kitdir/scripts/* $installdir/postscripts/"); + $callback->({data=>["Copying kit scripts from $kitdir/other_files/ to $installdir/postscripts"]}); + } + 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){ @@ -306,7 +828,7 @@ sub addkit chmod(644, "$kitdir/plugins/*"); if($::VERBOSE){ - $callback->({data=>["Copying kit plugins from $kitdir/plugins/ to $::XCATROOT/lib/perl/xCAT_plugin\n"]}); + $callback->({data=>["\nCopying kit plugins from $kitdir/plugins/ to $::XCATROOT/lib/perl/xCAT_plugin"]}); $rc = system("cp -rfv $kitdir/plugins/* $::XCATROOT/lib/perl/xCAT_plugin/"); } else { $rc = system("cp -rf $kitdir/plugins/* $::XCATROOT/lib/perl/xCAT_plugin/"); @@ -321,7 +843,7 @@ sub addkit } # Issue xcatd reload to load the new plugins -# system("/etc/init.d/xcatd reload"); + system("/etc/init.d/xcatd reload"); } @@ -359,12 +881,11 @@ sub rmkit my $rc; my $xusage = sub { - my $ec = shift; + my %rsp; push@{ $rsp{data} }, "rmkit: remove Kits from xCAT"; push@{ $rsp{data} }, "Usage: "; push@{ $rsp{data} }, "\trmkit [-h|--help]"; push@{ $rsp{data} }, "\trmkit [-f|--force] ] [-V]"; - if($ec){ $rsp{errorcode} = $ec; } $callback->(\%rsp); }; @@ -399,32 +920,32 @@ sub rmkit } # Convert to kitname if input is a basename - my $kitnames; + my %kitnames; my $des = shift @ARGV; - my @kits = split /,/, $des; + my @kits = split ',', $des; foreach my $kit (@kits) { # Check if it is a kitname or basename - my $ref1 = $tabs{kit}->getAttribs({kitname => $kit }, 'basename'); + (my $ref1) = $tabs{kit}->getAttribs({kitname => $kit}, 'basename'); if ( $ref1 and $ref1->{'basename'}){ - push @kitnames, $kit; + $kitnames{$kit} = 1; } else { my @entries = $tabs{kit}->getAllAttribsWhere( "basename = '$kit'", 'kitname' ); + unless (@entries) { + $callback->({error => ["Kit $kit could not be found in DB $t\n"],errorcode=>[1]}); + return 1; + } foreach my $entry (@entries) { - push @kitnames, $entry->{kitname}; + $kitnames{$entry->{kitname}} = 1; } } } - unless (@kitnames) { - $callback->({error => ["Nothing to do since the kits $des are not existing in xCAT DB"],errorcode=>[1]}); - } - # Remove each kit my @entries = $tabs{'osimage'}->getAllAttribs( 'imagename', 'kitcomponents' ); - foreach my $kitname (@kitnames) { + foreach my $kitname (keys %kitnames) { # Remove osimage.kitcomponents. @@ -435,7 +956,7 @@ sub rmkit if (defined(@entries) && (@entries > 0)) { if($::VERBOSE){ - $callback->({data=>["Deleting kit components from osimage.kitcomponents"]}); + $callback->({data=>["Removing kit components from osimage.kitcomponents"]}); } my @newkitcomponents; foreach my $entry (@entries) { @@ -443,7 +964,7 @@ sub rmkit my $catched = 0; # Check osimage.kitcomponents - my @kitcomponents = split /,/, $entry->{kitcomponents}; + my @kitcomponents = split ',', $entry->{kitcomponents}; foreach my $kitcomponent ( @kitcomponents ) { chomp $kitcomponent; @@ -478,58 +999,68 @@ sub rmkit # rm_gen_files(); } + } + + 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){ - $callback->({data=>["Deleting kit plugins from $::XCATROOT/lib/perl/xCAT_plugin/"]}); + $callback->({data=>["Removing kit plugins from $::XCATROOT/lib/perl/xCAT_plugin/"]}); } - my $kitdir; - my $ref1 = $tabs{kit}->getAttribs({kitname => $kitname }, 'kitdir'); - if ( $ref1 and $ref1->{'kitdir'}){ - - $kitdir = $ref1->{'kitdir'}; - chomp $kitdir; - - opendir($dir, $kitdir."/plugins"); - my @files = readdir($dir); - 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"); - } + opendir($dir, $kitdir."/plugins"); + my @files = readdir($dir); + 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){ - $callback->({data=>["Deleting kit scripts from installdir"]}); - } - # remove kit scripts from /install/postscripts/ - my $installdir = xCAT::TableUtils->getInstallDir(); - unless($installdir){ - $installdir = '/install'; - } - $installdir =~ s/\/$//; - opendir($dir, $kitdir."/scripts"); - my @files = readdir($dir); - 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"); + if($::VERBOSE){ + $callback->({data=>["Removing kit scripts from /install/postscripts/"]}); + } + # remove kit scripts from /install/postscripts/ + my $installdir = xCAT::TableUtils->getInstallDir(); + unless($installdir){ + $installdir = '/install'; + } + $installdir =~ s/\/$//; + + opendir($dir, $kitdir."/scripts"); + my @files = readdir($dir); + 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){ + $callback->({data=>["Removing kitdir from installdir"]}); + system("rm -rfv $kitdir"); + } else { + system("rm -rf $kitdir"); + } } + if($::VERBOSE){ - $callback->({data=>["Deleting kit from xCAT DB"]}); + $callback->({data=>["Removing kit from xCAT DB"]}); } # Remove kitcomponent foreach my $kitcomp ( @kitcomphash ) { @@ -552,10 +1083,268 @@ sub rmkit } # Issue xcatd reload to load the new plugins -# system("/etc/init.d/xcatd reload"); + system("/etc/init.d/xcatd reload"); } +#------------------------------------------------------- + +=head3 addkitcomp + + Assign Kit component to osimage + +=cut + +#------------------------------------------------------- +sub addkitcomp +{ + my $request = shift; + my $callback = shift; + my $kitdir; + my $rc; + + my $xusage = sub { + my %rsp; + push@{ $rsp{data} }, "addkitcomp: assign kit component to osimage"; + push@{ $rsp{data} }, "Usage: "; + push@{ $rsp{data} }, "\taddkitcomp [-h|--help]"; + push@{ $rsp{data} }, "\taddkitcomp [-a|--adddeps] [-f|--force] [-V|--verbose] -i "; + $callback->(\%rsp); + }; + + unless(defined($request->{arg})){ $xusage->(1); return; } + @ARGV = @{$request->{arg}}; + if($#ARGV eq -1){ + $xusage->(1); + return; + } + + + GetOptions( + 'h|help' => \$help, + 'V|verbose' => \$::VERBOSE, + 'a|adddeps' => \$adddeps, + 'f|force' => \$force, + 'i=s' => \$osimage + ); + + if($help){ + $xusage->(0); + return; + } + + 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} )) { + $callback->({error => ["Could not open xCAT table $t\n"],errorcode=>[1]}); + return 1; + } + } + + # Check if all the kitcomponents are existing before processing + + 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'); + if ( $kitcomptable and $kitcomptable->{'kitname'}){ + $kitcomps{$kitcomponent}{name} = $kitcomponent; + } else { + my @entries = $tabs{kitcomponent}->getAllAttribsWhere( "basename = '$kitcomponent'", 'kitcompname' , 'version', 'release'); + unless (@entries) { + $callback->({error => ["$kitcomponent kitcomponent does not exist\n"],errorcode=>[1]}); + return 1; + } + + my $highest = get_highest_version('kitcompname', 'version', 'release', @entries); + $kitcomps{$highest}{name} = $highest; + } + } + + # Verify if the kitcomponents fitting to the osimage or not. + my %os; + my $osdistrotable; + (my $osimagetable) = $tabs{osimage}->getAttribs({imagename=> $osimage}, 'osdistroname', 'serverrole', 'kitcomponents'); + if ( $osimagetable and $osimagetable->{'osdistroname'}){ + ($osdistrotable) = $tabs{osdistro}->getAttribs({osdistroname=> $osimagetable->{'osdistroname'}}, 'basename', 'majorversion', 'minorversion', 'arch', 'type'); + if ( !$osdistrotable or !$osdistrotable->{basename} ) { + $callback->({error => ["$osdistroname osdistro does not exist\n"],errorcode=>[1]}); + 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'}); + + } else { + $callback->({error => ["$osimage osimage does not exist or not saticified\n"],errorcode=>[1]}); + return 1; + } + + foreach my $kitcomp ( keys %kitcomps ) { + (my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomp}, 'kitname', 'kitreponame', 'serverroles'); + 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 { + $callback->({error => ["$kitcomptable->{'kitname'} ostype does not exist\n"],errorcode=>[1]}); + 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 { + $callback->({error => ["$kitcomp osbasename,osmajorversion,osminorversion or osarch does not exist\n"],errorcode=>[1]}); + return 1; + } + + } else { + $callback->({error => ["$kitcomp kitname or kitrepo name does not exist\n"],errorcode=>[1]}); + 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 ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute OS \n"],errorcode=>[1]}); + return 1; + } + + if ( $os{$osimage}{majorversion} ne $kitcomps{$kitcomp}{osmajorversion} ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute majorversion\n"],errorcode=>[1]}); + return 1; + } + + if ( $os{$osimage}{minorversion} and ($os{$osimage}{minorversion} ne $kitcomps{$kitcomp}{osminorversion}) ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute minorversion\n"],errorcode=>[1]}); + return 1; + } + + if ( $os{$osimage}{arch} ne $kitcomps{$kitcomp}{osarch} ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute arch\n"],errorcode=>[1]}); + return 1; + } + + if ( $os{$osimage}{type} ne $kitcomps{$kitcomp}{ostype} ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute type\n"],errorcode=>[1]}); + return 1; + } + + if ( $os{$osimage}{serverrole} and ($os{$osimage}{serverrole} ne $kitcomps{$kitcomp}{serverroles}) ) { + $callback->({error => ["osimage $osimage doesn't fit to kit component $kitcomp with attribute serverrole\n"],errorcode=>[1]}); + return 1; + } + + #TODO add checks to kit components' dependencies. + + } + + # Now assign each component to the osimage + + my @kitcomps; + my $catched = 0; + if ( $osimagetable and $osimagetable->{'kitcomponents'}) { + @oskitcomps = split ',', $osimagetable->{'kitcomponents'}; + } + foreach my $kitcomp ( keys %kitcomps ) { + # Check if this component is existing in osimage.kitcomponents + foreach my $oskitcomp ( @oskitcomps ) { + if ( $kitcomp eq $oskitcomp ) { + $callback->({data=>["kit component $kitcomp is already in osimage $osimage"]}); + $catched = 1; + last; + } + } + + # 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'} ) { + $callback->({error => ["$kitcomp kit component does not have basename"],errorcode=>[1]}); + return 1; + } + (my $oskitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $oskitcomp}, 'basename', 'version', 'release'); + if ( !$oskitcomptable or !$oskitcomptable->{'basename'} ) { + $callback->({error => ["$oskitcomp kit component does not have basename"],errorcode=>[1]}); + next; + } + + if ( $kitcomptable->{'basename'} eq $oskitcomptable->{'basename'} ) { + my $rc = compare_version($oskitcomptable,$kitcomptable,'kitcompname', 'version', 'release'); + if ( $rc == 1 ) { + $callback->({data=>["Upgrading kit component $oskitcomp to $kitcomp"]}); + system("rmkitcomp -f -u -i $osimage $kitcomp"); + $add = 1; + } elsif ( $rc == 0 ) { + $callback->({data=>["Do nothing since kit component $oskitcomp in osimage $osimage has the same basename/version and release with kit component $kitcomp."]}); + next; + } else { + $callback->({error => ["kit component $oskitcomp is already in osimage $osimage, and has a newer release/version than $kitcomp. Downgrading kit component is not supported"],errorcode=>[1]}); + return 1; + } + } + } + # Now assign this component to osimage + my $rc = assign_to_osimage( $osimage, $kitcomp, $callback, \%tabs); + } + + } + + +} + +#------------------------------------------------------- + +=head3 rmkitcomp + + Remove Kit component from osimage + +=cut + +#------------------------------------------------------- +sub rmkitcomp +{ + +} 1;