#!/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, ) ) { &usage; exit(1); } # display the usage if -h or --help is specified if ($::HELP) { &usage; exit(0); } my $debianflag = 0; my $tempstring = xCAT::BuildKitUtils->osver(); if ( $tempstring =~ /debian/ || $tempstring =~ /ubuntu/ ){ $debianflag = 1; } # 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='\${PackageSpec}: \${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 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 metapackage for $kc->{basename} \n";} if (&build_kitcomp_debian($kc)) { print "Error building kitcomponent metapackage for $kc->{basename} \n"; return 1; } } if ( system("dpkg-scanpackages $repodir > $repodir/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"; 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; } } print "Creating tar file $tarfile.\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`; my $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/; } } # 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})) { 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 .= '-'.$::bldkit_config->{kit}{entries}[0]->{osminorversion}; } 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})){ 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 .= '.'.$kr->{osminorversion}; } 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}) ) { $compname .= '.'.$repo{osminorversion}; } $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); $osinfo =~ s/\,//; my $repo_osinfo = "$repo->{osbasename}$repo->{osmajorversion}"; if (defined($repo->{osminorversion})){ $repo_osinfo .= ".$repo->{osminorversion}"; } $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 ( ($repo->{osminorversion} 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} || $comp->{preuninstall} ) { 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 (defined($comp->{preuninstall})) { $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); } } if ( $level eq 'METARPM' || $level eq 'ALL' ) { 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/<<>>//; 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); #Create debian directory for this kit component if ( &gen_kitcomp_debdir($comp,\%repo) ) { 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;dch -v $compversion -b -c debian/changelog $buildstring;dpkg-buildpackage -uc -us"; if ( !$::NON_NATIVE_PKGS->{$comp->{kitcompname}} ) { if ( system($debianbuildcmd) ) { print "Error running \"dpkg-buildpackage -uc -us\" 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 =cut #----------------------------------------------------------------------------- sub gen_kitcomp_debdir{ my $comp = shift; my $repo = 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 (defined($comp->{preinstall})) { $prescript = &load_script("$scriptdir$comp->{preinstall}"); } if (defined($comp->{postinstall})) { $postscript = &load_script("$scriptdir$comp->{postinstall}"); } if (defined($comp->{preupgrade})) { $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); } if (defined($comp->{postupgrade})) { $postupscript = &load_script("$scriptdir$comp->{postupgrade}"); } if (defined($comp->{preuninstall})) { $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); } 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"; } #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); for(@lines) { chomp; s/<<>>/$comp->{basename}/; s/<<>>/$comp->{ospkgdeps}/; s/<<>>/$comp->{kitpkgdeps}/; 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}) ) { $::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); # 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 -uc -us"; 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 = 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; } } } # 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; }