mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-04-01 22:53:30 +00:00
Merge pull request #2 from VersatusHPC/fix/mock-build-packaging
fix: build with mock
This commit is contained in:
314
buildrpms.pl
Executable file
314
buildrpms.pl
Executable file
@@ -0,0 +1,314 @@
|
||||
#!/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 %opts = (
|
||||
targets => \@TARGETS,
|
||||
packages => \@PACKAGES,
|
||||
nproc => int(`nproc --all`),
|
||||
force => 0,
|
||||
verbose => 0,
|
||||
xcat_dep_path => "$PWD/../xcat-dep/",
|
||||
configure_nginx => 0,
|
||||
help => 0,
|
||||
nginx_port => 8080,
|
||||
);
|
||||
|
||||
GetOptions(
|
||||
"target=s@" => \$opts{targets},
|
||||
"package=s@" => \$opts{packages},
|
||||
"nproc=i" => \$opts{nproc},
|
||||
"verbose" => \$opts{verbose},
|
||||
"force" => \$opts{force},
|
||||
"xcat_dep_path=s" => \$opts{xcat_dep_path},
|
||||
"configure_nginx" => \$opts{configure_nginx},
|
||||
"help" => \$opts{help},
|
||||
"nginx_port" => \$opts{nginx_port},
|
||||
) or usage();
|
||||
|
||||
sub sh {
|
||||
my ($cmd) = @_;
|
||||
say "Running: $cmd"
|
||||
if $opts{verbose};
|
||||
open my $fh, "-|", "bash -lc '$cmd'" or die "cannot run $cmd: $!";
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
print $line
|
||||
if $opts{verbose};
|
||||
}
|
||||
close $fh;
|
||||
return $? >> 8;
|
||||
}
|
||||
|
||||
# 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 && ! $opts{force};
|
||||
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) = @_;
|
||||
my $chroot = "$pkg-$target";
|
||||
|
||||
my $diskcache = "dist/$target/srpms/$pkg-$VERSION-$RELEASE.src.rpm";
|
||||
return if -f $diskcache and not $opts{force};
|
||||
|
||||
my @opts;
|
||||
push @opts, "--quiet" unless $opts{verbose};
|
||||
|
||||
say "Building $diskcache";
|
||||
|
||||
sh(<<"EOF");
|
||||
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/"
|
||||
EOF
|
||||
}
|
||||
|
||||
sub buildpkgs {
|
||||
my ($pkg, $target) = @_;
|
||||
my $optsref = \%opts;
|
||||
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 $opts{force};
|
||||
|
||||
my @opts;
|
||||
push @opts, "--quiet" unless $opts{verbose};
|
||||
|
||||
say "Building $diskcache";
|
||||
|
||||
sh(<<"EOF");
|
||||
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
|
||||
EOF
|
||||
}
|
||||
|
||||
sub buildall {
|
||||
my ($pkg, $target) = @_;
|
||||
createmockconfig($pkg, $target);
|
||||
buildsources($pkg, $target);
|
||||
buildspkgs($pkg, $target);
|
||||
buildpkgs($pkg, $target);
|
||||
}
|
||||
|
||||
sub configure_nginx {
|
||||
my $xcat_dep_path = $opts{xcat_dep_path};
|
||||
my $port = $opts{nginx_port};
|
||||
my $conf = <<"EOF";
|
||||
server {
|
||||
listen $port;
|
||||
listen [::]:$port;
|
||||
EOF
|
||||
|
||||
# We always generate the nginx config for all
|
||||
# the targets, not $opts{targets}
|
||||
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 $xcat_dep_path;
|
||||
autoindex on;
|
||||
index off;
|
||||
allow all;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
write_text("/etc/nginx/conf.d/xcat-repos.conf", $conf);
|
||||
`systemctl restart nginx`;
|
||||
}
|
||||
|
||||
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 "";
|
||||
say STDERR " RPM builder script";
|
||||
say STDERR " .. build xCAT RPMs for these targets:";
|
||||
say STDERR map { " $_\n" } @TARGETS;
|
||||
say STDERR "";
|
||||
say STDERR " Options:";
|
||||
say STDERR "";
|
||||
say STDERR " --target <tgt> .................. build only these targets";
|
||||
say STDERR " --package <pkg> ................. build only these packages";
|
||||
say STDERR " --force ......................... override built RPMS";
|
||||
say STDERR " --configure_nginx ............... update nginx configuration";
|
||||
say STDERR " --nginx_port=8080 ............... change the nginx port in";
|
||||
say STDERR " (use with --configure_nginx)";
|
||||
say STDERR " --nproc <N> ..................... run up to N jobs in parallel";
|
||||
say STDERR " --xcat_dep_path=../xcat-dep ..... path to xcat-dep repositories";
|
||||
say STDERR "";
|
||||
say STDERR " If no --target or --package is given all combinations are built";
|
||||
say STDERR "";
|
||||
say STDERR " See test/README.md for more information";
|
||||
|
||||
say STDERR $errmsg if $errmsg;
|
||||
exit -1;
|
||||
}
|
||||
|
||||
sub main {
|
||||
return usage() if $opts{help};
|
||||
return configure_nginx() if $opts{configure_nginx};
|
||||
|
||||
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);
|
||||
|
||||
$pm->finish;
|
||||
}
|
||||
|
||||
$pm->wait_all_children;
|
||||
|
||||
for my $target ($opts{targets}->@*) {
|
||||
$pm->start and next;
|
||||
|
||||
update_repo($target);
|
||||
|
||||
$pm->finish;
|
||||
}
|
||||
$pm->wait_all_children;
|
||||
|
||||
configure_nginx();
|
||||
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
170
buildrpms.sh
170
buildrpms.sh
@@ -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
|
||||
20
test/Containerfile
Normal file
20
test/Containerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
ARG RELEASEVER=9
|
||||
FROM quay.io/rockylinux/rockylinux:${RELEASEVER}-ubi-init
|
||||
ARG RELEASEVER
|
||||
|
||||
RUN dnf install -y epel-release
|
||||
|
||||
RUN echo "RELEASEVER=${RELEASEVER}"
|
||||
RUN if [[ "${RELEASEVER}" == "8" ]]; then \
|
||||
dnf config-manager --set-enabled powertools epel; \
|
||||
elif [[ "${RELEASEVER}" =~ /(9|10)/ ]]; then \
|
||||
dnf config-manager --set-enabled crb epel; \
|
||||
else \
|
||||
echo "Invalid RELEASEVER=${RELEASEVER}"; \
|
||||
exit -1; \
|
||||
fi
|
||||
RUN dnf makecache
|
||||
RUN dnf install -y hostname perl perl-core
|
||||
RUN dnf clean all
|
||||
|
||||
WORKDIR /workspace
|
||||
102
test/README.md
Normal file
102
test/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Testing Workflow for buildrpms.pl
|
||||
|
||||
## Overview
|
||||
|
||||
Requirements:
|
||||
|
||||
_The following software are assumed to be instaled in the host responsible for building the RPMs and running the tests._
|
||||
|
||||
* [mock](https://rpm-software-management.github.io/mock/) for building the RPMs
|
||||
* nginx for serving RPM repositories
|
||||
* [podman](https://podman.io)
|
||||
* This was tested on a RHEL9.7 host.
|
||||
|
||||
|
||||
_Note: Before start, ensure nginx is listening 8080. (the script will not do that for you, you need to change the nginx.conf and restart it), more on this below_
|
||||
|
||||
Workflow:
|
||||
|
||||
`buildrpms.pl` is the entry point for generating all xCAT RPMs required for a specific [mock](https://rpm-software-management.github.io/mock/) target (for example `rhel+epel-9-x86_64`, `rhel+epel-10-x86_64`). Use `mock --list-chroots` to see all possible postions. _But note that only `rhle+epel-{8,9,10}` are being tested now_. Each target corresponds to a mock chroot and eventually to a container image used by the test harness. The high-level flow is:
|
||||
|
||||
1. Prepare the dependency repositories (`../xcat-dep`) for the target (more on this below)
|
||||
2. Run `buildrpms.pl` to build or reuse RPMs for the target and export a repository.
|
||||
3. Provision the testing container for the same target.
|
||||
4. Execute the automated test suite inside the container.
|
||||
|
||||
All scripts are idempotent. They only rebuild or reinstall what is missing. Pass `--force` to any step when you want to overwrite existing content.
|
||||
|
||||
## xCAT Runtime Dependencies (`../xcat-dep`)
|
||||
- The dependency repositories must live one directory above this repo, in `../xcat-dep`.
|
||||
- We keep a tarball that already includes the EL 8, EL 9 and EL 10 dependency RPMs. Extract the tarball so that the directory tree looks like `../xcat-dep/<el version>/<arch>/`.
|
||||
- Dependencies are only required to run xCAT. Building does not require xcat-dep.
|
||||
|
||||
The expected structure is like this
|
||||
|
||||
xcat-dep/
|
||||
├── el10
|
||||
│ └── x86_64
|
||||
│ └── repodata
|
||||
| └── *.rpm
|
||||
├── el9
|
||||
│ └── x86_64
|
||||
│ └── repodata
|
||||
| └── *.rpm
|
||||
└── el8
|
||||
└── x86_64
|
||||
└── repodata
|
||||
└── *.rpm
|
||||
|
||||
|
||||
## Building RPMs for a Target
|
||||
```bash
|
||||
./buildrpms.pl [--target <target>] [--package <pkg>] [--force] [--nproc N] [--xcat_dep_path /path/to/xcat-dep] [--nginx_port 8080]
|
||||
```
|
||||
|
||||
- `--target` may be repeated; by default all supported targets (`rhel+epel-{8,9,10}-x86_64`) are built.
|
||||
- `--package` narrows the build to specific RPM names; the default list contains every xCAT component.
|
||||
- `--force` rebuilds even if the corresponding SRPM/RPM already exists under `dist/<target>/`.
|
||||
- `--nproc N` controls the amount of parallel mock jobs (defaults to `nproc --all`).
|
||||
- `--xcat_dep_path` tells the nginx helper where the dependency repos live (defaults to `../xcat-dep`).
|
||||
- `--nginx_port` changes the port used when generating `/etc/nginx/conf.d/xcat-repos.conf`.
|
||||
- Passing `--configure_nginx` alone regenerates the nginx configuration without building.
|
||||
|
||||
Example – rebuild only `perl-xCAT` for EL9 and overwrite previous artifacts:
|
||||
|
||||
```bash
|
||||
./buildrpms.pl --target rhel+epel-9-x86_64 --package perl-xCAT --force
|
||||
```
|
||||
|
||||
Under the hood the script invokes [mock](https://rpm-software-management.github.io/mock/) to build SRPMs and RPMs, skips work when files already exist (unless `--force` is used), runs `createrepo dist/<target>/rpms`, and finally rewrites the nginx configuration so the repo is served automatically.
|
||||
|
||||
All builds run in parallel according to `--nproc`. Be aware that mock consumes significant disk space (plan for at least ~50 GB between `/var/lib/mock` and `/var/cache/mock`).
|
||||
|
||||
### nginx on Port 8080
|
||||
- `buildrpms.pl` assumes nginx exposes the generated repository on port 8080. Manually update the main nginx configuration (for example `/etc/nginx/nginx.conf`) so that it listens on `8080` port. The scripts will create a `/etc/nginx/conf.d/xcat-repos.conf` file with all the repositories configured and restart
|
||||
nginx at each run.
|
||||
|
||||
## Preparing the Test Container
|
||||
```bash
|
||||
test/scripts/setuptesthost.pl --setup_container --target <target> [--force]
|
||||
```
|
||||
|
||||
- This builds a container image and creates a container named `xcattest-elX` (X is 8, 9 or 10 depending on the target).
|
||||
- The container setup is idempotent: it checks for an existing container/image and skips recreation unless you provide `--force`.
|
||||
- The EL `RELEASEVER` (8, 9 or 10) is deduced from the target which is expected to be a triple in the format `<DISTRO>-<RELEASEVER>-<ARCH>` and it is used to as `--build-arg RELEASEVER=<RELEASEVER>` during the container image building.
|
||||
|
||||
## Running the Automated Tests
|
||||
Once the container exists and nginx is serving the repo:
|
||||
|
||||
```bash
|
||||
podman exec -it xcattest-el10 scripts/testxcat.pl --all
|
||||
```
|
||||
|
||||
- Replace `xcattest-el10` with the appropriate container name. The script configures the repository inside the container, installs xCAT, ensures `xcatd` is running, and finally runs `lsdef` to verify daemon connectivity.
|
||||
- The tester exposes additional knobs: use `--setup_repos`, `--install`, `--uninstall`, `--reinstall`, `--validate`, or `--all` (default in the example) plus `--nginx_port` if your repo is served on a different port. Combine these as needed to drive just one phase or the entire install/validate pass.
|
||||
- You can safely rerun the command; it will reuse the container state unless `--force` is supplied to the helper scripts, and `--reinstall` forces a clean uninstall/install cycle inside the container.
|
||||
|
||||
## End-to-End Checklist
|
||||
- Dependencies extracted to `../xcat-dep` for all EL versions you plan to build.
|
||||
- `buildrpms.pl` completes successfully for the target and produces a repository.
|
||||
- nginx listens on port 8080 and serves the generated repository.
|
||||
- `test/scripts/setuptesthost.pl --setupcontainer --target <target>` creates or updates the `xcattest-elX` container.
|
||||
- `podman exec -it xcattest-elX scripts/testxcat.pl --all` runs to completion and verifies the xCAT stack inside the container.
|
||||
105
test/scripts/setuptesthost.pl
Executable file
105
test/scripts/setuptesthost.pl
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use Getopt::Long qw(GetOptions);
|
||||
use Cwd qw(cwd);
|
||||
|
||||
my $PWD = cwd();
|
||||
|
||||
sub sh {
|
||||
my ($cmd) = @_;
|
||||
say "Running: $cmd";
|
||||
open my $fh, "-|", $cmd or die "cannot run $cmd: $!";
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
print $line;
|
||||
}
|
||||
close $fh;
|
||||
return $? >> 8;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
say STDERR "Usage: $0 --setup_container --target <target> [--force]";
|
||||
exit -1;
|
||||
}
|
||||
|
||||
sub parseopts {
|
||||
my %opts = (
|
||||
target => "",
|
||||
setup_container => 0,
|
||||
force => 0,
|
||||
);
|
||||
|
||||
GetOptions(
|
||||
"target=s" => \$opts{target},
|
||||
"setup_container" => \$opts{setup_container},
|
||||
"force" => \$opts{force},
|
||||
) or usage();
|
||||
|
||||
usage()
|
||||
if $opts{setup_container}
|
||||
and not $opts{target};
|
||||
|
||||
|
||||
return \%opts;
|
||||
};
|
||||
|
||||
sub containerexists {
|
||||
my ($name) = @_;
|
||||
return sh("podman container exists $name") == 0;
|
||||
}
|
||||
|
||||
sub imageexists {
|
||||
my ($imagename) = @_;
|
||||
return sh("podman image exists $imagename") == 0;
|
||||
}
|
||||
|
||||
sub cleanupcontainerandimage {
|
||||
my ($container, $image) = @_;
|
||||
return sh(<<"EOF");
|
||||
podman kill $container
|
||||
podman rm -f $container
|
||||
podman rmi -f $image
|
||||
EOF
|
||||
}
|
||||
|
||||
sub setup_container {
|
||||
my ($opts) = @_;
|
||||
my $target = $opts->{target};
|
||||
|
||||
|
||||
my $releasever = int((split /-/, $target, 3)[1]);
|
||||
my $name = "xcattest-el$releasever";
|
||||
|
||||
cleanupcontainerandimage($name, "$name-image")
|
||||
if $opts->{force};
|
||||
|
||||
sh("podman build -t $name-image --build-arg RELEASEVER=$releasever test/")
|
||||
unless imageexists("$name-image");
|
||||
my $script = <<"EOF";
|
||||
podman create --name $name \\
|
||||
--privileged \\
|
||||
--systemd=true \\
|
||||
--cap-add=ALL \\
|
||||
-v "$PWD/test/scripts:/workspace/scripts:Z" \\
|
||||
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \\
|
||||
--tmpfs /tmp \\
|
||||
--tmpfs /run \\
|
||||
$name-image
|
||||
podman start $name
|
||||
EOF
|
||||
sh($script) unless containerexists($name);
|
||||
}
|
||||
|
||||
sub main {
|
||||
my $opts = parseopts();
|
||||
|
||||
return setup_container($opts) if $opts->{setup_container};
|
||||
|
||||
|
||||
usage();
|
||||
};
|
||||
|
||||
main();
|
||||
114
test/scripts/testxcat.pl
Executable file
114
test/scripts/testxcat.pl
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use Data::Dumper qw(Dumper);
|
||||
use Getopt::Long qw(GetOptions);
|
||||
use File::Slurper qw(read_text write_text);
|
||||
|
||||
my %opts = (
|
||||
releasever => int(`rpm --eval '%{rhel}'`),
|
||||
verbose => 0,
|
||||
setup_repos => 0,
|
||||
install => 0,
|
||||
uninstall => 0,
|
||||
reinstall => 0,
|
||||
validate => 0,
|
||||
quiet => 0,
|
||||
all => 0,
|
||||
nginx_port => 8080,
|
||||
);
|
||||
|
||||
GetOptions(
|
||||
'releasever=i' => \$opts{releasever},
|
||||
verbose => \$opts{verbose},
|
||||
quiet => \$opts{quiet},
|
||||
setup_repos => \$opts{setup_repos},
|
||||
install => \$opts{install},
|
||||
uninstall => \$opts{uninstall},
|
||||
reinstall => \$opts{reinstall},
|
||||
validate => \$opts{validate},
|
||||
all => \$opts{all},
|
||||
nginx_port => \$opts{nginx_port},
|
||||
) or usage();
|
||||
|
||||
sub sh {
|
||||
my ($cmd) = @_;
|
||||
say "Running: $cmd"
|
||||
unless $opts{quiet};
|
||||
open my $fh, "-|", "bash -lc '$cmd'" or die "cannot run $cmd: $!";
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
print $line
|
||||
unless $opts{quiet};
|
||||
}
|
||||
close $fh;
|
||||
return $? >> 8;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
say STDERR "usage $0: [--releasever=9] [--verbose] [--quiet] {--setup_repos|--install|--uninstall|--reinstall|--validate|--all} [--nginx-port=8080]";
|
||||
}
|
||||
|
||||
sub setup_repos {
|
||||
say "Setting up repositories"
|
||||
unless $opts{quiet};
|
||||
my $releasever = $opts{releasever};
|
||||
my $port = $opts{nginx_port};
|
||||
my $content = <<"EOF";
|
||||
[xcat3]
|
||||
name=xcat3
|
||||
baseurl=http://host.containers.internal:$port/rhel+epel-$releasever-x86_64/
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
|
||||
[xcat3-deps]
|
||||
name=xcat3-deps
|
||||
baseurl=http://host.containers.internal:$port/xcat-dep/el$releasever/x86_64/
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
EOF
|
||||
write_text("/etc/yum.repos.d/xcat-repos.repo", $content);
|
||||
sh("dnf makecache --repo=xcat3 --repo=xcat3-deps");
|
||||
}
|
||||
|
||||
sub uninstall {
|
||||
sh("dnf remove -y xCAT");
|
||||
sh("rm -rf /opt/xcat /etc/xcat /var/run/xcat /root/.xcat /install /tftpboot");
|
||||
}
|
||||
|
||||
sub install {
|
||||
sh("dnf install -y xCAT");
|
||||
}
|
||||
|
||||
sub validate {
|
||||
# Put commands to validate xcat installation here
|
||||
sh("systemctl is-active xcatd") == 0 or die("xcatd not running?");
|
||||
sh("lsdef") == 0 or die("lsdef not working");
|
||||
}
|
||||
|
||||
sub main {
|
||||
return setup_repos() if $opts{setup_repos};
|
||||
return install() if $opts{install};
|
||||
return uninstall() if $opts{uninstall};
|
||||
return validate() if $opts{validate};
|
||||
|
||||
return do {
|
||||
setup_repos();
|
||||
uninstall()
|
||||
if ($opts{reinstall} or $opts{uninstall});
|
||||
install();
|
||||
validate();
|
||||
} if $opts{all};
|
||||
|
||||
return do {
|
||||
uninstall();
|
||||
install();
|
||||
} if $opts{reinstall};
|
||||
|
||||
usage();
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -843,6 +843,9 @@ sub genSSHRootKeys
|
||||
sub settunables
|
||||
|
||||
{
|
||||
# tunnables are not settable inside containers, we use
|
||||
# container for integration testing
|
||||
return if $ENV{container};
|
||||
# tuning ARP on Linux
|
||||
# set for right now
|
||||
|
||||
|
||||
Reference in New Issue
Block a user