From e2e15184f2952649dc29a3b57fc1309475f68e24 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:27:13 -0300 Subject: [PATCH 1/9] fix(build-ubunturepo): derive a stable, filesystem-safe repo path The apt output directory is built from the current branch name. A branch containing a slash created nested directories, and builds run as root against a repository owned by another user collapsed the value to empty because git aborted with "dubious ownership". Resolve the branch with safe.directory and replace unsafe characters, so the output path is stable across branch names and run contexts. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- build-ubunturepo | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) 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 From 37212eea3ca10ab480e715deba16491ce99a5da5 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:27:13 -0300 Subject: [PATCH 2/9] fix(xcat): drop unsatisfiable ppc64 genesis-scripts dependency xcat and xcatsn declared a hard dependency on xcat-genesis-scripts-ppc64. In an amd64-only build that package is never produced, so apt could not satisfy the dependency and refused to install xcat. Depend only on the amd64 genesis-scripts package. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT/debian/control | 2 +- xCATsn/debian/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 From d8953b0ea67f4bae6d80ac0673e0076e7008d416 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:27:13 -0300 Subject: [PATCH 3/9] fix(xcat-genesis-base): bump package version to satisfy genesis-scripts The genesis-base deb version was frozen at an ancient value, below the lower bound required by xcat-genesis-scripts (xcat-genesis-base-amd64 >= 2.13.10). apt therefore refused to install it and its dependents. Bump the version to track current xCAT so the dependency resolves. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-genesis-builder/debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) 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 From 846e6117724546e09514ccef1c8be020af74095b Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:27:13 -0300 Subject: [PATCH 4/9] fix(xcat-server): allow an online apt mirror for Ubuntu Subiquity installs The Ubuntu live-server install media is not a complete apt package mirror. With the generated apt configuration pinned to the media only, an install that needs a package absent from the media stalls instead of fetching it. Emit an online-mirror apt configuration when one is configured (site.ubuntu_apt_mirror) so missing packages are retrieved from the archive; offline behaviour is unchanged when it is unset. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-server/lib/perl/xCAT/Template.pm | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index d233e94bb..153c1bca4 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 +{ + # Online apt mirror for Subiquity installs. When site.ubuntu_apt_mirror is set + # (e.g. http://archive.ubuntu.com/ubuntu or a local full mirror), the generated + # autoinstall apt config pulls from it so packages missing from the minimal + # live-server install media are fetched over the network. Unset => keep the + # airgapped file:///cdrom config (backward compatible). + my $site_tab = xCAT::Table->new('site'); + return '' unless $site_tab; + my $ent = $site_tab->getAttribs({ key => 'ubuntu_apt_mirror' }, 'value'); + return ($ent && defined($ent->{value}) && length($ent->{value})) ? $ent->{value} : ''; +} + 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', From 86e77bcd7f799288bd414b495ceeb6dac242f04d Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:27:42 -0300 Subject: [PATCH 5/9] fix(xcat-server): add an identity section to the Ubuntu autoinstall config The generated Subiquity autoinstall config defined no identity section. Newer Subiquity treats a config without an identity as incomplete and stops at an interactive "Continue with autoinstall?" confirmation, so the install never proceeds unattended (the prompt's advice to add 'autoinstall' to the kernel command line is a red herring -- it was already present). Provide an identity with a password sourced from the cluster passwd table so the install runs non-interactively. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl index 15b644596..14061a21c 100644 --- a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl +++ b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl @@ -12,6 +12,11 @@ autoinstall: 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 From c6e38483fbc7466c5666a89441cd259b46f5691f Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 06:28:18 -0300 Subject: [PATCH 6/9] fix(xcat-server): fix Ubuntu autoinstall netplan for match-by-MAC nodes When a node's install NIC is selected by MAC (installnic=mac), the generated netplan was invalid: it named the ethernet device the literal string 'mac' and set its MAC match to the full pipe-delimited list of all node MACs. The result had no valid interface, so neither the installer environment nor the installed system came up on the network. Match the install NIC by interface-name glob in the installer, and in the target use only the primary MAC and omit set-name when the install NIC is selected by MAC. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- .../share/xcat/install/ubuntu/compute.subiquity.tmpl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl index 14061a21c..31a978cbc 100644 --- a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl +++ b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl @@ -6,7 +6,9 @@ autoinstall: network: version: 2 ethernets: - '#TABLE:noderes:$NODE:installnic#': + xcat-install: + match: + name: "e*" dhcp4: true ssh: allow-pw: true @@ -74,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 From c0731a5e33bd0e5aef27ec5bfdba5cf8ba98b726 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:21:59 -0300 Subject: [PATCH 7/9] fix(xcat-test): run testcase commands under bash, not /bin/sh xcattest's runcmd ran each RUN: command via Perl backticks, i.e. /bin/sh. On Ubuntu /bin/sh is dash, so testcases using bashisms ([ x == y ], [[ ... ]]) error with "unexpected operator": the [ exits non-zero, the enclosing if is taken as false, and the case's distro-specific branch is silently skipped while the case still reports Passed -- a false pass. Run the command through bash via list-form open() so no intervening /bin/sh re-parses or re-expands the command's embedded quotes and backticks. EL is unaffected (its /bin/sh is already bash). Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-test/xcattest | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 = $?; From 03e155998930a8df414ffe4604419638aee3d7ef Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:21:59 -0300 Subject: [PATCH 8/9] fix(xcat-server): default the Ubuntu apt mirror for netboot and Subiquity The Ubuntu live-server ISO copycds imports is not a complete apt pool, so both Ubuntu install paths fail without an external mirror: the netboot genimage's debootstrap from the ISO-only pkgdir cannot resolve packages, and the Subiquity diskful install (Template.pm) fell back to the airgapped file:///cdrom config. Default site.ubuntu_apt_mirror to http://archive.ubuntu.com/ubuntu when unset (overridable for local/geo/ ports mirrors). In the Ubuntu genimage, when pkgdir has no http mirror, build the debootstrap source and chroot sources.list from that mirror with the codename derived from osvers and the release/-updates/-security pockets (main + universe) -- the compute pkglist needs universe (busybox-static, dracut*) and the security-updated openssh. Ubuntu-only; EL netboot (netboot/rh) and copycds/packimage are untouched. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-server/lib/perl/xCAT/Template.pm | 14 ++++----- .../share/xcat/netboot/ubuntu/genimage | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index 153c1bca4..c2a5c2137 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -1654,15 +1654,15 @@ sub crydb_or_locked sub ubuntu_subiquity_apt_mirror { - # Online apt mirror for Subiquity installs. When site.ubuntu_apt_mirror is set - # (e.g. http://archive.ubuntu.com/ubuntu or a local full mirror), the generated - # autoinstall apt config pulls from it so packages missing from the minimal - # live-server install media are fetched over the network. Unset => keep the - # airgapped file:///cdrom config (backward compatible). + # 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 '' unless $site_tab; + 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} : ''; + return ($ent && defined($ent->{value}) && length($ent->{value})) ? $ent->{value} : $default; } sub ubuntu_subiquity_apt_config 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/>); From 3a5cbef63041863b43beac9a42bc84901adf28ea Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:21:59 -0300 Subject: [PATCH 9/9] fix(xcat-server): stop Ubuntu diskless images carrying the builder's identity The Ubuntu netboot image inherited the build host's /etc/hostname -- genimage's chroot shares the build host's UTS namespace, so /etc/hostname ended up as the MN's name and every diskless node booted as that name instead of its own ("hostname poisoning"). xCAT keys on IP/MAC so provisioning still succeeds, but the node's local identity (hostname, prompt, syslog) is wrong and N nodes share one name. The image also shipped no netplan, so systemd-networkd-wait-online failed. In compute.postinstall, clear /etc/hostname so each node takes its name at boot from DHCP (udhcpc option host-name) / xCAT, and drop in a DHCP netplan (optional, dhcp-identifier mac) so systemd-networkd configures the boot NIC. Ubuntu-only. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- .../xcat/netboot/ubuntu/compute.postinstall | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) 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