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 #!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 base-url http://{{ gateway_ip }}:8080
set macfile 01-${mac:hexhyp} set hostfile ${base-url}/byMAC/01-${mac:hexhyp}.ipxe
set hostfile ${base-url}/byMAC/${macfile}.ipxe set fallbackfile ${base-url}/fallback.ipxe
set fallback ${base-url}/fallback.ipxe
# Verbosity (1..4) # --- Script Logic ---
set debug 2
# State
set debugmode 0
echo echo
echo === iPXE chainload stage (default) === echo "========================================"
echo MAC: ${mac} echo " iPXE Network Boot Initiated"
echo Base URL: ${base-url} echo "========================================"
echo Host file: ${hostfile} echo "Client MAC Address: ${mac}"
echo Fallback : ${fallback} echo "Boot Server URL: ${base-url}"
echo ======================================
echo 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 sleep 2
echo DEBUG MODE: ON (confirmations and extra sleeps enabled)
sleep 1
goto :start
:debug_disabled # The "&& exit ||" pattern works as follows:
echo DEBUG MODE: OFF (no confirmations; production behavior) # 1. iPXE attempts to 'chain' the hostfile.
sleep 1 # 2. If successful (returns 0), the "&& exit" part is executed, and this script terminates.
goto :start # 3. If it fails (returns non-zero), the "||" part is triggered, and execution continues below.
chain ${hostfile} && exit ||
:start # --- Fallback Boot Attempt ---
# Show network status briefly in both modes # This part of the script is only reached if the 'chain ${hostfile}' command above failed.
ifstat
iseq ${debugmode} 1 && sleep 2 || sleep 0
# Probe host-specific script via HTTP HEAD
echo echo
echo Probing host-specific script: ${hostfile} echo "--> Host-specific script not found or failed to load."
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 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
echo === iPXE debug shell === echo "--> Attempting to load fallback script..."
echo Try: echo " Location: ${fallbackfile}"
echo dhcp
echo ifstat sleep 8
echo ping {{ gateway_ip }}
echo http ${hostfile} chain ${fallbackfile} && exit ||
echo http ${fallback}
echo chain ${hostfile} # --- Final Failure ---
echo chain ${fallback} # This part is only reached if BOTH chain commands have failed.
sleep 1 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 shell
# A final exit is good practice, though 'shell' is a blocking command.
exit exit

View File

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