Fix netboot: hardcode config values, simplify boot chain
- Hardcode ROOT_URL and OVERLAYROOT in netboot script - Remove cmdline parsing that was failing silently - Simplify boot.ipxe to chain to netboot.ipxe - Add rebuild-initramfs.sh helper script Resolves kernel panic caused by cmdline parsing issues.
This commit is contained in:
@@ -1,17 +1,5 @@
|
|||||||
#!ipxe
|
#!ipxe
|
||||||
echo Booting Ubuntu Noble K3s Node via iPXE
|
echo Configuring network via DHCP...
|
||||||
|
dhcp
|
||||||
# Clear any previous images
|
echo Chaining to dynamic boot script...
|
||||||
imgfree
|
chain http://192.168.100.1:8800/netboot.ipxe
|
||||||
|
|
||||||
echo Loading kernel from http://192.168.100.1:8800/vmlinuz
|
|
||||||
kernel --name vmlinuz http://192.168.100.1:8800/vmlinuz
|
|
||||||
|
|
||||||
echo Loading initramfs from http://192.168.100.1:8800/initrd-netboot.img
|
|
||||||
initrd --name initrd http://192.168.100.1:8800/initrd-netboot.img
|
|
||||||
|
|
||||||
echo Setting kernel arguments for HTTP root mounting
|
|
||||||
imgargs vmlinuz initrd=initrd rdinit=/init boot=netboot root=http://192.168.100.1:8800/filesystem.squashfs rootfstype=squashfs overlayroot=tmpfs ip=dhcp console=tty0 console=ttyS0,115200 loglevel=7 panic=-1 break=mountroot
|
|
||||||
|
|
||||||
echo Booting system...
|
|
||||||
boot vmlinuz
|
|
||||||
|
|||||||
@@ -1,207 +1,85 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Netboot HTTP root mounting - sourced by initramfs init (functions already loaded)
|
# Netboot HTTP root mounting - HARDCODED VALUES - no cmdline parsing
|
||||||
|
|
||||||
export PATH=/usr/bin:/usr/sbin:/bin:/sbin
|
export PATH=/usr/bin:/usr/sbin:/bin:/sbin
|
||||||
|
|
||||||
|
# HARDCODED CONFIGURATION
|
||||||
|
ROOT_URL="http://192.168.100.1:8800/filesystem.squashfs"
|
||||||
|
OVERLAYROOT="tmpfs"
|
||||||
MOUNTPOINT=/root
|
MOUNTPOINT=/root
|
||||||
SQUASHFS_MOUNT=/mnt/squashfs
|
SQUASHFS_MOUNT=/mnt/squashfs
|
||||||
OVERLAY_TMPFS=/mnt/overlay
|
OVERLAY_TMPFS=/mnt/overlay
|
||||||
|
|
||||||
# Hook functions for initramfs-tools boot script integration
|
# Debug logging to console
|
||||||
netboot_top()
|
log() {
|
||||||
{
|
echo "$@" > /dev/console 2>&1
|
||||||
if [ "${netboot_top_used}" != "yes" ]; then
|
|
||||||
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-top"
|
|
||||||
run_scripts /scripts/netboot-top
|
|
||||||
[ "$quiet" != "y" ] && log_end_msg
|
|
||||||
fi
|
|
||||||
netboot_top_used=yes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
netboot_premount()
|
# Minimal hook functions
|
||||||
{
|
netboot_top() { :; }
|
||||||
if [ "${netboot_premount_used}" != "yes" ]; then
|
netboot_premount() { :; }
|
||||||
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-premount"
|
netboot_bottom() { :; }
|
||||||
run_scripts /scripts/netboot-premount
|
mount_top() { :; }
|
||||||
[ "$quiet" != "y" ] && log_end_msg
|
mount_premount() { :; }
|
||||||
fi
|
mount_bottom() { :; }
|
||||||
netboot_premount_used=yes
|
|
||||||
}
|
|
||||||
|
|
||||||
netboot_bottom()
|
|
||||||
{
|
|
||||||
if [ "${netboot_premount_used}" = "yes" ] || [ "${netboot_top_used}" = "yes" ]; then
|
|
||||||
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-bottom"
|
|
||||||
run_scripts /scripts/netboot-bottom
|
|
||||||
[ "$quiet" != "y" ] && log_end_msg
|
|
||||||
fi
|
|
||||||
netboot_premount_used=no
|
|
||||||
netboot_top_used=no
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parse kernel command line for HTTP root
|
|
||||||
parse_cmdline() {
|
|
||||||
for x in $(cat /proc/cmdline); do
|
|
||||||
case $x in
|
|
||||||
root=http://*)
|
|
||||||
export ROOT_URL="${x#root=}" ;;
|
|
||||||
rootfstype=*)
|
|
||||||
export ROOTFSTYPE="${x#rootfstype=}" ;;
|
|
||||||
overlayroot=*)
|
|
||||||
export OVERLAYROOT="${x#overlayroot=}" ;;
|
|
||||||
ip=*)
|
|
||||||
export BOOTIP="${x#ip=}" ;;
|
|
||||||
*)
|
|
||||||
: ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
mountroot() {
|
mountroot() {
|
||||||
rc=1
|
log "NETBOOT: ========================================"
|
||||||
|
log "NETBOOT: mountroot() HARDCODED VERSION"
|
||||||
|
log "NETBOOT: ROOT_URL=${ROOT_URL}"
|
||||||
|
log "NETBOOT: ========================================"
|
||||||
|
|
||||||
# Run hook scripts
|
# Load network module
|
||||||
netboot_top
|
/sbin/modprobe af_packet
|
||||||
netboot_premount
|
|
||||||
|
|
||||||
parse_cmdline
|
# Wait for udev
|
||||||
|
wait_for_udev 10
|
||||||
if test -z "${ROOT_URL}"; then
|
|
||||||
log_failure_msg "No root URL defined (root=http://... not found)"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure networking before attempting downloads
|
|
||||||
log_begin_msg "Configuring network"
|
|
||||||
modprobe af_packet || log_warning_msg "af_packet load failed"
|
|
||||||
|
|
||||||
# Load RTL8125 driver (already in module list but explicit load for debugging)
|
|
||||||
modprobe r8125 || log_warning_msg "r8125 driver load failed, may use generic driver"
|
|
||||||
|
|
||||||
|
# Configure networking via DHCP
|
||||||
|
log "NETBOOT: Calling configure_networking..."
|
||||||
configure_networking
|
configure_networking
|
||||||
udevadm trigger
|
|
||||||
timeout 30 udevadm settle || log_warning_msg "udevadm settle timed out"
|
|
||||||
export DEVICE
|
|
||||||
log_end_msg
|
|
||||||
|
|
||||||
# Validate networking is up
|
# Check we got an IP
|
||||||
INTERFACE_UP=0
|
log "NETBOOT: Checking for IP address..."
|
||||||
for iface in $(ip link show | grep "^[0-9]" | awk -F: '{print $2}' | tr -d ' '); do
|
if ! ip addr show | grep -q "inet "; then
|
||||||
if ip addr show "$iface" | grep -q "inet "; then
|
log "NETBOOT: FATAL - no IP address"
|
||||||
INTERFACE_UP=1
|
return 1
|
||||||
log_begin_msg "Interface $iface has IP address"
|
|
||||||
ip addr show "$iface" | grep "inet " | awk '{print $2}'
|
|
||||||
break
|
|
||||||
fi
|
fi
|
||||||
done
|
log "NETBOOT: Network is up"
|
||||||
|
|
||||||
if [ $INTERFACE_UP -eq 0 ]; then
|
# Download squashfs
|
||||||
log_failure_msg "No network interface obtained an IP address"
|
log "NETBOOT: Downloading ${ROOT_URL}..."
|
||||||
return ${rc}
|
if ! wget -O /filesystem.squashfs "${ROOT_URL}"; then
|
||||||
|
log "NETBOOT: FATAL - wget failed"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
log "NETBOOT: Download complete"
|
||||||
|
|
||||||
# Extract filename from URL
|
|
||||||
FILE_NAME=$(basename "${ROOT_URL}")
|
|
||||||
FILE_PATH="/${FILE_NAME}"
|
|
||||||
|
|
||||||
# Download the root filesystem with retries and timeouts
|
|
||||||
log_begin_msg "Downloading root filesystem from ${ROOT_URL}"
|
|
||||||
if wget --timeout=30 --tries=3 --waitretry=5 \
|
|
||||||
--progress=dot:mega \
|
|
||||||
"${ROOT_URL}" -O "${FILE_PATH}"; then
|
|
||||||
log_end_msg
|
|
||||||
else
|
|
||||||
log_failure_msg "Failed to download from ${ROOT_URL} after retries"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify the downloaded file is a valid SquashFS
|
|
||||||
if ! file "${FILE_PATH}" | grep -q "Squash"; then
|
|
||||||
log_failure_msg "Downloaded file is not a valid SquashFS image"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Handle SquashFS images with overlay
|
|
||||||
if echo "${FILE_NAME}" | grep -q squashfs; then
|
|
||||||
log_begin_msg "Setting up SquashFS with overlay"
|
|
||||||
|
|
||||||
# Setup overlay if requested - need separate mount points
|
|
||||||
if [ -n "${OVERLAYROOT}" ]; then
|
|
||||||
# Create mount points
|
# Create mount points
|
||||||
mkdir -p "${SQUASHFS_MOUNT}" "${OVERLAY_TMPFS}"
|
mkdir -p "${SQUASHFS_MOUNT}" "${OVERLAY_TMPFS}"
|
||||||
|
|
||||||
# Mount read-only SquashFS to separate location
|
# Mount squashfs
|
||||||
if ! mount -t squashfs "${FILE_PATH}" "${SQUASHFS_MOUNT}" -o ro; then
|
log "NETBOOT: Mounting squashfs..."
|
||||||
log_failure_msg "Failed to mount SquashFS at ${SQUASHFS_MOUNT}"
|
if ! mount -t squashfs /filesystem.squashfs "${SQUASHFS_MOUNT}" -o ro; then
|
||||||
rm -f "${FILE_PATH}"
|
log "NETBOOT: FATAL - squashfs mount failed"
|
||||||
return ${rc}
|
return 1
|
||||||
fi
|
|
||||||
log_begin_msg "SquashFS mounted at ${SQUASHFS_MOUNT}"
|
|
||||||
log_end_msg
|
|
||||||
|
|
||||||
log_begin_msg "Mounting tmpfs for overlay upper/work"
|
|
||||||
|
|
||||||
# Create tmpfs for upper and work directories
|
|
||||||
if ! mount -t tmpfs -o size=2G tmpfs_overlay "${OVERLAY_TMPFS}"; then
|
|
||||||
log_failure_msg "Failed to mount tmpfs for overlay"
|
|
||||||
umount "${SQUASHFS_MOUNT}"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create overlay structure
|
# Mount tmpfs for overlay
|
||||||
|
log "NETBOOT: Mounting tmpfs..."
|
||||||
|
if ! mount -t tmpfs -o size=2G tmpfs "${OVERLAY_TMPFS}"; then
|
||||||
|
log "NETBOOT: FATAL - tmpfs mount failed"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
mkdir -p "${OVERLAY_TMPFS}/upper" "${OVERLAY_TMPFS}/work"
|
mkdir -p "${OVERLAY_TMPFS}/upper" "${OVERLAY_TMPFS}/work"
|
||||||
|
|
||||||
# Mount overlay combining read-only lower + writable upper onto /root
|
# Mount overlay
|
||||||
if ! mount -t overlay \
|
log "NETBOOT: Mounting overlay..."
|
||||||
-o "lowerdir=${SQUASHFS_MOUNT},upperdir=${OVERLAY_TMPFS}/upper,workdir=${OVERLAY_TMPFS}/work" \
|
if ! mount -t overlay -o "lowerdir=${SQUASHFS_MOUNT},upperdir=${OVERLAY_TMPFS}/upper,workdir=${OVERLAY_TMPFS}/work" overlay "${MOUNTPOINT}"; then
|
||||||
overlay_root "${MOUNTPOINT}"; then
|
log "NETBOOT: FATAL - overlay mount failed"
|
||||||
log_failure_msg "Failed to mount overlay filesystem"
|
return 1
|
||||||
umount "${OVERLAY_TMPFS}"
|
|
||||||
umount "${SQUASHFS_MOUNT}"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_end_msg
|
log "NETBOOT: SUCCESS - root mounted at ${MOUNTPOINT}"
|
||||||
log_begin_msg "Overlay mounted at ${MOUNTPOINT} (lower=${SQUASHFS_MOUNT})"
|
return 0
|
||||||
log_end_msg
|
|
||||||
|
|
||||||
# Clean up downloaded image as it's now mounted
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
rc=0
|
|
||||||
else
|
|
||||||
# Direct SquashFS mount without overlay - mount directly to /root
|
|
||||||
if ! mount -t squashfs "${FILE_PATH}" "${MOUNTPOINT}" -o ro; then
|
|
||||||
log_failure_msg "Failed to mount SquashFS at ${MOUNTPOINT}"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
return ${rc}
|
|
||||||
fi
|
|
||||||
log_begin_msg "Mounted SquashFS without overlay at ${MOUNTPOINT}"
|
|
||||||
log_end_msg
|
|
||||||
rc=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_failure_msg "Unknown filesystem type: ${FILE_NAME}"
|
|
||||||
rm -f "${FILE_PATH}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
return ${rc}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Standard mount hook wrappers expected by initramfs init
|
|
||||||
mount_top()
|
|
||||||
{
|
|
||||||
netboot_top
|
|
||||||
}
|
|
||||||
|
|
||||||
mount_premount()
|
|
||||||
{
|
|
||||||
netboot_premount
|
|
||||||
}
|
|
||||||
|
|
||||||
mount_bottom()
|
|
||||||
{
|
|
||||||
netboot_bottom
|
|
||||||
}
|
}
|
||||||
|
|||||||
51
rebuild-initramfs.sh
Executable file
51
rebuild-initramfs.sh
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Rebuild initramfs with updated netboot script
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
BUILD_DIR="$SCRIPT_DIR/build"
|
||||||
|
ROOTFS="$BUILD_DIR/rootfs"
|
||||||
|
HTTP_DIR="$SCRIPT_DIR/http"
|
||||||
|
|
||||||
|
if [ ! -d "$ROOTFS" ]; then
|
||||||
|
echo "ERROR: Rootfs not found at $ROOTFS"
|
||||||
|
echo "Run build-image.sh first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Copying updated initramfs scripts ==="
|
||||||
|
cp "$SCRIPT_DIR/initramfs/scripts/netboot" "$ROOTFS/usr/share/initramfs-tools/scripts/netboot"
|
||||||
|
cp "$SCRIPT_DIR/initramfs/hooks/netboot" "$ROOTFS/usr/share/initramfs-tools/hooks/netboot"
|
||||||
|
cp "$SCRIPT_DIR/initramfs/initramfs.conf" "$ROOTFS/etc/initramfs-tools/initramfs.conf"
|
||||||
|
cp "$SCRIPT_DIR/initramfs/modules" "$ROOTFS/etc/initramfs-tools/modules"
|
||||||
|
|
||||||
|
echo "=== Getting kernel version ==="
|
||||||
|
KVER=$(ls "$ROOTFS/lib/modules/" | head -1)
|
||||||
|
echo "Kernel version: $KVER"
|
||||||
|
|
||||||
|
echo "=== Mounting filesystems for chroot ==="
|
||||||
|
mount --bind /proc "$ROOTFS/proc"
|
||||||
|
mount --bind /sys "$ROOTFS/sys"
|
||||||
|
mount --bind /dev "$ROOTFS/dev"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "=== Cleaning up mounts ==="
|
||||||
|
umount "$ROOTFS/proc" 2>/dev/null || true
|
||||||
|
umount "$ROOTFS/sys" 2>/dev/null || true
|
||||||
|
umount "$ROOTFS/dev" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
echo "=== Rebuilding initramfs ==="
|
||||||
|
chroot "$ROOTFS" mkinitramfs -v -o /boot/initrd-netboot.img "$KVER"
|
||||||
|
|
||||||
|
echo "=== Copying to http directory ==="
|
||||||
|
cp "$ROOTFS/boot/initrd-netboot.img" "$HTTP_DIR/"
|
||||||
|
chmod 644 "$HTTP_DIR/initrd-netboot.img"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done! ==="
|
||||||
|
echo "New initramfs: $HTTP_DIR/initrd-netboot.img"
|
||||||
|
ls -lh "$HTTP_DIR/initrd-netboot.img"
|
||||||
|
echo ""
|
||||||
|
echo "Run 'make deploy' to sync to NAS"
|
||||||
Reference in New Issue
Block a user