diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 3e009b684..5fda1acfd 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -177,19 +177,15 @@ my $mn; =head3 defer_syncfiles_to_postboot - On Ubuntu/Debian the DISKFUL install runs a node's postscripts inside the installer's - in-target chroot -- before the node has booted as itself. The syncfiles postscript works - by asking the management node to scp files INTO the running node, which cannot happen in - that phase: the not-yet-booted node has no sshd for the MN to reach, so the push times - out, syncfiles exits 1, and the node reports status=failed even though the OS installed - perfectly. Defer it to the postbootscripts, which run on the booted node where ssh is - already listening and the MN's push succeeds. + On the Ubuntu/Debian diskful install path a node's postscripts run inside the installer's + in-target chroot, before the node has booted as itself. syncfiles asks the management node + to scp files INTO the running node, which cannot work there -- there is no sshd yet -- so it + times out and the node reports status=failed although the OS installed. Defer it to the + postbootscripts, which run on the booted node. - Scoped to the diskful install path only: netboot and statelite already run their - postscripts on the booted node, so moving syncfiles there would change behaviour that - works. EL/SLES are unaffected either way -- their postscripts run on the booted node. - syncfiles is PREPENDED so it still runs before any postbootscript that consumes the - files it synchronises. + Scoped to the diskful install path: netboot and statelite already run their postscripts on + the booted node, and EL/SLES are unaffected either way. syncfiles is prepended so it still + runs before any postbootscript that consumes the files it synchronises. Arguments: $os nodetype.os for the node diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index a1f71aafd..920a99448 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -1686,17 +1686,11 @@ sub ubuntu_subiquity_apt_config ' primary:', " - uri: $online_mirror", ); - # On a classic-sources release (20.04/22.04) Subiquity renders the target's - # /etc/apt/sources.list from the install media alone (deb file:///cdrom), which lacks - # packages xCAT needs such as chrony -- curtin's in-target apt then fails with - # "E: Unable to locate package chrony". `sources_list:` is a curtin key that - # Subiquity's autoinstall schema ignores, so add the online archive through `sources:`, - # which Subiquity honours by writing /etc/apt/sources.list.d/*.list. $RELEASE is - # substituted with the release codename by curtin. - # - # Deb822 releases (24.04+) are deliberately excluded: there the primary mirror above - # already lands in /etc/apt/sources.list.d/ubuntu.sources, so adding these legacy .list - # files would configure the same suites twice. + # On 20.04/22.04 Subiquity renders the target's sources.list from the install media + # alone, so in-target apt cannot find packages the ISO does not carry (chrony). Add the + # online archive through `sources:` -- `sources_list:` is a curtin key Subiquity's + # schema ignores. Excluded on Deb822 releases, where the primary mirror already lands + # in ubuntu.sources and these legacy .list files would duplicate the same suites. my $need_sources_block = !$use_deb822; if ($need_sources_block) { push @lines, ' sources:'; diff --git a/xCAT-server/lib/xcat/plugins/debian.pm b/xCAT-server/lib/xcat/plugins/debian.pm index 4c7987195..1b039836d 100644 --- a/xCAT-server/lib/xcat/plugins/debian.pm +++ b/xCAT-server/lib/xcat/plugins/debian.pm @@ -513,25 +513,18 @@ sub copycd Build the kernel command line for a Subiquity (Ubuntu live installer) diskful install. - boot=casper is required: without it casper never processes netboot=nfs, it scans the local - disks, finds no live media and panics "Unable to find a medium containing a live file - system" (initramfs emergency shell -> PXE loop). + boot=casper: without it casper never processes netboot=nfs -- it scans the local disks, + finds no live media and panics into the initramfs shell, which PXE-loops. - nfsroot MUST be a literal IP: casper mounts the live filesystem with klibc's nfsmount, which - cannot resolve hostnames ("nfsmount: can't parse IP address ''"). The ds= URL is - fetched later by cloud-init in the booted live system where normal DNS works, so it keeps - the install server's name. + nfsroot must be a literal IP: casper mounts the live filesystem with klibc's nfsmount, + which has no resolver. The ds= URL is fetched later by cloud-init, where DNS works, so it + keeps the install server's name. - 'toram' makes casper copy the live squashfs into RAM and UNMOUNT the NFS source (casper - scripts/casper: copy_to_ram then umount of the copy source), so the installer runs from RAM - with NO network root. This is what lets the node reboot at all: with the NFS root still - mounted, a process doing I/O to it during systemd-shutdown (lvm, netplan, udev) blocks in - uninterruptible D state -- it cannot be SIGKILLed, so systemd-shutdown waits forever - ("Waiting for process: (lvm)") and the node never power-cycles into the disk it just - installed. casper has no cmdline knob for NFS mount options -- it parses only nfsroot=, - taking the whole value as the path, so appending ,soft breaks the mount; toram is casper's - supported way to avoid the network root. The 24.04 layers total ~1.5G, well within the CN's - RAM. + toram: casper copies the squashfs to RAM and unmounts the NFS source, so nothing holds the + network root at shutdown. Without it a process doing I/O to it blocks uninterruptibly, + systemd-shutdown waits forever and the node never reboots into the disk it just installed. + casper parses only nfsroot= and takes the whole value as the path, so mount options cannot + be appended; toram is its supported alternative. Arguments: $base the command line built so far diff --git a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl index 547a48aa1..783ebc2de 100644 --- a/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl +++ b/xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl @@ -66,12 +66,9 @@ autoinstall: sed -i '/^\.\.\.$/d' /autoinstall.yaml cat /tmp/partitionfile >> /autoinstall.yaml echo "=== DNS setup ===" - # A nameserver line in /etc/resolv.conf MUST hold an IP address -- glibc's resolver does - # NOT resolve a hostname written there, it discards the entry. Writing the xcatmaster - # *name* leaves the installer (and the in-target apt-get, which inherits this file) with - # no usable DNS, so the install hangs resolving archive.ubuntu.com. DNS still works at - # this point through the live installer's DHCP resolv.conf -- the wget calls above relied - # on it -- so resolve the xcatmaster to an IPv4 address first and write that. + # glibc's resolver discards a nameserver line naming a host, so writing the xcatmaster + # *name* leaves the installer -- and the in-target apt that inherits this file -- with no + # DNS. Resolve it here, while the live installer's DHCP resolv.conf still works. xcatmaster_host="#TABLE:noderes:$NODE:xcatmaster#" xcatmaster_ip="$(getent ahostsv4 "$xcatmaster_host" | awk '{print $1; exit}')" [ -n "$xcatmaster_ip" ] || xcatmaster_ip="$xcatmaster_host" @@ -110,16 +107,10 @@ autoinstall: cp ./#HOSTNAME#.post /target/root/post.script; curtin in-target --target /target /root/post.script; } >>/target/var/log/xcat/xcat.log 2>&1' - # Switch the node to boot from the local disk now the install is done, or it PXE-loops - # straight back into the installer when Subiquity reboots. xCAT flips the netboot state - # when the node reports "next" to xcatd on the install-monitor port, which makes xcatd run - # "nodeset next" and rewrite the node's xNBA script to fall through to local disk. - # The in-target post-script tries this through updateflag.awk, but that needs gawk's |& - # /inet coprocess and /usr/bin/awk on Ubuntu is normally mawk, so the flip silently fails. - # Send it from the live installer instead -- the connection then originates from the node's - # own IP, which xcatd trusts -- using bash's built-in /dev/tcp, with no gawk dependency. - # xcatd answers with a ready token, takes "next", and acknowledges; treat anything else as - # a failure and say so in the install log rather than rebooting into another install. + # Flip the node to local-disk boot, or it PXE-loops back into the installer on reboot. + # The in-target post-script does this through updateflag.awk, which needs gawk's |& and + # Ubuntu's /usr/bin/awk is mawk, so it silently failed. Send "next" to xcatd from the live + # installer over bash's /dev/tcp instead, and log a failure rather than reinstalling. - ['bash', '-c', 'xm=#XCATVAR:XCATMASTER#; ok=0; for i in 1 2 3 4 5; do if exec 3<>/dev/tcp/$xm/3002; then read -r r <&3 || true; printf "next\n" >&3; if read -r r <&3; then ok=1; fi; exec 3>&- 3<&-; [ "$ok" = 1 ] && break; fi; sleep 5; done; if [ "$ok" != 1 ]; then echo "xcat: FAILED to flip $(hostname) to local-disk boot via $xm:3002; the node will PXE back into the installer" >>/target/var/log/xcat/xcat.log; fi; exit 0'] error-commands: - tar -c --ignore-failed-read --transform='s/^/#HOSTNAME#-logs\//' /var/crash /var/log/installer /tmp/pre-install.log /autoinstall.yaml 2>/dev/null |nc -l 8080 diff --git a/xCAT-test/unit/ubuntu_subiquity_apt_sources.t b/xCAT-test/unit/ubuntu_subiquity_apt_sources.t index f857af48e..0c55d0e8c 100644 --- a/xCAT-test/unit/ubuntu_subiquity_apt_sources.t +++ b/xCAT-test/unit/ubuntu_subiquity_apt_sources.t @@ -8,18 +8,9 @@ use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; use Test::More; -# Regression: on an ONLINE Subiquity install of a classic-sources release (20.04 / 22.04), -# Subiquity renders the target's /etc/apt/sources.list from the install media alone -# ("deb file:///cdrom"). A live-server ISO does not carry everything xCAT's postscripts need -- -# chrony, for one -- so curtin's in-target apt fails with "E: Unable to locate package chrony" -# and the install crashes. `sources_list:` is a curtin key that Subiquity's autoinstall schema -# ignores, so the online archive has to be added through `sources:`, which Subiquity honours by -# writing /etc/apt/sources.list.d/*.list. -# -# That fix belongs to the classic-sources releases ONLY. On a Deb822 release (24.04 / 26.04) -# the primary mirror already lands in /etc/apt/sources.list.d/ubuntu.sources, so adding legacy -# .list files on top produces duplicate apt entries for the same suites -- exactly the source -# conflict the Deb822 branch elsewhere in this function goes out of its way to avoid. +# An online Subiquity install of a classic-sources release needs the online archive added, or +# in-target apt cannot find chrony and the install crashes. A Deb822 release must NOT get it, +# or the same suites are configured twice. See the comment in Template.pm. require xCAT::Template;