mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-02 00:41:42 +00:00
fix(xcat-server): an Ubuntu service node installs from a debian-installer preseed
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
#cloud-config
|
||||
autoinstall:
|
||||
version: 1
|
||||
keyboard: {layout: us, toggle: null, variant: ''}
|
||||
locale: en_US
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
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
|
||||
user-data:
|
||||
hostname: #HOSTNAME#
|
||||
disable_root: false
|
||||
package_update: false
|
||||
package_upgrade: false
|
||||
timezone: #TABLE:site:key=timezone:value#
|
||||
chpasswd:
|
||||
list:
|
||||
- "root:#CRYPTORLOCKED:passwd:key=system,username=root:password#"
|
||||
expire: false
|
||||
packages:
|
||||
- openssh-server
|
||||
- openssh-client
|
||||
- wget
|
||||
- vim
|
||||
- rsync
|
||||
- busybox-static
|
||||
- gawk
|
||||
- bind9-dnsutils
|
||||
- chrony
|
||||
- gpg
|
||||
- #INCLUDE_DEFAULT_PKGLIST_AUTOINSTALL#
|
||||
early-commands:
|
||||
- |
|
||||
exec >/tmp/pre-install.log 2>&1
|
||||
set -eux
|
||||
echo "=== xCAT early-commands ==="
|
||||
echo "=== network ==="
|
||||
ip addr show
|
||||
ip route show
|
||||
echo "=== disk detection ==="
|
||||
wget -T 30 -O /tmp/getinstdisk http://#XCATVAR:XCATMASTER##COLONHTTPPORT#/install/autoinst/getinstdisk
|
||||
test -s /tmp/getinstdisk
|
||||
chmod u+x /tmp/getinstdisk
|
||||
/tmp/getinstdisk
|
||||
echo "=== pre-install script ==="
|
||||
wget -T 30 -O /tmp/pre.sh http://#XCATVAR:XCATMASTER##COLONHTTPPORT#/install/autoinst/#HOSTNAME#.pre
|
||||
test -s /tmp/pre.sh
|
||||
chmod u+x /tmp/pre.sh
|
||||
/tmp/pre.sh
|
||||
echo "=== storage injection ==="
|
||||
test -s /tmp/partitionfile
|
||||
sed -i '/^\.\.\.$/d' /autoinstall.yaml
|
||||
cat /tmp/partitionfile >> /autoinstall.yaml
|
||||
echo "=== DNS setup ==="
|
||||
# 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, and keep
|
||||
# that file when the name does not resolve. A name written back is the case this step
|
||||
# exists to prevent.
|
||||
xcatmaster_host="#TABLE:noderes:$NODE:xcatmaster#"
|
||||
xcatmaster_ip="$(getent ahostsv4 "$xcatmaster_host" | awk '{print $1; exit}')"
|
||||
if [ -n "$xcatmaster_ip" ]; then
|
||||
rm -f /etc/resolv.conf
|
||||
echo "nameserver $xcatmaster_ip" >/etc/resolv.conf
|
||||
else
|
||||
echo "xcat: $xcatmaster_host has no IPv4 address; keeping the resolver DHCP supplied"
|
||||
fi
|
||||
echo "domain #TABLE:site:key=domain:value#" >>/etc/resolv.conf
|
||||
echo "=== early-commands complete ==="
|
||||
late-commands:
|
||||
- mkdir -p /target/var/log/xcat/
|
||||
- '{
|
||||
cat /tmp/pre-install.log >> /target/var/log/xcat/xcat.log;
|
||||
installnic="#SUBIQUITYINSTALLNIC#";
|
||||
installmac="#SUBIQUITYINSTALLMAC#";
|
||||
mkdir -p /target/etc/netplan;
|
||||
if [ -z "${installnic}" ]; then
|
||||
printf ''%s\n'' "network:" " version: 2" " ethernets:" " xcat-install:" " match:" " macaddress: \"${installmac}\"" " dhcp4: true" " dhcp4-overrides:" " use-domains: 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" " dhcp4-overrides:" " use-domains: 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
|
||||
sed -i ''s/^127\.0\.1\.1.*/127.0.1.1 #HOSTNAME#/'' /target/etc/hosts;
|
||||
else
|
||||
printf ''%s\n'' ''127.0.1.1 #HOSTNAME#'' >>/target/etc/hosts;
|
||||
fi;
|
||||
mkdir -p /target/etc/cloud;
|
||||
touch /target/etc/cloud/cloud-init.disabled;
|
||||
echo "Updating kernel command line...";
|
||||
printf ''%s\n'' ''GRUB_CMDLINE_LINUX="#TABLEBLANKOKAY:bootparams:$NODE:kcmdline#"'' >>/target/etc/default/grub;
|
||||
curtin in-target --target /target update-grub2;
|
||||
echo "Running late_command Installation script...";
|
||||
wget -T 30 http://#XCATVAR:XCATMASTER##COLONHTTPPORT#/install/autoinst/#HOSTNAME#.post;
|
||||
chmod u+x #HOSTNAME#.post;
|
||||
cp ./#HOSTNAME#.post /target/root/post.script;
|
||||
curtin in-target --target /target /root/post.script;
|
||||
} >>/target/var/log/xcat/xcat.log 2>&1'
|
||||
# The installer's sources for the otherpkgs repository and the pkgdir mirrors, and the apt
|
||||
# configuration that kept recommended packages out, served the install; ospkgs and otherpkgs
|
||||
# write their own after the first boot. A separate item, so the status of the post script above
|
||||
# still decides whether the install goes on.
|
||||
- rm -f /target/etc/apt/sources.list.d/xcat-otherpkgs-*.list /target/etc/apt/sources.list.d/xcat-otherpkgs-*.sources /target/etc/apt/sources.list.d/xcat-pkgdir-*.list /target/etc/apt/sources.list.d/xcat-pkgdir-*.sources /target/etc/apt/apt.conf.d/94curtin-config
|
||||
# Flip the node to local-disk boot, or it PXE-loops back into the installer on reboot.
|
||||
# xcatd's install monitor greets with "ready", then answers "next" with "done" and runs
|
||||
# "nodeset <node> next". Require both tokens: another service on that port is not a flipped
|
||||
# node. The monitor listens on site.xcatiport; TABLEBLANKOKAY because an absent key fails a
|
||||
# plain TABLE lookup, and with it the whole template.
|
||||
# Retry, and log a failure rather than reinstall silently. Both reads are bounded: a monitor
|
||||
# that accepts and never answers would block a bare read and hang the install here. A
|
||||
# monitor that died and never came back is #7759.
|
||||
- ['bash', '-c', 'xm=#XCATVAR:XCATMASTER#; port="#TABLEBLANKOKAY:site:key=xcatiport:value#"; [ -n "$port" ] || port=3002; ok=0; for i in 1 2 3 4 5; do if exec 3<>/dev/tcp/$xm/$port; then if read -r -t 10 hello <&3 && [ "$hello" = "ready" ]; then printf "next\n" >&3; if read -r -t 10 ack <&3 && [ "$ack" = "done" ]; then ok=1; fi; 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:$port; the node will PXE back into the installer" >>/target/var/log/xcat/xcat.log; fi; exit 0']
|
||||
error-commands:
|
||||
# Subiquity waits for every error command to return. "nc -l 8080" waits for a collector, which
|
||||
# an unattended install does not have. Keep the archive on the installer, and print the end of
|
||||
# the curtin log to the console, which the management node records.
|
||||
#
|
||||
# Both destinations are read from the environment so a test can point them at its own
|
||||
# directory. The installer sets neither, so an install writes where it always did.
|
||||
- ['sh', '-c', 'tar -c --ignore-failed-read --transform="s/^/#HOSTNAME#-logs\//" /var/crash /var/log/installer /tmp/pre-install.log /autoinstall.yaml >"${XCAT_ERROR_ARCHIVE:-/run/#HOSTNAME#-logs.tar}" 2>/dev/null; exit 0']
|
||||
- ['sh', '-c', 'tail -n 80 /var/log/installer/curtin-install.log >"${XCAT_ERROR_CONSOLE:-/dev/console}" 2>/dev/null; exit 0']
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use Test::More;
|
||||
|
||||
# xCAT decides that an Ubuntu osimage uses the Subiquity installer from the NAME of the template
|
||||
# it resolved: xCAT_plugin::debian::using_subiquity matches /subiquity/ in the path. That decision
|
||||
# controls the netboot kernel command line. A template whose name does not match it makes xCAT
|
||||
# boot the live-server initrd with the debian-installer preseed arguments, without boot=casper and
|
||||
# without nfsroot, and the node never finds a live filesystem.
|
||||
#
|
||||
# The compute profile has compute.subiquity.tmpl. The service profile had only service.tmpl, so an
|
||||
# Ubuntu 24.04 service node took the preseed path.
|
||||
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use xCAT::SvrUtils;
|
||||
|
||||
my $plugin = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/debian.pm";
|
||||
plan skip_all => 'debian.pm not found' unless -r $plugin;
|
||||
eval { require $plugin; 1 } or plan skip_all => "could not load debian.pm: $@";
|
||||
|
||||
my $share = "$FindBin::Bin/../../xCAT-server/share/xcat/install/ubuntu";
|
||||
plan skip_all => "$share not found" unless -d $share;
|
||||
|
||||
# get_file_name takes genos as its last argument. update_tables_with_templates passes 'subiquity'
|
||||
# for every Ubuntu 20.04 and later osimage.
|
||||
sub resolved {
|
||||
my ($profile, $osver, $genos) = @_;
|
||||
return xCAT::SvrUtils::get_tmpl_file_name($share, $profile, $osver, 'x86_64', $genos);
|
||||
}
|
||||
|
||||
for my $profile (qw(compute service)) {
|
||||
my $tmpl = resolved($profile, 'ubuntu24.04', 'subiquity');
|
||||
ok(defined $tmpl && -r $tmpl, "$profile: Ubuntu 24.04 resolves an install template");
|
||||
ok(xCAT_plugin::debian::using_subiquity('ubuntu24.04', $tmpl),
|
||||
"$profile: the Ubuntu 24.04 template xCAT resolved is a Subiquity one");
|
||||
}
|
||||
|
||||
# Ubuntu 18.04 predates Subiquity and keeps the preseed path. genos stays the os version there.
|
||||
for my $profile (qw(compute service)) {
|
||||
my $tmpl = resolved($profile, 'ubuntu18.04', 'ubuntu18.04');
|
||||
ok(defined $tmpl && -r $tmpl, "$profile: Ubuntu 18.04 resolves an install template");
|
||||
ok(!xCAT_plugin::debian::using_subiquity('ubuntu18.04', $tmpl),
|
||||
"$profile: Ubuntu 18.04 keeps the debian-installer template");
|
||||
}
|
||||
|
||||
# The service template must carry the autoinstall document Subiquity reads. A file named for
|
||||
# Subiquity that holds a preseed would satisfy using_subiquity and still not install.
|
||||
my $service = resolved('service', 'ubuntu24.04', 'subiquity');
|
||||
SKIP: {
|
||||
skip 'no service template resolved', 3 unless defined $service && -r $service;
|
||||
my $text = do { local $/; open my $fh, '<', $service or die "$service: $!"; <$fh> };
|
||||
like($text, qr/^#cloud-config/, 'the service template is a cloud-config document');
|
||||
like($text, qr/^autoinstall:/m, '... carrying an autoinstall section');
|
||||
unlike($text, qr/^d-i /m, '... and no debian-installer preseed directives');
|
||||
}
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user