diff --git a/.github/workflows/genesis-openembedded.yml b/.github/workflows/genesis-openembedded.yml index 0a80e22..326c776 100644 --- a/.github/workflows/genesis-openembedded.yml +++ b/.github/workflows/genesis-openembedded.yml @@ -35,6 +35,10 @@ jobs: perl -c mockbuild-all.pl perl -c BuildUtils.pm perl -c sbuild-all.pl + perl -c ipxe-xcat/mockbuild.pl + perl -c ipxe-xcat/sbuild.pl + perl -c ipxe-xcat/verify-payload.pl + rpmspec -P ipxe-xcat/ipxe-xcat.spec >/dev/null rpmspec -P \ -D 'genesis_arch x86_64' \ -D 'version 2.19.0' \ @@ -44,6 +48,9 @@ jobs: genesis-openembedded/build \ genesis-openembedded/package \ genesis-openembedded/verify-release \ + ipxe-xcat/mockbuild.pl \ + ipxe-xcat/sbuild.pl \ + ipxe-xcat/verify-payload.pl \ lib/XCAT/BuildUtils.pm \ lib/XCAT/GenesisRelease.pm \ mockbuild-all.pl \ @@ -51,6 +58,7 @@ jobs: t/common-repo-gate.t \ t/genesis_openembedded_release.t \ t/genesis_openembedded_consumer.t \ + t/ipxe_xcat_payload.t \ t/lib/XCAT/GenesisReleaseTest.pm - name: Run package tests @@ -58,8 +66,12 @@ jobs: prove -v t/build_utils.t prove -v t/build_timeout.t prove -v t/sbuild-all.t + prove -v t/goconserver_cross_build.t + prove -v t/ipxe_xcat_payload.t prove -v t/mockbuild-all.t prove -v t/net_dns_rr_types.t + prove -v t/repo-lock-race.t + prove -v t/nfslock.t prove -v -It/lib t/genesis_openembedded_release.t sudo -E prove -v -It/lib t/genesis_openembedded_consumer.t prove -v t/riscv64_perl_cell.t diff --git a/BUILD.md b/BUILD.md index e8fd921..27c8a77 100644 --- a/BUILD.md +++ b/BUILD.md @@ -50,6 +50,7 @@ This guide uses the following placeholders consistently: - `/goconserver/mockbuild.pl` - `/conserver/mockbuild.pl` - `/xnba/mockbuild.pl` +- `/ipxe-xcat/mockbuild.pl` - `/mockbuild-perl-packages.pl` - `/buildrpms.pl` — only to build the OS-dependent `xCAT-genesis-base` package (unless `--skip-genesis` is set); the full xCAT core is built separately by the xcat-core pipeline, not here. @@ -103,7 +104,7 @@ Use these flags to skip specific operations: - `--skip-genesis` - Skips the `xCAT-genesis-base` build (`/buildrpms.pl --package xCAT-genesis-base`). - `--skip-xcat-dep` - - Skips non-perl xcat-dep package builders (`elilo`, `grub2-xcat`, `ipmitool-xcat`, `syslinux-xcat`, `goconserver`, `conserver-xcat`, `xnba-undi`). + - Skips non-perl xcat-dep package builders (`elilo`, `grub2-xcat`, `ipmitool-xcat`, `syslinux-xcat`, `goconserver`, `conserver-xcat`, `xnba-undi`, `ipxe-xcat`). - `--skip-perl` - Skips `/mockbuild-perl-packages.pl`. - With any of the three flags above, the run repository, the tarball and the deployed cell keep @@ -138,8 +139,10 @@ Use these flags to skip specific operations: - Adds extra artifact roots to the collection phase (repeatable). - `--dry-run` - Prints planned actions without executing them. -- `--force-unlock` - - Removes a stale lock after the previous publisher has been checked. +- `--try-unlock-timeout ` + - Waits about N seconds for a lock that a live process holds, in retries of 3 seconds with + at least one retry, then fails and prints the command that removes the lock. A lock whose + owner is proven dead on this host is taken over at once. # Prerequisites @@ -245,12 +248,19 @@ published once under `xcat-dep/common`. Source RPMs stay in the verified release directory. Existing per-EL repositories keep the old Genesis packages and contain no OpenEmbedded copies. -The build holds separate locks for its work area and the published repository. -It prepares the complete common repository in a temporary directory, then +The build locks its work area (`/.lock`), each repository cell it deploys +(`/rh/..lock`) and, while it publishes, the common repository +(`/.common-publish.lock`). The per-arch runs of one build lock different +cells, so they run in parallel. A lock whose owner is dead is taken over only on the +owner's host. From any other host the build waits `--try-unlock-timeout` seconds, +then fails with the command that removes the lock. The protocol is documented at the +top of `lib/XCAT/NFSLock.pm`. + +The build prepares the complete common repository in a temporary directory, then replaces the previous repository only after package verification, metadata generation, and signing have succeeded. If a stopped publisher leaves staging -or backup directories behind, rerun it with ``--force-unlock`` to recover the -previous repository before starting a new publication. +or backup directories behind, the next run recovers the previous repository +when no other run holds the common lock. Repository publication requires all eight current architectures. Version 1 release manifests remain readable, but they cannot replace the current @@ -459,7 +469,7 @@ missing, and then builds the `[rocky-10-riscv64-xcat]` section of `packages-mani | goconserver | cross-compiled on the host (`GOARCH=riscv64`), packaged with `rpmbuild --target riscv64` | | grub2-xcat (noarch) | built in the native, EPEL-free `rocky-10-x86_64` chroot | | perl list6 + EPEL gap (`--epel-gap`) | `mockbuild-perl-packages.pl --target-arch riscv64 --noarch-mock-cfg rocky-10-x86_64 --epel-gap`: XS modules in the riscv64 chroot, noarch modules in the native chroot | -| elilo-xcat, syslinux-xcat, xnba-undi (noarch) | built in the native `rocky-10-x86_64` chroot, like grub2-xcat: a riscv64 management node serves the x86 nodes of a mixed cluster. The target is cross-built on x86_64 only, as its mock config states | +| elilo-xcat, ipxe-xcat, syslinux-xcat, xnba-undi (noarch) | built in the native `rocky-10-x86_64` chroot, like grub2-xcat: a riscv64 management node serves the x86 nodes of a mixed cluster. The target is cross-built on x86_64 only, as its mock config states | There is no EPEL for riscv64, so the perl deps of xCAT that EL10 otherwise takes from EPEL are built here as well (`--epel-gap` in `mockbuild-perl-packages.pl`: perl-Crypt-Blowfish, @@ -611,16 +621,16 @@ Codename ↔ version (the single supported set — `BuildUtils` is the source of `mk-build-deps`, so version constraints, `a | b` alternatives and arch qualifiers are honoured) are all **fatal** on failure — and since nothing survives the session, a package whose `debian/control` forgets a `Build-Depends` cannot build green on a sibling package's leftovers. -- **Per-arch package sets (`debs-manifest.conf`).** One `[-]` section per target. The - noarch boot components (`syslinux-xcat`/`grub2-xcat`/`elilo-xcat`/`xnba-undi`, `Architecture:all`) - are built ONCE on amd64 — single producer, their source is x86-only — and assembled into every - arch's `Packages` index. They are listed for **ppc64el too, as required-present**, so the gate - verifies the ppc repo actually carries them (a ppc MN needs them for netboot, matching the EL - manifest). `build_one_codename` **skips** an `Architecture:all` package on any non-amd64 arch - (detected via `control_binary_arch`), so ppc64el and riscv64 build only the genuinely - arch-specific compiled deps (`ipmitool-xcat`, `conserver-xcat`, `goconserver`) yet still verify the - boot components they need. The riscv64 sections require the same four boot components as - ppc64el: a riscv64 management node serves the x86 nodes of a mixed cluster. +- **Per-arch package sets (`debs-manifest.conf`).** One `[-]` section per target. + The noarch boot components (`syslinux-xcat`/`grub2-xcat`/`elilo-xcat`/`xnba-undi`/`ipxe-xcat`, + `Architecture:all`) are built ONCE on amd64 — single producer, most of them from x86-only source — + and assembled into every arch's `Packages` index. They are listed for **ppc64el too, as + required-present**, so the gate verifies the ppc repo actually carries them (a ppc MN needs them + for netboot, matching the EL manifest). `build_one_codename` **skips** an `Architecture:all` + package on any non-amd64 arch (detected via `control_binary_arch`), so ppc64el and riscv64 build + only the genuinely arch-specific compiled deps (`ipmitool-xcat`, `conserver-xcat`, `goconserver`) + yet still verify the boot components they need. The riscv64 sections require the same five boot + components as ppc64el: a riscv64 management node serves the x86 nodes of a mixed cluster. - **Fail-hard.** Any required chroot / package / artifact failure, or any version-pin mismatch, fails the whole run non-zero. - **Genesis keeps its maintained packaging.** A native `xcat-genesis-base` deb is INGESTED as-is when @@ -686,7 +696,7 @@ needs no `--mirror`. | ipmitool-xcat, conserver-xcat | `dpkg-buildpackage` in the emulated riscv64 chroot | | goconserver | same chroot, compiled by the Go toolchain the chroot installs for riscv64 | | grub2-xcat (`Architecture:all`) | built once on amd64 and assembled into the riscv64 index; listed in the riscv64 manifest sections as required-present, because a riscv64 management node needs it to netboot | -| syslinux-xcat, elilo-xcat, xnba-undi (`Architecture:all`) | built once on amd64 and assembled into the riscv64 index; required-present like grub2-xcat, because a riscv64 management node serves the x86 nodes of a mixed cluster | +| syslinux-xcat, elilo-xcat, xnba-undi, ipxe-xcat (`Architecture:all`) | built once on amd64 and assembled into the riscv64 index; required-present like grub2-xcat, because a riscv64 management node serves the x86 nodes of a mixed cluster | | xcat-genesis-base | not built: no riscv64 section names it, and the build skips the step when the manifest does not ask for it, so `--skip-genesis` is unnecessary here | The riscv64 ipmitool-xcat deb is installed into the chroot that built it and diff --git a/BuildUtils.pm b/BuildUtils.pm index c99005f..3753608 100644 --- a/BuildUtils.pm +++ b/BuildUtils.pm @@ -37,7 +37,7 @@ our @EXPORT_OK = qw( supported_arches is_supported_arch chroot_name chroot_sources_list chroot_is_disposable chroot_build_script chroot_build_timeout - control_field genesis_deb_control + control_field genesis_debs_for_codename deb_field deb_version deb_hash cross_copy_genesis_deb build_deb_in_chroot ); @@ -476,53 +476,6 @@ sub control_field { return undef; } -# genesis_deb_control: build the DEBIAN/control text for the cross-arch-converted xcat-genesis-base -# deb, PRESERVING the maintained packaging's semantics (Depends/Breaks/Replaces/Section/Priority) -# instead of hand-rolling a bare 5-field control (the bug in build-dep-debs.sh flagged by review -# concern #2). $maintained is the text of xCAT-genesis-builder/debian/control (or undef when it -# cannot be located — then a minimal-but-honest control is produced and the caller should warn). -# $pkgname is e.g. xcat-genesis-base-ppc64el, $version the deb version, $arch 'all'. Pure/testable. -sub genesis_deb_control { - my ($maintained, $pkgname, $version, $arch) = @_; - $arch ||= 'all'; - my %f = ( - Package => $pkgname, - Version => $version, - Architecture => $arch, - Section => 'admin', - Priority => 'optional', - Maintainer => 'xCAT ', - ); - if (defined $maintained && $maintained ne '') { - for my $k (qw(Section Priority Maintainer Depends Pre-Depends Recommends - Suggests Breaks Replaces Conflicts Provides)) { - my $v = control_field($maintained, $k); - $f{$k} = $v if defined $v && $v ne ''; - } - my $desc = control_field($maintained, 'Description'); - $f{Description} = $desc if defined $desc && $desc ne ''; - } - $f{Description} ||= 'xCAT Genesis netboot image (converted from the rpm for cross-arch netboot)'; - # ${misc:Depends} is a debhelper substitution var that only resolves during a real dpkg build; - # in a hand-assembled control it would ship literally, so drop it from a preserved Depends. - for my $k (qw(Depends Pre-Depends Recommends Suggests)) { - next unless defined $f{$k}; - $f{$k} =~ s/\$\{[^}]+\}//g; - $f{$k} =~ s/^[,\s]+|[,\s]+$//g; - $f{$k} =~ s/\s*,\s*,\s*/, /g; - delete $f{$k} if $f{$k} eq ''; - } - my @order = qw(Package Version Section Priority Architecture Maintainer - Pre-Depends Depends Recommends Suggests Breaks Replaces Conflicts - Provides Description); - my $out = ''; - for my $k (@order) { - next unless defined $f{$k} && $f{$k} ne ''; - $out .= "$k: $f{$k}\n"; - } - return $out; -} - # --------------------------------------------------------------------------------------------------- # Built-.deb inspection + cross-arch genesis provisioning (filesystem; tested with real dpkg-deb). # --------------------------------------------------------------------------------------------------- @@ -596,9 +549,30 @@ sub deb_hash { # Idempotent; content is compared by deb_hash so a stale same-name deb is refreshed rather than # mistaken for up to date. $sign is an optional coderef($deb_path) invoked on each copied deb; pass # undef to skip. Mirrors MockBuildUtils::cross_copy_genesis for the apt world. +# $codename, when given, narrows the set to the image built for that release -- see +# genesis_debs_for_codename. +# genesis_debs_for_codename: the Genesis debs that belong to ONE Ubuntu release. +# +# The Genesis image carries the kernel of the root that built it, so xcat-core builds one deb per +# codename and stamps the codename into the version (2.19.0-snap...~noble). Staging all of them into +# every suite publishes three images per suite, and apt serves the newest -- the image of another +# release. A deb with no codename in its version predates the native build and serves every release. +sub genesis_debs_for_codename { + my ($debs, $codename) = @_; + my @debs = @{ $debs || [] }; + return @debs unless @debs && defined $codename && $codename ne ''; + my $marked = qr/_[^_]*~[A-Za-z0-9.]+_[^_]*\.deb\z/; + return @debs unless grep { basename($_) =~ $marked } @debs; + return grep { + my $base = basename($_); + $base =~ /_[^_]*~\Q$codename\E_[^_]*\.deb\z/ || $base !~ $marked; + } @debs; +} + sub cross_copy_genesis_deb { - my ($from, $to, $arch, $sign) = @_; - my @src = glob("$from/xcat-genesis-base-$arch\_*.deb"); + my ($from, $to, $arch, $sign, $codename) = @_; + my @src = genesis_debs_for_codename( + [ glob("$from/xcat-genesis-base-$arch\_*.deb") ], $codename); return 0 if !@src; my %want = map { basename($_) => $_ } @src; my @existing = glob("$to/xcat-genesis-base-$arch\_*.deb"); diff --git a/MockBuildUtils.pm b/MockBuildUtils.pm index ff62ed0..3f2bf85 100644 --- a/MockBuildUtils.pm +++ b/MockBuildUtils.pm @@ -6,10 +6,13 @@ package MockBuildUtils; use strict; use warnings; use Exporter 'import'; -use File::Basename qw(basename); +use File::Basename qw(basename dirname); use File::Copy qw(copy); use File::Glob qw(bsd_glob); use File::Find; +use File::Path qw(remove_tree); +use lib dirname(__FILE__) . '/lib'; +use XCAT::NFSLock (); use Sys::Hostname; use Digest::MD5 qw(md5_hex); @@ -23,7 +26,8 @@ our @EXPORT_OK = qw( parse_evr evr_cmp evr_constraint_ok parse_pin rpmkeys_checksig_problem rpm_version rpm_release rpm_sigmd5 rpm_is_signed restamp_release_line cross_copy_genesis finalize_xcat_dep bump_dep_release_suffix - build_mock_uniqueext rpm_in_cell + build_mock_uniqueext rpm_in_cell resolve_mock_cfg + recover_common_repository ); # install_deps_packages($os_id): the host packages mockbuild-all.pl needs to run at all, for the @@ -545,6 +549,15 @@ sub finalize_xcat_dep { my ($x86_64_repo, $ppc64le_repo, %opt) = @_; my $sign = $opt{sign}; my $reindex = $opt{reindex}; + # The arches whose cells this run writes. The others are read only: each host finalizes the + # cells it deploys, so it never holds a cell lock that only another host could reclaim. + my %known = map { $_->{arch} => 1 } @GENESIS_ARCHES; + my @only = @{ $opt{only} // [ map { $_->{arch} } @GENESIS_ARCHES ] }; + for my $a (@only) { + die "FATAL: [finalize] no cross-arch genesis for arch '$a'\n" unless $known{$a}; + } + my %write = map { $_ => 1 } @only; + my @dst_arches = grep { $write{ $_->{arch} } } @GENESIS_ARCHES; print_step('Finalize xcat-dep: cross-arch genesis-base provisioning (issue #7610)'); print "x86_64-repo: $x86_64_repo\n"; print "ppc64le-repo: $ppc64le_repo\n"; @@ -585,7 +598,7 @@ sub finalize_xcat_dep { # N-way cross-copy: put each arch's genesis into EVERY other arch's repo dir. my @summary; for my $src (@GENESIS_ARCHES) { - for my $dst (@GENESIS_ARCHES) { + for my $dst (@dst_arches) { next if $src->{arch} eq $dst->{arch}; my $n = cross_copy_genesis($adir{$src->{arch}}, $adir{$dst->{arch}}, $src->{tarch}, $sign); push @summary, "$n $src->{tarch} -> $dst->{arch}"; @@ -596,7 +609,7 @@ sub finalize_xcat_dep { # rpm on disk (so cross_copy_genesis now returns 0) yet ABSENT from repomd.xml -- which no # signature gate catches. Re-indexing is cheap (tiny repos) and idempotent, and heals that # partial state; skipped only when no signer/indexer was injected. - if ($reindex) { $reindex->($adir{$_->{arch}}) for @GENESIS_ARCHES; } + if ($reindex) { $reindex->($adir{$_->{arch}}) for @dst_arches; } print "[finalize] $osdir: " . join(', ', @summary) . "\n"; $pairs++; } @@ -723,4 +736,78 @@ sub build_mock_uniqueext { return sprintf("mba-%02d-%s-%s", $idx, $run_part, $label_part); } +#-------------------------------------------------------------------------------- + +=head3 recover_common_repository + + Descriptions: + Put back the common tree that an interrupted publication moved aside, and + remove the staging trees it left. Runs only under the common lock, so it + never removes the staging tree of a run that is still publishing. + Arguments: + $base: the --repo-dep directory + Returns: + 1 when the recovery ran, 0 when another run holds the common lock. + +=cut + +#-------------------------------------------------------------------------------- +sub recover_common_repository { + my ($base) = @_; + my $path = "$base/.common-publish.lock"; + my $lock = eval { XCAT::NFSLock->acquire($path, label => 'common lock') }; + unless ($lock) { + # The lock is live or unproven: this is not the place to offer its removal. + print "common recovery skipped: another run holds $path\n"; + return 0; + } + my $destination = "$base/common"; + my @backups = sort { + ((stat($a))[9] // 0) <=> ((stat($b))[9] // 0) + } grep { -d $_ && !-l $_ } bsd_glob("$base/.common.previous.*"); + + if (!-e $destination && !-l $destination && @backups) { + my $backup = pop(@backups); + unless (rename($backup, $destination)) { + my $error = $!; + $lock->release; + die "Cannot restore interrupted common repository $backup: $error\n"; + } + } + remove_tree($_) for grep { -d $_ && !-l $_ } @backups; + + for my $staging (bsd_glob("$base/.common.*")) { + next if $staging =~ m{/\.common\.previous\.}; + remove_tree($staging) if -d $staging && !-l $staging; + } + $lock->release; + return 1; +} + +# resolve_mock_cfg($os_id, $rel, $arch[, $cfg_dir]): the mock config for EL release $rel on this +# host, +epel--. /etc/os-release says 'almalinux' where mock-core-configs names the +# file 'alma', so the short form is tried too. $cfg_dir defaults to /etc/mock. +sub resolve_mock_cfg { + my ($os_id, $rel, $arch, $cfg_dir) = @_; + $cfg_dir //= '/etc/mock'; + my %short_forms = ( + almalinux => 'alma', + 'centos-stream' => 'centos-stream', + rocky => 'rocky', + ); + # Resolve by CONFIG-FILE existence, not by running `mock --print-root-path`: the latter can fail + # transiently (bootstrap chroot setup, a concurrent mock holding a lock) and made el10 flakily + # "resolve" to the long form that has no .cfg. Checking /.cfg is deterministic. + for my $id ($os_id, (exists $short_forms{$os_id} ? ($short_forms{$os_id}) : ())) { + my $candidate = "${id}+epel-${rel}-${arch}"; + if (-f "$cfg_dir/${candidate}.cfg") { + print "Mock config resolved: $candidate\n" if $id ne $os_id; + return $candidate; + } + } + my $short = $short_forms{$os_id} // $os_id; + die "Could not find mock config for ${os_id}+epel-${rel}-${arch} " + . "(tried $cfg_dir/${os_id}+epel-${rel}-${arch}.cfg and $cfg_dir/${short}+epel-${rel}-${arch}.cfg)\n"; +} + 1; diff --git a/debs-manifest.conf b/debs-manifest.conf index f4707b4..d991942 100644 --- a/debs-manifest.conf +++ b/debs-manifest.conf @@ -31,10 +31,11 @@ # PER-ARCH SETS (review concern #3 -- the arch matrix must be valid): # * Compiled, arch-specific deps that genuinely build on BOTH arches are listed for amd64 AND # ppc64el: ipmitool-xcat, conserver-xcat, goconserver (debian/control Architecture: any / *-ppc64el). -# * The noarch boot components (syslinux-xcat, grub2-xcat, elilo-xcat, xnba-undi) are +# * The noarch boot components (syslinux-xcat, grub2-xcat, elilo-xcat, xnba-undi, ipxe-xcat) are # Architecture:all: their SOURCE is x86-only (syslinux compiles with nasm/gcc-multilib; elilo/xnba -# are x86/EFI loaders; grub2-xcat is config/scripts), so they are BUILT ONCE on amd64 -- SINGLE -# PRODUCER, concern #3b -- and, being arch:all, assembled into EVERY arch's Packages index. They +# are x86/EFI loaders; grub2-xcat is config/scripts; ipxe-xcat repackages the iPXE release +# tree), so they are BUILT ONCE on amd64 -- SINGLE PRODUCER, concern #3b -- and, being +# arch:all, assembled into EVERY arch's Packages index. They # ARE listed for ppc64el too, as REQUIRED-PRESENT: a ppc MN needs them for netboot, so the gate # must verify the ppc repo carries them (matching the EL manifest and the historical 2.16 ppc dep # repo, minus the obsolete yaboot-xcat). sbuild-all.pl's build phase SKIPS an Architecture:all @@ -67,6 +68,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [focal-ppc64el] @@ -77,6 +79,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [focal-riscv64] @@ -87,6 +90,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 # ============================ jammy (ubuntu22.04) ============================ [jammy-amd64] @@ -97,6 +101,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [jammy-ppc64el] @@ -107,6 +112,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [jammy-riscv64] @@ -117,6 +123,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 # ============================ noble (ubuntu24.04) ============================ [noble-amd64] @@ -127,6 +134,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [noble-ppc64el] @@ -137,6 +145,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [noble-riscv64] @@ -147,6 +156,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 # ============================ resolute (ubuntu26.04) ========================= [resolute-amd64] @@ -157,6 +167,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [resolute-ppc64el] @@ -167,6 +178,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 xcat-genesis-base=2.* [resolute-riscv64] @@ -177,6 +189,7 @@ syslinux-xcat=3.86-2 grub2-xcat=2.12-2 elilo-xcat=3.14-6 xnba-undi=1.21.1-1 +ipxe-xcat=2.0.0-1 # [shared] is NOT a build target. It describes the ONE pool the OpenEmbedded Genesis release is # published into (pool/main/xcat-genesis-openembedded), which every suite indexes and which no diff --git a/goconserver/sbuild.pl b/goconserver/sbuild.pl index cf509cb..06e36e8 100755 --- a/goconserver/sbuild.pl +++ b/goconserver/sbuild.pl @@ -44,7 +44,14 @@ $build_timestamp = time() unless defined $build_timestamp; # The maintained debian/ is at ./debian in the copied package dir; the upstream source is cloned fresh # at the pinned SHA into ./gcsrc, the maintained debian/ copied in, and dpkg-buildpackage run there # (its .deb(s) land in the copied package dir, which the collector picks up). -my $build = <<'BUILD'; +# The build script below is lifted by t/goconserver_cross_build.t and run with the commands it +# calls shadowed. Keep the marker: the test dies when it can no longer find this region. +my $host_deb_arch = `dpkg --print-architecture 2>/dev/null`; +chomp $host_deb_arch; +die "FATAL: cannot read the build host architecture from dpkg\n" + unless $host_deb_arch =~ /^[a-z0-9]+$/; + +my $build = "HOST_DEB_ARCH=$host_deb_arch\n" . <<'BUILD'; set -e VERSION=0.3.3 REPO=https://github.com/xcat2/goconserver.git @@ -52,13 +59,23 @@ REF=6166fe5ec1c5b3c20475e322a9f0e8e93c87e45f GO_PIN=1.25.12 # pinned modern Go toolchain (static CGO-free build, portable across codenames; reproducible compiler) -go_arch=$(dpkg --print-architecture); [ "$go_arch" = ppc64el ] && go_arch=ppc64le -echo "installing pinned go${GO_PIN} (${go_arch}) for the goconserver build" -rm -rf /usr/local/go -curl -fsSL "https://go.dev/dl/go${GO_PIN}.linux-${go_arch}.tar.gz" | tar -C /usr/local -xz -export PATH=/usr/local/go/bin:$PATH +# The toolchain is the BUILD HOST's and the target comes from GOARCH, because riscv64 has no build +# host: its chroot runs under qemu-user, and a riscv64 `go build` there parks in futex_wait and never +# returns. Go cross-compiles a CGO-free binary, and a Go toolchain is statically linked, so the host +# one runs inside the foreign chroot at native speed. HOST_DEB_ARCH is stamped in by sbuild.pl: it +# cannot be read here, because qemu makes the chroot's dpkg and uname both answer for the target. +deb_to_goarch() { case "$1" in ppc64el) echo ppc64le;; *) echo "$1";; esac; } +go_host_arch=$(deb_to_goarch "$HOST_DEB_ARCH") +go_target_arch=$(deb_to_goarch "$(dpkg --print-architecture)") +echo "installing pinned go${GO_PIN} (${go_host_arch}) to compile for ${go_target_arch}" +gotoolchain="$PWD/.gotoolchain" +mkdir -p "$gotoolchain" +curl -fsSL "https://go.dev/dl/go${GO_PIN}.linux-${go_host_arch}.tar.gz" | tar -C "$gotoolchain" --strip-components=1 -xz +export PATH="$gotoolchain/bin:$PATH" export GOTOOLCHAIN=local # use exactly the pinned toolchain; never auto-download another +export GOOS=linux GOARCH="$go_target_arch" go version +go env GOHOSTARCH GOARCH if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then SNAP_TS=$(date -d "@$SOURCE_DATE_EPOCH" --utc '+%Y%m%d%H%M') diff --git a/ipxe-xcat/.gitattributes b/ipxe-xcat/.gitattributes new file mode 100644 index 0000000..a23b4c5 --- /dev/null +++ b/ipxe-xcat/.gitattributes @@ -0,0 +1,2 @@ +# The licence texts stay byte-identical to their upstream sources. +licenses/** -whitespace diff --git a/ipxe-xcat/README b/ipxe-xcat/README new file mode 100644 index 0000000..0098522 --- /dev/null +++ b/ipxe-xcat/README @@ -0,0 +1,87 @@ +ipxe-xcat +========= + +This package installs the ipxeboot.tar.gz tree of the iPXE v2.0.0 release +under /tftpboot/xcat/ipxe. Nothing is rebuilt, and only the two shims are +replaced: see The shim. The x86_64-sb +and arm64-sb builds carry their Secure Boot signatures inside the files, and +the shim finds snponly.efi and ipxe.efi by name in its own directory, so the +package keeps every name, symlink and byte of the release tree. + +Files +----- + +ipxeboot-2.0.0.tar.gz + The ipxeboot.tar.gz asset of + https://github.com/ipxe/ipxe/releases/tag/v2.0.0, renamed. Its SHA-256, + 01a526d4cc791fc30362259c609d6c506cc64a7bdff51b9a5eb788354e17eee1, is the + digest that GitHub publishes for the asset. + +ipxe-2.0.0-source.tar.gz + The source archive of tag v2.0.0, commit + 12798ec29aa8a64d8675c4378b99f5fe28447afb, from + https://github.com/ipxe/ipxe/archive/refs/tags/v2.0.0.tar.gz. Its content + equals "git archive --prefix=ipxe-2.0.0/ v2.0.0". snpnet.c and undinet.c + are GPL2_OR_LATER without the UBDL, so snponly.efi and undionly.kpxe are + GPLv2+ as a whole. The package installs this archive with the binaries. + +ipxe-shimx64.efi, ipxe-shimaa64.efi + The ipxe-shimx64.efi and ipxe-shimaa64.efi assets of + https://github.com/ipxe/shim/releases/tag/ipxe-16.1, as ipxe replaced + them on 2026-05-27. Their SHA-256 values are the digests that GitHub + publishes for the assets. + +SHA256SUMS + The SHA-256 of both archives and both shims. Both builders check it + before the build. + +payload.sha256 + One line for each directory, file and symlink of the release tree, with + the SHA-256 of each file and the target of each symlink. After the build, + both builders unpack the RPM or deb and compare its /tftpboot/xcat/ipxe + with this list, entry for entry, with verify-payload.pl. A difference + fails the build. + +licenses/ + ipxe/COPYING, COPYING.GPLv2 and COPYING.UBDL are from iPXE tag v2.0.0. + shim/COPYRIGHT is from ipxe/shim tag ipxe-16.1. + shim/openssl/LICENSE is from openssl/openssl tag OpenSSL_1_0_2k, the + OpenSSL version that shim 16.1 carries in Cryptlib. + shim/gnu-efi/README.efilib is from rhboot/gnu-efi commit dc7fd96, the + gnu-efi commit that tag ipxe-16.1 pins. + +The shim +-------- + +The release tree carries shim 16.1 as x86_64-sb/shimx64.efi and +arm64-sb/shimaa64.efi, signed by the Microsoft Corporation UEFI CA 2011 +only. Firmware that trusts only the UEFI CA 2023 refuses them with Secure +Boot on. On 2026-05-27 ipxe replaced the ipxe/shim ipxe-16.1 release assets +with a build signed by both CAs. Both builders install ipxe-shimx64.efi and +ipxe-shimaa64.efi over the shims of the tree, under the same names, so the +ipxe-shim.efi and snponly-shim.efi links still point to them. payload.sha256 +lists the digests of the replacements. + +Update to a new release +----------------------- + +1. Download ipxeboot.tar.gz from the release, and compare its SHA-256 with + the digest on the release page. +2. Download the source archive of the tag, and compare its content with + "git archive" of the tag. +3. Replace both archives. Download ipxe-shimx64.efi and ipxe-shimaa64.efi + from the latest ipxe/shim release, and compare their SHA-256 with the + digests on its page. Drop them and their install lines when the shims of + the new tree carry the UEFI CA 2023 signature. +4. Write SHA256SUMS with sha256sum. +5. Write payload.sha256 from the tree with the shims in place: + + mkdir tree + tar -xzf ipxeboot-.tar.gz --strip-components=1 -C tree + cp ipxe-shimx64.efi tree/x86_64-sb/shimx64.efi + cp ipxe-shimaa64.efi tree/arm64-sb/shimaa64.efi + ./verify-payload.pl --generate tree > payload.sha256 + +6. Update licenses/ when the release changes its licence texts or its shim. +7. Set the version in ipxe-xcat.spec and debian/changelog, and the ipxe-xcat + pins in packages-manifest.conf and debs-manifest.conf. diff --git a/ipxe-xcat/SHA256SUMS b/ipxe-xcat/SHA256SUMS new file mode 100644 index 0000000..4759990 --- /dev/null +++ b/ipxe-xcat/SHA256SUMS @@ -0,0 +1,4 @@ +9ed6d029be901a0ccc87cb2e5f9c774620f30f84ebdd507c6dd3e1e6229b7bd5 ipxe-2.0.0-source.tar.gz +31c6d8ef9ed24dc810dd7b951cf86b2e9036a02dea8a32548c0e1c0ae4d6f1c9 ipxe-shimaa64.efi +5eecca2780bd49c900565e124516a1bd666ec5e012825f34991b6ba1ef2fa6cf ipxe-shimx64.efi +01a526d4cc791fc30362259c609d6c506cc64a7bdff51b9a5eb788354e17eee1 ipxeboot-2.0.0.tar.gz diff --git a/ipxe-xcat/debian/changelog b/ipxe-xcat/debian/changelog new file mode 100644 index 0000000..0770d47 --- /dev/null +++ b/ipxe-xcat/debian/changelog @@ -0,0 +1,6 @@ +ipxe-xcat (2.0.0-1) unstable; urgency=medium + + * Package the ipxeboot.tar.gz tree of the iPXE v2.0.0 release, with the + ipxe/shim 16.1 shims signed by both Microsoft UEFI CAs. + + -- xCAT Fri, 25 Sep 2026 12:00:00 +0000 diff --git a/ipxe-xcat/debian/compat b/ipxe-xcat/debian/compat new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/ipxe-xcat/debian/compat @@ -0,0 +1 @@ +12 diff --git a/ipxe-xcat/debian/control b/ipxe-xcat/debian/control new file mode 100644 index 0000000..4cafab9 --- /dev/null +++ b/ipxe-xcat/debian/control @@ -0,0 +1,16 @@ +Source: ipxe-xcat +Section: admin +Priority: optional +Maintainer: xCAT +Build-Depends: debhelper (>= 12) +Standards-Version: 4.5.0 +Homepage: https://ipxe.org/ + +Package: ipxe-xcat +Architecture: all +Depends: ${misc:Depends} +Description: iPXE network boot binaries from the upstream release + The ipxeboot.tar.gz tree of the iPXE 2.0.0 release, installed unchanged + under /tftpboot/xcat/ipxe. It carries the signed Secure Boot builds and + their shim. The source archive of the release tag is installed with the + documentation. diff --git a/ipxe-xcat/debian/copyright b/ipxe-xcat/debian/copyright new file mode 100644 index 0000000..4be3d40 --- /dev/null +++ b/ipxe-xcat/debian/copyright @@ -0,0 +1,37 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: iPXE +Source: https://github.com/ipxe/ipxe/releases/tag/v2.0.0 +Comment: ipxeboot-2.0.0.tar.gz is the ipxeboot.tar.gz asset of the iPXE v2.0.0 + release, unchanged. ipxe-2.0.0-source.tar.gz is the source archive of tag + v2.0.0, installed as /usr/share/doc/ipxe-xcat/ipxe-2.0.0-source.tar.gz. + . + The files x86_64-sb/shimx64.efi and arm64-sb/shimaa64.efi in the release tree + are shim 16.1, built by the iPXE project from ipxe/shim tag ipxe-16.1. Shim is + under the BSD licence in licenses/shim/COPYRIGHT and includes OpenSSL 1.0.2k + (licenses/shim/openssl/LICENSE) and gnu-efi (licenses/shim/gnu-efi/README.efilib). + . + The licence texts are installed in /usr/share/doc/ipxe-xcat/licenses/. + +Files: * +Copyright: Michael Brown and the iPXE contributors +License: GPL-2+ + iPXE files are licensed under the GNU General Public License, version 2 or + (at your option) any later version, unless the file states another licence. + Some files are licensed under version 2 only, some under BSD or MIT terms, + and most may also be used under the Unmodified Binary Distribution Licence + (licenses/ipxe/COPYING.UBDL). Each file in the source archive states its + own licence. + . + On Debian systems, the complete text of the GNU General Public License + version 2 can be found in /usr/share/common-licenses/GPL-2. + +Files: debian/* +Copyright: xCAT contributors +License: GPL-2+ + This packaging is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + . + On Debian systems, the complete text of the GNU General Public License + version 2 can be found in /usr/share/common-licenses/GPL-2. diff --git a/ipxe-xcat/debian/rules b/ipxe-xcat/debian/rules new file mode 100755 index 0000000..76ea015 --- /dev/null +++ b/ipxe-xcat/debian/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f +# The payload is the upstream release tree, byte for byte: nothing strips it, and dh_compress and +# dh_fixperms leave /tftpboot and the licence texts alone. + +VERSION := $(shell dpkg-parsechangelog -S Version | sed 's/-[^-]*$$//') +DEST := debian/ipxe-xcat +DOC := $(DEST)/usr/share/doc/ipxe-xcat + +build build-arch build-indep: + +clean: + dh_testdir + dh_clean + +binary-arch: + +binary-indep: + dh_testdir + dh_testroot + dh_prep + install -d $(DEST)/tftpboot/xcat/ipxe $(DOC) + tar -xzf ipxeboot-$(VERSION).tar.gz --no-same-owner --strip-components=1 -C $(DEST)/tftpboot/xcat/ipxe + install -m 0644 ipxe-shimx64.efi $(DEST)/tftpboot/xcat/ipxe/x86_64-sb/shimx64.efi + install -m 0644 ipxe-shimaa64.efi $(DEST)/tftpboot/xcat/ipxe/arm64-sb/shimaa64.efi + install -m 0644 ipxe-$(VERSION)-source.tar.gz $(DOC)/ + cp -R licenses $(DOC)/licenses + dh_installdocs + dh_installchangelogs + dh_compress -Xlicenses/ + dh_fixperms -Xtftpboot/ + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch + +.PHONY: build build-arch build-indep clean binary-arch binary-indep binary diff --git a/ipxe-xcat/debian/source/format b/ipxe-xcat/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/ipxe-xcat/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/ipxe-xcat/ipxe-2.0.0-source.tar.gz b/ipxe-xcat/ipxe-2.0.0-source.tar.gz new file mode 100644 index 0000000..8b65f90 Binary files /dev/null and b/ipxe-xcat/ipxe-2.0.0-source.tar.gz differ diff --git a/ipxe-xcat/ipxe-shimaa64.efi b/ipxe-xcat/ipxe-shimaa64.efi new file mode 100644 index 0000000..23cbd01 Binary files /dev/null and b/ipxe-xcat/ipxe-shimaa64.efi differ diff --git a/ipxe-xcat/ipxe-shimx64.efi b/ipxe-xcat/ipxe-shimx64.efi new file mode 100644 index 0000000..0e215b1 Binary files /dev/null and b/ipxe-xcat/ipxe-shimx64.efi differ diff --git a/ipxe-xcat/ipxe-xcat.spec b/ipxe-xcat/ipxe-xcat.spec new file mode 100644 index 0000000..1bebff5 --- /dev/null +++ b/ipxe-xcat/ipxe-xcat.spec @@ -0,0 +1,59 @@ +# The payload is the upstream release, byte for byte: signed EFI files must not be stripped or +# otherwise touched by the build-root policy scripts. +%global debug_package %{nil} +%global __os_install_post %{nil} + +Name: ipxe-xcat +Version: 2.0.0 +Release: 1 +Summary: iPXE network boot binaries from the upstream release +License: GPL-2.0-only AND GPL-2.0-or-later AND BSD-2-Clause AND BSD-2-Clause-Patent AND BSD-3-Clause AND MIT AND OpenSSL +URL: https://ipxe.org/ +BuildArch: noarch + +Source0: ipxeboot-%{version}.tar.gz +Source1: ipxe-%{version}-source.tar.gz +Source2: licenses/ipxe/COPYING +Source3: licenses/ipxe/COPYING.GPLv2 +Source4: licenses/ipxe/COPYING.UBDL +Source5: licenses/shim/COPYRIGHT +Source6: licenses/shim/openssl/LICENSE +Source7: licenses/shim/gnu-efi/README.efilib +Source8: ipxe-shimx64.efi +Source9: ipxe-shimaa64.efi + +%description +The ipxeboot.tar.gz tree of the iPXE %{version} release, installed under +/tftpboot/xcat/ipxe. It carries the signed Secure Boot builds and their +shim. The shims are the ipxe/shim 16.1 assets signed by both Microsoft UEFI +CAs, 2011 and 2023, and every other file is unchanged. The source archive +of the release tag is installed with the documentation. + +%prep +%setup -q -c -T +install -D -m 0644 %{SOURCE2} licenses/ipxe/COPYING +install -D -m 0644 %{SOURCE3} licenses/ipxe/COPYING.GPLv2 +install -D -m 0644 %{SOURCE4} licenses/ipxe/COPYING.UBDL +install -D -m 0644 %{SOURCE5} licenses/shim/COPYRIGHT +install -D -m 0644 %{SOURCE6} licenses/shim/openssl/LICENSE +install -D -m 0644 %{SOURCE7} licenses/shim/gnu-efi/README.efilib + +%build + +%install +mkdir -p %{buildroot}/tftpboot/xcat/ipxe +tar -xzf %{SOURCE0} --no-same-owner --strip-components=1 -C %{buildroot}/tftpboot/xcat/ipxe +install -m 0644 %{SOURCE8} %{buildroot}/tftpboot/xcat/ipxe/x86_64-sb/shimx64.efi +install -m 0644 %{SOURCE9} %{buildroot}/tftpboot/xcat/ipxe/arm64-sb/shimaa64.efi +install -D -m 0644 %{SOURCE1} %{buildroot}%{_pkgdocdir}/ipxe-%{version}-source.tar.gz + +%files +/tftpboot/xcat/ipxe +%license licenses/ipxe licenses/shim +%dir %{_pkgdocdir} +%doc %{_pkgdocdir}/ipxe-%{version}-source.tar.gz + +%changelog +* Fri Sep 25 2026 xCAT - 2.0.0-1 +- Package the ipxeboot.tar.gz tree of the iPXE v2.0.0 release, with the + ipxe/shim 16.1 shims signed by both Microsoft UEFI CAs diff --git a/ipxe-xcat/ipxeboot-2.0.0.tar.gz b/ipxe-xcat/ipxeboot-2.0.0.tar.gz new file mode 100644 index 0000000..f206749 Binary files /dev/null and b/ipxe-xcat/ipxeboot-2.0.0.tar.gz differ diff --git a/ipxe-xcat/licenses/ipxe/COPYING b/ipxe-xcat/licenses/ipxe/COPYING new file mode 100644 index 0000000..342330b --- /dev/null +++ b/ipxe-xcat/licenses/ipxe/COPYING @@ -0,0 +1,12 @@ +In general iPXE files are licensed under the GPL. For historical +reasons, individual files may contain their own licence declarations. +Most builds of iPXE do not contain all iPXE code (in particular, most +builds will include only one driver), and so the overall licence can +vary depending on what target you are building. + +The resultant applicable licence(s) for any particular build can be +determined by using "make bin/xxxxxxx.yyy.licence"; for example: + + make bin/rtl8139.rom.licence + +to determine the resultant licence(s) for the build bin/rtl8139.rom diff --git a/ipxe-xcat/licenses/ipxe/COPYING.GPLv2 b/ipxe-xcat/licenses/ipxe/COPYING.GPLv2 new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/ipxe-xcat/licenses/ipxe/COPYING.GPLv2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ipxe-xcat/licenses/ipxe/COPYING.UBDL b/ipxe-xcat/licenses/ipxe/COPYING.UBDL new file mode 100644 index 0000000..780ddcd --- /dev/null +++ b/ipxe-xcat/licenses/ipxe/COPYING.UBDL @@ -0,0 +1,59 @@ +UNMODIFIED BINARY DISTRIBUTION LICENCE + + +PREAMBLE + +The GNU General Public License provides a legal guarantee that +software covered by it remains free (in the sense of freedom, not +price). It achieves this guarantee by imposing obligations on anyone +who chooses to distribute the software. + +Some of these obligations may be seen as unnecessarily burdensome. In +particular, when the source code for the software is already publicly +and freely available, there is minimal value in imposing upon each +distributor the obligation to provide the complete source code (or an +equivalent written offer to provide the complete source code). + +This Licence allows for the distribution of unmodified binaries built +from publicly available source code, without imposing the obligations +of the GNU General Public License upon anyone who chooses to +distribute only the unmodified binaries built from that source code. + +The extra permissions granted by this Licence apply only to unmodified +binaries built from source code which has already been made available +to the public in accordance with the terms of the GNU General Public +Licence. Nothing in this Licence allows for the creation of +closed-source modified versions of the Program. Any modified versions +of the Program are subject to the usual terms and conditions of the +GNU General Public License. + + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +This Licence applies to any Program or other work which contains a +notice placed by the copyright holder saying it may be distributed +under the terms of this Unmodified Binary Distribution Licence. All +terms used in the text of this Licence are to be interpreted as they +are used in version 2 of the GNU General Public License as published +by the Free Software Foundation. + +If you have made this Program available to the public in both source +code and executable form in accordance with the terms of the GNU +General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later +version, then you are hereby granted an additional permission to use, +copy, and distribute the unmodified executable form of this Program +(the "Unmodified Binary") without restriction, including the right to +permit persons to whom the Unmodified Binary is furnished to do +likewise, subject to the following conditions: + +- when started running, the Program must display an announcement which + includes the details of your existing publication of the Program + made in accordance with the terms of the GNU General Public License. + For example, the Program could display the URL of the publicly + available source code from which the Unmodified Binary was built. + +- when exercising your right to grant permissions under this Licence, + you do not need to refer directly to the text of this Licence, but + you may not grant permissions beyond those granted to you by this + Licence. diff --git a/ipxe-xcat/licenses/shim/COPYRIGHT b/ipxe-xcat/licenses/shim/COPYRIGHT new file mode 100644 index 0000000..3b5a464 --- /dev/null +++ b/ipxe-xcat/licenses/shim/COPYRIGHT @@ -0,0 +1,30 @@ +Copyright 2012 Red Hat, Inc + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +Significant portions of this code are derived from Tianocore +(http://tianocore.sf.net) and are Copyright 2009-2012 Intel +Corporation. diff --git a/ipxe-xcat/licenses/shim/gnu-efi/README.efilib b/ipxe-xcat/licenses/shim/gnu-efi/README.efilib new file mode 100644 index 0000000..bb857ec --- /dev/null +++ b/ipxe-xcat/licenses/shim/gnu-efi/README.efilib @@ -0,0 +1,30 @@ + +The files in the "lib" and "inc" subdirectories are using the EFI Application +Toolkit distributed by Intel at http://developer.intel.com/technology/efi + +This code is covered by the following agreement: + +Copyright (c) 1998-2000 Intel Corporation + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and +the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. THE EFI SPECIFICATION AND ALL OTHER INFORMATION +ON THIS WEB SITE ARE PROVIDED "AS IS" WITH NO WARRANTIES, AND ARE SUBJECT +TO CHANGE WITHOUT NOTICE. diff --git a/ipxe-xcat/licenses/shim/openssl/LICENSE b/ipxe-xcat/licenses/shim/openssl/LICENSE new file mode 100644 index 0000000..fb03713 --- /dev/null +++ b/ipxe-xcat/licenses/shim/openssl/LICENSE @@ -0,0 +1,127 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/ipxe-xcat/mockbuild.pl b/ipxe-xcat/mockbuild.pl new file mode 100755 index 0000000..fd674ff --- /dev/null +++ b/ipxe-xcat/mockbuild.pl @@ -0,0 +1,172 @@ +#!/usr/bin/perl +# ipxe-xcat/mockbuild.pl -- build the ipxe-xcat noarch RPM with mock from the committed release +# archives. The archives are checked against SHA256SUMS before the build, and the built RPM payload +# against payload.sha256 before anything is copied to --result-dir. +use strict; +use warnings; +use Cwd qw(abs_path); +use File::Basename qw(basename); +use File::Copy qw(copy); +use File::Path qw(make_path remove_tree); +use FindBin qw($RealBin); +use Getopt::Long qw(GetOptions); +use lib "$RealBin/..", "$RealBin/../lib"; +use MockBuildUtils qw(resolve_mock_cfg); +use XCAT::BuildUtils qw(capture_command digest_file print_step require_command run_command shell_quote); + +my $pkg_dir = abs_path($RealBin); +my $repo_root = abs_path("$pkg_dir/.."); +my $spec_file = "$pkg_dir/ipxe-xcat.spec"; + +my $work_dir = '/tmp/ipxe-xcat-mockbuild'; +my $mock_cfg = ''; +my $mock_uniqueext = ''; +my $result_dir = "$repo_root/build-output/list3/ipxe-xcat"; +my $log_dir = "$repo_root/build-logs/list3/ipxe-xcat"; +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, + 'build-timestamp=i' => \$build_timestamp, +) or die usage(); + +die "Run as root (current uid=$>)\n" if $> != 0; +require_command($_) for qw(mock rpm rpm2cpio cpio bash sha256sum); + +my ($version, @sources) = spec_sources($spec_file); +die "Could not parse Version from $spec_file\n" if !$version; + +if (!$mock_cfg) { + my $os_id = capture_command('bash', '-c', 'source /etc/os-release; echo $ID'); + my $arch = capture_command('uname', '-m'); + $mock_cfg = resolve_mock_cfg($os_id, 10, $arch); +} +my @uniqueext = $mock_uniqueext ne '' ? ('--uniqueext', $mock_uniqueext) : (); + +my $epoch = $build_timestamp; +if (!defined $epoch) { + $epoch = `git -C \Q$repo_root\E log -1 --format=%ct HEAD 2>/dev/null` // ''; + chomp $epoch; + $epoch = time() if $epoch !~ /^\d+$/; +} +$ENV{SOURCE_DATE_EPOCH} = $epoch; + +print_step('Configuration'); +print "pkg_dir: $pkg_dir\n"; +print "version: $version\n"; +print "work_dir: $work_dir\n"; +print "result_dir: $result_dir\n"; +print "log_dir: $log_dir\n"; +print "mock_cfg: $mock_cfg\n"; + +print_step('Check the release archives'); +run_command('bash', '-c', 'cd ' . shell_quote($pkg_dir) . ' && sha256sum --check --strict SHA256SUMS'); + +print_step('Stage the sources'); +remove_tree($work_dir) if -d $work_dir; +my $sources_dir = "$work_dir/sources"; +make_path($sources_dir, $result_dir, $log_dir); +my %staged; +for my $source (@sources) { + my $name = basename($source); + die "Two Source files share the name $name\n" if $staged{$name}++; + copy("$pkg_dir/$source", "$sources_dir/$name") + or die "Failed to copy $pkg_dir/$source: $!\n"; +} +run_command('bash', '-c', 'cd ' . shell_quote($sources_dir) + . ' && sha256sum --check --strict ' . shell_quote("$pkg_dir/SHA256SUMS")); + +my $det_cfg = "$work_dir/mock-deterministic.cfg"; +open(my $cfg_fh, '>', $det_cfg) or die "Cannot write $det_cfg: $!\n"; +print {$cfg_fh} "include('/etc/mock/${mock_cfg}.cfg')\n"; +print {$cfg_fh} "config_opts['environment']['SOURCE_DATE_EPOCH'] = '$epoch'\n"; +close($cfg_fh) or die "Cannot write $det_cfg: $!\n"; +my @defines = map { ('--define', $_) } + ('use_source_date_epoch_as_buildtime 1', 'clamp_mtime_to_source_date_epoch 1', '_buildhost xcat-build'); + +print_step('Build the SRPM with mock'); +my $srpm_out = "$work_dir/srpm"; +make_path($srpm_out); +run_mock('mock', '-r', $det_cfg, @uniqueext, '--buildsrpm', '--spec', $spec_file, + '--sources', $sources_dir, '--resultdir', $srpm_out, @defines); +my @srpms = glob("$srpm_out/ipxe-xcat-*.src.rpm"); +die "Expected one SRPM in $srpm_out, found " . scalar(@srpms) . "\n" if @srpms != 1; + +print_step('Rebuild the RPM with mock'); +my $rpm_out = "$work_dir/rpm"; +make_path($rpm_out); +run_mock('mock', '-r', $det_cfg, @uniqueext, '--rebuild', $srpms[0], '--resultdir', $rpm_out, @defines); +my @rpms = glob("$rpm_out/ipxe-xcat-$version-*.noarch.rpm"); +die "Expected one ipxe-xcat noarch RPM in $rpm_out, found " . scalar(@rpms) . "\n" if @rpms != 1; +my $rpm = $rpms[0]; + +print_step('Check the RPM payload'); +my $payload = "$work_dir/payload"; +make_path($payload); +run_command('bash', '-o', 'pipefail', '-c', 'cd ' . shell_quote($payload) + . ' && rpm2cpio ' . shell_quote($rpm) . ' | cpio -idm --quiet'); +run_command('perl', "$pkg_dir/verify-payload.pl", "$payload/tftpboot/xcat/ipxe", + "$pkg_dir/payload.sha256"); +check_installed("$payload/usr/share/doc/ipxe-xcat/ipxe-$version-source.tar.gz", + "$pkg_dir/ipxe-$version-source.tar.gz"); +for my $licence (grep { m{^licenses/} } @sources) { + (my $installed = $licence) =~ s{^licenses/}{}; + check_installed("$payload/usr/share/licenses/ipxe-xcat/$installed", "$pkg_dir/$licence"); +} + +print_step('Collect the results'); +for my $file ($rpm, $srpms[0]) { + copy($file, $result_dir) or die "Failed to copy $file to $result_dir: $!\n"; + print "Copied: $result_dir/" . basename($file) . "\n"; +} +for my $log (qw(build.log root.log state.log)) { + copy("$rpm_out/$log", "$log_dir/$log") if -f "$rpm_out/$log"; + copy("$srpm_out/$log", "$log_dir/srpm-$log") if -f "$srpm_out/$log"; +} +print_step('Completed'); +exit 0; + +sub usage { + return <<"USAGE"; +Usage: $0 [options] + --work-dir PATH Temporary work directory (default: $work_dir) + --mock-cfg NAME Mock config (default: the EL10 config of this host) + --mock-uniqueext TEXT mock --uniqueext suffix for concurrent builds + --result-dir PATH Output directory for the RPM and SRPM + --log-dir PATH Output directory for the mock logs + --build-timestamp EPOCH SOURCE_DATE_EPOCH for a reproducible build +USAGE +} + +sub spec_sources { + my ($path) = @_; + open(my $fh, '<', $path) or die "Cannot read $path: $!\n"; + my ($version, @sources) = (''); + while (my $line = <$fh>) { + $version = $1 if $line =~ /^Version:\s*(\S+)/; + push @sources, $1 if $line =~ /^Source\d*:\s*(\S+)/; + } + close($fh); + s/%\{version\}/$version/g for @sources; + return ($version, @sources); +} + +sub check_installed { + my ($installed, $committed) = @_; + die "Missing from the RPM payload: $installed\n" if !-f $installed || -l $installed; + die "The RPM payload changed $installed\n" if digest_file($installed) ne digest_file($committed); +} + +# mock exits 30 when its package manager failed, most often a transient mirror error: retry once. +sub run_mock { + my (@command) = @_; + my $ok = eval { run_command(@command) }; + return 1 if $ok; + die $@ if $@ !~ /\(rc=30\)/; + print "mock failed with rc=30 (package manager); retrying once\n"; + return run_command(@command); +} diff --git a/ipxe-xcat/payload.sha256 b/ipxe-xcat/payload.sha256 new file mode 100644 index 0000000..3141d9b --- /dev/null +++ b/ipxe-xcat/payload.sha256 @@ -0,0 +1,54 @@ +# ipxe-xcat payload manifest, written by verify-payload.pl --generate +dir - arm32 +file 2a8d50db2b3b5f02302302b3161931c1142301f42d52c64c0005974b602b7092 arm32/ipxe-legacy.efi +file fa58061710e6fab23fc27c6d200d510453c3f14f3bc0715fa6804111f1e5fc74 arm32/ipxe.efi +file 206310f30306569ed2c6e0ef015b3ad24230b303a1ad1171e19c117c914a65d6 arm32/snponly.efi +dir - arm64 +dir - arm64-sb +link shimaa64.efi arm64-sb/ipxe-shim.efi +file 01b2438e6dc354c343590c308f1d4f000bc098be4d2237540432023abdbddcb8 arm64-sb/ipxe.efi +file 31c6d8ef9ed24dc810dd7b951cf86b2e9036a02dea8a32548c0e1c0ae4d6f1c9 arm64-sb/shimaa64.efi +link shimaa64.efi arm64-sb/snponly-shim.efi +file bed8da8639b45eeec55d41627349863efa5085a2113bb1193838b8a463e5f49e arm64-sb/snponly.efi +file cff2abf51b7b491d7c5e2ef68c45003a0b4c5e866cb5b20f162569746d53390d arm64/ipxe-legacy.efi +file a9cb6df506a68f3afa4bb94cf6cb8e3862a5a2ff3bf1d8027fea83f7e1d49217 arm64/ipxe.efi +file 03665b4184e4a0b8b9a889de0c7fb833fc48b02385e3fa40a4460db1122f1b36 arm64/snponly.efi +dir - i386 +file 9dc4aee199f582fb8f55cf8bfb4622998c5e71c2dde149d5bbdfe33121c925d8 i386/ipxe-legacy.efi +file df9bab29487d20af3fe9dda46afc775009ba1c089d2216098b9a6e82d906939b i386/ipxe-legacy.pxe +file ea63c6d3745e751e8db4f9c8d4c97efa883fb6d0fc57c697b3d13ad98c1bfe0c i386/ipxe.efi +file a0f144a5f7e10e567d189606c6c2320c1f43a228f9fb6148e7e52f5009fd789f i386/ipxe.pxe +file 81a086995758b889fba7f13d7c5255dc7eb87ed38350b8c03112b9f56556de98 i386/snponly.efi +file ef6ff013f988c52feb3e543dccf0bdc50cd1d68b8a4ab84b8975cef33f64e848 i386/undionly.kpxe +link x86_64/ipxe-legacy.efi ipxe-legacy.efi +link x86_64/ipxe-legacy.pxe ipxe-legacy.pxe +link x86_64/ipxe.efi ipxe.efi +link x86_64/ipxe.pxe ipxe.pxe +dir - loong64 +file 03b078b2ba00e97427b5d99b14035bdb7abdb48631aba8759cf95c24a2620b7e loong64/ipxe-legacy.efi +file c326c8bf54d8fc40fa6730907ee07cb44e8151ecc1397e1ddd2c0edef7cb2872 loong64/ipxe.efi +file fd7cb2df195ad5cc3a09f41fab23713afa23624ff664f83de0e7ca0fd5776fb7 loong64/snponly.efi +dir - riscv32 +file 41f76da3efc3293887a701f35cac389c04a3a8110743673e37451e3c6e24e507 riscv32/ipxe-legacy.efi +file 4afd51329213e50a4aaf24b397e8aba67910ca1e94ea3a6fab0e089d91ac69b8 riscv32/ipxe.efi +file 0a901453bde1392051e53bb1e75584a4eb7cc9c75a27a2b34d7b26ad21734f8f riscv32/snponly.efi +dir - riscv64 +file a72923e2ff600bd94628ef5f97a7ddd5c23fabdc9736fdaa2c22cfb7f0fe908d riscv64/ipxe-legacy.efi +file 53c926c45043c1f2ad03aa70aa22921accc3202865c791cc6023fa17d92f8f24 riscv64/ipxe.efi +file 95b9f6466e0d88fafe642c46d3d6024e4107cac24d2197664b62610f21a48585 riscv64/snponly.efi +link x86_64-sb sb +link x86_64/snponly.efi snponly.efi +link x86_64/undionly.kpxe undionly.kpxe +dir - x86_64 +dir - x86_64-sb +link shimx64.efi x86_64-sb/ipxe-shim.efi +file 6558e37887516b246d6a97122e8d18bedfe4197b7ba7f67bf1bf102a16678d33 x86_64-sb/ipxe.efi +file 5eecca2780bd49c900565e124516a1bd666ec5e012825f34991b6ba1ef2fa6cf x86_64-sb/shimx64.efi +link shimx64.efi x86_64-sb/snponly-shim.efi +file b1e67c3e4a1e8708ddfd0079ad4505e3a02245acb55ee9a95437ab3c507be82a x86_64-sb/snponly.efi +file 1d567f2e89a3c0cf0a184549918a3e799a47dc542df385c56e6b464e4765fae2 x86_64/ipxe-legacy.efi +file fc37ef1e4a4bd5d22f8db3c84e1718ac8b03fe20156cf2fc4b9e2ae5e4a348db x86_64/ipxe-legacy.pxe +file 868aa34057ff416ebf2fdfb5781de035e2c540477c04039198a9f8a9c6130034 x86_64/ipxe.efi +file 0fb21c695c82fd70d4f89732ddcd285063776e2bbd71de9a2c39e9cfe4b180b8 x86_64/ipxe.pxe +file f61c2ce34e05d7d857633df2e512d547df75b6aa18b2da152a7c9af222cfe28f x86_64/snponly.efi +file 4186562d21ff54e970d905751c9f36d628e73a51a94afe4a6a42f925b0df448c x86_64/undionly.kpxe diff --git a/ipxe-xcat/sbuild.pl b/ipxe-xcat/sbuild.pl new file mode 100755 index 0000000..c8a79c9 --- /dev/null +++ b/ipxe-xcat/sbuild.pl @@ -0,0 +1,55 @@ +#!/usr/bin/env perl +# ipxe-xcat/sbuild.pl -- per-package Ubuntu/Debian builder for ipxe-xcat, the apt analogue of +# ipxe-xcat/mockbuild.pl. Invoked by sbuild-all.pl per (codename,arch); also runnable standalone. +# The build runs on a copy of the package tree inside the --sbuild chroot, and it +# checks the archives before dpkg-buildpackage and the built payload after it, so a deb that +# differs from the release never reaches --result-dir. +use strict; +use warnings; +use Cwd qw(abs_path); +use File::Basename qw(basename); +use Getopt::Long qw(GetOptions); +use FindBin qw($RealBin); +use lib "$RealBin/.."; +use BuildUtils qw(chroot_name build_deb_in_chroot); + +my $pkg_dir = abs_path($RealBin); +my $pkg = basename($pkg_dir); +my ($codename, $arch, $chroot, $result_dir, $log_dir) = ('', '', '', '', ''); +my ($build_timestamp, $build_number, $skip_install) = (undef, undef, 0); +# --log-dir, --build-number and --skip-install keep the command line sbuild-all.pl passes to every +# builder; this package has no use for them. +GetOptions( + 'codename=s' => \$codename, 'arch=s' => \$arch, 'chroot=s' => \$chroot, + 'result-dir=s' => \$result_dir, 'log-dir=s' => \$log_dir, + 'build-timestamp=i' => \$build_timestamp, 'build-number=i' => \$build_number, + 'skip-install!' => \$skip_install, +) or die "bad options\n"; +$arch ||= `dpkg --print-architecture 2>/dev/null`; chomp $arch; $arch ||= 'amd64'; +die "FATAL: --codename required\n" unless $codename; +$chroot ||= chroot_name($codename, $arch); +$result_dir ||= "$pkg_dir/../build-output/sbuild/$codename/$arch"; +$build_timestamp = time() unless defined $build_timestamp; + +# ipxe-xcat is Architecture:all and is built once on amd64 (see debs-manifest.conf). +my $build = <<'BUILD'; +set -e +sha256sum --check --strict SHA256SUMS +dpkg-buildpackage -uc -us -b +version=$(dpkg-parsechangelog -S Version) +payload=$(mktemp -d) +dpkg-deb -x "../ipxe-xcat_${version}_all.deb" "$payload" +perl ./verify-payload.pl "$payload/tftpboot/xcat/ipxe" payload.sha256 +source_archive="ipxe-${version%-*}-source.tar.gz" +grep -F " $source_archive" SHA256SUMS \ + | (cd "$payload/usr/share/doc/ipxe-xcat" && sha256sum --check --strict -) +for licence in $(cd licenses && find . -type f); do + cmp "licenses/$licence" "$payload/usr/share/doc/ipxe-xcat/licenses/$licence" +done +rm -rf "$payload" +BUILD + +build_deb_in_chroot( + pkg => $pkg, chroot => $chroot, pkg_dir => $pkg_dir, result_dir => $result_dir, + build_timestamp => $build_timestamp, build => $build, +); diff --git a/ipxe-xcat/verify-payload.pl b/ipxe-xcat/verify-payload.pl new file mode 100755 index 0000000..fd5f759 --- /dev/null +++ b/ipxe-xcat/verify-payload.pl @@ -0,0 +1,118 @@ +#!/usr/bin/perl +# verify-payload.pl -- compare an unpacked ipxe-xcat tree with payload.sha256. +# +# verify-payload.pl --generate > payload.sha256 +# verify-payload.pl +# +# Each manifest line is "\t\t", sorted by path: "file" with the SHA-256 of the +# content, "link" with the symlink target, "dir" with "-". Paths are relative to , and +# symlinks are never followed. The check exits 0 when the tree matches the manifest entry for +# entry, 1 when it differs, and 2 on a usage or read error. +use strict; +use warnings; +use Digest::SHA (); +use File::Find (); +use Getopt::Long qw(GetOptions); + +my $generate = 0; +GetOptions('generate' => \$generate) or usage(); + +if ($generate) { + usage() if @ARGV != 1; + my $tree = scan_tree($ARGV[0]); + print "# ipxe-xcat payload manifest, written by verify-payload.pl --generate\n"; + for my $path (sort keys %{$tree}) { + print join("\t", @{ $tree->{$path} }, $path), "\n"; + } + exit 0; +} + +usage() if @ARGV != 2; +my ($root, $manifest_file) = @ARGV; +my $expected = read_manifest($manifest_file); +my $found = scan_tree($root); + +my @problems; +for my $path (sort keys %{$expected}) { + my ($type, $value) = @{ $expected->{$path} }; + if (!exists $found->{$path}) { + push @problems, "missing: $path"; + next; + } + my ($found_type, $found_value) = @{ $found->{$path} }; + if ($found_type ne $type) { + push @problems, "type changed: $path (expected $type, found $found_type)"; + } elsif ($type eq 'file' && $found_value ne $value) { + push @problems, "content changed: $path"; + } elsif ($type eq 'link' && $found_value ne $value) { + push @problems, "link target changed: $path (expected $value, found $found_value)"; + } +} +push @problems, map { "unexpected: $_" } grep { !exists $expected->{$_} } sort keys %{$found}; + +if (@problems) { + print STDERR "$_\n" for @problems; + print STDERR "payload does not match $manifest_file: " . scalar(@problems) . " difference(s)\n"; + exit 1; +} +print "payload matches $manifest_file: " . scalar(keys %{$expected}) . " entries\n"; +exit 0; + +sub usage { + print STDERR "Usage: $0 --generate \n $0 \n"; + exit 2; +} + +sub fail { + my ($message) = @_; + print STDERR "$0: $message\n"; + exit 2; +} + +sub scan_tree { + my ($dir) = @_; + $dir =~ s{/+\z}{} if $dir ne '/'; + fail("not a directory: $dir") if -l $dir || !-d $dir; + my %entries; + File::Find::find({ + no_chdir => 1, + wanted => sub { + my $path = $File::Find::name; + return if $path eq $dir; + my $relative = substr($path, length($dir) + 1); + lstat($path) or fail("cannot stat $path: $!"); + if (-l _) { + my $target = readlink($path); + fail("cannot read link $path: $!") if !defined $target; + $entries{$relative} = ['link', $target]; + } elsif (-d _) { + $entries{$relative} = ['dir', '-']; + } elsif (-f _) { + my $sha = Digest::SHA->new(256); + eval { $sha->addfile($path, 'b'); 1 } or fail("cannot read $path: $@"); + $entries{$relative} = ['file', $sha->hexdigest]; + } else { + $entries{$relative} = ['other', '-']; + } + }, + }, $dir); + return \%entries; +} + +sub read_manifest { + my ($file) = @_; + open(my $fh, '<', $file) or fail("cannot read $file: $!"); + my %entries; + while (my $line = <$fh>) { + chomp $line; + next if $line =~ /^\s*(?:#|$)/; + my ($type, $value, $path) = split(/\t/, $line, 3); + fail("$file line $.: malformed entry") + if !defined $path || $path eq '' || $type !~ /^(?:file|link|dir)$/ + || ($type eq 'file' && $value !~ /^[0-9a-f]{64}$/); + fail("$file line $.: duplicate path $path") if exists $entries{$path}; + $entries{$path} = [$type, $value]; + } + close($fh); + return \%entries; +} diff --git a/lib/XCAT/NFSLock.pm b/lib/XCAT/NFSLock.pm new file mode 100644 index 0000000..ed2eff2 --- /dev/null +++ b/lib/XCAT/NFSLock.pm @@ -0,0 +1,494 @@ +package XCAT::NFSLock; + +# NFS lock protocol +# +# A lock on a shared, possibly re-exported, NFS tree. flock and fcntl are not +# available there. The protocol uses mkdir, rmdir, unlink and plain file +# writes. It uses no rename. +# +# Names in this module +# lock.d the lock path given to acquire +# lock.d/metadata the metadata of the owner +# lock.borrow .borrow, beside lock.d +# R, T, δ the options retries, delay and jitter +# +# Assumptions +# 1. mkdir(path) is atomic and exclusive among contenders, and successful +# namespace changes eventually become visible. +# 2. machine-id is unique among participating hosts. +# Cloned VMs and images can share it by accident unless it is regenerated. +# 3. Metadata writes eventually become readable completely and consistently. +# 4. A host never declares one of its own live process incarnations dead. +# 5. A process cannot die: +# - after it creates lock.d, until it publishes valid metadata; +# - while it holds lock.borrow, until it removes it. +# 6. A crashed worker leaves recoverable state. The owning host eventually +# returns and retries. Eventually one worker and its release complete. +# 7. All participants follow the protocol. +# +# Metadata +# lock.d/metadata contains: +# machine-id, boot-id, pid, pstart, token, hash +# +# Ownership identity: (machine-id, boot-id, pid, pstart, token) +# token is random per acquisition. +# hash = HASH(canonical(SORT(k, v))) over all fields except hash. +# +# If the metadata is missing, cannot be parsed or hashed, or the hash does not +# match, assume a partial or inconsistent read and retry. Never infer stale +# ownership from invalid metadata. +# +# Retry +# R = max retries, T = base delay, δ = jitter +# R > 0, δ >= 0, T >= 3, T > 2δ +# +# Generic retry: +# if retries >= R: fail +# sleep(T + rand(-δ, δ)) +# retries++ +# goto 1 +# +# Protocol +# 1. mkdir lock.d +# - success: write valid metadata, go to 8 +# - EEXIST: continue +# - other error: fail +# 2. Read and validate the metadata. +# - invalid or missing: retry +# - different machine-id: retry +# - same host: save the observed ownership identity +# 3. mkdir lock.borrow +# - failure: retry +# 4. Read and validate the metadata again. +# - invalid, missing, or ownership identity changed: rmdir lock.borrow, retry +# 5. Prove that the recorded (boot-id, pid, pstart) is dead. +# - not provably dead: rmdir lock.borrow, retry +# - dead: continue +# 6. Replace the metadata with the identity of this process and a fresh token. +# 7. rmdir lock.borrow +# 8. Call the worker. +# 9. mkdir lock.borrow +# - failure: sleep(T + rand(-δ, δ)), retry step 9 +# 10. unlink lock.d/metadata +# 11. rmdir lock.d (the actual unlock) +# 12. rmdir lock.borrow +# +# Core invariants +# lock.d exists => locked +# lock.d absent => acquirable +# invalid metadata => retry only +# different machine-id => never recover here +# lock.borrow exists => ownership transition or release in progress +# +# Steps 1 to 7 are acquire, step 8 is the caller, steps 9 to 12 are release. +# release does steps 10 and 11 only when the metadata names this acquisition. +# +# Log +# Unless quiet => 1, each lock event prints one line to the selected output handle: +# [nfslock] pid=