diff --git a/build-ubunturepo b/build-ubunturepo index ae516d722..a65cd75bc 100755 --- a/build-ubunturepo +++ b/build-ubunturepo @@ -110,6 +110,11 @@ done # Supported distributions. Set DISTS="jammy noble resolute" to limit local validation builds. dists="${DISTS:-saucy trusty utopic xenial bionic focal jammy noble resolute}" +# GPG key used to sign the apt repo (reprepro SignWith). Defaults to the historic +# name. Override with GPG_KEY_ID= (space-free, since it is passed via +# the attr=value parser above), e.g. GPG_KEY_ID=xcat-build@xcat.org +GPG_KEY_ID="${GPG_KEY_ID:-xCAT Automatic Signing Key}" + c_flag= # xcat-core (trunk-delvel) path d_flag= # xcat-dep (trunk) path r_flag= #genesis base rpm package path @@ -160,13 +165,15 @@ fi # for the git case, query the current branch and set REL (changing master to devel if necessary) function setbranch { - # Get the current branch name - branch=`git rev-parse --abbrev-ref HEAD` + # Get the current branch name. safe.directory='*' so this still works when the + # build runs as root against a repo owned by another user (otherwise git errors + # with "dubious ownership", returns empty, and REL collapses to an unstable value). + branch=`git -c safe.directory='*' rev-parse --abbrev-ref HEAD 2>/dev/null` if [ "$branch" = "master" ]; then REL="devel" - elif [ "$branch" = "HEAD" ]; then + elif [ "$branch" = "HEAD" ] || [ -z "$branch" ]; then # Special handling when in a 'detached HEAD' state - branch=`git describe --abbrev=0 HEAD` + branch=`git -c safe.directory='*' describe --abbrev=0 HEAD 2>/dev/null` [[ -n "$branch" ]] && REL=`echo $branch|cut -d. -f 1,2` else REL=$branch @@ -206,6 +213,11 @@ REL=xcat-core if [ "$c_flag" ] then setbranch + # Sanitize REL into a stable, filesystem-safe token: replace any character that + # isn't [A-Za-z0-9._-] (e.g. the '/' in a branch like feat/ubuntu-e2e, which would + # otherwise create nested dirs) with '-', and never let it be empty. + REL=${REL//[^A-Za-z0-9._-]/-} + [ -z "$REL" ] && REL="local" package_dir_name=debs$REL #define the dep source code path, core build target path and dep build target path @@ -416,7 +428,7 @@ __EOF__ #echo "GPGSIGN=$GPGSIGN specified, the repo will not be signed" echo "" >> conf/distributions else - keyid=$(gpg --list-keys --keyid-format long "xCAT Automatic Signing Key" | grep '^pub' | sed -e 's/.*\///' -e 's/ .*//') + keyid=$(gpg --list-keys --keyid-format long "$GPG_KEY_ID" | grep '^pub' | sed -e 's/.*\///' -e 's/ .*//') echo "SignWith: $keyid" >> conf/distributions echo "" >> conf/distributions fi @@ -565,7 +577,7 @@ __EOF__ echo "GPGSIGN=$GPGSIGN specified, the repo will not be signed" echo "" >> conf/distributions else - keyid=$(gpg --list-keys --keyid-format long "xCAT Automatic Signing Key" | grep '^pub' | sed -e 's/.*\///' -e 's/ .*//') + keyid=$(gpg --list-keys --keyid-format long "$GPG_KEY_ID" | grep '^pub' | sed -e 's/.*\///' -e 's/ .*//') echo "SignWith: $keyid" >> conf/distributions echo "" >> conf/distributions fi diff --git a/xCAT-genesis-builder/debian/changelog b/xCAT-genesis-builder/debian/changelog index 4ae900969..e8716f2dc 100644 --- a/xCAT-genesis-builder/debian/changelog +++ b/xCAT-genesis-builder/debian/changelog @@ -1,3 +1,10 @@ +xcat-genesis-base-amd64 (2.18.0) stable; urgency=low + + * Bump version to track current xCAT so the xcat-genesis-scripts dependency + (xcat-genesis-base-amd64 >= 2.13.10) is satisfiable. + + -- xCAT Tue, 23 Jun 2026 21:12:00 +0000 + xcat-genesis-base-amd64 (2.8) stable; urgency=low * Initial Release diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index d233e94bb..c2a5c2137 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -1652,12 +1652,50 @@ sub crydb_or_locked return '*'; } +sub ubuntu_subiquity_apt_mirror +{ + # Apt mirror for Subiquity installs. site.ubuntu_apt_mirror overrides; otherwise default to the + # public archive. The minimal live-server install media is not a complete package source, so a + # real mirror is always required -- set site.ubuntu_apt_mirror to a local full mirror for + # airgapped clusters (or to a geo/ports mirror as needed). + my $default = 'http://archive.ubuntu.com/ubuntu'; + my $site_tab = xCAT::Table->new('site'); + return $default unless $site_tab; + my $ent = $site_tab->getAttribs({ key => 'ubuntu_apt_mirror' }, 'value'); + return ($ent && defined($ent->{value}) && length($ent->{value})) ? $ent->{value} : $default; +} + sub ubuntu_subiquity_apt_config { my ($media_dir) = @_; my $use_deb822 = ubuntu_subiquity_uses_deb822_sources($media_dir); my @otherpkg_sources = ubuntu_subiquity_otherpkg_sources(); + my $online_mirror = ubuntu_subiquity_apt_mirror(); + if ($online_mirror) { + # Online install: use the configured archive as the primary apt mirror so + # Subiquity/curtin can fetch whatever the minimal media lacks. No + # disable_suites / offline fallback here -- updates & security stay enabled. + my @lines = ( + ' apt:', + ' preserve_sources_list: false', + ' geoip: false', + ' mirror-selection:', + ' primary:', + " - uri: $online_mirror", + ); + if (@otherpkg_sources) { + push @lines, ' sources:'; + my $index = 0; + foreach my $source (@otherpkg_sources) { + push @lines, " xcat-otherpkgs-$index.list:"; + push @lines, qq( source: "deb [trusted=yes] $source ./"); + $index++; + } + } + return join( "\n", @lines ); + } + my @lines = ( ' apt:', ' preserve_sources_list: false', diff --git a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl index 15b644596..31a978cbc 100644 --- a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl +++ b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl @@ -6,12 +6,19 @@ autoinstall: network: version: 2 ethernets: - '#TABLE:noderes:$NODE:installnic#': + xcat-install: + match: + name: "e*" dhcp4: true ssh: allow-pw: true authorized-keys: [] install-server: true + identity: + realname: 'xCAT Admin' + username: xcatadm + hostname: #HOSTNAME# + password: "#CRYPTORLOCKED:passwd:key=system,username=root:password#" #UBUNTU_SUBIQUITY_APT_CONFIG# kernel: package: linux-generic @@ -69,9 +76,13 @@ autoinstall: cat /tmp/pre-install.log >> /target/var/log/xcat/xcat.log; installnic="#TABLE:noderes:$NODE:installnic#"; installmac="#TABLE:mac:$NODE:mac#"; - installmac="$(printf ''%s'' "${installmac}" | tr ''A-F'' ''a-f'')"; + installmac="$(printf ''%s'' "${installmac}" | cut -d''|'' -f1 | cut -d''!'' -f1 | tr ''A-F'' ''a-f'')"; mkdir -p /target/etc/netplan; - printf ''%s\n'' "network:" " version: 2" " ethernets:" " xcat-install:" " match:" " macaddress: \"${installmac}\"" " set-name: ${installnic}" " dhcp4: true" >/target/etc/netplan/00-xcat-install.yaml; + if [ "${installnic}" = "mac" ]; then + printf ''%s\n'' "network:" " version: 2" " ethernets:" " xcat-install:" " match:" " macaddress: \"${installmac}\"" " dhcp4: true" >/target/etc/netplan/00-xcat-install.yaml; + else + printf ''%s\n'' "network:" " version: 2" " ethernets:" " xcat-install:" " match:" " macaddress: \"${installmac}\"" " set-name: ${installnic}" " dhcp4: true" >/target/etc/netplan/00-xcat-install.yaml; + fi; chmod 600 /target/etc/netplan/00-xcat-install.yaml; printf ''%s\n'' ''#HOSTNAME#'' >/target/etc/hostname; if grep -q ''^127\.0\.1\.1'' /target/etc/hosts; then diff --git a/xCAT-server/share/xcat/netboot/ubuntu/compute.postinstall b/xCAT-server/share/xcat/netboot/ubuntu/compute.postinstall index 2edc861c3..d22ef9876 100755 --- a/xCAT-server/share/xcat/netboot/ubuntu/compute.postinstall +++ b/xCAT-server/share/xcat/netboot/ubuntu/compute.postinstall @@ -51,3 +51,27 @@ chroot $installroot \ update-locale DEBIAN_FRONTEND=noninteractive chroot $installroot \ dpkg-reconfigure locales + +#-- A shared diskless image must not carry the builder's identity. genimage's chroot shares +#-- the build host's UTS namespace, so /etc/hostname ends up as the MN's name and every node +#-- booting this image inherits it ("hostname poisoning"). Clear it so each node takes its name +#-- at boot from DHCP (udhcpc option host-name) / xCAT instead of the build host. +: > $installroot/etc/hostname + +#-- Ship a DHCP netplan so systemd-networkd configures the boot NIC. Without any netplan in the +#-- image, systemd-networkd-wait-online has nothing to bring up and the unit fails. optional:true +#-- keeps it from blocking boot; dhcp-identifier:mac matches xCAT's MAC-based DHCP. +mkdir -p $installroot/etc/netplan +cat <<'NETPLAN' > $installroot/etc/netplan/90-xcat-dhcp.yaml +network: + version: 2 + renderer: networkd + ethernets: + xcat-cluster: + match: + name: "e*" + dhcp4: true + dhcp-identifier: mac + optional: true +NETPLAN +chmod 600 $installroot/etc/netplan/90-xcat-dhcp.yaml diff --git a/xCAT-server/share/xcat/netboot/ubuntu/genimage b/xCAT-server/share/xcat/netboot/ubuntu/genimage index 6feb870ba..a825913b4 100755 --- a/xCAT-server/share/xcat/netboot/ubuntu/genimage +++ b/xCAT-server/share/xcat/netboot/ubuntu/genimage @@ -257,6 +257,35 @@ unless ($onlyinitrd) { } } + # If pkgdir provided no http mirror, fall back to site.ubuntu_apt_mirror -- the same knob the + # Subiquity diskful install uses (Template.pm::ubuntu_subiquity_apt_mirror). The Ubuntu + # live-server ISO that copycds imports is NOT a complete apt mirror, so debootstrap needs a + # real online/local mirror to build the netboot/statelite rootimg. The mirror is codename- + # independent (one URL serves all releases); the codename comes from the osimage's osvers. + # The parser below expects the entry as " ". + unless (@pkgdir_internet) { + # site.ubuntu_apt_mirror overrides; otherwise default to the public archive. A live-server + # ISO is never a complete debootstrap source, so a real mirror is always required here. + my @aptmirror = xCAT::TableUtils->get_site_attribute("ubuntu_apt_mirror"); + my $mirror = (defined $aptmirror[0] && length $aptmirror[0]) + ? $aptmirror[0] : 'http://archive.ubuntu.com/ubuntu'; + (my $codename = $osver) =~ s/^ubuntu//; + $codename =~ s/\.\d+$//; # 24.04.4 -> 24.04 + my %cn = ('24.04' => 'noble', '22.04' => 'jammy', '20.04' => 'focal', + '18.04' => 'bionic', '26.04' => 'resolute'); + $codename = $cn{$codename} if exists $cn{$codename}; + # " ": debootstrap consumes only url+suite of the FIRST entry + # (ignores the rest); every entry becomes a line in the chroot's sources.list. The compute + # pkglist pulls from main + universe (busybox-static, dracut*), and needs the -updates / + # -security pockets too -- e.g. openssh-server depends on a security-updated openssh-client + # absent from the base release pocket. archive.ubuntu.com (and standard mirrors) serve all + # three pockets from the one base URL. + foreach my $pocket ($codename, "$codename-updates", "$codename-security") { + push @pkgdir_internet, "$mirror $pocket main universe"; + } + print "genimage: pkgdir has no http mirror; using '$mirror' [$codename {,-updates,-security} main universe] (site.ubuntu_apt_mirror or default)\n"; + } + # Add the dir for kernel deb to be installed if ($kernelver) { find(\&isaptdir, <$kerneldir/>); diff --git a/xCAT-test/xcattest b/xCAT-test/xcattest index 708ae79ca..bc89b4532 100755 --- a/xCAT-test/xcattest +++ b/xCAT-test/xcattest @@ -1683,7 +1683,13 @@ sub runcmd my $rc = 0; $::RUNCMD_RC = 0; my $outref = []; - @$outref = `$cmd 2>&1`; + # xCAT-test cases use bashisms ([ x == y ], [[ ]]); on Ubuntu /bin/sh is dash, so run + # the command under bash. open('-|', LIST) execs bash directly -- no intervening + # /bin/sh, so the cases' embedded quotes/backticks are not re-parsed or re-expanded. + if (open(my $cfh, '-|', '/bin/bash', '-c', "$cmd 2>&1")) { + @$outref = <$cfh>; + close($cfh); # sets $? just like the backtick did + } if ($?) { $rc = $?; diff --git a/xCAT/debian/control b/xCAT/debian/control index a1688a6db..8a50d3941 100644 --- a/xCAT/debian/control +++ b/xCAT/debian/control @@ -9,7 +9,7 @@ Homepage: https://xcat.org/ Package: xcat Architecture: amd64 ppc64el -Depends: ${perl:Depends}, goconserver(>= 0.3.3-snap000000000000), xcat-server (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libdbd-sqlite3-perl, isc-dhcp-server | kea, apache2, nfs-kernel-server, libxml-parser-perl, rsync, tftpd-hpa, libnet-telnet-perl, xcat-genesis-scripts-ppc64 (>= 2.13-snap000000000000), xcat-genesis-scripts-amd64 (>= 2.13-snap000000000000) +Depends: ${perl:Depends}, goconserver(>= 0.3.3-snap000000000000), xcat-server (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libdbd-sqlite3-perl, isc-dhcp-server | kea, apache2, nfs-kernel-server, libxml-parser-perl, rsync, tftpd-hpa, libnet-telnet-perl, xcat-genesis-scripts-amd64 (>= 2.13-snap000000000000) Recommends: bind9, net-tools, nmap, kea, tftp-hpa, ipmitool-xcat (>= 1.8.17-1), syslinux[any-amd64], libsys-virt-perl, syslinux-xcat, xnba-undi, elilo-xcat, xcat-buildkit (>= 2.13-snap000000000000), xcat-probe (>= 2.13-snap000000000000) Suggests: yaboot-xcat Description: Metapackage for a common, default xCAT setup diff --git a/xCATsn/debian/control b/xCATsn/debian/control index 8d7baf13e..3a295e28b 100644 --- a/xCATsn/debian/control +++ b/xCATsn/debian/control @@ -8,7 +8,7 @@ Homepage: https://xcat.org/ Package: xcatsn Architecture: amd64 ppc64el -Depends: ${perl:Depends}, goconserver (>=0.3.3-snap000000000000), xcat-server (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libdbd-sqlite3-perl, libxml-parser-perl, tftpd-hpa, libnet-telnet-perl, isc-dhcp-server | kea, apache2, nfs-kernel-server, xcat-genesis-scripts-ppc64 (>= 2.13-snap000000000000), xcat-genesis-scripts-amd64 (>= 2.13-snap000000000000) +Depends: ${perl:Depends}, goconserver (>=0.3.3-snap000000000000), xcat-server (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libdbd-sqlite3-perl, libxml-parser-perl, tftpd-hpa, libnet-telnet-perl, isc-dhcp-server | kea, apache2, nfs-kernel-server, xcat-genesis-scripts-amd64 (>= 2.13-snap000000000000) Recommends: bind9, net-tools, nmap, kea, tftp-hpa, ipmitool-xcat (>= 1.8.17-1), syslinux[any-amd64], libsys-virt-perl, syslinux-xcat, xnba-undi, elilo-xcat, xcat-buildkit (>= 2.13-snap000000000000), xcat-probe (>= 2.13-snap000000000000) Suggests: yaboot-xcat Description: Metapackage for a common, default xCAT service node setup