diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit new file mode 100755 index 000000000..eb119cde1 --- /dev/null +++ b/xCAT-buildkit/bin/buildkit @@ -0,0 +1,4142 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# + +#----------------------------------------------------------------------------- + +=head1 buildkit + + xCAT/PCM Kit Build utilities + +This script is designed to run on a non-xCAT system so that Kits can be +built on any product build machine. + +=cut + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + $::XCATDIR = $ENV{'XCATDIR'} ? $ENV{'XCATDIR'} : '/etc/xcat'; + $::XCATSHARE = $::XCATROOT . '/share/xcat'; +} + +if ($^O =~ /^aix/i) { + print "ERROR - the buildkit command is not supported on AIX \n"; + exit 1; +} + +use lib "$::XCATROOT/lib/perl"; +require xCAT::BuildKitUtils; +use Getopt::Long; +use strict; +use Cwd; +use Cwd 'abs_path'; +use File::Path; +use File::Basename; + +#----------------------------------------------------------------------------- +# Main + +$::progname = "buildkit"; +$::buildkit_conf = "buildkit.conf"; +$::kit_conf = "kit.conf"; +$::current_dir = cwd(); + +# this code will build a kit using framework 1. +$::KITFRAMEWORK = "2"; + +# this code is compatible with other kits that are at framework 0 or 1. +$::COMPATIBLE_KITFRAMEWORKS = "0,1,2"; + +%::buildkit_def = ( + kit => { basename => { + description => 'The kit base name (e.g., kit-lsf)', + value_desc => 'Must be: Generic Name String', + mandatory => 1, + cp_to_kitconfig => 1 }, + description => { + description => 'The kit description', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + version => { + description => 'The kit version (e.g., 9.0)', + value_desc => 'Must be: Generic Name String', + mandatory => 1, + cp_to_kitconfig => 1 }, + release => { + description => 'The kit release (e.g., 1)', + value_desc => 'Must be: Generic Name String', + mandatory => 0, + cp_to_kitconfig => 1 }, + ostype => { + description => 'The kit OS type (e.g., Linux)', + value_desc => 'Must be: OS Type String', + mandatory => 1, + cp_to_kitconfig => 1 }, + osbasename => { + description => 'The kit OS basename', + value_desc => 'Must be: Generic Name String', + mandatory => 0, + cp_to_kitconfig => 0 }, + osmajorversion => { + description => 'The kit OS majorversion', + value_desc => 'Must be: Generic Name String', + mandatory => 0, + cp_to_kitconfig => 0 }, + osminorversion => { + description => 'The kit OS minorversion', + value_desc => 'Must be: Generic Name String', + mandatory => 0, + cp_to_kitconfig => 0 }, + osarch => { + description => 'The kit OS architecture', + value_desc => 'Must be: Generic Name String', + mandatory => 0, + cp_to_kitconfig => 0 }, + isinternal => { + description => 'Flag to say if this Kit is used for internal use only. It is only used for information purposes.', + value_desc => 'Must be: empty string or boolean string', + mandatory => 0, + cp_to_kitconfig => 1 }, + kitdeployparams => { + description => 'The path to the Kit Deployment Parameters file.', + value_desc => 'Must be: empty string or relative path string', + mandatory => 0, + base_dir => 'other_files', + cp_to_kitconfig => 2 }, # 2 = rename with KIT_KITNAME_ on cp + kitlicense => { + description => 'The Kit license string to be built into all kitcomponent packages.', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 0 }, + kittarfilename => { + description => 'The filename to use for the generated kit.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + vendor => { + description => 'The Vendor value to use when building the rpms.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + packager => { + description => 'The Packager value to use when building the rpms.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + url => { + description => 'The URL value to use when building the rpms.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 } }, + kitrepo => { kitrepoid => { + description => 'The Kit Package Repository ID. (e.g., rhels-6.2-x86_64)', + value_desc => 'Must be: Generic Name String, unique in kit', + mandatory => 1, + cp_to_kitconfig => 0 }, + osbasename => { + description => 'The OS distro base name (e.g., rhels)', + value_desc => 'Must be OS Name String', + mandatory => 1, + cp_to_kitconfig => 1 }, + osmajorversion => { + description => 'The OS distro major version (e.g., 6)', + value_desc => 'Must be Generic Number String', + mandatory => 1, + cp_to_kitconfig => 1 }, + osminorversion => { + description => 'The OS distro minor version (e.g., 3)', + value_desc => 'Must be Generic Number String', + mandatory => 0, + cp_to_kitconfig => 1 }, + osarch => { + description => 'The OS distro architecture (e.g., x86_64)', + value_desc => 'Must be OS Arch String', + mandatory => 1, + cp_to_kitconfig => 1 }, + compat_osbasenames => { + description => 'Comma-separated list of compatible OS base names. ', + value_desc => 'Must be Empty String or list of OS Name Strings', + mandatory => 0, + cp_to_kitconfig => 1 } }, + kitcomponent => { basename => { + description => 'The component name. It is used as the meta-package name.', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 1 }, + description => { + description => 'The component description. The description is added to the meta-package.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + version => { + description => 'The component version (e.g., 9.0). It is used as the meta-package version.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + release => { + description => 'The component release number (e.g., 1). It is used as the meta-package release number.', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + serverroles => { + description => 'tbd', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 1 }, + kitrepoid => { + description => 'tbd', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 0 }, + kitcompdeps => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + ospkgdeps => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + kitpkgdeps => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + non_native_pkgs => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + driverpacks => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 1 }, + exlist => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + base_dir => 'other_files', + cp_to_kitconfig => 2 }, + preinstall => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + postinstall => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + preuninstall => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + postuninstall => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + preupgrade => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + postupgrade => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + postbootscripts => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + base_dir => 'scripts', + cp_to_kitconfig => 2 }, + genimage_postinstall => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + base_dir => 'scripts', + cp_to_kitconfig => 2 } }, + kitpackage => { filename => { + description => 'tbd', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 0 }, + kitrepoid => { + description => 'tbd', + value_desc => 'any string', + mandatory => 1, + cp_to_kitconfig => 0 }, + rpm_spec => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + rpm_srcdir => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + rpm_srctarball => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + rpm_srpm => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + rpm_prebuiltdir => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 }, + isexternalpkg => { + description => 'tbd', + value_desc => 'any string', + mandatory => 0, + cp_to_kitconfig => 0 } } +); + + +my $args = join ' ', @ARGV; +$::command = "$0 $args"; +Getopt::Long::Configure("bundling"); +$Getopt::Long::ignorecase = 0; + +# parse the options +if ( + !GetOptions( + 'h|help' => \$::HELP, + 'v|version' => \$::VERSION, + 'V|verbose' => \$::VERBOSE, + 'n|noprerequisite' => \$::PREREQUISITE, + 'p|pkgdir=s' => \$::PKGDIR, + 'k|kitversion=s' => \$::KITVERSION, + 'r|kitrelease=s' => \$::KITRELEASE, + 'l|kitloc=s' => \$::KITLOC, + 'for=s' => \$::FOROSVERSARCH, + ) + ) +{ + &usage; + exit(1); +} + +# display the usage if -h or --help is specified +if ($::HELP) +{ + &usage; + exit(0); +} + +my $debianflag = 0; +my $dpkg_flag = '-uc -us'; +my $tempstring = xCAT::BuildKitUtils->osver(); +if ($tempstring =~ /debian/ || $tempstring =~ /ubuntu/) { + $debianflag = 1; +} + +# This is an undocumented flag to support our local build team +# to allow building Ubuntu kits on our RH build machines. +# It requires RH rpms such as dep, fakeroot, perl-File-DesktopEntry, +# perl-File-BaseDir, and html2text to be installed on the build server +# for this to work. To use this flag: +# buildkit --for ubuntu buildrepo +# buildkit --for ubuntu buildtar +if ($::FOROSVERSARCH) { + if ($::FOROSVERSARCH =~ /debian/ || $::FOROSVERSARCH =~ /ubuntu/) { + $debianflag = 1; + $dpkg_flag .= ' -A -d'; + } +} + +# display the version statement if -v or --version is specified +if ($::VERSION) +{ + my $versioncmd = "rpm -q --qf \"%{NAME}: %{VERSION}-%{RELEASE} \n\" xCAT-buildkit"; + my $message = "Error quering xCAT-buildkit rpm. Version info is not available. \n"; + if ($debianflag) { + + $versioncmd = "dpkg-query --show -f='\${binary:Package}: \${Version}\n' xcat-buildkit"; + $message = "Error quering xcat-buildkit package. Version info is not available. \n"; + } + if (system($versioncmd)) { + + # non-zero return from system call + print $message; + exit 1; + } + + # add framework info to output + print "\tkitframework = $::KITFRAMEWORK\n"; + print "\tcompatible_frameworks = $::COMPATIBLE_KITFRAMEWORKS\n"; + + exit 0; +} + +my $arg = shift(@ARGV); +if (!$arg) { + &usage; + exit(0); +} + +# set kit location +if ($::KITLOC) { + $::workdir = $::KITLOC; + $::current_dir = $::workdir; +} else { + $::workdir = $::current_dir; +} + +$::full_buildkit_conf = $::workdir . "/" . $::buildkit_conf; +$::build_dir = $::workdir . "/build"; +$::deploy_dir = $::build_dir; #kitname appended by validate_bldkitconf routine +$::base_repodir = $::build_dir . "/kit_repodir"; + +while ($arg) { + my $command = $arg; + $command =~ tr/A-Z/a-z/; # convert to lowercase + if ($command eq 'create') { + $::KIT_CREATE = shift(@ARGV); + if ($::KITLOC) { + $::workdir = dirname($::KITLOC); + $::current_dir = $::workdir; + } + if (!$::KIT_CREATE) { + print "The Kit basename was not specified for the buildkit create command.\n"; + &usage; + exit 1; + } + } elsif ($command eq 'chkconfig') { + $::KIT_CHKCONFIG = 1; + } elsif ($command eq 'buildrepo') { + $::KIT_BUILDREPO = shift(@ARGV); + if (!$::KIT_BUILDREPO) { + print "The Kit package repository name was not specified for buildkit buildrepo command.\n"; + &usage; + exit 1; + } + } elsif ($command eq 'listrepo') { + $::KIT_LISTREPO = 1; + } elsif ($command eq 'cleanrepo') { + $::KIT_CLEANREPO = shift(@ARGV); + if (!$::KIT_CLEANREPO) { + print "kit package repository name not specified for buildkit cleanrepo command \n"; + &usage; + exit 1; + } + } elsif ($command eq 'buildtar') { + $::KIT_BUILDTAR = 1; + } elsif ($command eq 'cleantar') { + $::KIT_CLEANTAR = 1; + } elsif ($command eq 'cleanall') { + $::KIT_CLEANALL = 1; + } elsif ($command eq 'addpkgs') { + $::KIT_ADDPKGS = shift(@ARGV); + if (!($::KIT_ADDPKGS)) { + print "Missing parameter: the name must be specified when using the \'buildkit addpkgs\' command.\n"; + &usage; + exit(1); + } + if (!($::PKGDIR)) { + print "Missing option: the -p option must be specified with \'buildkit addpkgs\' command. \n"; + &usage; + exit(1); + } + } else { + print "The buildkit command $arg is not recognized.\n"; + &usage; + exit(1); + } + $arg = shift(@ARGV); +} + +my $rc = 0; +if ($::KIT_CREATE) { + $rc = &kit_create; +} +if ($::KIT_CHKCONFIG) { + unless ($rc = &kit_chkconfig) { + print "No errors were found in Kit Build File $::full_buildkit_conf. \n"; + } +} +if ($::KIT_LISTREPO) { + unless ($rc = &kit_chkconfig) { $rc = &kit_listrepo; } +} +if ($::KIT_BUILDREPO) { + unless ($rc = &kit_chkconfig) { $rc = &kit_buildrepo; } +} +if ($::KIT_CLEANREPO) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleanrepo; } +} +if ($::KIT_BUILDTAR) { + unless ($rc = &kit_chkconfig) { $rc = &kit_buildtar; } +} +if ($::KIT_CLEANTAR) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleantar; } +} +if ($::KIT_CLEANALL) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleanall; } +} +if ($::KIT_ADDPKGS) { $rc = &kit_addpkgs; } + +exit $rc; + +##################################### +# subroutines +##################################### + +#----------------------------------------------------------------------------- + +=head3 usage + + Displays message for -h option + +=cut + +#----------------------------------------------------------------------------- +sub usage +{ + print "Usage: + buildkit [-?│-h│--help] [-v│--version] + + To build a new Kit + + buildkit [-V│--verbose] [] [│all] + [-l│--kitloc ] + + To add packages to an existing Kit. + + buildkit [-V│--verbose] addpkgs [-p│--pkgdir ] [-k│--kitversion ] [-r│--kitrelease ] + + This tool is used to build and manage a Kit package. + The options are: + -h - Provide usage info. + -k - Kit version. + -l - Location of kit files. (Including kit name.) + -p - RPM package directory locations. + -r - Kit release. + -v - Provide the version info. + command - Several commands are supported. See the list below. + -V - Verbose mode. Outputs additional debug messages. + + Supported subcommands: + create - creates a new Kit with the specified basename + chkconfig - checks the Kit build file + listrepo - lists the Kit package repositories in the Kit + build file, and their build status + buildrepo - builds the specified Kit package repository + buildrepo all - builds all the Kit package repositories + cleanrepo - deletes the build files for the specified Kit + package repository + cleanrepo all - deletes the build files for all Kit package + repositories + buildtar - builds the Kit tarfile + cleantar - deletes the Kit deployment directory and Kit + tarfile + cleanall - equivalent to buildkit cleanrepo all and + buildkit cleantar + addpkgs -p + - add product package rpms to a shipped tarfile + named kitname.NEEDS_PRODUCT_PKGS.tar.bz2 + \n"; +} + +#----------------------------------------------------------------------------- + +=head3 kit_create + + buildkit create + +=cut + +#----------------------------------------------------------------------------- + +sub kit_create + +{ + # create Kit directory in pwd + my $kitname = $::KIT_CREATE; + my $kitdir; + if ($::KITLOC) { + $kitdir = $::KITLOC; + } else { + $kitdir = $::workdir . "/$kitname"; + } + + if (-d $kitdir) { + print "Another directory already exists with the name $kitdir. Not able to create new Kit. \n"; + exit 1; + } + if (!mkdir($kitdir)) { + print "Error creating Kit directory $kitdir. Verify that the current user has privileges to create the directory. \n"; + exit 1; + } + + # Recursive copy the shipped template directory to the Kit directory + if (system("cp -fRp $::XCATSHARE/kits/kit_template/* $kitdir")) { + + # non-zero return from system call + print "Error copying sample Kit template files from $::XCAT_SHARE/kits/kit_template to $kitdir \n"; + exit 1; + } + + if (&edit_bldkitconf($kitdir . "/" . $::buildkit_conf, $kitname)) { + exit 1; + } + + print "Kit template for $kitname created in $kitdir directory \n"; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_chkconfig + + buildkit chkconfig + +=cut + +#----------------------------------------------------------------------------- + +sub kit_chkconfig + +{ + if ($::CHKCONFIG_DONE) { return 0; } + my $bldkitconf = $::full_buildkit_conf; + + my $chkrc = &load_bldkitconf($bldkitconf); + if ($chkrc != 0) { return 1; } + + $chkrc = &validate_bldkitconf(); + if ($chkrc != 0) { return 1; } + + $::CHKCONFIG_DONE = 1; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildrepo + + buildkit buildrepo + +=cut + +#----------------------------------------------------------------------------- + +sub kit_buildrepo +{ + my $rc = 0; + my $repoid = $::KIT_BUILDREPO; + + if (!$debianflag) { + + # Check if createrepo exists or not. Fail at the beginning. + #- don't use specific path - may not be correct in build env + my $rcmd = "createrepo -h > /dev/null"; + if (system($rcmd )) { + print "Error: the createrepo command does not seem to be installed. Make sure createrepo is installed before running the buildkit command. \n"; + return 1; + } + } + + $repoid =~ s/\s+//g; + $repoid =~ tr/A-Z/a-z/; # convert to lowercase + if ($repoid ne 'all') { + return &kit_buildrepo1($::KIT_BUILDREPO); + } else { + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if (&kit_buildrepo1($kr->{kitrepoid})) { return 1; } + } + } + return $rc; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildrepo1 + + + +=cut + +#----------------------------------------------------------------------------- +sub kit_buildrepo1 +{ + my $rc = 0; + my $repoid = shift; + $repoid =~ s/\s+//g; + my $repodir = $::base_repodir; + my $srcdir = $::workdir . "/source_packages/"; + my $basedir = $repodir; + my $repo; + + # find the repo + my $found = 0; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($kr->{kitrepoid} eq $repoid) { + $found = 1; + $repo = $kr; + if (&validate_os($kr)) { + print "The buildrepo operation will continue, but errors may occur. You may need to run this command on a host with the same OS.\n"; + } + $repodir .= "/$kr->{kitreponame}"; + last; + } + } + if (!$found) { + print "The specified Kit Package Repository \"$repoid\" does not exist in the Kit Build File. \n"; + return 1; + } + + # Create repo build directory + if ((!-d $repodir) && (!mkpath($repodir))) { + print "Error creating build repository directory $repodir.\n"; + return 1; + } + + # Build kitpackages first + my $kitrepohash; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + $kitrepohash->{ $kr->{kitrepoid} } = $kr->{kitreponame}; + } + + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + + # For this kitrepo? + my $found = 0; + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($repoid eq $kprid) { + $found = 1; + last; + } + } + if (!$found) { next; } + + # is this package already built? + my $rpm = "$repodir/$kp->{filename}"; + if (-r $rpm) { next; } + + my $kprid; + my $rpm_built; + foreach $kprid (split(/,/, $kp->{kitrepoid})) { + if ($repoid eq $kprid) { + next; + } + if ((-d "$basedir/$kitrepohash->{$kprid}") and (-f "$basedir/$kitrepohash->{$kprid}/$kp->{filename}")) { + $rpm_built = $kitrepohash->{$kprid}; + last; + } + } + + + # determine build method + if ($kp->{isexternalpkg} eq 'yes') { + if ($::VERBOSE) { print "skipping build of external kitpackage $kp->{filename} \n"; } + next; + } else { + if ($::VERBOSE) { print "building kitpackage $kp->{filename} \n"; } + } + if (defined($kp->{rpm_prebuiltdir})) { + + # simply copy the file to the build directory + my $full_prebuiltrpm = $srcdir . $kp->{rpm_prebuiltdir} . "/" . $kp->{filename}; + + if ($rpm_built) { + if (system("cd $repodir;ln -sf ../$rpm_built/$kp->{filename} $kp->{filename}")) { + + # non-zero return from system call + print "Error create symlink for prebuilt rpm $kp->{filename} to Kit Build directory. \n"; + return; + } + } else { + if (system("cp -fp $full_prebuiltrpm $repodir")) { + + # non-zero return from system call + print "Error copying prebuilt rpm $kp->{filename} to Kit Build directory. \n"; + return 1; + } + } + } elsif (defined($kp->{rpm_srpm})) { + + # run rpmbuild --rebuild on the source rpm + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } elsif (defined($kp->{rpm_srctarball}) && + defined($kp->{rpm_spec})) { + + # run rpmbuild + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } elsif (defined($kp->{rpm_srcdir}) && + defined($kp->{rpm_spec})) { + + # build tarfile and run rpmbuild + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } else { + print "Cannot determine build method for Kit Package $kp->{filename}. Verify that your Kit Build File is correct. \n"; + return 1; + } + } + + # Build kitcomponent preppackages and metapackages + if ($debianflag) { + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if ($repoid ne $kc->{kitrepoid}) { next; } + my $debname = "$repodir/" . &comppkgname($kc); + if (-r $debname) { next; } + if ($::VERBOSE) { print "building kitcomponent package for $kc->{basename} \n"; } + if (&build_kitcomp_debian($kc)) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + + if (system("cd $repodir;dpkg-scanpackages . > Packages")) { + print "Error building the repository meta-data with the dpkg-scanpackages command \n"; + return 1; + } + } + else { + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + + # Check if this kitcomponent is in the requested repo + if ($repoid ne $kc->{kitrepoid}) { next; } + + # Check if already built + my $rpm = "$repodir/" . &comppkgname($kc); + if (-r $rpm) { next; } + + # Build it + if ($::VERBOSE) { print "building kitcomponent metapackage for $kc->{basename} \n"; } + if (&build_kitcomp($kc)) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + + # run createrepo + my $cr_opts = ''; + if (($repo->{osbasename} =~ m/rh|RH|centos|CentOS/) && + ($repo->{osmajorversion} eq '5')) { + $cr_opts = '-s md5'; + } + if (system("createrepo $cr_opts $repodir")) { + print "Error building the repository meta-data with the createrepo command \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_listrepo + + buildkit listrepo + +=cut + +#----------------------------------------------------------------------------- +sub kit_listrepo +{ + # print "Kit Repository: Status \n"; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + my $rc = 0; + my $status = "NOT DONE"; + unless ($rc = &validate_repo($kr)) { $status = "DONE"; } + print "$kr->{kitrepoid}: $status \n"; + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleanrepo + + buildkit cleanrepo + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleanrepo +{ + my $repoid = $::KIT_CLEANREPO; + my $tmp_repoid = $repoid; + $tmp_repoid =~ tr/A-Z/a-z/; # convert to lowercase + + if (($tmp_repoid eq 'all') && + -d $::base_repodir) { + if (system("rm -Rf $::base_repodir ")) { + print "Error removing contents of $::base_repodir \n"; + return 1; + } else { + print "Contents of $::base_repodir has been successfully removed. \n"; + } + } else { + my $got_one = 0; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($repoid eq $kr->{kitrepoid}) { + my $repodir = $::base_repodir . '/' . $kr->{kitreponame}; + if (-d $repodir) { + if (system("rm -Rf $repodir ")) { + print "Error removing directory $repodir \n"; + return 1; + } else { + print "Kit repository $kr->{kitrepoid} has been removed. \n"; + } + } else { + print "Kit repository $kr->{kitrepoid} directory $repodir does not exist. Nothing to remove for this repository. \n"; + } + $got_one = 1; + last; + } + } + if (!$got_one) { + print "Kit repository $repoid does not exist.\n"; + return 1; + } + } + if (-d "$::workdir/rpmbuild") { + system("rm -Rf $::workdir/rpmbuild "); + } + if (-d "$::workdir/tmp") { + system("rm -Rf $::workdir/tmp "); + } + if (-d "$::workdir/debbuild") { + system("rm -Rf $::workdir/debbuild"); + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildtar + + buildkit buildtar + +=cut + +#----------------------------------------------------------------------------- +sub kit_buildtar +{ + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if (&validate_repo($kr)) { + print "Kit Repository $kr->{kitrepoid} not built. Run: \n"; + print " buildkit buildrepo $kr->{kitrepoid} \n"; + return 1; + } + } + + if (&create_kitconf) { + print "Error creating kit configuration file \n"; + return 1; + } + + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + if (&create_PARTIAL_builddir) { + print "Error creating PARTIAL kit build directory contents \n"; + return 1; + } + } else { + if (&create_builddir) { + print "Error creating kit build directory contents \n"; + return 1; + } + } + + if (!-d "$::deploy_dir/repos") { + symlink "$::build_dir/kit_repodir", "$::deploy_dir/repos"; + } + + # build the tarfile + my $extpkgs = ''; + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + $extpkgs = '.NEED_PRODUCT_PKGS'; + } + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + my $kitfilename = $kitname; + if (defined($::bldkit_config->{kit}{entries}[0]->{kittarfilename})) { + $kitfilename = $::bldkit_config->{kit}{entries}[0]->{kittarfilename}; + $kitfilename =~ s/tar\.bz2\s*$//; + } + $kitfilename = $kitfilename . $extpkgs . ".tar.bz2"; + + my $tarfile = $::deploy_dir . "/" . $kitfilename; + + my $dir = dirname($::deploy_dir); + my $bidir = "$dir/build_input"; + + #It is for partial kit. + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + if (-d "$bidir") { + if (system("cd $::deploy_dir; cd ..; cp -r build_input $kitname")) { + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } + } + } else { + + #If it is complete kit and there is build_input directory in deploy_dir + #If there is tmp rpmbuild source_packages + #delete them from complete kit build_input + if (-d "$bidir") { + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/tmp")) { + print "Error:Could not delete build_input/tmp \n"; + } + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/rpmbuild")) { + print "Error:Could not delete build_input/tmp \n"; + } + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/source_packages")) { + print "Error:Could not delete build_input/source_packages \n"; + } + if (system("cd $::deploy_dir; cd ..; cp -fr build_input $kitname")) { + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } + } else { + + #If kit build dir is new created + #partial kit is never created before + #make sure there is build_input dir in complete kit dir + if (system("cd $::deploy_dir; mkdir -p build_input")) { + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -fp $::workdir/buildkit.conf build_input")) { + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/other_files build_input")) { + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/plugins build_input")) { + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/scripts build_input")) { + print "Error creating kit build directory contents \n"; + return 1; + } + } + } + + print "Creating tar file $::current_dir/$kitfilename.\n"; + + if (system("cd $::deploy_dir; cd ..; tar -cjhf $tarfile $kitname/*")) { + print "Error building tarfile $tarfile \n"; + return 1; + } + + system("mv $tarfile $::current_dir"); + print "Kit tar file $::current_dir/$kitfilename successfully built. \n"; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleantar + + buildkit cleantar + + Remove tar files from the kit location directory. + + This removes all tar files - not just the last one created! + + Also clean up several other files/dirs + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleantar +{ + my $basename = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $rmfiles = "$basename\*tar.bz2"; + + my $tarfile = "$::workdir/$rmfiles"; + + if ($rmfiles) { + if (system("rm -f $tarfile ")) { + print "Error removing kit tar files in $::workdir.\n"; + } else { + print "Kit tar files have been successfully removed from $::workdir.\n"; + } + } + + if (-d $::deploy_dir) { + if (system("rm -Rf $::deploy_dir ")) { + print "Error removing contents of $::deploy_dir \n"; + } else { + print "Removed $::deploy_dir.\n"; + } + } + if (-d "$::workdir/rpmbuild") { + if (system("rm -Rf $::workdir/rpmbuild ")) { + + # print "Error removing $::workdir/rpmbuild\n"; + } else { + print "Removed $::workdir/rpmbuild\n"; + } + } + if (-d "$::workdir/tmp") { + if (system("rm -Rf $::workdir/tmp ")) { + + # print "Error removing $::workdir/tmp \n"; + } else { + print "Removed $::workdir/tmp \n"; + } + } + if (-d "$::workdir/debbuild") { + if (system("rm -Rf $::workdir/debbuild")) { + + # print "Error removing $::workdir/debbuild.\n"; + } else { + print "Removed $::workdir/debbuild\n"; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleanall + + buildkit cleanall + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleanall +{ + print "Running buildkit cleanall... \n"; + + &kit_cleantar; + + if (-d $::build_dir) { + if (system("rm -Rf $::build_dir/* ")) { + print "Error removing contents of $::build_dir \n"; + } else { + print "All $::build_dir contents have been successfully removed \n"; + } + } + if (-d "$::workdir/rpmbuild") { + system("rm -Rf $::workdir/rpmbuild "); + } + if (-d "$::workdir/tmp") { + system("rm -Rf $::workdir/tmp "); + } + if (-d "$::workdir/debbuild") { + system("rm -Rf $::workdir/debbuild"); + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_bldkitconf + + edit the shipped template buildkit.conf file to insert initial values + for the new kit +=cut + +#----------------------------------------------------------------------------- +sub edit_bldkitconf +{ + my $bldkitconf = shift; + my $kitname = shift; + + # read in the buildkit.conf file + my $CF; + unless (open($CF, "<", $bldkitconf)) { + print "The Kit build file $bldkitconf does not exist. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading kit configuration file $bldkitconf \n"; + } + my @lines = <$CF>; + close $CF; + + my $osinfo = xCAT::BuildKitUtils->osver(); + my $kitrepoid = $osinfo; + $kitrepoid =~ s/\,//; + my ($osbasename, $osmore) = split(/\,/, $osinfo); + my ($osmajorversion, $osminorversion) = split(/\./, $osmore); + my $osarch = `uname -p`; + chomp($osarch); + my $kitcomponent_basename = $kitname . "_compute"; + + if ($debianflag == 1) { + if ($osarch eq "ppc64le") { + $osarch = "ppc64el"; + } + $kitcomponent_basename = $kitname . "-compute"; + } + + for (@lines) { + s/<<>>/$kitname/; + s/<<>>/$kitrepoid/; + s/<<>>/$osbasename/; + s/<<>>/$osmajorversion/; + s/<<>>/$osminorversion/; + s/<<>>/$osarch/; + s/<<>>/$kitcomponent_basename/; + if ($debianflag) { + s/(filename=.*?)\-(.*)\.noarch\.rpm/$1_$2_all.deb/; + } + if ($osbasename =~ /rh/) { + s/.*<<>>/ compat_osbasenames=centos/; + } + } + + # Write the buildkit.conf back out + my $NCF; + unless (open($NCF, ">$bldkitconf")) { + return 1; + } + if ($::VERBOSE) { + print "Inserted initial values into $bldkitconf \n"; + } + print $NCF @lines; + close($NCF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 load_bldkitconf + + load the kitbuild.conf file into a global data structure and + verify that the general syntax is correct. + +=cut + +#----------------------------------------------------------------------------- +sub load_bldkitconf +{ + my $bldkitconf = shift; + + # read in the buildkit.conf file + my $CF; + unless (open($CF, "<", $bldkitconf)) { + print "The Kit build file $bldkitconf does not exist in the current directory. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading kit configuration file $bldkitconf \n"; + } + my @lines = <$CF>; + close $CF; + + my $current_section = 'no section'; + my %current_entry; + my $syntax_error = ''; + my $bad_line = ''; + my $line_number = 0; + foreach my $l (@lines) { + $line_number++; + + # skip blank and comment lines + next if ($l =~ /^\s*$/ || $l =~ /^\s*#/); + + # process a real line + # new section? + if ($l =~ /^\s*(\w+)\s*:/) { + my $section = $1; + if (defined($::buildkit_def{$section})) { + if (($section eq 'kit') && + ($::bldkit_config->{$section}{'exists'})) { + $syntax_error = "More than one \"$section:\" section exists "; + $bad_line = $l; + last; + } + $::bldkit_config->{$section}{'exists'} = 1; + push(@{ $::bldkit_config->{$current_section}{'entries'} }, {%current_entry}); + $current_section = $section; + undef %current_entry; + next; + } + } + if ($l =~ /^\s*(\w+)\s*=\s*(.*)\s*/) { + my $attr = $1; + my $val = $2; + my $orig_attr = $attr; + my $orig_val = $val; + $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 (defined($::buildkit_def{$current_section}{$attr})) { + if ($val ne '') { $current_entry{$attr} = $val; } + } else { + if ($current_section eq 'no section') { + $syntax_error = "No section specified for attribute $attr."; + } else { + my $valid_attrs = join(', ', (keys(%{ $::buildkit_def{$current_section} }))); + $syntax_error = "Attribute \"$attr\" is not valid for section \"$current_section\". Valid attributes are: $valid_attrs.\n"; + } + $bad_line = $l; + last; + } + + } else { + $syntax_error = "Invalid line format"; + $bad_line = $l; + last; + + } + } + + # Need at least one kit and one kitrepo section + if (!$syntax_error) { + if (!($::bldkit_config->{'kit'}{'exists'})) { + $syntax_error = "No \"kit:\" section found. At least one section required. "; + $bad_line = ''; + } elsif (!($::bldkit_config->{'kitrepo'}{'exists'})) { + $syntax_error = "No \"kitrepo:\" section found. At least one section required. "; + $bad_line = ''; + } else { + push(@{ $::bldkit_config->{$current_section}{'entries'} }, {%current_entry}); + } + } + + if ($syntax_error) { + print "Error processing file $bldkitconf \n"; + print "Syntax error found on line $line_number:\n"; + print "$bad_line \n"; + print "$syntax_error \n"; + print "\n"; + print "The Kit build file does not have the correct format. \n"; + print "The format should be: \n"; + print "
: \n"; + print " = \n"; + print " = \n"; + print " ... \n"; + print "
: \n"; + print " = \n"; + print " = \n"; + print " ... \n"; + print "The valid section names are: kit, kitrepo, kitcomponent, kitpackages. \n"; + print "There must be exactly one kit, and must be at least one kitrepo section. \n"; + return 1; + } + + # Check for mandatory attributes + foreach my $s (keys %{$::bldkit_config}) { + if (!defined($::buildkit_def{$s})) { next; } + foreach my $se (@{ $::bldkit_config->{$s}{entries} }) { + foreach my $a (keys %{ $::buildkit_def{$s} }) { + if (($::buildkit_def{$s}{$a}->{mandatory}) && + (!defined($se->{$a}))) { + print "The \"$a\" mandatory attribute must be defined in the \"$s\" section of the Kit build file \n"; + return 1; + } + } + } + } + + #use Data::Dumper; + #print Dumper($::bldkit_config); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 validate_bldkitconf + + validate the loaded buildkit configuration data + +=cut + +#----------------------------------------------------------------------------- +sub validate_bldkitconf +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $full_kitname = $kitname; + $full_kitname .= '-' . $::bldkit_config->{kit}{entries}[0]->{version}; + if (defined($::bldkit_config->{kit}{entries}[0]->{release})) { + $full_kitname .= '-' . $::bldkit_config->{kit}{entries}[0]->{release}; + } + my $short_kitname = $full_kitname; + if (defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) { + $full_kitname .= '-' . $::bldkit_config->{kit}{entries}[0]->{osbasename}; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion})) { + if (!defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) { + print "Error: Kit osmajorversion attribute was specified but Kit osbasename was not set. \n"; + return 1; + } + $full_kitname .= '-' . $::bldkit_config->{kit}{entries}[0]->{osmajorversion}; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osminorversion})) { + my $kitminor = $::bldkit_config->{kit}{entries}[0]->{osminorversion}; + unless ($kitminor =~ /^\d/) { + $kitminor = split /<=|>=|==|<|>|=/, $::bldkit_config->{kit}{entries}[0]->{osminorversion}; + } + if ((!defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) || + (!defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion}))) { + print "Error: Kit osminorversion attribute was specified but either Kit osbasename or Kit osmajorversion were not set. \n"; + return 1; + } + $full_kitname .= '-' . $kitminor; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osarch})) { + $full_kitname .= '-' . $::bldkit_config->{kit}{entries}[0]->{osarch}; + } + $::bldkit_config->{kit}{entries}[0]->{kitname} = $full_kitname; + $::deploy_dir .= "/" . $full_kitname; + + # Make sure each kit kitdeployparams file exists + if (defined($::bldkit_config->{kit}{entries}[0]->{kitdeployparams})) { + my $kd_file = $::workdir . "/other_files/" . $::bldkit_config->{kit}{entries}[0]->{kitdeployparams}; + if (!-r $kd_file) { + print "Kit Deployment Parameters file $kd_file does not exist or is not readable\n"; + return 1; + } + if (&edit_deployparams($kd_file, 1)) { return 1; } + } + + # Make sure each kitrepo has unique distro info + my $kr_count = scalar @{ $::bldkit_config->{kitrepo}{entries} }; + if ($kr_count > 1) { + foreach my $kri (0 .. $kr_count - 2) { + foreach my $kri2 ($kri + 1 .. $kr_count - 1) { + my $kr = $::bldkit_config->{kitrepo}{entries}[$kri]; + my $kr2 = $::bldkit_config->{kitrepo}{entries}[$kri2]; + if ($kr->{kitrepoid} eq $kr2->{kitrepoid}) { + print "There are two or more kitrepo sections with the same kitrepoid \"$kr->{kitrepoid}\". \n"; + return 1; + } + if (($kr->{osbasename} eq $kr2->{osbasename}) && + ($kr->{osmajorversion} eq $kr2->{osmajorversion}) && + ($kr->{osarch} eq $kr2->{osarch})) { + if ((defined($kr->{osminorversion}) && + defined($kr2->{osminorversion}) && + ($kr->{osminorversion} eq $kr2->{osminorversion})) || + (!defined($kr->{osminorversion}) && + !defined($kr2->{osminorversion}))) { + print "There are two or more kitrepo sections which are defined with the same OS name, major/minor version, and architecture. \n"; + return 1; + } + } + } + } + } + + # Kitcomponent version/release are now optional - + # default to kit version/release + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if (!defined($kc->{version})) { + $kc->{version} = $::bldkit_config->{kit}{entries}[0]->{version}; + } + if (!defined($kc->{release})) { + if (!defined($::bldkit_config->{kit}{entries}[0]->{release})) { + print "Kitcomponent $kc->{basename} does not have a release specified and there is no Kit release value set to use as a default. \n"; + return 1; + } else { + $kc->{release} = $::bldkit_config->{kit}{entries}[0]->{release}; + } + } + + } + + # Make sure each kitcomponent has unique basename/repoid + # If same basename, make sure version/release are same, too + my $kc_count = scalar @{ $::bldkit_config->{kitcomponent}{entries} }; + if ($kc_count > 1) { + foreach my $kci (0 .. $kc_count - 2) { + foreach my $kci2 ($kci + 1 .. $kc_count - 1) { + if ($::bldkit_config->{kitcomponent}{entries}[$kci]->{basename} + eq $::bldkit_config->{kitcomponent}{entries}[$kci2]->{basename}) { + if ($::bldkit_config->{kitcomponent}{entries}[$kci]->{kitrepoid} + eq $::bldkit_config->{kitcomponent}{entries}[$kci2]->{kitrepoid}) { + + print "Two or more kitcomponents are defined with the same basename \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{basename}\" and the same repoid \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{kitrepoid}\". \n"; + return 1; + } + if (($::bldkit_config->{kitcomponent}{entries}[$kci]->{version} + ne $::bldkit_config->{kitcomponent}{entries}[$kci2]->{version}) || + ($::bldkit_config->{kitcomponent}{entries}[$kci]->{release} + ne $::bldkit_config->{kitcomponent}{entries}[$kci2]->{release}) + ) { + print "Two or more kitcomponents are defined with the same basename \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{basename}\" but with different version or release. \n"; + return 1; + } + } + } + } + } + + # Kitrepo checks + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + my $reponame = $short_kitname; + if ((defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) && + ($::bldkit_config->{kit}{entries}[0]->{osbasename} ne + $kr->{osbasename})) { + print "Warning: Kit osbasename is set to \"$::bldkit_config->{kit}{entries}[0]->{osbasename}\", but this does not match kitrepo $kr->{kitrepoid} osbasename \"$kr->{osbasename}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-' . $kr->{osbasename}; + if ((defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion})) && + ($::bldkit_config->{kit}{entries}[0]->{osmajorversion} ne + $kr->{osmajorversion})) { + print "Warning: Kit osmajorversion is set to \"$::bldkit_config->{kit}{entries}[0]->{osmajorversion}\", but this does not match kitrepo $kr->{kitrepoid} osmajorversion \"$kr->{osmajorversion}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-' . $kr->{osmajorversion}; + if (defined($kr->{osminorversion})) { + my $krminor = $kr->{osminorversion}; + unless ($krminor =~ /^\d/) { + $krminor = split /<=|>=|==|<|>|=/, $kr->{osminorversion}; + } + if ((defined($::bldkit_config->{kit}{entries}[0]->{osminorversion})) && + ($::bldkit_config->{kit}{entries}[0]->{osminorversion} ne + $kr->{osminorversion})) { + print "Warning: Kit osminorversion is set to \"$::bldkit_config->{kit}{entries}[0]->{osminorversion}\", but this does not match kitrepo $kr->{kitrepoid} osminorversion \"$kr->{osminorversion}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '.' . $krminor; + $::bldkit_config->{kit}{entries}[0]->{osminorversion} = $krminor; + } + if ((defined($::bldkit_config->{kit}{entries}[0]->{osarch})) && + ($::bldkit_config->{kit}{entries}[0]->{osarch} ne + $kr->{osarch})) { + print "Warning: Kit osarch is set to \"$::bldkit_config->{kit}{entries}[0]->{osarch}\", but this does not match kitrepo $kr->{kitrepoid} osarch \"$kr->{osarch}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-' . $kr->{osarch}; + $kr->{kitreponame} = $reponame; + } + + # Kitcomponent checks + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + + # Make sure all kitcomponent kitrepoids are defined + my $found = 0; + my %repo; + if ($debianflag) { + if ($kc->{basename} =~ /_/) { + print "Kit Component basename can not contain underscore.\n"; + return 1; + } + } + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($kc->{kitrepoid} eq $kr->{kitrepoid}) { + $found = 1; + %repo = %{$kr}; + $kc->{kitreponame} = $kr->{kitreponame}; + push(@{ $kr->{packages} }, &comppkgname($kc, $kr)); + last; + } + } + if (!$found) { + print "Kit Repository \"$kc->{kitrepoid}\" required by the Kit Component \"$kc->{basename}\" not defined in the Kit Build file.\n"; + return 1; + } + + # Create full kitcomponent name + my $compname = $kc->{basename}; + $compname .= '-' . $kc->{version}; + $compname .= '-' . $kc->{release}; + $compname .= '-' . $repo{osbasename}; + $compname .= '-' . $repo{osmajorversion}; + if (defined($repo{osminorversion})) { + my $minorversion = $repo{osminorversion}; + unless ($minorversion =~ /^\d/) { + $minorversion = split /<=|>=|==|<|>|=/, $repo{osminorversion}; + } + $compname .= '.' . $minorversion; + } + $compname .= '-' . $repo{osarch}; + $kc->{kitcompname} = $compname; + + # Make sure all kitcomponent kitpkgdeps are defined + if (defined($kc->{kitpkgdeps})) { + foreach my $d (split(/,/, $kc->{kitpkgdeps})) { + $d =~ s/\s+//g; + $d =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + my $found = 0; + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + if ($kp->{filename} =~ /^$d[\.\-]?/) { + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($kc->{kitrepoid} eq $kprid) { + $found = 1; + last; + } + } + } + if ($found) { last; } + } + if (!$found) { + print "Kit Package \"$d\" required by the Kit Component \"$kc->{basename}\" was not found in the Kit Component\'s repository \"$kc->{kitrepoid}\".\n"; + return 1; + } + } + } + + # Make sure all kitcomponent driverpacks are defined + if (defined($kc->{driverpacks})) { + my @drvs = split(/,/, $kc->{driverpacks}); + foreach my $d (@drvs) { + $d =~ s/\s+//g; + my $found = 0; + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + if ($kp->{filename} eq $d) { + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($kc->{kitrepoid} eq $kprid) { + $found = 1; + last; + } + } + } + if ($found) { last; } + } + if (!$found) { + print "Driver package \"$d\" required by the Kit Component \"$kc->{basename}\" was not found in the Kit Component\'s repository \"$kc->{kitrepoid}\".\n"; + return 1; + } + } + } + + # Make sure files exist + if (defined($kc->{exlist})) { + my $ck_file = $::workdir . "/other_files/" . $kc->{exlist}; + if (!-r $ck_file) { + print "Exclude List file $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preinstall})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{preinstall}; + if (!-r $ck_file) { + print "Pre-Install script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postinstall})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{postinstall}; + if (!-r $ck_file) { + print "Post-Install script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preuninstall})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{preuninstall}; + if (!-r $ck_file) { + print "Pre-Uninstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postuninstall})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{postuninstall}; + if (!-r $ck_file) { + print "Post-Uninstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preupgrade})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{preupgrade}; + if (!-r $ck_file) { + print "Pre-Upgrade script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postupgrade})) { + my $ck_file = $::workdir . "/scripts/" . $kc->{postupgrade}; + if (!-r $ck_file) { + print "Post-Upgrade script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{genimage_postinstall})) { + foreach my $script (split(/\,/, $kc->{genimage_postinstall})) { + $script =~ s/\s+//g; + my $ck_file = $::workdir . "/scripts/" . $script; + if (!-r $ck_file) { + print "genimage_postinstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + } + if (defined($kc->{postbootscripts})) { + foreach my $script (split(/\,/, $kc->{postbootscripts})) { + $script =~ s/\s+//g; + my $ck_file = $::workdir . "/scripts/" . $script; + if (!-r $ck_file) { + print "Postboot script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + } + if (defined($kc->{non_native_pkgs})) { + if ($kc->{non_native_pkgs} =~ /EXTERNALPKGS/) { + $::NON_NATIVE_PKGS->{ $kc->{kitcompname} } = 1; + $::HAVE_NON_NATIVE_PKGS = 1; + } + } + } + + # Kitpackage checks + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + + # determine if valid build method + if ((defined($kp->{isexternalpkg})) || + (defined($kp->{rpm_prebuiltdir}))) { + if ((defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srctarball})) || + (defined($kp->{rpm_spec})) || + (defined($kp->{rpm_srcdir}))) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + if (!(defined($kp->{isexternalpkg}))) { $kp->{isexternalpkg} = 'no'; } + my $orig_isext = $kp->{isexternalpkg}; + $kp->{isexternalpkg} =~ s/\s+//g; + $kp->{isexternalpkg} =~ tr/A-Z/a-z/; # convert to lowercase + if ($kp->{isexternalpkg} eq '0') { $kp->{isexternalpkg} = 'no'; } + if ($kp->{isexternalpkg} eq '1') { $kp->{isexternalpkg} = 'yes'; } + if (($kp->{isexternalpkg} ne 'yes') && + ($kp->{isexternalpkg} ne 'no')) { + print "Error in definition for Kit Package $kp->{filename}. Invalid attribute value \'isexternalpkg=$orig_isext\'. Valid values are \'no\'|\'0\' or \'yes\'|\'1\'.\n"; + return 1; + } + if (($kp->{isexternalpkg} eq 'yes')) { + $::HAVE_EXTERNAL_PKG = 1; + } + if (($kp->{isexternalpkg} eq 'yes') && + (defined($kp->{rpm_prebuiltdir}))) { + print "Error in definition for Kit Package $kp->{filename}. Do not specify \'isexternalpkg=$orig_isext\' with 'rpm_prebuiltdir'.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srpm})) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srctarball})) || + (defined($kp->{rpm_spec})) || + (defined($kp->{rpm_srcdir}))) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srctarball}) && + defined($kp->{rpm_spec})) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srcdir}))) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srcdir}) && + defined($kp->{rpm_spec})) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srctarball}))) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } else { + print "Cannot determine build method for Kit Package $kp->{filename}. Verify that your Kit Build File is correct. \n"; + return 1; + } + + # Make sure all kitpackage kitrepoids are defined + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + my $found = 0; + $kprid =~ s/\s+//g; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($kprid eq $kr->{kitrepoid}) { + $found = 1; + $kp->{kitreponame} .= "," . $kr->{kitreponame}; + if (!($kp->{isexternalpkg} eq 'yes')) { + push(@{ $kr->{packages} }, $kp->{filename}); + } + last; + } + } + if (!$found) { + print "Kit Repository \"$kprid\" required by the Kit Package \"$kp->{filename}\" is not defined in the Kit Build file.\n"; + return 1; + } + } + $kp->{kitreponame} =~ s/^,//; + if (!$::NEW_PARTIAL_KIT) { + + # Make sure files exist + if (defined($kp->{rpm_spec})) { + my $ck_file = $::workdir . "/source_packages/" . $kp->{rpm_spec}; + if (!-r $ck_file) { + print "RPM spec file $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srcdir})) { + my $ck_dir = $::workdir . "/source_packages/" . $kp->{rpm_srcdir}; + if (!-d $ck_dir) { + print "RPM source directory $ck_dir defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srctarball})) { + my $ck_file = $::workdir . "/source_packages/" . $kp->{rpm_srctarball}; + if (!-r $ck_file) { + print "RPM source tarfile $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srpm})) { + my $ck_file = $::workdir . "/source_packages/" . $kp->{rpm_srpm}; + if (!-r $ck_file) { + print "Source RPM $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_prebuiltdir})) { + my $ck_dir = $::workdir . "/source_packages/" . $kp->{rpm_prebuiltdir}; + if (!-d $ck_dir) { + print "Pre-built RPM directory $ck_dir defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + my $ck_file = $ck_dir . "/" . $kp->{filename}; + if (system("ls $ck_file > /dev/null")) { + + # if (! -r $ck_file ) { + print "Pre-built rpm $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + } + } + + #use Data::Dumper; + #print Dumper($::bldkit_config->{kitrepo}); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 comppkgname + + build a metapkg rpm filename for this kitcomponent + input: kitcomponent hash + kitrepo hash that this kitcomponent belongs to + +=cut + +#----------------------------------------------------------------------------- +sub comppkgname +{ + my $comp = shift; + + my $pkgname = $comp->{basename}; + if ($debianflag) { + $pkgname .= '_' . $comp->{version}; + $pkgname .= '-' . $comp->{release}; + $pkgname .= '_all.deb'; + } + else { + $pkgname .= '-' . $comp->{version}; + $pkgname .= '-' . $comp->{release}; + $pkgname .= '.noarch.rpm'; + } + return $pkgname; +} + +#----------------------------------------------------------------------------- + +=head3 validate_repo + + validate whether a kit repo has been built + input: repo hash + returns rc: + 0 - repo status is DONE + 1 - repo status is NOT DONE + verbose mode displays message for first rpm not built + +=cut + +#----------------------------------------------------------------------------- +sub validate_repo +{ + my $repo = shift; + + my $repodir = $::base_repodir . "/" . $repo->{kitreponame}; + if (!-d $repodir) { + if ($::VERBOSE) { + print "\n$repodir does not exist. No rpms have been built for this kitrepo. \n"; + } + return 1; + } + + # Make sure each repo pkg exists + foreach my $pkg (@{ $repo->{packages} }) { + + # skip check for kit component meta rpm if it includes + # external non-native pkgs + my $skip_check = 0; + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if ($repo->{kitrepoid} eq $kc->{kitrepoid}) { + my $kitpkgname = comppkgname($kc); + if (($kitpkgname eq $pkg) && + ($::NON_NATIVE_PKGS->{ $kc->{kitcompname} })) { + $skip_check = 1; + last; + } + } + } + if (!$skip_check) { + my $pkg_filename = $repodir . '/' . $pkg; + if (system("ls $pkg_filename > /dev/null")) { + if ($::VERBOSE) { + print "\nFile $pkg in directory $repodir does not exist or is not readable. \n"; + } + return 1; + } + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 validate_os + + validate whether a kit repo matches the current OS + input: repo hash + returns rc: + 0 - match + 1 - no match + verbose mode displays message for mismatch details + +=cut + +#----------------------------------------------------------------------------- +sub validate_os +{ + my $repo = shift; + + my $osinfo = xCAT::BuildKitUtils->osver(); + my ($osbasename, $osmore) = split(/\,/, $osinfo); + my ($osmajorversion, $osminorversion) = split(/\./, $osmore); + my $osarch = `uname -p`; + chomp($osarch); + + if ($debianflag == 1) { + if ($osarch eq "ppc64le") { + $osarch = "ppc64el"; + } + } + $osinfo =~ s/\,//; + my $repo_osinfo = "$repo->{osbasename}$repo->{osmajorversion}"; + my $minorversion; + if (defined($repo->{osminorversion})) { + $minorversion = $repo->{osminorversion}; + unless ($minorversion =~ /^\d/) { + $minorversion = split /<=|>=|==|<|>|=/, $repo->{osminorversion}; + } + $repo_osinfo .= ".$minorversion"; + } + $repo_osinfo .= "-$repo->{osarch} "; + my $mismatch_msg = "The local host is running $osinfo-$osarch. This does not match the Kit Repository \"$repo->{kitrepoid}\" data: $repo_osinfo"; + if (defined($repo->{compat_osbasenames})) { + $mismatch_msg .= " or the compatible OS distros: $repo->{compat_osbasenames} "; + } + + + my $compat_match = 0; + if ($repo->{osbasename} ne $osbasename) { + if (defined($repo->{compat_osbasenames})) { + foreach my $cos (split(/,/, $repo->{compat_osbasenames})) { + if ($cos eq $osbasename) { + $compat_match = 1; + last; + } + } + } + if (!$compat_match) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS basename $osbasename does not match repository.\n"; + } + return 1; + } + } + if (($repo->{osmajorversion} ne $osmajorversion) && + (!$compat_match)) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS major version $osmajorversion does not match repository.\n"; + } + return 1; + } + if (defined($repo->{osminorversion})) { + if (($minorversion ne $osminorversion) && + (!$compat_match)) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS minor version $osminorversion does not match repository.\n"; + } + return 1; + } + } + if ($repo->{osarch} ne $osarch) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS arch $osarch does not match repository.\n"; + } + return 1; + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 build_kitcomp + + build a metapkg rpm for this kitcomponent + input: kitcomponent hash + +=cut + +#----------------------------------------------------------------------------- +sub build_kitcomp +{ + my $comp = shift; + my %repo; + my $rpmbuild_dir = $::workdir . "/rpmbuild"; + my $tmpdir = $::workdir . "/tmp/$comp->{kitcompname}"; + my $kcmetaname = comppkgname($comp); + + # If this kitcomponent has external non-native pkgs, + # skip the meta rpm build + if (defined($::NON_NATIVE_PKGS) && + defined($::NON_NATIVE_PKGS->{ $comp->{kitcompname} }) && + $::NON_NATIVE_PKGS->{ $comp->{kitcompname} }) { + if ($::VERBOSE) { + print "Kit component $comp->{kitcompname} has external non-native packages. Skipping rpm build for $kcmetaname. \n"; + } + return 0; + } + + # find the kitrepo hash for this component + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($comp->{kitrepoid} eq $kr->{kitrepoid}) { + %repo = %{$kr}; + last; + } + } + my $repodir = $::base_repodir . "/" . $repo{kitreponame}; + + # Fix the kitpkgdeps value for this kitcomponent + # For any kitpkgdep that has an rpm file in the repo, + # specifically reference it's version-release + if (&update_kitcomp_kitpkgdeps($comp, $repodir)) { return 1; } + + $::VALID_PRER_COMPONENT = 0; + + if (!$::PREREQUISITE) { + if ($comp->{ospkgdeps} || $comp->{preinstall} || $comp->{preupgrade}) { + if (&gen_kitcomp_spec($comp, \%repo, 'PREREQUISITE')) { return 1; } + + # run the rpmbuild command + my $curdir = $::workdir; + my $cmd = "rm -Rf $curdir/rpmbuild"; + system($cmd); + my $avoiderr = $rpmbuild_dir . "/BUILDROOT/prep_" . $comp->{basename}; + $avoiderr .= "-$comp->{version}-$comp->{release}.$repo{osarch}"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/RPMS/noarch/"; + mkpath($avoiderr); + + # Read the kit component prerequisite rpm name + + my $specfile = $::workdir . "/tmp/$comp->{kitcompname}-prep.spec"; + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $specfile"; + + # don't want debug info - 3845 + # if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; + + # } + if (system($rpmbuild_cmd)) { + print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if (system("cp -fp $rpm $repodir")) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + + $::VALID_PRER_COMPONENT = 1; + + } + + if (&gen_kitcomp_spec($comp, \%repo, 'METARPM')) { return 1; } + } else { + + # Create spec file for this kit component + if (&gen_kitcomp_spec($comp, \%repo, 'ALL')) { return 1; } + } + + # run the rpmbuild command + my $curdir = $::workdir; + my $cmd = "rm -Rf $curdir/rpmbuild"; + system($cmd); + my $avoiderr = $rpmbuild_dir . "/BUILDROOT/" . $comp->{basename}; + $avoiderr .= "-$comp->{version}-$comp->{release}.$repo{osarch}"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/RPMS/noarch/"; + mkpath($avoiderr); + + # Read the kit component meta rpm name + + my $specfile = $::workdir . "/tmp/$comp->{kitcompname}.spec"; + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $specfile"; + + # Copy in any non-native packages + if (defined($comp->{non_native_pkgs})) { + mkpath($tmpdir); + mkpath("$rpmbuild_dir/SOURCES"); + my $sourcedir = $::workdir . "/source_packages"; + + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkg_file; + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkg_file = $value; + } else { + $pkg_file = $key; + } + + $cmd = "cp -p $sourcedir/$pkg_file $tmpdir"; + if (system($cmd)) { + print "Error copying non-native package file $sourcedir/$pkg_file to $tmpdir\n"; + return 1; + } + } + $cmd = "cd $tmpdir/..;mv $comp->{kitcompname} $comp->{basename}; tar -czf $rpmbuild_dir/SOURCES/$comp->{basename}.tar.gz $comp->{basename};mv $comp->{basename} $comp->{kitcompname}"; + if (system($cmd)) { + print "Error creating tarfile $rpmbuild_dir/SOURCES/$comp->{kitreponame}-$comp->{kitcompname}.tar from $sourcedir/*"; + return 1; + } + } + + # - don't want debug info - 3845 + # if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; + + # } + + if (system($rpmbuild_cmd)) { + print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if (system("cp -fp $rpm $repodir")) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 update_kitcomp_kitpkgdeps + + Update the kitcomponent kitpkgdeps string + For any kitpkgdep that does not explicitly specify a version-release + comparison string and for which an rpm exists in the repo, + query the rpm for its version-release info and set an explicit + comparison string. + Reason we need to do all this: We need to force yum/zypper to update + the product rpms. A simple package name in the kitcomponent meta rpm + REQUIRES entry will not cause the product to get updated if an older + version is already installed. Need to explicitly require this version + and release of the product package. + input: kitcomponent hash + kitrepo directory + +=cut + +#----------------------------------------------------------------------------- +sub update_kitcomp_kitpkgdeps +{ + my $comp = shift; + my $repodir = shift; + + if (defined($comp->{kitpkgdeps})) { + + # we have some rpms listed in buildkit.conf file + my $new_kitpkgdeps = ''; + foreach my $d (split(/,/, $comp->{kitpkgdeps})) { + $d =~ s/\s+//g; + my $d_short = $d; + + # strip off everything after ">=" + $d_short =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + + # if they are the same then there was no v/r info provided + if ($d_short eq $d) { + + # no version-release comparisons specified for this kitpkgdep + # do we have this rpm file? + # get a list of any matches + my $lscmd = "cd $repodir; /bin/ls $d-\[0-9\]\*.rpm 2>/dev/null"; + my @rpmlist = `$lscmd`; + + if (scalar(@rpmlist) == 0) { + next; + } + + # get the newest version there is + my $newestrpm = xCAT::BuildKitUtils->get_latest_version($repodir, \@rpmlist); + + if (!$newestrpm) { + print "Error: Could not determine the latest version of rpm $d contained in $repodir. \n"; + next; + } + + # get the Version and release values for this rpm + my $cmd = "rpm -q --qf \"%{NAME} >= %{VERSION}-%{RELEASE}\" -p $repodir/$newestrpm 2>/dev/null"; + if ($::VERBOSE) { + print "running rpm query to get version-release info: \n $cmd \n"; + } + + my $new_d = `$cmd`; + if (!$new_d) { + print "Error: Could not determine the latest version of rpm $d. \n"; + next; + } + + chomp($new_d); + if ($::VERBOSE) { + print "output: \n \'$new_d\' \n"; + } + if ($new_d ne '') { + $new_kitpkgdeps .= "$new_d,"; + } else { + $new_kitpkgdeps .= "$d,"; + } + } else { + $new_kitpkgdeps .= "$d,"; + } + } + + $new_kitpkgdeps =~ s/(\,)*$//; + $comp->{kitpkgdeps} = $new_kitpkgdeps; + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 gen_kitcomp_spec + + generate the rpm spec file for the kitcomponent metapkg rpm + input: kitcomponent hash + kitrepo hash + +=cut + +#----------------------------------------------------------------------------- +sub gen_kitcomp_spec +{ + my $comp = shift; + my $repo = shift; + my $level = shift; + my $scriptdir = $::workdir . "/scripts/"; + my $tmpdir = $::workdir . "/tmp/"; + + # read in the template spec file + my $spec_template = $::XCATSHARE . "/kits/kitcomponent.spec.template"; + my $SF; + unless (open($SF, "<", $spec_template)) { + print "Error attempting to open the xCAT Kit Component template file $spec_template. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading the xCAT Kit Component template file $spec_template. \n"; + } + my @lines = <$SF>; + close $SF; + + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $kitcompname = $comp->{kitcompname}; + + my ($prescript, $postscript, $preupscript, $postupscript, $preunscript, $postunscript, $nonnativepkgs, $sourcetar, $setup, $files) = ' '; + if ($level eq 'PREREQUISITE' || $level eq 'ALL') { + if (defined($comp->{preinstall})) { + $prescript = &load_script("$scriptdir$comp->{preinstall}"); + $prescript = "if [ \"\$1\" = \"1\" ] ; then\n" . $prescript . "\nfi"; } + if (defined($comp->{preupgrade})) { + $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); + $preupscript = "if [ \"\$1\" = \"2\" ] ; then\n" . $preupscript . "\nfi"; } + } + if ($level eq 'METARPM' || $level eq 'ALL') { + if (defined($comp->{preuninstall})) { + $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); } + if (defined($comp->{postinstall})) { + $postscript = &load_script("$scriptdir$comp->{postinstall}"); + $postscript = "if [ \"\$1\" = \"1\" ] ; then\n" . $postscript . "\nfi"; } + if (defined($comp->{postupgrade})) { + $postupscript = &load_script("$scriptdir$comp->{postupgrade}"); + $postupscript = "if [ \"\$1\" = \"2\" ] ; then\n" . $postupscript . "\nfi"; } + if (defined($comp->{postuninstall})) { + $postunscript = &load_script("$scriptdir$comp->{postuninstall}"); } + if (defined($comp->{non_native_pkgs})) { + $nonnativepkgs = "\n"; + $nonnativepkgs .= "mkdir -p \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $nonnativepkgs .= "cp -a * \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $sourcetar = "Source: $comp->{basename}.tar.gz"; + $setup = "\%setup -q -n $comp->{basename}"; + $files = "/opt/xcat/kits"; + } + } + + # remove lines that correspond to optional tags that have no values + # in this instance. Adding lines to the spec file that have + # no values will cause a build error. + my @newlines; + foreach my $l (@lines) { + chomp; + + # don't add vendor,packager,url to spec file unless we have a value + if ($l =~ /INSERT_vendor_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{vendor}) { + next; + } + } + if ($l =~ /INSERT_packager_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{packager}) { + next; + } + } + if ($l =~ /INSERT_url_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{url}) { + next; + } + } + push @newlines, $l; + } + @lines = @newlines; + + if ($level eq 'ALL') { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>/$comp->{kitpkgdeps}/; + s/<<>>/$comp->{kitcompdeps}/; + s/<<>>/$comp->{description}/; + s/<<>>/$nonnativepkgs/; + s/<<>>/$sourcetar/; + s/<<>>/$setup/; + s/<<>>/$files/; + s/<<>>/$prescript/; + s/<<>>/$postscript/; + s/<<>>/$preupscript/; + s/<<>>/$postupscript/; + s/<<>>/$preunscript/; +s/<<>>/$postunscript/; + } + } elsif ($level eq 'PREREQUISITE') { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/prep_$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>//; + s/<<>>//; + s/<<>>/$comp->{description}/; + s/<<>>//; + s/<<>>//; + s/<<>>//; + s/<<>>//; + s/<<>>/$prescript/; + s/<<>>//; + s/<<>>/$preupscript/; + s/<<>>//; + s/<<>>/$preunscript/; + s/<<>>//; + } + + } elsif ($level eq 'METARPM') { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>//; + s/<<>>/$comp->{kitpkgdeps}/; + + #Update kitcompdeps for prep_ + if ($::VALID_PRER_COMPONENT) { +s/<<>>/$comp->{kitcompdeps},prep_$comp->{basename}/; + } else { +s/<<>>/$comp->{kitcompdeps}/; + } + s/<<>>/$comp->{description}/; + s/<<>>/$nonnativepkgs/; + s/<<>>/$sourcetar/; + s/<<>>/$setup/; + s/<<>>/$files/; + s/<<>>//; + s/<<>>/$postscript/; + s/<<>>//; + s/<<>>/$postupscript/; + s/<<>>/$preunscript/; +s/<<>>/$postunscript/; + } + } + + # Write the generated spec file + mkpath($tmpdir); + + my $fn; + my $NSF; + if ($level eq 'PREREQUISITE') { + $fn = $comp->{kitcompname} . "-prep.spec" + } else { + $fn = $comp->{kitcompname} . ".spec" + } + unless (open($NSF, ">$tmpdir$fn")) { + return 1; + } + if ($::VERBOSE) { + print "Created kitcomponent spec file \'$tmpdir$fn\'\n"; + + } + foreach my $line (@lines) { + print $NSF $line, "\n"; + } + + close($NSF); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 build_kitcomp_debian + + + +=cut + +#----------------------------------------------------------------------------- +sub build_kitcomp_debian { + my $comp = shift; + my %repo; + my $debbuilddir = $::workdir . "/debbuild/" . $comp->{kitcompname}; + my $kcmetaname = comppkgname($comp); + + #If this kitcomponent has external non-native pkgs, + #skip the meta package build + if (defined($::NON_NATIVE_PKGS) && + defined($::NON_NATIVE_PKGS->{ $comp->{kitcompname} }) && + $::NON_NATIVE_PKGS->{ $comp->{kitcompname} }) { + if ($::VERBOSE) { + print "Kit component $comp->{kitcompname} has external non-native packages. Skipping rpm build for $kcmetaname. \n"; + } + return 0; + } + + # find the kitrepo hash for this component + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + if ($comp->{kitrepoid} eq $kr->{kitrepoid}) { + %repo = %{$kr}; + last; + } + } + + + #run the dpkg-buildpackage command + my $curdir = $::workdir; + my $cmd = "rm -Rf $debbuilddir"; + system($cmd); + mkpath($debbuilddir); + + $::VALID_PREP_COMPONENT = 0; + + if (!$::PREREQUISITE) { + if ($comp->{ospkgdeps} || $comp->{preinstall} || $comp->{preupgrade} || $comp->{preuninstall}) { + + #Create debian directory for this kit component preppackage + + if (&gen_kitcomp_debdir_prep($comp, \%repo)) { return 1; } + $::VALID_PREP_COMPONENT = 1; + + # build prep deb + my $prep_compversion = $comp->{version} . "-" . $comp->{release}; + my $prep_buildstring = "Prep Kit component build package."; + my $prep_debbuilddir = $::workdir . "/debbuild/" . "prep-" . $comp->{kitcompname}; + my $prep_debianbuildcmd = "cd $prep_debbuilddir;debchange -v $prep_compversion -b -c debian/changelog $prep_buildstring;dpkg-buildpackage $dpkg_flag"; + + if (system($prep_debianbuildcmd)) { + print "Error running \"dpkg-buildpackage $dpkg_flag\" command for kit component prep-$comp->{kitcompname} meta package\n"; + return 1; + } + } + + #Create debian directory for this kit component metapackage + + if (&gen_kitcomp_debdir($comp, \%repo, 'METADEB')) { return 1; } + + } else { + + #Create debian directory for this kit component + + if (&gen_kitcomp_debdir($comp, \%repo, 'ALL')) { return 1; } + + } + + + + if (defined($comp->{non_native_pkgs})) { + my $sourcedir = $::workdir . "/source_packages"; + + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkg_file; + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkg_file = $value; + } else { + $pkg_file = $key; + } + + $cmd = "cp -p $sourcedir/$pkg_file $debbuilddir"; + if (system($cmd)) { + print "Error copying non-native package file $sourcedir/$pkg_file to debbuilddir\n"; + return 1; + } + } + } + my $compversion = $comp->{version} . "-" . $comp->{release}; + my $buildstring = "\'Kit component build package.\'"; + my $debianbuildcmd = "cd $debbuilddir;debchange -v $compversion -b -c debian/changelog $buildstring;dpkg-buildpackage $dpkg_flag"; + if (!$::NON_NATIVE_PKGS->{ $comp->{kitcompname} }) { + if (system($debianbuildcmd)) { + print "Error running \"dpkg-buildpackage $dpkg_flag\" command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my $repodir = $::base_repodir . "/" . $repo{kitreponame}; + my @builtdebs = `find $::workdir/debbuild -maxdepth 1 -name "*.deb"`; + foreach my $deb (@builtdebs) { + chomp($deb); + if (system("cp -fp $deb $repodir")) { + print "Error copying package $deb to build repo directory $repodir \n"; + return 1; + } + } + } + return 0; +} + + +#----------------------------------------------------------------------------- + +=head3 gen_kitcomp_debdir_prep + + + +=cut + +#----------------------------------------------------------------------------- +sub gen_kitcomp_debdir_prep { + my $comp = shift; + my $repo = shift; + my $scriptdir = $::workdir . "/scripts/"; + my $combuilddir = $::workdir . "/debbuild/" . "prep-" . $comp->{kitcompname}; + + #copy the debian dir template to the build path + mkpath("$combuilddir/debian"); + my $cmd = "cp -Rf " . $::XCATSHARE . "/kits/debian_template/* $combuilddir/debian/"; + system($cmd); + + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $kitcompname = "prep-" . $comp->{kitcompname}; + my $upgradeflag = "pre-" . $comp->{basename} . ".tmp"; + + my ($prescript, $postscript, $preupscript, $postupscript, $preunscript, $postunscript, $nonnativepkgs) = ''; + if (defined($comp->{preinstall})) { + $prescript = &load_script("$scriptdir$comp->{preinstall}"); + } + if (defined($comp->{preupgrade})) { + $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); + } + if (defined($comp->{preuninstall})) { + $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); + } + + #replace all special sub string in all files under debian + unless (opendir(DH, "${combuilddir}/debian/")) { + print "Can not open the xCAT Kit Component debian dir: ${combuilddir}/debian/"; + return 1; + } + + foreach (readdir(DH)) { + my $file = "${combuilddir}/debian/$_"; + if (-d $file) { + next; + } + + unless (open(FH, "<", $file)) { + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian template file $file.\n"; + close(DH); + return 1; + } + + if ($::VERBOSE) { + print "Reading the xCAT Kit Component ${kitcompname}'s debian template file $file. \n"; + } + my @lines = ; + close(FH); + my $prep_comp_name = "prep-" . $comp->{basename}; + for (@lines) { + chomp; + s/<<>>/$prep_comp_name/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>//; + s/<<>>//; + s/<<>>/$comp->{description}/; + s/<<>>/$upgradeflag/; + s/<<>>/$prescript/; + s/<<>>//; + s/<<>>/$preupscript/; + s/<<>>//; + s/<<>>/$preunscript/; + s/<<>>//; + + } + my $joined_lines = join("\n", @lines); + @lines = split(/\\n/, $joined_lines); + + open(FH, ">", $file); + if ($::VERBOSE) { + print "Created kitcomponent ${kitcompname}'s build file under debian dir $file"; + } + print FH @lines; + close(FH); + } + closedir(DH); + + return 0; +} + + + +#----------------------------------------------------------------------------- + +=head3 gen_kitcomp_debdir + + + +=cut + +#----------------------------------------------------------------------------- +sub gen_kitcomp_debdir { + my $comp = shift; + my $repo = shift; + my $level = shift; + my $scriptdir = $::workdir . "/scripts/"; + my $combuilddir = $::workdir . "/debbuild/" . $comp->{kitcompname}; + + #copy the debian dir template to the build path + mkpath("$combuilddir/debian"); + my $cmd = "cp -Rf " . $::XCATSHARE . "/kits/debian_template/* $combuilddir/debian/"; + system($cmd); + + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $kitcompname = $comp->{kitcompname}; + my $upgradeflag = $comp->{basename} . ".tmp"; + + my ($prescript, $postscript, $preupscript, $postupscript, $preunscript, $postunscript, $nonnativepkgs) = ''; + + if ($level eq 'METADEB' || $level eq 'ALL') + { + if (defined($comp->{postinstall})) { + $postscript = &load_script("$scriptdir$comp->{postinstall}"); + } + + if (defined($comp->{postupgrade})) { + $postupscript = &load_script("$scriptdir$comp->{postupgrade}"); + } + if (defined($comp->{postuninstall})) { + $postunscript = &load_script("$scriptdir$comp->{postuninstall}"); + } + if (defined($comp->{non_native_pkgs})) { + $nonnativepkgs = "\n"; + $nonnativepkgs .= "mkdir -p \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $nonnativepkgs .= "cp -a * \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + } + } + if ($level eq 'ALL') + { + if (defined($comp->{preinstall})) { + $prescript = &load_script("$scriptdir$comp->{preinstall}"); + } + if (defined($comp->{preupgrade})) { + $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); + } + if (defined($comp->{preuninstall})) { + $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); + } + } + + + #replace all special sub string in all files under debian + unless (opendir(DH, "${combuilddir}/debian/")) { + print "Can not open the xCAT Kit Component debian dir: ${combuilddir}/debian/"; + return 1; + } + + foreach (readdir(DH)) { + my $file = "${combuilddir}/debian/$_"; + if (-d $file) { + next; + } + + unless (open(FH, "<", $file)) { + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian template file $file.\n"; + close(DH); + return 1; + } + + if ($::VERBOSE) { + print "Reading the xCAT Kit Component ${kitcompname}'s debian template file $file. \n"; + } + my @lines = ; + close(FH); + my $prepcomp = "prep-" . $comp->{basename}; + for (@lines) { + chomp; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>/$comp->{kitpkgdeps}/; + if ($::VALID_PREP_COMPONENT) { +s/<<>>/$comp->{kitcompdeps},$prepcomp/; + } + else + { +s/<<>>/$comp->{kitcompdeps}/; + } + + s/<<>>/$comp->{description}/; + s/<<>>/$upgradeflag/; + s/<<>>/$prescript/; + s/<<>>/$postscript/; + s/<<>>/$preupscript/; + s/<<>>/$postupscript/; + s/<<>>/$preunscript/; +s/<<>>/$postunscript/; + } + my $joined_lines = join("\n", @lines); + @lines = split(/\\n/, $joined_lines); + + open(FH, ">", $file); + if ($::VERBOSE) { + print "Created kitcomponent ${kitcompname}'s build file under debian dir $file"; + } + print FH @lines; + close(FH); + } + closedir(DH); + + if (defined($comp->{non_native_pkgs})) { + unless (open(FH, ">", "${combuilddir}/debian/dir")) { + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian file dir.\n"; + return 1; + } + print FH "opt/xcat/kits/$kitname/$kitcompname/"; + close(FH); + + unless (open(FH, ">", "${combuilddir}/debian/install")) { + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian file dir.\n"; + return 1; + } + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkgname = ''; + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkgname = $value; + } else { + $pkgname = $key; + } + print FH "$pkgname opt/xcat/kits/$kitname/$kitcompname/ \n"; + } + close(FH); + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 load_script + + load a kitcomponent script into a single return string + with imbedded newline chars + input: fullpath of scriptname + +=cut + +#----------------------------------------------------------------------------- +sub load_script +{ + my $scriptname = shift; + my $SF; + unless (open($SF, "<", $scriptname)) { + print "Error attempting to open the file $scriptname. \n"; + return; + } + if ($::VERBOSE) { + print "Reading the file $scriptname. \n"; + } + my @lines = <$SF>; + close $SF; + + my $script_contents = join('', @lines); + return $script_contents; +} + +#----------------------------------------------------------------------------- + +=head3 create_kitconf + + Create the kit configuration file to put into the kit tar file. + +=cut + +#----------------------------------------------------------------------------- +sub create_kitconf +{ + # Build kit config file entries from buildkit config input + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + foreach my $s (keys %{$::bldkit_config}) { + if (!defined($::buildkit_def{$s})) { next; } + if ($s eq 'kitpackage') { next; } + my $li = 0; + foreach my $se (@{ $::bldkit_config->{$s}{entries} }) { + $::kit_config->{$s}{entries}[$li]->{kitname} = $kitname; + + # copy all defined attrs over + foreach my $a (keys %{ $::buildkit_def{$s} }) { + if (($::buildkit_def{$s}{$a}->{cp_to_kitconfig} eq '1') && + (defined($se->{$a}))) { + if ($s eq 'kitcomponent') { + if ($a eq 'kitpkgdeps') { + my $value; + foreach my $d (split(/,/, $se->{$a})) { + $d =~ s/\s+//g; + $d =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + $value .= "$d,"; + } + $value =~ s/(\,)*$//; + $se->{$a} = $value; + } + } + $::kit_config->{$s}{entries}[$li]->{$a} = $se->{$a}; + } + + # cp_to_kitconfig=2 means copy the file to the new kit + # but only do the copy if this is a final kit build + if (($::buildkit_def{$s}{$a}->{cp_to_kitconfig} eq '2') && + (defined($se->{$a})) && + !$::HAVE_EXTERNAL_PKG && !$::HAVE_NON_NATIVE_PKGS) { + my $prefix = "$kitname"; + if ($s eq 'kitcomponent') { + $prefix = "$::bldkit_config->{$s}{entries}[$li]->{kitcompname}"; + if (($a eq 'postbootscripts') || + ($a eq 'genimage_postinstall')) { + $prefix = "KIT_" . $prefix; + } + if (!($::kit_config->{$s}{entries}[$li]->{$a} = + &cp_to_builddir($a, $se->{$a}, $::workdir . '/' . $::buildkit_def{$s}{$a}->{base_dir}, $prefix, $::bldkit_config->{$s}{entries}[$li]))) { + return 1; + } + } else { + if (!($::kit_config->{$s}{entries}[$li]->{$a} = + &cp_to_builddir($a, $se->{$a}, $::workdir . '/' . $::buildkit_def{$s}{$a}->{base_dir}, $prefix))) { + return 1; + } + } + } + } + + # Handle special attrs, these 3 attributes did not defined in the buildkit.conf, special cases. + if ($s eq 'kitrepo') { + $::kit_config->{$s}{entries}[$li]->{kitreponame} = + $se->{kitreponame}; + } elsif ($s eq 'kitcomponent') { + $::kit_config->{$s}{entries}[$li]->{kitcompname} = + $se->{kitcompname}; + $::kit_config->{$s}{entries}[$li]->{kitreponame} = + $se->{kitreponame}; + if (!$::PREREQUISITE and ($se->{ospkgdeps} || $se->{preinstall} || $se->{preupgrade} || $se->{preuninstall})) { + if ($debianflag) { + $::kit_config->{$s}{entries}[$li]->{prerequisite} = + "prep-" . $se->{basename}; + } else { + $::kit_config->{$s}{entries}[$li]->{prerequisite} = + "prep_" . $se->{basename}; + } + } + } + $li++; + } + } + + # Handle external packages + if ($::HAVE_EXTERNAL_PKG) { + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + if ($kp->{isexternalpkg} eq 'yes') { + my %current_entry; + $current_entry{filename} = $kp->{filename}; + $current_entry{kitreponame} = $kp->{kitreponame}; + push(@{ $::kit_config->{EXTERNALPKG}{'entries'} }, {%current_entry}); + } + } + } + + + # Handle non_native_pkgs + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if ($::NON_NATIVE_PKGS->{ $kc->{kitcompname} }) { + my @nativefiles; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + push(@nativefiles, $value); + } + } + + my %current_entry; + $current_entry{filename} = join ',', @nativefiles; + $current_entry{kitcompname} = $kc->{kitcompname}; + $current_entry{basename} = $kc->{basename}; + $current_entry{kitreponame} = $kc->{kitreponame}; + push(@{ $::kit_config->{NONNATIVEPKGS}{'entries'} }, {%current_entry}); + } + } + + + # Write Kit Config File + my @lines; + my $li = 0; + $lines[ $li++ ] = "# Kit Configuration File for $kitname generated by buildkit\n"; + $lines[ $li++ ] = "kitbuildinfo: \n"; + my $xCAT_buildkit_version = ''; + if ($debianflag) { + $xCAT_buildkit_version = `dpkg-query --show -f='\${Version}' xcat-buildkit`; + } + else { + $xCAT_buildkit_version = `rpm -q --qf \"%{VERSION}-%{RELEASE}\" xCAT-buildkit`; + } + $lines[ $li++ ] = " xCAT_version = $xCAT_buildkit_version \n"; + $lines[ $li++ ] = " build_date = " . localtime() . "\n"; + $lines[ $li++ ] = " kitframework = $::KITFRAMEWORK \n"; + $lines[ $li++ ] = " compatible_kitframeworks = $::COMPATIBLE_KITFRAMEWORKS \n"; + + foreach my $s ('kit', 'kitrepo', 'kitcomponent', 'EXTERNALPKG', 'NONNATIVEPKGS') { + foreach my $se (@{ $::kit_config->{$s}{entries} }) { + $lines[ $li++ ] = "$s: \n"; + foreach my $a (keys %{$se}) { + $lines[ $li++ ] = " $a = $se->{$a} \n"; + } + } + } + + if ((!-d $::deploy_dir) && (!mkpath($::deploy_dir))) { + print "Error creating build directory $::deploy_dir.\n"; + return; + } + + my $full_kit_conf = $::deploy_dir . "/" . $::kit_conf; + my $NCF; + unless (open($NCF, ">$full_kit_conf")) { + return 1; + } + if ($::VERBOSE) { + print "Wrote new kit configuration file $full_kit_conf \n"; + } + print $NCF @lines; + close($NCF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 cp_to_builddir + + Copy specified files into the build directory renaming as indicated + and substituting strings if needed + +=cut + +#----------------------------------------------------------------------------- +sub cp_to_builddir +{ + my $type = shift; + my $files = shift; + my $from_dir = shift; + my $prefix = shift; + my $kitcomp = shift; + + my $copied_files; + my $other_files = $::deploy_dir . "/other_files"; + if ((!-d $other_files) && (!mkpath($other_files))) { + print "Error creating build directory $other_files.\n"; + return; + } + foreach my $file (split(/\,/, $files)) { + $file =~ s/\s+//g; + my $from_file = $from_dir . "/" . $file; + my $from_file_base = basename($file); + my $to_file_base = $prefix . "_" . $from_file_base; + my $to_file = $other_files . "/" . $to_file_base; + + # Read in the file + my $FF; + unless (open($FF, "<", $from_file)) { + print "The Kit file $from_file could not be read. \n"; + return 1; + } + my @lines = <$FF>; + for (@lines) { +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitname}/g; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{basename}/g; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{version}/g; +s/<<>>/$::bldkit_config->{kit}{entries}[0]->{release}/g; + if (defined($kitcomp)) { +s/<<>>/$kitcomp->{kitcompname}/g; +s/<<>>/$kitcomp->{basename}/g; +s/<<>>/$kitcomp->{version}/g; +s/<<>>/$kitcomp->{release}/g; + } + } + + # Write the file back out + my $TF; + unless (open($TF, ">$to_file")) { + print "Error copying file $from_file to build directory $other_files \n"; + return 1; + } + if ($::VERBOSE) { + print "Copied $from_file to $to_file replacing kit and kitcomponent strings as needed. \n"; + } + print $TF @lines; + close($TF); + + $copied_files .= ",$to_file_base"; + + if (($type eq 'postbootscripts') || + ($type eq 'genimage_postinstall')) { + system("chmod 755 $to_file"); + } + } + $copied_files =~ s/^\,//; + return $copied_files; +} + +#----------------------------------------------------------------------------- + +=head3 create_builddir + + Create the build directory and copy in all required files for building + the kit tar file. + +=cut + +#----------------------------------------------------------------------------- +sub create_builddir +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Note: + # - repos already created and validated + # - kit.conf file already created + # - exlists, postbootscripts, and deployparams already copied + + # copy plugins to build dir and edit to insert correct plugin and kit names + my $plugin_dir = $::deploy_dir . "/plugins"; + if (-d "$::workdir/plugins") { + if ((!-d $plugin_dir) && (!mkpath($plugin_dir))) { + print "Error creating build directory $plugin_dir.\n"; + return 1; + } + + foreach my $plugin (<$::workdir/plugins/*.pm>) { + my $plugin_base = basename($plugin); + my $mod_kitname = $kitname; + $mod_kitname =~ s/\-/\_/g; + $mod_kitname =~ s/\./\_/g; + my $to_plugin = $plugin_dir . "/" . $mod_kitname . "_" . $plugin_base; + + if (system("cp -fp $plugin $to_plugin")) { + + # non-zero return from system call + print "Error copying plugin file $plugin to build directory $plugin_dir \n"; + return 1; + } + if (&edit_plugin($to_plugin)) { return 1; } + } + } + + # copy docs to build dir + if (-d "$::workdir/docs") { + if (system("cp -fRp $::workdir/docs $::deploy_dir")) { + + # non-zero return from system call + print "Error copying doc files $::workdir/docs to build directory $::deploy_dir \n"; + return 1; + } + } + + # Edit deploy params file to make sure correct format for xCAT + if (defined($::kit_config->{kit}{entries}[0]->{kitdeployparams})) { + my $kd_file = $::deploy_dir . "/other_files/" . $::kit_config->{kit}{entries}[0]->{kitdeployparams}; + if (&edit_deployparams($kd_file)) { return 1; } + } + + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + + # Copy the kitcomponent meta rpm spec if there is external non_native_pkgs. + if ($debianflag) { + foreach my $comp (keys %{$::NON_NATIVE_PKGS}) { + my $kitrepo; + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if ($comp eq $kc->{kitcompname}) { + $kitrepo = $kc->{kitreponame} + } + } + mkpath("$::deploy_dir/tmp/"); + my $cmd = "cp -fRP $::workdir/debbuild/$comp $::deploy_dir/tmp/$comp"; + if (system("$cmd")) { + print "Error copying kitcomponent meta debian build file $::workdir/debbuild/$comp to build directory $::deploy_dir \n"; + return 1; + } + } + } + + # Copy over the original buildkit.conf file and input files + # to help make addpkgs processing easier later + mkpath("$::deploy_dir/build_input/"); + if (system("cp -fp $::full_buildkit_conf $::deploy_dir/build_input")) { + + # non-zero return from system call + print "Error copying buildkit config file $::full_buildkit_conf to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 create_PARTIAL_builddir + + Create the build directory for a PARTIAL kit (needs external pkgs) + and copy in all required files for building the kit tar file. + This includes most build input without editting files since + they will need to be generated at addpkgs time. + +=cut + +#----------------------------------------------------------------------------- +sub create_PARTIAL_builddir +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Note: + # - repos already created and validated + # - kit.conf file already created + # - exlists, postbootscripts, and deployparams already copied + + # copy docs to build dir + if (-d "$::workdir/docs") { + if (system("cp -fRp $::workdir/docs $::deploy_dir")) { + + # non-zero return from system call + print "Error copying doc files $::workdir/docs to build directory $::deploy_dir \n"; + return 1; + } + } + + # Copy over the original buildkit.conf file and input files + # to help make addpkgs processing easier later + mkpath("$::deploy_dir/build_input/"); + if (system("cp -fp $::full_buildkit_conf $::deploy_dir/build_input")) { + + # non-zero return from system call + print "Error copying buildkit config file $::full_buildkit_conf to build directory $::deploy_dir/build_input \n"; + return 1; + } + if (-d "$::workdir/other_files") { + if (system("cp -fpR $::workdir/other_files $::deploy_dir/build_input")) { + + # non-zero return from system call + print "Error copying $::workdir/otherfiles to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + if (-d "$::workdir/plugins") { + if (system("cp -fpR $::workdir/plugins $::deploy_dir/build_input")) { + + # non-zero return from system call + print "Error copying $::workdir/plugins to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + if (-d "$::workdir/scripts") { + if (system("cp -fpR $::workdir/scripts $::deploy_dir/build_input")) { + + # non-zero return from system call + print "Error copying $::workdir/scripts to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + + # Copy over any provided non-native packages + my $to_source_dir = "$::deploy_dir/build_input/source_packages"; + mkpath("$to_source_dir"); + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if (defined($kc->{non_native_pkgs})) { + my $sourcedir = $::workdir . "/source_packages"; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my $pkg_file; + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + next; + } else { + $pkg_file = $key; + } + + my $cmd = "cp -p $sourcedir/$pkg_file $to_source_dir"; + if (system($cmd)) { + print "Error copying non-native package file $sourcedir/$pkg_file to $to_source_dir \n"; + return 1; + } + } + } + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_deployparams + + Edit the kit deployment parameters to make sure it has correct + syntax for xCAT otherpkglist support + + +=cut + +#----------------------------------------------------------------------------- +sub edit_deployparams +{ + my $file = shift; + my $validate_only = shift; + + # read in the file + my $DF; + unless (open($DF, "<", $file)) { + print "The Kit deployment parameters file $file could not be read. \n"; + return 1; + } + my @lines = <$DF>; + close $DF; + + # Edit the files + my $changed = 0; + my @new_lines; + my $ln = 0; + foreach my $l (@lines) { + $ln++; + + # skip blank lines + if ($l =~ /^\s*$/) { + push(@new_lines, $l); + next; + } + + # #ENV lines + $l =~ s/^\s+//; # compress leading blanks + if ($l =~ /^\#ENV\:/) { + if (!($l =~ /\#\s*$/)) { + chomp $l; + $l .= "#\n"; + $changed = 1; + } + push(@new_lines, $l); + next; + } + + # skip all other comments + if ($l =~ /^\s*#/) { + push(@new_lines, $l); + next; + } + + # Add #ENV if not specified + if ($l =~ /^\w*\s*\=/) { + chomp $l; + $l = "#ENV: $l #"; + $changed = 1; + push(@new_lines, $l); + next; + } + + # Syntax error + print "Syntax error in kit deployment parameters file $file \n"; + print "line $ln: \n"; + print "$l \n"; + return 1; + } + + # Write the file back out + if ($changed && !$validate_only) { + my $NDF; + unless (open($NDF, ">$file")) { + return 1; + } + if ($::VERBOSE) { + print "Editted kit deployment parameters file $file \n"; + } + print $NDF @lines; + close($NDF); + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_plugin + + Edit the kit plugin file to insert the full kit name + + +=cut + +#----------------------------------------------------------------------------- +sub edit_plugin +{ + my $file = shift; + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # convert dashes to underscore since the kitname is used as perl pkg names + # in the plugin and this causes perl syntax errors + my $mod_kitname = $kitname; + $mod_kitname =~ s/\-/\_/g; + $mod_kitname =~ s/\./\_/g; + + # read in the file + my $PF; + unless (open($PF, "<", $file)) { + print "The Kit plugin file $file could not be read. \n"; + return 1; + } + my @lines = <$PF>; + close $PF; + + for (@lines) { + s/<<>>/$kitname/g; + s/<<>>/$mod_kitname/g; + } + + # Write the plugin back out + my $NPF; + unless (open($NPF, ">$file")) { + return 1; + } + if ($::VERBOSE) { + print "Inserted kitname values into $file \n"; + } + print $NPF @lines; + close($NPF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_addpkgs + + buildkit addpkgs + +=cut + +#----------------------------------------------------------------------------- +sub kit_addpkgs +{ + # add RPM pkgs to an existing kit tarfile + my $kittarfile = $::KIT_ADDPKGS; + my $kitbfname = basename($kittarfile); + $kitbfname =~ s/.tar.bz2$//; + $kitbfname =~ s/.NEED_PRODUCT_PKGS$//; + my $tmpdir_base = "/tmp/$kitbfname"; + + # - could be list of pkgdir s + my @pkgdirlist = split(",", $::PKGDIR); + + print "$tmpdir_base\n"; + # Cleanup - should have been removed when last command ran + # - but just in case + system("rm -Rf $tmpdir_base"); + + # the tar file may not be in the current dir + $kittarfile = "$::workdir/$kittarfile"; + + if (!(-r $kittarfile)) { + print "The Kit tar file $kittarfile could not be read. \n"; + return 1; + } + $kittarfile = abs_path($kittarfile); + + foreach my $rpmdir (@pkgdirlist) { + if (!(-d $rpmdir)) { + print "The package directory $rpmdir could not be read. \n"; + return 1; + } + } + + # Create work directory + if ((!-d $tmpdir_base) && (!mkpath($tmpdir_base))) { + print "Error creating temporary work directory $tmpdir_base\n"; + return 1; + } + + print "Extracting tar file $kittarfile. Please wait.\n"; + + if (system("cd $tmpdir_base; tar -jxf $kittarfile ")) { + print "Error extracting tarfile $kittarfile \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + + my $tmp_kit_conf = `find $tmpdir_base -name kit.conf`; + chomp($tmp_kit_conf); + my $tmpdir = dirname($tmp_kit_conf); + + # read in the file + my $CKF; + unless (open($CKF, "<", $tmp_kit_conf)) { + print "The Kit configuration file $tmp_kit_conf could not be read or was not included in the kit tar file. \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + my @lines = <$CKF>; + close $CKF; + + $::PREREQUISITE = 1; + foreach my $l (@lines) { + + # skip blank and comment lines + if ($l =~ /^\s*$/ || $l =~ /^\s*#/) { + next; + } + if ($l =~ /prerequisite/) { + $::PREREQUISITE = 0; + } + } + + # + # check contents of kit.conf to make sure the framework + # is compatible with this codes framework + $::kitframework = &check_framework(\@lines); + if (!defined($::kitframework)) { + return 1; + } + + # if this in not a partial kit then the framework must be 2 or greater + my $kit_name = basename($kittarfile); + if ((!($kit_name =~ /NEED_PRODUCT_PKGS/)) && ($::kitframework < 2)) { + print "This kit cannot be updated. To update a complete kit the kit framework\n value must be greater than or equal to 2. You can use the\n\t\'lskit -F \' \ncommand to check the framework value of the kit.\n"; + return 1; + } + + ### Check if this is a new partial kit built with xCAT 2.8.1 or newer + if (-d "$tmpdir/build_input") { + system("mv $tmpdir/build_input $tmpdir_base"); + return &NEW_kit_addpkgs($tmpdir_base, $tmpdir); + } + + ### OLD KITS BUILT PRIOR TO xCAT 2.8.1 + ### this code will eventually become obsolete and should be removed + ### do not update + if (defined($::KITVERSION) || defined($::KITRELEASE)) { + print "kitversion and kitrelease substitution is not supported for this incomplete kit. Run \"buildkit addpkgs\" without the \"-k|--kitversion\" and \"-r| --kitrelease\" options. \n"; + exit 1; + } + + my $rpmdir = $::PKGDIR; + + my $ext_filename = ''; + my $ext_reponames = ''; + my $non_native_filename = ''; + my $non_native_kitcompname = ''; + my $non_native_basename = ''; + my $non_native_kitreponame = ''; + my %create_repodata_list; + my @new_lines; + my $section = ''; + my $kitname = ''; + my $kitbasename = ''; + my $kitversion = ''; + my $kitostype = ''; + + foreach my $l (@lines) { + + # skip blank and comment lines + if ($l =~ /^\s*$/ || $l =~ /^\s*#/) { + push(@new_lines, $l); + next; + } + + # new section? + if ($l =~ /^\s*(\w+)\s*:/) { + $section = $1; + if ($section eq 'EXTERNALPKG') { + $ext_filename = ''; + $ext_reponames = ''; + next; + } + if ($section eq 'NONNATIVEPKGS') { + $non_native_filename = ''; + $non_native_kitcompname = ''; + $non_native_basename = ''; + $non_native_kitreponame = ''; + next; + } + push(@new_lines, $l); + next; + } + if ($l =~ /^\s*(\w+)\s*=\s*(.*)\s*/) { + my $attr = $1; + my $val = $2; + my $orig_attr = $attr; + my $orig_val = $val; + $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 'kit') { + if ($attr eq 'basename') { $kitbasename = $val; } + if ($attr eq 'version') { $kitversion = $val; } + if ($attr eq 'ostype') { $kitostype = $val; } + if (($kitbasename ne '') && ($kitversion ne '') && + ($kitostype ne '')) { + $kitname = "$kitbasename-$kitversion-$kitostype"; + } + } + + if ($section eq 'EXTERNALPKG') { + if ($attr eq 'filename') { + $ext_filename = $val; + } elsif ($attr eq 'kitreponame') { + $ext_reponames = $val; + } else { + next; + } + if (($ext_filename ne '') && ($ext_reponames ne '')) { + my $fromfile = $rpmdir . "/" . $ext_filename; + if (system("ls $fromfile > /dev/null")) { + print "The product package file $ext_filename could not be read from the package directory $rpmdir. \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + foreach my $repo (split(/,/, $ext_reponames)) { + my $repodir = $tmpdir . "/repos/" . $repo; + if (!-d ($repodir) && (!mkpath($repodir))) { + print "Error creating repository directory $repodir\n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + if (system("cp -fp $fromfile $repodir")) { + print "Error copying package file $fromfile to $repodir \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + $create_repodata_list{$repodir} = 1; + } + } + next; + } + + if ($section eq 'NONNATIVEPKGS') { + if ($attr eq 'filename') { + $non_native_filename = $val; + } elsif ($attr eq 'kitcompname') { + $non_native_kitcompname = $val; + } elsif ($attr eq 'basename') { + $non_native_basename = $val; + } elsif ($attr eq 'kitreponame') { + $non_native_kitreponame = $val; + } else { + next; + } + if (($non_native_filename ne '') + && ($non_native_kitcompname ne '') + && ($non_native_basename ne '') + && ($non_native_kitreponame ne '')) { + + #find out the useful dir + my $tdir = $tmpdir . "/tmp/"; + my $source_dir = "$tdir/$non_native_kitcompname"; + my $spec = "$tdir/$non_native_kitcompname.spec"; + if (!-d "$tdir" or !-d "$source_dir") { + print "Error open kitcomponent rpm build direcotry $tdir or $tdir/$non_native_kitcompname \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + + #copy the nan_native_pkgs to the source dir + foreach my $tepmfilename (split(/,/, $non_native_filename)) { + + #the $non_native_filename may contain several pkgs, can check and copy at the same time + my $fromfile = $rpmdir . "/" . $tepmfilename; + if (system("ls $fromfile > /dev/null")) { + print "The product package file $non_native_filename could not be read from the package directory $rpmdir. \n"; + system("rm -Rf $tmpdir_base"); + return 1; + } + if (system("cp -fp $fromfile $tdir/$non_native_kitcompname")) { + print "Error copying package file $fromfile to $tdir/$non_native_kitcompname \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + } + + #for debian/ubuntu + my $repodir = $tmpdir . "/repos/" . $non_native_kitreponame; + if ($debianflag) { + my $debbuildcmd = "cd $source_dir;dpkg-buildpackage $dpkg_flag"; + if (system($debbuildcmd)) { + print "error running debian build cmd for kit component $non_native_basename meta package.\n"; + return 1; + } + my @debs = `find $tdir -maxdepth 1 -name "*.deb"`; + foreach my $debname (@debs) { + chomp($debname); + if (system("mv -f $debname $repodir")) { + print "Error copying package $debname to build repo directory $repodir. \n"; + return 1; + } + } + } + else { + if (!-r "$spec") { + print "Error open kitcomponent rpm build spec $tdir/$non_native_kitcompname.spec \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + my $rpmbuild_dir = $tmpdir . "/rpmbuild"; + my $cmd = "rm -Rf $rpmbuild_dir"; + system($cmd); + + my $avoiderr = $rpmbuild_dir . "/BUILDROOT/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir . "/RPMS/noarch/"; + mkpath($avoiderr); + + unless (open(SF, "<", $spec)) { + print "Error attempting to open spec $spec of kitcomponent $non_native_basename. \n"; + return 1; + } + + mkpath("$rpmbuild_dir/SOURCES"); + $cmd = "cd $source_dir/..;mv $non_native_kitcompname $non_native_basename; tar -czf $rpmbuild_dir/SOURCES/$non_native_basename.tar.gz $non_native_basename;mv $non_native_basename $non_native_kitcompname;"; + if (system($cmd)) { + print "Error creating tarfile $rpmbuild_dir/SOURCES/$non_native_basename.tar from $source_dir/*"; + return 1; + } + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $spec"; + if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; + } + if (system($rpmbuild_cmd)) { + print "Error running rpmbuild command for kit component $non_native_basename meta package\n"; + return 1; + } + + # Copy the built meta rpm to repo + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if (system("cp -fp $rpm $repodir")) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + } + $create_repodata_list{$repodir} = 1; + } + next; + } + + push(@new_lines, $l); + } + } + + # Re-write kit.conf with EXTERNALPKG and NONNATIVEPKGS sections removed + my $NCF; + unless (open($NCF, ">$tmp_kit_conf")) { + return 1; + } + print $NCF @new_lines; + close($NCF); + + # Clean up RPMBUILD and tmp in kit directory + my $cmd = "rm -Rf $tmpdir/tmp"; + system("$cmd"); + unless ($debianflag) { + $cmd = "rm -Rf $tmpdir/rpmbuild"; + system("$cmd"); + } + + # Run createrepo for each updated directory + foreach my $repo (keys(%create_repodata_list)) { + my $createrepocmd = ''; + if ($debianflag) { + $createrepocmd = "cd $repo;dpkg-scanpackages . > Packages"; + } + else { + $createrepocmd = "createrepo $repo"; + } + if (system($createrepocmd )) { + print "Error running $createrepocmd. \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + } + + # Create new tar file in current directory + my $new_tarfile = $::workdir . '/' . $kitbfname . '.tar.bz2'; + if (system("cd $tmpdir; cd ..; tar -cjhf $new_tarfile $kitname/*")) { + print "Error building tarfile $new_tarfile \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + print "Kit tar file $new_tarfile successfully built \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 NEW_kit_addpkgs + + buildkit addpkgs + +=cut + +#----------------------------------------------------------------------------- +sub NEW_kit_addpkgs +{ + # add RPM pkgs to an existing kit tarfile + my $tmpdir_base = shift; + my $tmpdir = shift; + + # - could be list of pkgdir dirs + my @pkgdirlist = split(",", $::PKGDIR); + + $::NEW_PARTIAL_KIT = 1; + $::workdir = "$tmpdir_base/build_input"; + $::full_buildkit_conf = $::workdir . "/" . $::buildkit_conf; + $::deploy_dir = $tmpdir_base; #kitname appended by validate_bldkitconf routine + + my $tmp_buildkit_conf = `find $tmpdir_base -name $::buildkit_conf`; + + chomp($tmp_buildkit_conf); + if ($tmp_buildkit_conf ne $::full_buildkit_conf) { + print "$tmp_buildkit_conf should match $::full_buildkit_conf .... error??? \n"; + } + + my $loadrc = &load_bldkitconf($tmp_buildkit_conf); + if ($loadrc != 0) { + print "Error reading buildkit config file $tmp_buildkit_conf \n"; + return 1; + } + + if (defined($::KITVERSION)) { + $::bldkit_config->{kit}{entries}[0]->{version} = $::KITVERSION; + } + if (defined($::KITRELEASE)) { + $::bldkit_config->{kit}{entries}[0]->{release} = $::KITRELEASE; + } + + my $chkrc = &validate_bldkitconf(); + if ($chkrc != 0) { + print "Error validating buildkit config file $tmp_buildkit_conf \n"; + return 1; + } + + if ($tmpdir ne $::deploy_dir) { + if (system("mv $tmpdir $::deploy_dir ")) { + print "Error moving $tmpdir to $::deploy_dir \n"; + return 1; + } + } + $::build_dir = $::deploy_dir; + $::base_repodir = "$::deploy_dir/repos"; + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Handle external packages + if ($::HAVE_EXTERNAL_PKG) { + foreach my $kp (@{ $::bldkit_config->{kitpackage}{entries} }) { + if ($kp->{isexternalpkg} eq 'yes') { + my $ext_filename = $kp->{filename}; + my $ext_reponames = $kp->{kitreponame}; + my $files; + if ($debianflag) { + $files = xCAT::BuildKitUtils->find_latest_pkg_deb(\@pkgdirlist, $ext_filename); + } + else { + $files = xCAT::BuildKitUtils->find_latest_pkg(\@pkgdirlist, $ext_filename); + } + if (!defined($files)) { + print "Error: The product package file $ext_filename was not found in the package directory(s) @pkgdirlist.\n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + + my @fromfiles = @$files; + + foreach my $repo (split(/,/, $ext_reponames)) { + my $repodir = $::base_repodir . "/" . $repo; + if (!-d ($repodir) && (!mkpath($repodir))) { + print "Error creating repository directory $repodir\n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + + foreach my $fromfile (@fromfiles) { + if (system("cp -fp $fromfile $repodir")) { + print "Error copying package file $fromfile to $repodir \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + return 1; + } + } + if ($::VERBOSE) { + print "Copied @fromfiles\n to $repodir\n"; + } + } + } + } + } + + # Handle non_native_pkgs + # Comma-separated list of non-native package + # paths that will be included as files in this kit + # component. + # these are not RPMs! + my $to_source_dir = "$::workdir/source_packages"; + mkpath("$to_source_dir"); + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + if ($::NON_NATIVE_PKGS->{ $kc->{kitcompname} }) { + my @nativefiles; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my ($key, $value) = split /:/, $pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + + #the $non_native_filename may contain several pkgs, can check and copy at the same time + foreach my $nnpkg (split(/,/, $value)) { + my $found = 0; + foreach my $pdir (@pkgdirlist) { + my $fromfile = $pdir . "/" . $nnpkg; + if (system("ls $fromfile > /dev/null")) { + next; + } else { + $found++; + if (system("cp -fp $fromfile $to_source_dir")) { + print "Error copying package file $fromfile to $to_source_dir \n"; + + # Cleanup + system("rm -Rf $tmpdir_base"); + next; + } else { + if ($::VERBOSE) { + print "Copied $fromfile to $to_source_dir\n"; + } + } + } + } + if (!$found) { + print "Could not find $nnpkg.\n"; + } + } + } + } + } + } + + # Turn off external pkg flags and build the kit component meta pkgs + $::HAVE_EXTERNAL_PKG = ''; + $::HAVE_NON_NATIVE_PKGS = ''; + $::NON_NATIVE_PKGS = {}; + + foreach my $kc (@{ $::bldkit_config->{kitcomponent}{entries} }) { + my $rc = 0; + if ($debianflag) { + $rc = &build_kitcomp_debian($kc); + } + else { + $rc = &build_kitcomp($kc); + } + if ($rc) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + + # run createrepo + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) { + my $repodir = "$::base_repodir/$kr->{kitreponame}"; + if (-d $repodir) { + my $cr_opts = ''; + if (($kr->{osbasename} =~ m/rh|RH|centos|CentOS/) && + ($kr->{osmajorversion} eq '5')) { + $cr_opts = '-s md5'; + } + my $repocmd = ""; + if ($debianflag) { + $repocmd = "cd $repodir;dpkg-scanpackages . > Packages"; + } + else { + $repocmd = "createrepo $cr_opts $repodir"; + } + if (system($repocmd )) { + print "Error building the repository meta-data with the createrepo command \n"; + return 1; + } + } + } + + + #When using -k -r, there are useless repodir + #delete useless repo dir + my $kitrepodirby = $::base_repodir; + my $cmdby = "/bin/ls $kitrepodirby 2>/dev/null"; + my $outputby = `$cmdby`; + my @allrepolist = split(/\n/, $outputby); + my @dellist; + + foreach my $reponame (@allrepolist) + { + my $match = 0; + foreach my $kr (@{ $::bldkit_config->{kitrepo}{entries} }) + { + my $repodirname = "$kr->{kitreponame}"; + + if (${repodirname} eq ${reponame}) + { + ${match}++; + } + } + if (${match} == 0) + { + push(@dellist, $reponame); + } + } + + foreach my $del (@dellist) + { + my $delrepodir = $::base_repodir . "/" . $del; + if (-d $delrepodir) + { + my $delcmd = "rm -Rf $delrepodir"; + if (system($delcmd)) + { + print "Failed to delete useless repo directory \n"; + } + } + } + + + # Build the full kit tar file + my $buildtar_rc = &kit_buildtar; + + # clean out the tmp dir + system("rm -Rf $tmpdir_base"); + + if ($buildtar_rc) { + print "Error building full kit tarfile \n"; + return 1; + } + return 0; +} + +#----------------------------------------------------------------------------- + +=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 - kit framework value + undef - error + + Example: + my $kitframework = &check_framework(\@lines); + +=cut + +#----------------------------------------------------------------------------- +sub check_framework +{ + my $lines = shift; + + my @kitconflines = @$lines; + + my $kitbasename; + my $kitcompat; + my $kitframework; + 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 ($attr eq 'kitframework') { + $kitframework = $val; + } + } + if ($section eq 'kit') { + if ($attr eq 'basename') { $kitbasename = $val; } + } + } + } + + if (!$kitcompat) { + print "Warning: Could not determine the kit compatible framework values for \'$kitbasename\' from the kit.conf file. Continuing for now.\n"; + 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 $kitframework; + } + } + } + print "Error: 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\'\n"; + return undef; +} diff --git a/xCAT-buildkit/xCAT-buildkit.spec b/xCAT-buildkit/xCAT-buildkit.spec index 2b7d550a4..8531dac38 100644 --- a/xCAT-buildkit/xCAT-buildkit.spec +++ b/xCAT-buildkit/xCAT-buildkit.spec @@ -35,6 +35,8 @@ xCAT-buildkit provides the buildkit tool and sample kit files to build an xCAT k # Convert pods to man pages and html pages mkdir -p share/man/man1 mkdir -p share/doc/man1 +pod2man pods/man1/buildkit.1.pod > share/man/man1/buildkit.1 +pod2html pods/man1/buildkit.1.pod > share/doc/man1/buildkit.1.html %install rm -rf $RPM_BUILD_ROOT @@ -44,18 +46,30 @@ mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1 mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 +# These were built dynamically in the build phase +cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1 +chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/* +cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 +chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/* + %ifos linux cp -aR share/xcat/kits/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits/ +#chmod -R 644 $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits/* find $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits -type d -exec chmod 755 {} \; find $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits -type f -exec chmod 644 {} \; cp -a lib/perl/xCAT/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT +#chmod -R 644 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT/* find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT -type d -exec chmod 755 {} \; find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT -type f -exec chmod 644 {} \; +cp -a bin/* $RPM_BUILD_ROOT/%{prefix}/bin/ +chmod -R 755 $RPM_BUILD_ROOT/%{prefix}/bin/* %else cp -hpR share/xcat/kits/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits/ chmod -R 644 $RPM_BUILD_ROOT/%{prefix}/share/xcat/kits/* cp -hpR lib/perl/xCAT/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT/ chmod -R 755 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT/* +cp -hpR bin/* $RPM_BUILD_ROOT/%{prefix}/bin/ +chmod -R 755 $RPM_BUILD_ROOT/%{prefix}/bin/* %endif mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT-buildkit