@@ -98,7 +98,7 @@ use tokio::sync::Semaphore;
9898use tracing:: instrument;
9999use version_compare:: Cmp ;
100100
101- use crate :: boot_interface:: boot_interface_target ;
101+ use crate :: boot_interface:: { BootInterfaceResolution , resolve_boot_interface } ;
102102use crate :: config:: {
103103 FirmwareGlobal , MachineStateHandlerSiteConfig , MachineValidationConfig , TimePeriod ,
104104} ;
@@ -3339,6 +3339,7 @@ async fn handle_dpu_reprovision(
33393339 SetBootOrderOutcome :: WaitingForReboot ( reason) => {
33403340 Ok ( StateHandlerOutcome :: wait ( reason) )
33413341 }
3342+ SetBootOrderOutcome :: Wait ( reason) => Ok ( StateHandlerOutcome :: wait ( reason) ) ,
33423343 }
33433344 }
33443345 ReprovisionState :: LockHostAfterBootRepair => {
@@ -3527,13 +3528,24 @@ async fn check_host_boot_config(
35273528 ) ) ;
35283529 }
35293530
3530- // Resolve the interface whose boot option should be first in host UEFI.
3531- let boot_interface = boot_interface_target ( mh_snapshot) . ok_or_else ( || {
3532- StateHandlerError :: GenericError ( eyre:: eyre!(
3533- "Missing boot interface for host: {}" ,
3534- mh_snapshot. host_snapshot. id
3535- ) )
3536- } ) ?;
3531+ // Resolve the interface whose boot option should be first in host UEFI. A
3532+ // zero-DPU host whose boot NIC has not taken its first HostInband lease yet
3533+ // has no boot interface to resolve -- wait for it rather than failing.
3534+ let boot_interface = match resolve_boot_interface ( mh_snapshot) {
3535+ BootInterfaceResolution :: Ready ( target) => target,
3536+ BootInterfaceResolution :: AwaitingNic => {
3537+ return Ok ( HostBootConfigDecision :: Wait ( format ! (
3538+ "Waiting for zero-DPU host {} to discover its boot NIC before configuring boot." ,
3539+ mh_snapshot. host_snapshot. id
3540+ ) ) ) ;
3541+ }
3542+ BootInterfaceResolution :: Missing => {
3543+ return Err ( StateHandlerError :: GenericError ( eyre:: eyre!(
3544+ "Missing boot interface for host: {}" ,
3545+ mh_snapshot. host_snapshot. id
3546+ ) ) ) ;
3547+ }
3548+ } ;
35373549
35383550 let vendor = mh_snapshot. host_snapshot . bmc_vendor ( ) ;
35393551
@@ -4835,6 +4847,10 @@ enum SetBootOrderOutcome {
48354847 Continue ( SetBootOrderInfo ) ,
48364848 Done ,
48374849 WaitingForReboot ( String ) ,
4850+ /// No boot interface to act on yet -- e.g. a zero-DPU host whose boot NIC
4851+ /// has not been discovered. Distinct from `WaitingForReboot`: nothing was
4852+ /// rebooted, the caller just waits and retries.
4853+ Wait ( String ) ,
48384854}
48394855
48404856/// Decision from checking whether host boot repair is still required.
@@ -5237,6 +5253,9 @@ async fn handle_host_boot_order_setup(
52375253 SetBootOrderOutcome :: WaitingForReboot ( reason) => {
52385254 return Ok ( StateHandlerOutcome :: wait ( reason) ) ;
52395255 }
5256+ SetBootOrderOutcome :: Wait ( reason) => {
5257+ return Ok ( StateHandlerOutcome :: wait ( reason) ) ;
5258+ }
52405259 }
52415260 }
52425261 None => ManagedHostState :: HostInit {
@@ -10876,6 +10895,9 @@ async fn handle_instance_host_platform_config(
1087610895 SetBootOrderOutcome :: WaitingForReboot ( reason) => {
1087710896 return Ok ( StateHandlerOutcome :: wait ( reason) ) ;
1087810897 }
10898+ SetBootOrderOutcome :: Wait ( reason) => {
10899+ return Ok ( StateHandlerOutcome :: wait ( reason) ) ;
10900+ }
1087910901 }
1088010902 }
1088110903 HostPlatformConfigurationState :: LockHost => {
@@ -10922,13 +10944,24 @@ async fn set_host_boot_order(
1092210944 // for verification.
1092310945 //
1092410946 // Resolve the boot NIC MAC the same way `CheckHostConfig` does,
10925- // supporting hosts with DPU(s) and zero DPUs alike.
10926- let boot_interface = boot_interface_target ( mh_snapshot) . ok_or_else ( || {
10927- StateHandlerError :: GenericError ( eyre:: eyre!(
10928- "Missing boot interface for host: {}" ,
10929- mh_snapshot. host_snapshot. id
10930- ) )
10931- } ) ?;
10947+ // supporting hosts with DPU(s) and zero DPUs alike. A zero-DPU host
10948+ // whose boot NIC has not taken its first HostInband lease yet has no
10949+ // boot interface to resolve -- wait for it rather than failing.
10950+ let boot_interface = match resolve_boot_interface ( mh_snapshot) {
10951+ BootInterfaceResolution :: Ready ( target) => target,
10952+ BootInterfaceResolution :: AwaitingNic => {
10953+ return Ok ( SetBootOrderOutcome :: Wait ( format ! (
10954+ "Waiting for zero-DPU host {} to discover its boot NIC before setting boot order." ,
10955+ mh_snapshot. host_snapshot. id
10956+ ) ) ) ;
10957+ }
10958+ BootInterfaceResolution :: Missing => {
10959+ return Err ( StateHandlerError :: GenericError ( eyre:: eyre!(
10960+ "Missing boot interface for host: {}" ,
10961+ mh_snapshot. host_snapshot. id
10962+ ) ) ) ;
10963+ }
10964+ } ;
1093210965
1093310966 let jid = match set_boot_order_dpu_first_and_handle_no_dpu_error (
1093410967 redfish_client,
@@ -11207,12 +11240,21 @@ async fn set_host_boot_order(
1120711240
1120811241 let retry_count = set_boot_order_info. retry_count ;
1120911242
11210- let boot_interface = boot_interface_target ( mh_snapshot) . ok_or_else ( || {
11211- StateHandlerError :: GenericError ( eyre:: eyre!(
11212- "Missing boot interface for host: {}" ,
11213- mh_snapshot. host_snapshot. id
11214- ) )
11215- } ) ?;
11243+ let boot_interface = match resolve_boot_interface ( mh_snapshot) {
11244+ BootInterfaceResolution :: Ready ( target) => target,
11245+ BootInterfaceResolution :: AwaitingNic => {
11246+ return Ok ( SetBootOrderOutcome :: Wait ( format ! (
11247+ "Waiting for zero-DPU host {} to discover its boot NIC before verifying boot order." ,
11248+ mh_snapshot. host_snapshot. id
11249+ ) ) ) ;
11250+ }
11251+ BootInterfaceResolution :: Missing => {
11252+ return Err ( StateHandlerError :: GenericError ( eyre:: eyre!(
11253+ "Missing boot interface for host: {}" ,
11254+ mh_snapshot. host_snapshot. id
11255+ ) ) ) ;
11256+ }
11257+ } ;
1121611258
1121711259 let boot_order_configured = boot_interface
1121811260 . run ( |bi| redfish_client. is_boot_order_setup ( bi) )
0 commit comments