2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-06-16 08:30:47 +00:00

fix: Fix build with mock

Add buildrpms.pl to build RPMs in parallel using mock
Add xCAT-buildkit to the build list
Fix build dependency in xCAT-buildkit.spec
Add fallback in /etc/init.d/xcatd for /etc/rc.d/init.d/functions

Signed-off-by: Daniel Hilst Selli <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst Selli
2025-12-03 15:50:05 -03:00
parent 619c00ee54
commit bfe52d03a7
4 changed files with 279 additions and 170 deletions
+270
View File
@@ -0,0 +1,270 @@
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
use File::Copy ();
use File::Slurper qw(read_text write_text);
use Parallel::ForkManager;
use Getopt::Long qw(GetOptions);
use Cwd qw();
my $SOURCES = "$ENV{HOME}/rpmbuild/SOURCES";
my $VERSION = read_text("Version");
my $RELEASE = read_text("Release");
my $GITINFO = read_text("Gitinfo");
my $PWD = Cwd::cwd();
chomp($VERSION);
chomp($RELEASE);
chomp($GITINFO);
my @PACKAGES = qw(
perl-xCAT
xCAT
xCAT-buildkit
xCAT-client
xCAT-confluent
xCAT-openbmc-py
xCAT-probe
xCAT-rmc
xCAT-server
xCAT-test
xCAT-vlan);
my @TARGETS = qw(
rhel+epel-8-x86_64
rhel+epel-9-x86_64
rhel+epel-10-x86_64);
my $NPROC = `nproc --all`;
# cp $src, $dst copies $src to $dst or aborts with an error message
sub cp {
my ($src, $dst) = @_;
File::Copy::copy($src, $dst) or die "copy $src, $dst failed: $!";
}
# sed { s/foo/bar/ } $filepath applies s/foo/bar/ to the file at $filepath
sub sed (&$) {
my ($block, $path) = @_;
my $content = read_text($path);
local $_ = $content;
$block->();
$content = $_;
write_text($path, $content);
}
# product(\@A, \@B) returns the catersian product of \@A and \@B
sub product {
my ($a, $b) = @_;
return map {
my $x = $_;
map [ $x, $_ ], @$b;
} @$a
}
sub createmockconfig {
my ($pkg, $target) = @_;
my $chroot = "$pkg-$target";
my $cfgfile = "/etc/mock/$chroot.cfg";
return if -f $cfgfile;
cp "/etc/mock/$target.cfg", $cfgfile;
my $contents = read_text($cfgfile);
$contents =~ s/config_opts\['root'\]\s\+=.*/config_opts['root'] = \"$chroot\"/;
if ($pkg eq "perl-xCAT") {
# perl-generators is required for having perl(xCAT::...) symbols
# exported by the RPM
$contents .= "config_opts['chroot_additional_packages'] = 'perl-generators'\n";
}
write_text($cfgfile, $contents);
}
sub buildsources {
my ($pkg, $target) = @_;
if ($pkg eq "xCAT") {
my @files = ("bmcsetup", "getipmi");
for my $f (@files) {
cp "xCAT-genesis-scripts/usr/bin/$f", "$pkg/postscripts/$f";
sed { s/xcat.genesis.$f/$f/ } "${pkg}/postscripts/$f";
}
qx {bash -c '
cd xCAT
tar --exclude upflag -czf $SOURCES/postscripts.tar.gz postscripts LICENSE.html
tar -czf $SOURCES/prescripts.tar.gz prescripts
tar -czf $SOURCES/templates.tar.gz templates
tar -czf $SOURCES/winpostscripts.tar.gz winpostscripts
tar -czf $SOURCES/etc.tar.gz etc
cp xcat.conf $SOURCES
cp xcat.conf.apach24 $SOURCES
cp xCATMN $SOURCES
'};
} else {
`tar -czf "$SOURCES/$pkg-$VERSION.tar.gz" $pkg`;
}
}
sub buildspkgs {
my ($pkg, $target, $optsref) = @_;
my $chroot = "$pkg-$target";
my $diskcache = "dist/$target/srpms/$pkg-$VERSION-$RELEASE.src.rpm";
return if -f $diskcache and not $optsref->{force};
my @opts;
push @opts, "--quiet" unless $optsref->{verbose};
say "Building $diskcache";
`mock -r $chroot \\
-N \\
@{[ join " ", @opts ]} \\
--define "version $VERSION" \\
--define "release $RELEASE" \\
--define "gitinfo $GITINFO" \\
--buildsrpm \\
--spec $pkg/$pkg.spec \\
--sources $SOURCES \\
--resultdir "dist/$target/srpms/"`;
}
sub buildpkgs {
my ($pkg, $target, $optsref) = @_;
my $chroot = "$pkg-$target";
my $targetarch = (split /-/, $target, 3)[2];
my $arch = $pkg eq "xCAT" ? $targetarch : "noarch";
my $diskcache = "dist/$target/rpms/$pkg-$VERSION-$RELEASE.$arch.rpm";
return if -f $diskcache and not $optsref->{force};
my @opts;
push @opts, "--quiet" unless $optsref->{verbose};
say "Building $diskcache";
`mock -r $chroot \\
-N \\
@{[ join " ", @opts ]} \\
--define "version $VERSION" \\
--define "release $RELEASE" \\
--define "gitinfo $GITINFO" \\
--resultdir "dist/$target/rpms/" \\
--rebuild dist/$target/srpms/$pkg-${VERSION}-${RELEASE}.src.rpm`;
}
sub buildall {
my ($pkg, $target, $optsref) = @_;
createmockconfig($pkg, $target, $optsref);
buildsources($pkg, $target, $optsref);
buildspkgs($pkg, $target, $optsref);
buildpkgs($pkg, $target, $optsref);
}
sub configure_nginx {
my ($args) = @_;
my @targets = $args->{targets}->@*;
my $deps = $args->{deps};
my $conf = <<"EOF";
server {
listen 8080;
listen [::]:8080;
EOF
for my $target (@targets) {
my $fullpath = "$PWD/dist/$target/rpms";
$conf .= <<"EOF";
location /$target/ {
alias $fullpath/;
autoindex on;
index off;
allow all;
}
EOF
}
# TODO:I need one xcat-dep for each target
$conf .= <<"EOF";
location /xcat-dep/ {
alias $deps;
autoindex on;
index off;
allow all;
}
}
EOF
write_text("/etc/nginx/conf.d/xcat-repos.conf", $conf);
}
sub update_repo {
my ($target) = @_;
say "Creating repository dist/$target/rpms";
`find dist/$target/rpms -name ".src.rpm" -delete`;
`createrepo --update dist/$target/rpms`;
}
sub usage {
my ($errmsg) = @_;
say STDERR "Usage: $0 [--package=<pkg1>] [--target=<tgt1>] [--package=<pgk2>] [--target=<tgt2>] ...";
say STDERR $errmsg if $errmsg;
exit -1;
}
sub parseopts {
my %opts = (
targets => \@TARGETS,
packages => \@PACKAGES,
nproc => int(`nproc --all`),
force => 0,
verbose => 0,
deps => "$PWD/../xcat-dep/",
);
GetOptions(
"target=s@" => \$opts{targets},
"package=s@" => \$opts{packages},
"nproc=i" => \$opts{nproc},
"verbose" => \$opts{verbose},
"force" => \$opts{force},
"deps=s" => \$opts{deps},
) or usage();
return \%opts;
};
sub main {
my $opts = parseopts();
my @rpms = product($opts->{packages}, $opts->{targets});
my $pm = Parallel::ForkManager->new($opts->{nproc});
for my $pair (@rpms) {
my ($pkg, $target) = $pair->@*;
$pm->start and next;
buildall($pkg, $target, $opts);
$pm->finish;
}
$pm->wait_all_children;
for my $target ($opts->{targets}->@*) {
$pm->start and next;
update_repo($target, $opts);
$pm->finish;
}
$pm->wait_all_children;
configure_nginx($opts);
`systemctl restart nginx`;
}
main();
-170
View File
@@ -1,170 +0,0 @@
#!/bin/bash -e
# Build xCAT rpms for multiple targets using mock for
# chroot encapsulation. There are multiple packages and
# multiple targets. A package is a xCAT package, like
# xCAT-server, a target is a mock chroot, like rhel+epel-9-x86_64.
#
# This script has two modes:
# ./buildrpms.sh all
# ./buildrpms.sh single <PACKAGE> <TARGET>
#
# In 'all' mode it builds ALL packages for ALL targets, this
# is, a cartesian product PKGS x TARGETS, a RPM is a pair
# (PKG, TARGET).
#
# In 'single' mode a single RPM is built. It is intented for
# reproducing failing builds and for debugging.
#
# In order to make 'all' mode faster the builds are parallelized. Since mock
# lock chroots a distinct chroot is created for each RPM with name
# <PKG>-<TARGET>, then multiple mock processes are spawn, each with its own
# chroot.
#
# The output is generated at dist/ folder, both .src.rpm and .rpm files are
# in this folder.
#
# Notes:
# - `xargs` requires shell functions and variables to be exported
# - Because `buildall` is executed by xargs, I updated it to accept a single
# argument <pkg>:<target> intead of two arguments <pkg> <target>
# pkgs built by default
PACKAGES=(xCAT-{server,client,probe,openbmc-py,rmc,test,vlan,confluent} perl-xCAT xCAT)
# All targets
TARGETS=(rhel+epel-{8,9,10}-x86_64)
SOURCES=${SOURCES:-/root/rpmbuild/SOURCES/}
VERSION=$(cat Version)
RELEASE=$(cat Release)
GITINFO=$(cat Gitinfo)
NPROC=${NPROC:-$(nproc --all)}
export SOURCES VERSION RELEASE GITINFO
# Holds all RPMS to be built
declare -a RPMS=()
for target in ${TARGETS[@]}; do
for pkg in ${PACKAGES[@]}; do
RPMS+=("$pkg:$target")
done
done
# Create the mock chroot configurations for each $pkg $target
function createmockchroot() {
local pkg=$1
local target=$2
local chroot="$pkg-$target"
if [ ! -f "/etc/mock/$chroot.cfg" ]; then
cp "/etc/mock/$target.cfg" "/etc/mock/$chroot.cfg"
sed -e "s/config_opts\['root'\]\s\+=.*/config_opts['root'] = \"$chroot\"/" \
-i "/etc/mock/$chroot.cfg"
fi
}
export -f createmockchroot
# Create a tarball of the source code into $SOURCES/. These tarballs
# are then read by the .spec files
function buildsources() {
local pkg=$1
case $1 in
xCAT)
# shipping bmcsetup and getipmi scripts as part of postscripts
files=("bmcsetup" "getipmi")
for f in "${files[@]}"; do
cp "xCAT-genesis-scripts/usr/bin/"$f ${pkg}/postscripts/$f
sed -i "s/xcat.genesis.$f/$f/g" ${pkg}/postscripts/$f
done
cd xCAT
tar --exclude upflag -czf $SOURCES/postscripts.tar.gz postscripts LICENSE.html
tar -czf $SOURCES/prescripts.tar.gz prescripts
tar -czf $SOURCES/templates.tar.gz templates
tar -czf $SOURCES/winpostscripts.tar.gz winpostscripts
tar -czf $SOURCES/etc.tar.gz etc
cp xcat.conf $SOURCES
cp xcat.conf.apach24 $SOURCES
cp xCATMN $SOURCES
cd ..
;;
*)
tar -czf "$SOURCES/$pkg-$VERSION.tar" $pkg
;;
esac
}
export -f buildsources
# Build the .src.rpm files
function buildspkgs() {
local pkg=$1
local target=$2
local chroot="$pkg-$target"
mock -r $chroot \
-N \
--quiet \
--define "version $VERSION" \
--define "release $RELEASE" \
--define "gitinfo $GITINFO" \
--buildspkg \
--spec $pkg/$pkg.spec \
--sources $SOURCES \
--resultdir "dist/$target/$pkg/"
}
export -f buildspkgs
# Build the .noarch.rpm files
function buildpkgs() {
local pkg=$1
local target=$2
local chroot="$pkg-$target"
mock -r $chroot \
-N \
--quiet \
--define "version $VERSION" \
--define "release $RELEASE" \
--define "gitinfo $GITINFO" \
--resultdir "dist/$target/$pkg/" \
dist/$target/$pkg/$pkg-${VERSION}-${RELEASE}.src.rpm
}
export -f buildpkgs
# Receive a single argument with the format <pkg>:<target>
# Call each step required to build <pkg> for <target>
function buildall() {
IFS=: read -r pkg target <<< "$1"
createmockchroot $pkg $target
buildsources $pkg $target
buildspkgs $pkg $target
buildpkgs $pkg $target
}
export -f buildall
function usage() {
echo "usage:. $0 single <PKG> <TARGET>"
echo "usage:. $0 all"
echo " where:"
echo " PKG = one of xCAT-server,xCAT-client,.."
echo ' TARGET = one of `mock --list-chroots`'
echo ' all = build all combinations'
exit -1
}
test -d dist/ || mkdir dist/
if [ $# -ne 1 ] && [ $# -ne 3 ]; then
usage
fi
case $1 in
'single')
buildall "$2:$3"
;;
'all')
echo -n ${RPMS[@]} | xargs -d ' ' -I% -P $NPROC -t bash -euc "buildall %"
;;
*)
usage
;;
esac
+2
View File
@@ -12,6 +12,8 @@ Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
Prefix: /opt/xcat
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root
BuildRequires: perl-Pod-Html
#%ifnos linux
AutoReqProv: no
#%endif
+7
View File
@@ -61,6 +61,13 @@ if [ -f /etc/init.d/functions ]; then
LOG_SUCCESS=RHSuccess
LOG_FAILURE=RHFailure
LOG_WARNING=passed
elif [ -f /etc/rc.d/init.d/functions ]; then
. /etc/rc.d/init.d/functions
START_DAEMON=daemon
STATUS=MStatus
LOG_SUCCESS=RHSuccess
LOG_FAILURE=RHFailure
LOG_WARNING=passed
elif [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
START_DAEMON=start_daemon