New boot ipxe default file, much better logging and easier to follow . Also Tolerate the opnsense lack of reloading every time
Some checks failed
Run Check Script / check (pull_request) Failing after 28s

This commit is contained in:
Jean-Gabriel Gill-Couture 2025-09-03 20:53:44 -04:00
parent f0d907d92f
commit c5427b983c
2 changed files with 50 additions and 108 deletions

View File

@ -1,122 +1,63 @@
#!ipxe
# Default chainloader with optional debug mode.
# - Press any key within 3 seconds at start to enable debug mode.
# - In debug mode: confirmations and extra sleeps are enabled.
# - In production (no key pressed): continues without prompts.
# Config
# iPXE Chainloading Script
#
# Attempts to load a host-specific configuration file. If that fails,
# it logs the failure, waits for a few seconds, and then attempts to
# load a generic fallback configuration.
# --- Configuration ---
set base-url http://{{ gateway_ip }}:8080
set macfile 01-${mac:hexhyp}
set hostfile ${base-url}/byMAC/${macfile}.ipxe
set fallback ${base-url}/fallback.ipxe
set hostfile ${base-url}/byMAC/01-${mac:hexhyp}.ipxe
set fallbackfile ${base-url}/fallback.ipxe
# Verbosity (1..4)
set debug 2
# State
set debugmode 0
# --- Script Logic ---
echo
echo === iPXE chainload stage (default) ===
echo MAC: ${mac}
echo Base URL: ${base-url}
echo Host file: ${hostfile}
echo Fallback : ${fallback}
echo ======================================
echo "========================================"
echo " iPXE Network Boot Initiated"
echo "========================================"
echo "Client MAC Address: ${mac}"
echo "Boot Server URL: ${base-url}"
echo
echo Press any key within 3 seconds to enter DEBUG MODE...
prompt --timeout 3 Entering debug mode... && set debugmode 1 || set debugmode 0
iseq ${debugmode} 1 && goto :debug_enabled || goto :debug_disabled
# --- Primary Boot Attempt ---
echo "--> Attempting to load host-specific script..."
echo " Location: ${hostfile}"
:debug_enabled
echo DEBUG MODE: ON (confirmations and extra sleeps enabled)
sleep 1
goto :start
sleep 2
:debug_disabled
echo DEBUG MODE: OFF (no confirmations; production behavior)
sleep 1
goto :start
# The "&& exit ||" pattern works as follows:
# 1. iPXE attempts to 'chain' the hostfile.
# 2. If successful (returns 0), the "&& exit" part is executed, and this script terminates.
# 3. If it fails (returns non-zero), the "||" part is triggered, and execution continues below.
chain ${hostfile} && exit ||
:start
# Show network status briefly in both modes
ifstat
iseq ${debugmode} 1 && sleep 2 || sleep 0
# Probe host-specific script via HTTP HEAD
# --- Fallback Boot Attempt ---
# This part of the script is only reached if the 'chain ${hostfile}' command above failed.
echo
echo Probing host-specific script: ${hostfile}
http --head ${hostfile}
iseq ${rc} 0 && goto :has_hostfile || goto :no_hostfile
:has_hostfile
echo Found host-specific script: ${hostfile}
iseq ${debugmode} 1 && goto :confirm_host || goto :chain_host
:confirm_host
prompt --timeout 8 Press Enter to chain host script, Esc to abort... && goto :chain_host || goto :abort
:chain_host
echo Chaining ${hostfile} ...
iseq ${debugmode} 1 && sleep 2 || sleep 0
chain ${hostfile} || goto :host_chain_fail
# On success, control does not return.
:host_chain_fail
echo ERROR: chain to ${hostfile} failed (rc=${rc})
iseq ${debugmode} 1 && sleep 5 || sleep 1
goto :try_fallback
:no_hostfile
echo NOT FOUND or unreachable: ${hostfile} (rc=${rc})
iseq ${debugmode} 1 && sleep 2 || sleep 0
:try_fallback
echo "--> Host-specific script not found or failed to load."
echo
echo Probing fallback script: ${fallback}
http --head ${fallback}
iseq ${rc} 0 && goto :has_fallback || goto :fallback_missing
:has_fallback
iseq ${debugmode} 1 && goto :confirm_fallback || goto :chain_fallback
:confirm_fallback
prompt --timeout 8 Press Enter to chain fallback, Esc to shell... && goto :chain_fallback || goto :shell
:chain_fallback
echo Chaining ${fallback} ...
iseq ${debugmode} 1 && sleep 2 || sleep 0
chain ${fallback} || goto :fallback_chain_fail
# On success, control does not return.
:fallback_chain_fail
echo ERROR: chain to fallback failed (rc=${rc})
iseq ${debugmode} 1 && sleep 5 || sleep 1
goto :shell
:fallback_missing
echo ERROR: Fallback script not reachable: ${fallback} (rc=${rc})
iseq ${debugmode} 1 && sleep 5 || sleep 1
goto :shell
:abort
echo Aborted by user.
iseq ${debugmode} 1 && sleep 2 || sleep 1
goto :shell
:shell
echo
echo === iPXE debug shell ===
echo Try:
echo dhcp
echo ifstat
echo ping {{ gateway_ip }}
echo http ${hostfile}
echo http ${fallback}
echo chain ${hostfile}
echo chain ${fallback}
sleep 1
echo "--> Attempting to load fallback script..."
echo " Location: ${fallbackfile}"
sleep 8
chain ${fallbackfile} && exit ||
# --- Final Failure ---
# This part is only reached if BOTH chain commands have failed.
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo " FATAL: All boot scripts failed!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Could not load either the host-specific script or the fallback script."
echo "Dropping to iPXE shell for manual troubleshooting in 10 seconds."
sleep 8
shell
# A final exit is good practice, though 'shell' is a blocking command.
exit

View File

@ -1,7 +1,7 @@
use crate::config::{manager::ConfigManager, OPNsenseShell};
use crate::error::Error;
use async_trait::async_trait;
use log::info;
use log::{info, warn};
use russh_keys::key::KeyPair;
use sha2::Digest;
use std::sync::Arc;
@ -61,9 +61,10 @@ impl ConfigManager for SshConfigManager {
let current_content = self.load_as_str().await?;
if !check_hash(&current_content, hash) {
return Err(Error::Config(format!(
"OPNSense config file changed since loading it! Hash when loading : {hash}"
)));
warn!("OPNSense config file changed since loading it! Hash when loading : {hash}");
// return Err(Error::Config(format!(
// "OPNSense config file changed since loading it! Hash when loading : {hash}"
// )));
}
let temp_filename = self