2
0
mirror of https://github.com/xcat2/xcat-dep.git synced 2026-09-23 08:14:05 +00:00

Merge pull request #3 from VersatusHPC/feat/ci-x86-targets

Feat build xcat-dep for multiple targets Ubuntu, EL, SUSE
This commit is contained in:
Daniel Hilst
2026-07-10 11:04:14 -03:00
committed by GitHub
14 changed files with 613 additions and 69 deletions
+3 -3
View File
@@ -21,10 +21,10 @@ License: BSD
Group: System Environment/Daemons
URL: http://www.conserver.com/
Source: http://www.conserver.com/%{pkg}-%{ver}.tar.gz
Patch: initscript_8.2.1.patch
Patch0: initscript_8.2.1.patch
Patch1: openssl3-dh-opaque.patch
BuildRoot: %{_tmppath}/%{pkg}-buildroot
BuildRequires: openssl-devel
BuildRequires: gcc make glibc-devel openssl-devel
Prefix: %{_prefix}
Obsoletes: conserver conserver-client
@@ -40,7 +40,7 @@ bells and whistles to accentuate that basic functionality.
%prep
%{__rm} -rf %{buildroot}
%setup -n %{pkg}-%{ver}
%patch -p1
%patch0 -p1
%patch1 -p1
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/perl
#
# mockbuild.pl - build conserver-xcat (the traditional C conserver, 8.2.1) for one
# mock target and smoke-test the resulting binaries. Mirrors the other xcat-dep
# builders (goconserver/mockbuild.pl, ipmitool/mockbuild.pl): stage sources + spec,
# build a SRPM, `mock --rebuild` it in the target chroot, copy the RPMs to
# --result-dir, then (unless --skip-install) install into the chroot and run
# `console -V` / `conserver -V` to confirm the binaries work.
#
# conserver is NOT part of the default mockbuild-all.pl dep set (xCAT uses goconserver),
# so this builder is standalone. Usage:
# ./mockbuild.pl --mock-cfg alma+epel-9-x86_64 --result-dir /path/out
#
use strict;
use warnings;
use Cwd qw(abs_path);
use File::Basename qw(dirname basename);
use File::Path qw(make_path remove_tree);
use File::Copy qw(copy);
use Getopt::Long qw(GetOptions);
my $script_dir = abs_path(dirname(__FILE__));
my $pkg_dir = $script_dir; # tarball + patches + spec live alongside this script
my $version = '8.2.1';
my $work_dir = '/tmp/conserver-mockbuild';
my $mock_cfg = '';
my $mock_uniqueext = '';
my $result_dir = "$script_dir/../build-output/list-conserver/conserver";
my $log_dir = "$script_dir/../build-logs/list-conserver/conserver";
my $skip_install = 0;
my $build_timestamp;
GetOptions(
'work-dir=s' => \$work_dir,
'mock-cfg=s' => \$mock_cfg,
'mock-uniqueext=s' => \$mock_uniqueext,
'result-dir=s' => \$result_dir,
'log-dir=s' => \$log_dir,
'skip-install!' => \$skip_install,
'build-timestamp=i' => \$build_timestamp,
) or die usage();
die "Run as root (current uid=$>)\n" if $> != 0;
for my $bin (qw(mock rpmbuild rpm)) {
run("command -v " . sh_quote($bin) . " >/dev/null 2>&1");
}
# Deterministic builds: honor --build-timestamp (else Gitepoch, else git HEAD time),
# matching the other xcat-dep builders so mockbuild-all.pl can drive this one.
my $repo_root = abs_path("$script_dir/..");
my $sde = $build_timestamp;
if (!$sde && -f "$repo_root/Gitepoch") { $sde = capture("cat " . sh_quote("$repo_root/Gitepoch")); }
if (!$sde || $sde !~ /^\d+$/) {
$sde = capture("git -C " . sh_quote($repo_root) . " log -1 --format=%ct HEAD 2>/dev/null");
}
$ENV{SOURCE_DATE_EPOCH} = $sde if defined $sde && $sde =~ /^\d+$/;
my $arch = capture('uname -m');
if (!$mock_cfg) {
my $os_id = capture(q{bash -lc 'source /etc/os-release; echo $ID'});
$os_id = 'alma' if $os_id eq 'almalinux';
my ($rel) = capture('rpm -E %rhel');
$mock_cfg = "${os_id}+epel-${rel}-${arch}";
}
my $uniq = $mock_uniqueext ne '' ? ' --uniqueext ' . sh_quote($mock_uniqueext) : '';
make_path($result_dir, $log_dir);
print "package: conserver-xcat\n";
print "version: $version\n";
print "arch: $arch\n";
print "mock-cfg: $mock_cfg\n";
print "result-dir: $result_dir\n";
# ---- stage sources + spec into a private rpmbuild tree -----------------------
remove_tree($work_dir) if -d $work_dir;
make_path("$work_dir/SOURCES", "$work_dir/SPECS");
copy("$pkg_dir/conserver-$version.tar.gz", "$work_dir/SOURCES/")
or die "FATAL: cannot stage conserver-$version.tar.gz: $!\n";
for my $p (glob("$pkg_dir/*.patch")) {
copy($p, "$work_dir/SOURCES/") or die "FATAL: cannot stage patch $p: $!\n";
}
copy("$pkg_dir/conserver.spec", "$work_dir/SPECS/")
or die "FATAL: cannot stage conserver.spec: $!\n";
# ---- build the SRPM (host rpm just packages sources+spec; no %prep here) ------
print "== Build SRPM ==\n";
run("rpmbuild -bs --define " . sh_quote("_topdir $work_dir")
. " " . sh_quote("$work_dir/SPECS/conserver.spec")
. " > " . sh_quote("$log_dir/srpm.log") . " 2>&1");
my ($srpm) = glob("$work_dir/SRPMS/conserver-xcat-$version-*.src.rpm");
die "FATAL: SRPM not produced (see $log_dir/srpm.log)\n" unless $srpm && -f $srpm;
print "SRPM: $srpm\n";
# ---- mock rebuild in the target chroot --------------------------------------
print "== mock --rebuild ($mock_cfg) ==\n";
my $mock_result = "$work_dir/mock-result";
make_path($mock_result);
run("mock -r " . sh_quote($mock_cfg) . $uniq
. " --rebuild " . sh_quote($srpm)
. " --resultdir " . sh_quote($mock_result)
. " > " . sh_quote("$log_dir/mock-rebuild.log") . " 2>&1");
my @rpms = grep { $_ !~ /\.src\.rpm$/ && $_ !~ /-debug(info|source)-/ }
glob("$mock_result/*.rpm");
die "FATAL: no binary RPM produced (see $log_dir/mock-rebuild.log)\n" unless @rpms;
my ($main) = grep { basename($_) =~ /^conserver-xcat-\Q$version\E-.*\.(?:$arch|noarch)\.rpm$/ } @rpms;
die "FATAL: main conserver-xcat RPM not found among: @rpms\n" unless $main;
for my $r (@rpms) {
copy($r, $result_dir) or die "FATAL: cannot copy $r -> $result_dir: $!\n";
}
print "built: " . join(', ', map { basename($_) } @rpms) . "\n";
# ---- smoke test: install into the chroot and run the binaries ---------------
unless ($skip_install) {
print "== Smoke test (install + run) ==\n";
run("mock -r " . sh_quote($mock_cfg) . $uniq . " --install " . sh_quote($main)
. " > " . sh_quote("$log_dir/install.log") . " 2>&1");
# console (client) and conserver (daemon) both print their version to stderr/stdout.
my $smoke = capture("mock -r " . sh_quote($mock_cfg) . $uniq
. " --chroot -- " . sh_quote('/usr/bin/console -V 2>&1; /usr/sbin/conserver -V 2>&1')
. " 2>&1");
print " output: $smoke\n";
die "FATAL: smoke test did not report version $version\n" unless $smoke =~ /\Q$version\E/;
print "smoke test PASSED (console/conserver report $version)\n";
}
print "DONE: conserver-xcat $version for $mock_cfg -> $result_dir\n";
# ---- helpers ----------------------------------------------------------------
sub run {
my ($cmd) = @_;
my $rc = system('bash', '-c', $cmd);
die "FATAL: command failed (rc=" . ($rc >> 8) . "): $cmd\n" if $rc != 0;
return 1;
}
sub capture {
my ($cmd) = @_;
my $out = `$cmd`;
chomp $out if defined $out;
return $out // '';
}
sub sh_quote { my ($s) = @_; $s =~ s/'/'\\''/g; return "'$s'"; }
sub usage {
return "usage: mockbuild.pl --mock-cfg <cfg> [--result-dir DIR] [--work-dir DIR]\n"
. " [--log-dir DIR] [--mock-uniqueext EXT] [--skip-install]\n";
}
+5 -2
View File
@@ -89,7 +89,10 @@ print_step("Stage build environment");
remove_tree($work_dir) if -d $work_dir;
make_path($work_dir);
my $rpmbuild_top = "/var/tmp/xcat-rpmbuild-goconserver";
# Unique per run (nested under the run/target-scoped --work-dir) so concurrent builds -- e.g.
# parallel EL targets on one host -- don't wipe each other. (Was a shared
# /var/tmp/xcat-rpmbuild-goconserver, which collided under parallelism.)
my $rpmbuild_top = "$work_dir/rpmbuild";
remove_tree($rpmbuild_top) if -d $rpmbuild_top;
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
make_path("$rpmbuild_top/$d");
@@ -187,7 +190,7 @@ print_step("Create spec and build RPM");
my $spec_content = <<"SPEC";
Name: goconserver
Version: $version
Release: 2.el$rel
Release: 3.el$rel
Summary: Console server written in Go for xCAT
License: EPL-1.0
URL: https://github.com/xcat2/goconserver
+4
View File
@@ -1,5 +1,9 @@
Summary: grub2 resources generated by grub2-mknetdir
Name: grub2-xcat
# This el10 rewrite reset the version scheme from the el7-era 2.02 down to 1.0, but
# xCAT-server still Requires: grub2-xcat >= 2.02-0.76.el7.1.snap201905160255. An Epoch
# bump makes 1:1.0 outrank 0:2.02 so the (unchanged) xCAT-server dependency resolves.
Epoch: 1
Version: 1.0
#Release: snap%(date +"%Y%m%d%H%M")
Release: 2
+6 -34
View File
@@ -3,7 +3,7 @@
use strict;
use warnings;
use Cwd qw(abs_path);
use File::Basename qw(dirname basename);
use File::Basename qw(dirname);
use File::Copy qw(copy);
use File::Path qw(make_path remove_tree);
use Getopt::Long qw(GetOptions);
@@ -15,28 +15,22 @@ my $spec_file = "$pkg_dir/grub2-xcat.spec";
my $recompile_dir = "$repo_root/grub2-xcat.recompile";
my $resource_mode = 'reuse-grub2-res';
my $upstream_url = 'https://mirror.stream.centos.org/10-stream/BaseOS/source/tree/Packages/grub2-2.12-37.el10.src.rpm';
my $upstream_file = '';
my $work_dir = '/tmp/grub2-xcat-mockbuild';
my $mock_cfg = '';
my $mock_uniqueext = '';
my $result_dir = "$repo_root/build-output/list3/grub2-xcat";
my $log_dir = "$repo_root/build-logs/list3/grub2-xcat";
my $skip_install = 0;
my $skip_upstream_download = 0;
my $build_timestamp;
GetOptions(
'resource-mode=s' => \$resource_mode,
'upstream-url=s' => \$upstream_url,
'upstream-file=s' => \$upstream_file,
'work-dir=s' => \$work_dir,
'mock-cfg=s' => \$mock_cfg,
'mock-uniqueext=s' => \$mock_uniqueext,
'result-dir=s' => \$result_dir,
'log-dir=s' => \$log_dir,
'skip-install!' => \$skip_install,
'skip-upstream-download!' => \$skip_upstream_download,
'build-timestamp=i' => \$build_timestamp,
) or die usage();
@@ -49,18 +43,17 @@ die "Mode regenerate-from-el10-srcrpm is not supported in this script yet; use r
make_path($recompile_dir) if !-d $recompile_dir;
for my $bin (qw(wget mock rpmbuild rpm dnf file bash tar sha256sum grep cmp cut)) {
for my $bin (qw(mock rpmbuild rpm dnf file bash tar grep cmp)) {
run("command -v " . sh_quote($bin) . " >/dev/null 2>&1");
}
my ($version, @spec_assets) = parse_spec($spec_file);
die "Could not parse Version from $spec_file\n" if !$version;
if (!$upstream_file) {
$upstream_file = basename($upstream_url);
}
die "Could not derive upstream file name from URL: $upstream_url\n" if !$upstream_file;
my $upstream_path = "$recompile_dir/$upstream_file";
# NOTE: grub2-xcat is a pure noarch repackaging of the committed grub2-res.tar.gz (Source1),
# so the build needs no external source. Fetching the distro grub2 src.rpm would only ever be
# needed by the (currently unimplemented) regenerate-from-el10-srcrpm mode, which would rebuild
# the grub tree from source and commit a fresh grub2-res.tar.gz rather than download at build time.
my $arch = capture('uname -m');
if (!$mock_cfg) {
@@ -95,10 +88,7 @@ print "result_dir: $result_dir\n";
print "log_dir: $log_dir\n";
print "mock_cfg: $mock_cfg\n";
print "mock_uniqueext: " . ($mock_uniqueext ne '' ? $mock_uniqueext : '(none)') . "\n";
print "upstream_url: $upstream_url\n";
print "upstream_file: $upstream_file\n";
print "skip_install: $skip_install\n";
print "skip_upstream_download: $skip_upstream_download\n";
make_path($result_dir);
make_path($log_dir);
@@ -106,21 +96,6 @@ make_path($log_dir);
print_step("Mock config check");
run("mock -r " . sh_quote($mock_cfg) . $mock_uniqueext_opt . " --print-root-path >/dev/null");
if (!$skip_upstream_download) {
print_step("Download upstream source RPM");
run("wget --spider " . sh_quote($upstream_url));
run("wget -O " . sh_quote($upstream_path) . " " . sh_quote($upstream_url));
my $sha = capture("sha256sum " . sh_quote($upstream_path) . " | cut -d ' ' -f1");
my $meta_file = "$log_dir/upstream-source.txt";
open my $mfh, '>', $meta_file or die "Cannot write $meta_file: $!\n";
print {$mfh} "url=$upstream_url\n";
print {$mfh} "file=$upstream_path\n";
print {$mfh} "sha256=$sha\n";
close $mfh;
print "Downloaded upstream source rpm: $upstream_path\n";
print "SHA256: $sha\n";
}
print_step("Verify grub2 resource payload");
my $resource_tar = "$pkg_dir/grub2-res.tar.gz";
die "Missing required resource tarball: $resource_tar\n" if !-f $resource_tar;
@@ -295,14 +270,11 @@ sub usage {
return <<"USAGE";
Usage: $0 [options]
--resource-mode MODE Build mode: reuse-grub2-res|regenerate-from-el10-srcrpm (default: $resource_mode)
--upstream-url URL Upstream grub2 source RPM URL (default: $upstream_url)
--upstream-file FILE Source RPM filename stored in grub2-xcat.recompile/ (default: basename of URL)
--work-dir PATH Temporary work dir (default: $work_dir)
--mock-cfg NAME Mock config (default: <ID>+epel-10-<ARCH>)
--mock-uniqueext TXT Optional mock --uniqueext suffix to isolate concurrent builds
--result-dir PATH Output RPM/SRPM directory (default: $result_dir)
--log-dir PATH Log directory (default: $log_dir)
--skip-upstream-download Skip wget of upstream source RPM
--skip-install Skip dnf install + smoke tests
--build-timestamp EPOCH Unix timestamp for deterministic builds (SOURCE_DATE_EPOCH)
USAGE
Binary file not shown.
+4
View File
@@ -88,6 +88,10 @@ for f in AUTHORS ChangeLog; do
done
%build
# OpenSSL 3 ships a stub openssl/md2.h, so configure's header probe sets
# HAVE_CRYPTO_MD2 even though MD2_CTX/MD2_* are gone -> auth.c fails to compile.
# Force the probe negative so the no-MD2 code path is used (MD2 IPMI auth is obsolete).
export ac_cv_header_openssl_md2_h=no
# --disable-dependency-tracking speeds up the build
# --enable-file-security adds some security checks
# --disable-intf-free disables FreeIPMI support - we don't want to depend on
+407 -27
View File
@@ -14,11 +14,18 @@ use POSIX qw(strftime);
my $script_dir = abs_path(dirname(__FILE__));
my $repo_root = abs_path($script_dir);
my $xcat_src = "$repo_root/xcat-source-code";
my $output_root = "$repo_root/build-output/mockbuild-all";
my $xcat_src = "$repo_root/../xcat-core";
# Single knob for all NFS-shared output; --output-root/--repo-dep derive from it below
# unless explicitly overridden. Empty means "not set on the command line".
my $output = '';
my $output_root = '';
my $target = '';
my $nproc = 1;
my $parallel_builds;
my $parallel_targets = 1; # 1 = serial (default; safe). 0/auto = all EL targets at once; N = cap.
# NOTE: parallel targets need every per-package mockbuild.pl to avoid
# shared-path writes (repo tarballs, $HOME/rpmbuild); serial is safe today.
my $max_parallel = 0; # 0/auto = host nproc: global cap on concurrent mock builds (all targets)
my $run_id = '';
my $build_timestamp;
my $skip_install = 0;
@@ -26,19 +33,35 @@ my $skip_build = 0;
my $skip_xcat_dep = 0;
my $skip_perl = 0;
my $skip_xcat = 0;
my $skip_genesis = 0;
my $skip_createrepo = 0;
my $skip_tarball = 0;
my $scrub_all_chroots = 0;
my $dry_run = 0;
my @extra_collect_dirs;
my $repo_dep = '';
my $gpg_sign = 0;
my $gpg_key_name = 'xCAT Signing Key';
my $gpg_home = '';
my $force_unlock = 0;
my $HELD_LOCK; # path of the output lock this process owns (for cleanup on exit)
my $LOCK_OWNER_PID; # pid that created the lock; forked children must NOT remove it
GetOptions(
'repo-root=s' => \$repo_root,
'xcat-source=s' => \$xcat_src,
'output=s' => \$output,
'output-root=s' => \$output_root,
'repo-dep=s' => \$repo_dep,
'gpg-sign!' => \$gpg_sign,
'gpg-key-name=s' => \$gpg_key_name,
'gpg-home=s' => \$gpg_home,
'force-unlock!' => \$force_unlock,
'target=s' => \$target,
'nproc=i' => \$nproc,
'parallel-builds=i' => \$parallel_builds,
'parallel-targets=i' => \$parallel_targets,
'max-parallel=i' => \$max_parallel,
'run-id=s' => \$run_id,
'build-timestamp=i' => \$build_timestamp,
'skip-install!' => \$skip_install,
@@ -46,6 +69,7 @@ GetOptions(
'skip-xcat-dep!' => \$skip_xcat_dep,
'skip-perl!' => \$skip_perl,
'skip-xcat!' => \$skip_xcat,
'skip-genesis!' => \$skip_genesis,
'skip-createrepo!' => \$skip_createrepo,
'skip-tarball!' => \$skip_tarball,
'scrub-all-chroots!' => \$scrub_all_chroots,
@@ -75,6 +99,23 @@ if ($run_id eq '') {
$run_id = strftime('%Y%m%d-%H%M%S', gmtime($SOURCE_DATE_EPOCH));
}
# Single output base for every NFS-shared write. Two hosts build in parallel on one NFS by
# passing distinct --output paths. --output-root/--repo-dep, if given, override the derived
# values. Default keeps the historical layout so existing callers are unaffected.
# Create the dir first, THEN abs_path -- abs_path() on a not-yet-existing path returns undef,
# and abs_path(undef) silently resolves to cwd, which would misdirect all output.
my $output_base = $output ne '' ? $output : "$repo_root/build-output";
make_path($output_base) if !-d $output_base;
$output_base = abs_path($output_base)
or die "Cannot resolve --output base directory\n";
$output_root = "$output_base/mockbuild-all" if $output_root eq '';
# Deployable per-EL xcat-dep repo root (rh8/rh9/rh10/<arch> assembled here).
$repo_dep = "$output_base/xcat-dep" if $repo_dep eq '';
# Fail-fast lock on the output base so a second run against the same --output aborts instead of
# racing on the shared NFS tree. Held for the whole invocation; released by the exit handlers.
acquire_output_lock($output_base, $force_unlock);
$xcat_src = resolve_xcat_source($xcat_src, $repo_root);
my $arch = capture('uname -m');
@@ -87,13 +128,80 @@ die "Could not resolve ID from /etc/os-release\n" if $os_id eq '';
die "Could not resolve major release from VERSION_ID='$version_id' in /etc/os-release\n"
if !defined($rel) || $rel eq '';
if (!$target) {
$target = resolve_mock_cfg($os_id, $rel, $arch);
}
for my $bin (qw(perl uname createrepo tar find rpm)) {
for my $bin (qw(perl uname createrepo_c tar find rpm)) {
require_command($bin);
}
require_command('mock') if $scrub_all_chroots;
require_command('rpmsign') if $gpg_sign;
require_command('gpg') if $gpg_sign;
# An explicit --target builds just that target; otherwise build the current host
# arch across rh8/rh9/rh10 into a deployable per-EL xcat-dep repo. This script builds
# ONLY the host arch (uname -m) -- the other arch is produced on its own build host.
my @build_targets = $target
? ($target)
: map { resolve_mock_cfg($os_id, $_, $arch) } (8, 9, 10);
# NOTE: no dhcp- packages are built here. DHCP backend selection is an install-time
# rich dep in xCAT.spec (kea if system-release>=10 else /usr/sbin/dhcpd), so there is
# nothing arch/EL-specific to build or to exclude for el10.
print_step('Targets to build');
print " $_\n" for @build_targets;
print "output_base: $output_base\n";
print "deploy repo-dep: $repo_dep\n";
print "lock: $output_base/.lock (held)\n";
print "gpg_sign: $gpg_sign\n";
print "gpg_key_name: $gpg_key_name\n" if $gpg_sign;
print "gpg_home: " . ($gpg_home ne '' ? $gpg_home : '(default keyring)') . "\n" if $gpg_sign;
# Build (and deploy) EL targets concurrently. Each target is fully isolated -- distinct run_id
# (target-folded), mock --uniqueext, /tmp work dir, xcat_src/dist/<target>, and deploy dir
# rh<rel>/<arch> -- so there is no cross-target contention. 0/auto = all at once; 1 = serial.
my $tgt_workers = $parallel_targets > 0 ? $parallel_targets : scalar(@build_targets);
$tgt_workers = scalar(@build_targets) if $tgt_workers > scalar(@build_targets);
# Global cap on concurrent mock builds so parallel targets don't oversubscribe the host. Each
# mock build already gets a unique --uniqueext (separate chroot), so the only limit needed is
# hardware: total concurrent builds across all targets stays <= $cap (default host nproc). The
# per-target build-step concurrency is therefore the cap divided across the active targets.
my $cap = $max_parallel > 0 ? $max_parallel : (capture('nproc') || 4);
my $per_target_builds = defined($parallel_builds) ? $parallel_builds : int($cap / $tgt_workers);
$per_target_builds = 1 if $per_target_builds < 1;
print "parallel_targets: " . ($parallel_targets > 0 ? $parallel_targets : "auto($tgt_workers)") . "\n";
print "max_parallel: $cap (per-target build workers: $per_target_builds)\n";
my $tgt_pm = Parallel::ForkManager->new($tgt_workers <= 1 ? 0 : $tgt_workers);
my $tgt_fail = 0;
$tgt_pm->run_on_finish(sub {
my ($pid, $exit) = @_;
$tgt_fail++ if $exit;
});
for my $tgt (@build_targets) {
$tgt_pm->start and next;
my $rc = 0;
eval {
my $info = build_one_target($tgt, $run_id, $per_target_builds);
deploy_target($tgt, $info);
1;
} or do { warn "ERROR: target $tgt failed: $@"; $rc = 1; };
$tgt_pm->finish($rc);
}
$tgt_pm->wait_all_children;
die "FATAL: $tgt_fail target(s) failed\n" if $tgt_fail;
print_step('All targets completed');
exit 0;
# Build a single target into its own build-output/<target-runid> tree and return
# { repo_dir, rel }. Everything below through the summary is per-target work.
sub build_one_target {
my ($target, $run_id, $max_build_workers) = @_;
# The build output identity must be per-target (os version + arch). SOURCE_DATE_EPOCH
# is the same across targets for a given commit, so a timestamp-only run_id makes
# different targets (e.g. alma+epel-8 vs -9) share build-output/<run_id> and
# cross-contaminate. Fold the target into run_id so each target gets its own tree.
$run_id = "$target-$run_id" unless index($run_id, $target) >= 0;
my ($rel) = $target =~ /epel-(\d+)-/;
die "Could not parse EL release from target '$target'\n" unless defined $rel;
my $run_root = "$output_root/$run_id";
my $build_root = "$run_root/build-results";
@@ -104,18 +212,19 @@ my $tarball = "$output_root/mockbuild-all-$target-$run_id.tar.gz";
my $srpm_repo_dir = "$run_root/repo-src";
my $srpm_tarball = "$output_root/mockbuild-all-$target-$run_id-srpm.tar.gz";
# All dep builders run natively on every arch. xnba-undi and grub2-xcat are noarch packagings of
# committed artifacts (an x86 UNDI ROM / the grub2 resource tarball) with no arch-specific build
# step, so ppc builds them the same as x86 -- no cross-arch import.
my @dep_builders = (
{ name => 'elilo-xcat', script => "$repo_root/elilo/mockbuild.pl" },
{ name => 'grub2-xcat', script => "$repo_root/grub2-xcat/mockbuild.pl" },
{ name => 'ipmitool-xcat', script => "$repo_root/ipmitool/mockbuild.pl" },
{ name => 'syslinux-xcat', script => "$repo_root/syslinux/mockbuild.pl" },
{ name => 'goconserver', script => "$repo_root/goconserver/mockbuild.pl" },
{ name => 'conserver-xcat', script => "$repo_root/conserver/mockbuild.pl" },
{ name => 'xnba-undi', script => "$repo_root/xnba/mockbuild.pl" },
);
if ($arch eq 'x86_64') {
push @dep_builders, { name => 'xnba-undi', script => "$repo_root/xnba/mockbuild.pl" };
}
my $perl_builder = "$repo_root/mockbuild-perl-packages.pl";
die "Missing xCAT build script: $xcat_src/buildrpms.pl\n"
@@ -152,6 +261,7 @@ print "skip_build: $skip_build\n";
print "skip_xcat_dep: $skip_xcat_dep\n";
print "skip_perl: $skip_perl\n";
print "skip_xcat: $skip_xcat\n";
print "skip_genesis: $skip_genesis\n";
print "skip_install: $skip_install\n";
print "skip_createrepo: $skip_createrepo\n";
print "skip_tarball: $skip_tarball\n";
@@ -189,6 +299,8 @@ if (!$skip_build) {
'--mock-uniqueext', sh_quote($step_uniqueext),
'--result-dir', sh_quote($step_result),
'--log-dir', sh_quote($step_log),
# host-local, run-scoped work dir so /tmp doesn't collide between runs
'--work-dir', sh_quote("/tmp/mockbuild-all-$run_id/$name"),
'--build-timestamp', $SOURCE_DATE_EPOCH,
($skip_install ? '--skip-install' : ()),
);
@@ -206,12 +318,17 @@ if (!$skip_build) {
my $perl_result = "$build_root/perl/$arch";
my $perl_log = "$log_root/perl/$arch";
my $perl_uniqueext = build_mock_uniqueext($run_id, ++$build_step_seq, 'perl-list6');
# Bound the perl builder's OWN internal parallelism to this target's budget; otherwise it
# forks one mock build per perl package (~7), which -- multiplied by parallel EL targets --
# oversubscribes the host.
my $cmd = join(' ',
'perl', sh_quote($perl_builder),
'--mock-cfg', sh_quote($target),
'--mock-uniqueext', sh_quote($perl_uniqueext),
'--result-dir', sh_quote($perl_result),
'--log-dir', sh_quote($perl_log),
'--work-dir', sh_quote("/tmp/mockbuild-all-$run_id/perl-list6"),
(($max_build_workers && $max_build_workers >= 1) ? ('--jobs', $max_build_workers) : ()),
'--build-timestamp', $SOURCE_DATE_EPOCH,
($skip_install ? '--skip-install' : ()),
);
@@ -225,7 +342,10 @@ if (!$skip_build) {
}
if (!$skip_xcat) {
my $cmd = join(' ',
# Own HOME per target (buildrpms.pl uses $HOME/rpmbuild) so parallel targets don't race.
my $xcat_home = "/tmp/mockbuild-all-$run_id/xcat-home";
my $mktree = join(' ', map { sh_quote("$xcat_home/rpmbuild/$_") } qw(SOURCES SPECS BUILD BUILDROOT RPMS SRPMS));
my $cmd = "mkdir -p $mktree && HOME=" . sh_quote($xcat_home) . ' ' . join(' ',
'perl', sh_quote("$xcat_src/buildrpms.pl"),
'--target', sh_quote($target),
'--nproc', int($nproc),
@@ -242,10 +362,45 @@ if (!$skip_build) {
};
}
# xCAT-genesis-base is OS-dependent (its initramfs bundles the build chroot's
# kernel + glibc/busybox/perl), so it is built here, per target, and shipped
# in this per-EL xcat-dep repo rather than in the flat xcat-core. buildrpms.pl
# (run in the xcat-core dir) derives the same snapYYYYMMDDHHMM Release from
# xcat-core's Gitepoch, so it matches xCAT-genesis-scripts (built in core) and
# the exact-version dependency genesis-scripts -> genesis-base resolves.
if (!$skip_genesis) {
# buildrpms.pl stages sources in $HOME/rpmbuild (via rpmdev-setuptree). Give each
# per-target genesis build its own HOME so parallel EL targets don't race on the shared
# /root/rpmbuild tree (that race is what made concurrent genesis builds fail).
my $genesis_home = "/tmp/mockbuild-all-$run_id/genesis-home";
# buildrpms.pl's rpmdev-setuptree only runs during env setup, not per build, so create the
# rpmbuild tree ourselves for this per-target HOME (else $HOME/rpmbuild/SOURCES is missing).
my $mktree = join(' ', map { sh_quote("$genesis_home/rpmbuild/$_") } qw(SOURCES SPECS BUILD BUILDROOT RPMS SRPMS));
my $cmd = "mkdir -p $mktree && HOME=" . sh_quote($genesis_home) . ' ' . join(' ',
'perl', sh_quote("$xcat_src/buildrpms.pl"),
'--package', 'xCAT-genesis-base',
'--target', sh_quote($target),
'--nproc', int($nproc),
'--force',
'--verbose',
'--xcat_dep_path', sh_quote($repo_root),
);
push @build_steps, {
id => 'genesis',
step => 'Build xCAT-genesis-base (per-target, OS-dependent)',
cmd => $cmd,
cwd => $xcat_src,
log => "$log_root/genesis-build.log",
};
}
if (@build_steps) {
my $effective_parallel_builds = defined($parallel_builds)
? $parallel_builds
: scalar(@build_steps);
# Prefer the caller-supplied cap (global budget / active targets). Fall back to the old
# behaviour (all steps at once) only when unset.
my $effective_parallel_builds =
($max_build_workers && $max_build_workers >= 1) ? $max_build_workers
: defined($parallel_builds) ? $parallel_builds
: scalar(@build_steps);
run_build_steps_parallel(
steps => \@build_steps,
max_processes => $effective_parallel_builds,
@@ -255,7 +410,16 @@ if (!$skip_build) {
my $xcat_rpms_dir = "$xcat_src/dist/$target/rpms";
my $xcat_srpms_dir = "$xcat_src/dist/$target/srpms";
push @collect_roots, $xcat_rpms_dir;
# In monolithic mode (no --skip-xcat) the whole xCAT core built here (incl.
# genesis-base) is collected into this repo. In the split pipeline (--skip-xcat,
# core built separately) the orchestrator (cluster-test.pl) routes
# xCAT-genesis-base from the xCAT dist tree into the per-EL dep repo itself --
# robust to this script exiting non-zero on tolerated dep-builder failures -- so
# we deliberately do NOT collect the xCAT dist tree here.
if (!$skip_xcat) {
push @collect_roots, $xcat_rpms_dir;
}
if ($skip_build) {
push @collect_roots,
@@ -272,7 +436,9 @@ if ($skip_build) {
push @collect_roots, @extra_collect_dirs;
@collect_roots = uniq(@collect_roots);
my @srpm_collect_roots = uniq(@collect_roots, $xcat_srpms_dir);
my @srpm_collect_roots = (!$skip_xcat)
? uniq(@collect_roots, $xcat_srpms_dir)
: uniq(@collect_roots);
print_step('Collect RPM artifacts');
print "collection roots:\n";
@@ -288,6 +454,17 @@ if (!$dry_run && $copied == 0) {
die "No binary RPMs were collected. Check build logs and collection roots.\n";
}
# Ensure the OS-dependent xCAT-genesis-base rpm (built by the genesis step above)
# lands in the dep repo even when the full xCAT core is built elsewhere (--skip-xcat).
if (!$skip_genesis && !$dry_run) {
for my $g (glob("$xcat_rpms_dir/xCAT-genesis-base-*.rpm")) {
next if $g =~ /\.src\.rpm$/;
copy($g, "$repo_dir/" . basename($g))
or die "Failed to copy genesis-base $g -> $repo_dir: $!\n";
$copied++;
}
}
print_step('Collect source RPM artifacts');
print "source collection roots:\n";
print " $_\n" for @srpm_collect_roots;
@@ -305,12 +482,12 @@ if (!$dry_run && $copied_srpms == 0) {
if (!$skip_createrepo) {
run_step(
step => 'Run createrepo',
cmd => 'createrepo --update --revision ' . sh_quote($SOURCE_DATE_EPOCH) . ' ' . sh_quote($repo_dir),
cmd => createrepo_c_cmd($repo_dir),
log => "$log_root/createrepo.log",
);
run_step(
step => 'Run createrepo for SRPM repo',
cmd => 'createrepo --update --revision ' . sh_quote($SOURCE_DATE_EPOCH) . ' ' . sh_quote($srpm_repo_dir),
cmd => createrepo_c_cmd($srpm_repo_dir),
log => "$log_root/createrepo-srpm.log",
);
}
@@ -375,7 +552,114 @@ print "SRPM repo dir: $srpm_repo_dir\n";
print "Summary: $summary_file\n" if !$dry_run;
print "Tarball: $tarball\n" if !$skip_tarball;
print "SRPM Tarball: $srpm_tarball\n" if !$skip_tarball;
exit 0;
return { repo_dir => $repo_dir, rel => $rel };
}
# Assemble the built per-target repo into the deployable, signed per-EL layout
# <repo-dep>/rh<rel>/<arch>: copy the binary rpms, sign, createrepo, and drop the
# xcat-dep.repo / mklocalrepo.sh / buildinfo.txt (ready to push to xcat.org).
sub deploy_target {
my ($tgt, $info) = @_;
my $rel = $info->{rel};
my $src = $info->{repo_dir};
my $dest = "$repo_dep/rh$rel/$arch";
print_step("Deploy $tgt -> $dest");
return if $dry_run;
make_path($dest);
for my $rpm (glob("$src/*.rpm")) {
next if $rpm =~ /\.src\.rpm$/;
copy($rpm, "$dest/" . basename($rpm))
or die "Failed to copy $rpm -> $dest: $!\n";
}
assert_required_deps($dest);
sign_and_index_repo($dest);
write_dep_repo_metadata($dest, $rel);
my $n = scalar(grep { !/\.src\.rpm$/ } glob("$dest/*.rpm"));
print "Deployed rh$rel/$arch: $n rpms\n";
}
# createrepo_c command with upstream-matching, deterministic metadata. The tool's
# defaults emit primary/filelists/other as *.xml.zst plus *.sqlite.bz2 (--database),
# exactly the upstream shape; --set-timestamp-to-revision pins repomd to SOURCE_DATE_EPOCH.
sub createrepo_c_cmd {
my ($dir) = @_;
return 'createrepo_c --update --database '
. '--revision ' . sh_quote($SOURCE_DATE_EPOCH) . ' --set-timestamp-to-revision '
. sh_quote($dir);
}
sub sign_and_index_repo {
my ($dir) = @_;
my @rpms = grep { !/\.src\.rpm$/ } glob("$dir/*.rpm");
if ($gpg_sign && @rpms) {
local $ENV{GNUPGHOME} = $gpg_home if $gpg_home;
run_simple(qq(rpmsign --define "%_gpg_name $gpg_key_name" --addsign )
. join(' ', map { sh_quote($_) } @rpms));
}
run_simple(createrepo_c_cmd($dir));
if ($gpg_sign) {
local $ENV{GNUPGHOME} = $gpg_home if $gpg_home;
my $repomd = "$dir/repodata/repomd.xml";
unlink "$repomd.asc" if -f "$repomd.asc";
run_simple(qq(gpg -a --detach-sign --default-key "$gpg_key_name" ) . sh_quote($repomd));
run_simple(qq(gpg -a --export "$gpg_key_name" > ) . sh_quote("$repomd.key"));
}
}
sub write_dep_repo_metadata {
my ($dir, $rel) = @_;
my $baseurl = "https://xcat.org/files/xcat/repos/yum/devel/xcat-dep/rh$rel/$arch";
my $gpgcheck = $gpg_sign ? 1 : 0;
my $gpgkey_line = $gpg_sign ? "gpgkey=$baseurl/repodata/repomd.xml.key" : "# gpgkey=";
open my $r, '>', "$dir/xcat-dep.repo" or die "Cannot write $dir/xcat-dep.repo: $!\n";
print {$r} <<"EOF";
[xcat-dep]
name=xCAT 2 dependencies (rh$rel $arch)
baseurl=$baseurl
enabled=1
gpgcheck=$gpgcheck
$gpgkey_line
EOF
close $r;
open my $m, '>', "$dir/mklocalrepo.sh" or die "Cannot write $dir/mklocalrepo.sh: $!\n";
print {$m} <<'EOS';
#!/bin/sh
cd `dirname $0`
REPOFILE=`basename xcat-*.repo`
if [[ $REPOFILE == "xcat-*.repo" ]]; then
echo "ERROR: For xcat-dep, please execute $0 in the correct <os>/<arch> subdirectory"
exit 1
fi
DIRECTORY="/etc/yum.repos.d"
if [ ! -d "$DIRECTORY" ]; then
DIRECTORY="/etc/zypp/repos.d"
fi
sed -e 's|baseurl=.*|baseurl=file://'"`pwd`"'|' $REPOFILE | sed -e 's|gpgkey=.*|gpgkey=file://'"`pwd`"'/repodata/repomd.xml.key|' > "$DIRECTORY/$REPOFILE"
cd -
EOS
close $m;
chmod 0775, "$dir/mklocalrepo.sh";
my $build_time = strftime("%a %b %e %H:%M:%S %Z %Y", gmtime($SOURCE_DATE_EPOCH));
my $build_machine = `hostname`; chomp $build_machine;
my $commit = `git -C "$repo_root" rev-parse HEAD 2>/dev/null`; chomp $commit;
$commit ||= 'unknown';
my $commit_short = substr($commit, 0, 7);
my $release = strftime('snap%Y%m%d%H%M', gmtime($SOURCE_DATE_EPOCH));
open my $b, '>', "$dir/buildinfo.txt" or die "Cannot write $dir/buildinfo.txt: $!\n";
print {$b} <<"EOF";
TARGET=rh$rel/$arch
RELEASE=$release
BUILD_TIME=$build_time
BUILD_MACHINE=$build_machine
COMMIT_ID=$commit_short
COMMIT_ID_LONG=$commit
SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH
EOF
close $b;
}
sub usage {
return <<"USAGE";
@@ -385,11 +669,26 @@ Build xcat-dep and xCAT RPMs, consolidate binary/source artifacts, run createrep
Options:
--repo-root PATH xcat-dep repository root (default: script directory)
--xcat-source PATH xCAT source root with buildrpms.pl (default: <repo-root>/xcat-source-code)
--output-root PATH Root output directory (default: <repo-root>/build-output/mockbuild-all)
--target NAME Optional unified target in <ID>+epel-<REL>-<ARCH> format
--xcat-source PATH xCAT source root with buildrpms.pl (default: <repo-root>/../xcat-core)
--output PATH Single base for ALL output; --output-root and --repo-dep derive from
it. A fail-fast lock is held at <PATH>/.lock, so pass distinct paths
to run on two hosts in parallel on one NFS (default: <repo-root>/build-output)
--output-root PATH Override the derived build tree root (default: <output>/mockbuild-all)
--repo-dep PATH Override the derived deployable per-EL output root; rh8/rh9/rh10/<arch>
are assembled + signed here (default: <output>/xcat-dep)
--force-unlock Remove a stale <output>/.lock before acquiring it
--gpg-sign Sign rpms + repomd.xml of each per-EL repo
--gpg-key-name NAME GPG key name (default: "xCAT Signing Key")
--gpg-home PATH GNUPGHOME for signing (default: system keyring)
--target NAME Build only this target (<ID>+epel-<REL>-<ARCH>); default is
the host arch across rh8, rh9 and rh10
--nproc N Parallel jobs for buildrpms.pl (default: 1)
--parallel-builds N Max concurrent top-level build steps (default: auto=queued steps)
--parallel-builds N Max concurrent top-level build steps within one EL target (default: auto)
--parallel-targets N Concurrent EL targets (rh8/rh9/rh10). 0/auto = all at once, 1 = serial,
N = cap at N. Each target is fully output-isolated (default: auto)
--max-parallel N Global cap on concurrent mock builds across ALL targets, to avoid
oversubscribing the host. Split evenly across active targets.
0/auto = host nproc (default: auto)
--run-id ID Run identifier suffix (default: derived from build timestamp)
--build-timestamp EPOCH Unix epoch for deterministic builds (default: Gitepoch or git log)
--skip-install Skip install/smoke tests in child builder scripts
@@ -407,7 +706,7 @@ Notes:
- Run this script as root on the build host.
- ARCH is derived from: uname -m
- Top-level parallel queue includes xcat-dep mockbuild.pl steps, perl builder,
and xcat-source-code/buildrpms.pl.
and ../xcat-core/buildrpms.pl.
- Child mockbuild scripts are invoked with per-step mock --uniqueext values
to avoid lock collisions on the same mock config.
- If --target is omitted, it is deduced from /etc/os-release:
@@ -487,9 +786,14 @@ sub run_build_steps_parallel {
my $max_processes = $args{max_processes} // 1;
return if !@{$steps};
# Individual dep-builder failures are TOLERATED (some packages are el-/arch-pinned or
# have dead upstream source URLs, e.g. elilo on el10, perl-Sys-Virt on el8, a moved grub2
# src.rpm). We collect whatever built and assert the REQUIRED set later (assert_required_deps),
# matching the historical build behaviour.
if ($dry_run || $max_processes <= 1 || @{$steps} == 1) {
for my $step (@{$steps}) {
run_step(%{$step});
my $ok = eval { run_step(%{$step}); 1 };
warn "WARN: build step failed (tolerated): $step->{step}\n" . ($@ // '') unless $ok;
}
return;
}
@@ -546,10 +850,35 @@ sub run_build_steps_parallel {
push @lines,
"$id (exit=$f->{exit}, signal=$f->{signal}, core_dump=$f->{core_dump})";
}
die "Parallel build steps failed:\n " . join("\n ", @lines) . "\n";
# Tolerated: warn, don't die. The REQUIRED set is asserted after collection/deploy.
warn "WARN: some build steps failed (tolerated; required deps asserted after deploy):\n "
. join("\n ", @lines) . "\n";
}
}
# have_rpm: is there a non-src rpm named <name>-... under $dir?
sub have_rpm {
my ($dir, $name) = @_;
my @m = grep { !/\.src\.rpm$/ } glob("$dir/${name}-*.rpm");
return scalar(@m) > 0;
}
# assert_required_deps: the per-EL dep repo is unusable without these, so a MISSING one is
# fatal even though individual builder failures are tolerated above. genesis-base is required
# unless --skip-genesis.
sub assert_required_deps {
my ($dir) = @_;
# xCAT Requires all of these on every arch, and every one of them builds natively on every
# arch (the noarch deps -- grub2-xcat, xnba-undi -- just repackage committed artifacts), so
# a self-sufficient per-arch build produces the whole set with no cross-arch import.
my @req = qw(ipmitool-xcat syslinux-xcat grub2-xcat xnba-undi
perl-IO-Stty perl-HTTP-Async perl-Net-HTTPS-NB);
push @req, 'xCAT-genesis-base' unless $skip_genesis;
my @missing = grep { !have_rpm($dir, $_) } @req;
die "FATAL: required deps missing from $dir: @missing\n" if @missing;
print "[deps] required set present in $dir: @req\n";
}
sub collect_rpms {
my (%args) = @_;
my $roots = $args{roots} // [];
@@ -695,10 +1024,12 @@ sub build_mock_uniqueext {
sub resolve_xcat_source {
my ($requested, $root) = @_;
# Prefer the sibling ../xcat-core (the real layout: source/xcat-core beside source/xcat-dep)
# before the legacy xcat-source-code location.
my @candidates = (
$requested,
"$root/xcat-source-code",
"$root/../xcat-core",
"$root/xcat-source-code",
);
for my $c (@candidates) {
next if !defined($c) || $c eq '';
@@ -709,6 +1040,55 @@ sub resolve_xcat_source {
return eval { abs_path($requested) } || $requested;
}
# Fail-fast advisory lock on the output base. Uses an atomic mkdir (portable and reliable over
# NFS, unlike flock) of "<base>/.lock". A second run against the same --output dies immediately
# rather than racing on the shared tree. Only the process that created the lock removes it.
sub acquire_output_lock {
my ($base, $force) = @_;
my $lock = "$base/.lock";
if ($force && -d $lock) {
print "force-unlock: removing stale lock $lock\n";
_rmdir_lock($lock);
}
if (mkdir $lock) {
$HELD_LOCK = $lock;
$LOCK_OWNER_PID = $$;
my $host = capture('uname -n') || 'unknown';
if (open my $fh, '>', "$lock/owner") {
print {$fh} "host=$host\npid=$$\nepoch=" . time() . "\n";
close $fh;
}
return;
}
# mkdir failed: either it already exists (locked) or a real error.
if (-d $lock) {
my $info = '';
if (open my $fh, '<', "$lock/owner") { local $/; $info = <$fh>; close $fh; }
$info =~ s/\s+/ /g;
die "output $base is locked ($lock): $info\n"
. "another mockbuild-all run owns it; use a different --output or --force-unlock if stale.\n";
}
die "Cannot create lock $lock: $!\n";
}
sub _rmdir_lock {
my ($lock) = @_;
unlink "$lock/owner";
rmdir $lock;
}
# Release the lock on any exit path (normal, die, or signal) -- but ONLY in the process that
# created it. Forked children (per-builder and per-target ForkManager workers) inherit
# $HELD_LOCK; without the pid guard their exit would delete the parent's lock mid-run.
sub _release_lock_if_owner {
return unless $HELD_LOCK && defined $LOCK_OWNER_PID && $$ == $LOCK_OWNER_PID;
_rmdir_lock($HELD_LOCK) if -d $HELD_LOCK;
}
END { _release_lock_if_owner(); }
for my $sig (qw(INT TERM HUP)) {
$SIG{$sig} = sub { _release_lock_if_owner(); exit 1; };
}
sub read_os_release {
my ($path) = @_;
my %vals;
Binary file not shown.
+13 -1
View File
@@ -39,7 +39,19 @@ using 'select' lists.
%prep
%setup -q -n %{upstream_name}-%{upstream_version}
%patch 0 -p1
# Use the explicit -P form so the patch applies on EL8 (rpm 4.14) and EL9
# (rpm 4.16), EL10 (rpm 4.19), and openSUSE Leap 15 (rpm 4.14). The bare-number
# "%patch 0" form is only understood by rpm >= 4.18 and fails older rpm with
# "%patch without corresponding Patch: tag".
%patch -P 0 -p1
# openSUSE's brp-compress gzips man pages after the install file list is built,
# so the packaged file list then looks for *.3pm but finds *.3pm.gz. Disable the
# install-post hooks there (harmless for a noarch perl module) to keep names in
# sync; EL's brp-compress handling already matches, so scope this to SUSE.
%if 0%{?suse_version}
%define __os_install_post %{nil}
%endif
%build
CFLAGS="$RPM_OPT_FLAGS $CFLAGS" %__perl Makefile.PL
+13 -1
View File
@@ -37,7 +37,19 @@ addition allows non-blocking connect.
%prep
%setup -q -n %{upstream_name}-%{upstream_version}
%patch 0 -p1
# Use the explicit -P form so the patch applies on EL8 (rpm 4.14) and EL9
# (rpm 4.16), EL10 (rpm 4.19), and openSUSE Leap 15 (rpm 4.14). The bare-number
# "%patch 0" form is only understood by rpm >= 4.18 and fails older rpm with
# "%patch without corresponding Patch: tag".
%patch -P 0 -p1
# openSUSE's brp-compress gzips man pages after the install file list is built,
# so the packaged file list then looks for *.3pm but finds *.3pm.gz. Disable the
# install-post hooks there (harmless for a noarch perl module) to keep names in
# sync; EL's brp-compress handling already matches, so scope this to SUSE.
%if 0%{?suse_version}
%define __os_install_post %{nil}
%endif
%build
%__perl Makefile.PL
Binary file not shown.
+7
View File
@@ -1,6 +1,13 @@
# -*- rpm -*-
%define RPMVERSION 6.03
%define VERSION 6.03
# The syslinux-xcat subpackage is BuildArch: noarch but deliberately ships the
# arch-dependent PXELINUX/SYSLINUX bootloader blobs (pxelinux.0, *.c32) under
# /opt/xcat/share/xcat/netboot/syslinux. Newer rpm (EL10) does not flag these
# real-mode/COM32 binaries, but EL8/EL9 rpm aborts the build with
# "Arch dependent binaries in noarch package". Disable that QA gate so the
# self-contained xcat netboot payload builds across EL8/EL9/EL10.
%global _binaries_in_noarch_packages_terminate_build 0
Summary: Kernel loader which uses a FAT, ext2/3 or iso9660 filesystem or a PXE network
Name: syslinux
Version: %{RPMVERSION}
+4 -1
View File
@@ -80,7 +80,10 @@ make_path($log_dir);
print_step("Stage build environment");
remove_tree($work_dir) if -d $work_dir;
my $rpmbuild_top = "/var/tmp/xcat-rpmbuild-xnba";
# rpmbuild staging dir must be unique per run: --work-dir is run/target-scoped, so nesting it
# here keeps concurrent builds (e.g. parallel EL targets on one host) from wiping each other's
# tree. (Was a shared /var/tmp/xcat-rpmbuild-xnba, which collided under parallelism.)
my $rpmbuild_top = "$work_dir/rpmbuild";
remove_tree($rpmbuild_top) if -d $rpmbuild_top;
for my $d (qw(BUILD BUILDROOT RPMS SOURCES SPECS SRPMS)) {
make_path("$rpmbuild_top/$d");