@@ -16,10 +16,12 @@ use nexus_types::deployment::TargetReleaseDescription;
1616use nexus_types:: external_api:: shared:: TufSignedRootRole ;
1717use nexus_types:: external_api:: views;
1818use nexus_types:: internal_api:: views as internal_views;
19+ use nexus_types:: inventory:: RotSlot ;
1920use omicron_common:: api:: external:: InternalContext ;
2021use omicron_common:: api:: external:: {
2122 DataPageParams , Error , TufRepoInsertResponse , TufRepoInsertStatus ,
2223} ;
24+ use omicron_common:: disk:: M2Slot ;
2325use omicron_uuid_kinds:: { GenericUuid , TufTrustRootUuid } ;
2426use semver:: Version ;
2527use std:: collections:: BTreeMap ;
@@ -247,16 +249,55 @@ impl super::Nexus {
247249 & inventory,
248250 ) ;
249251
250- let zone_versions = status
251- . zones
252- . values ( )
253- . flat_map ( |zones| zones. iter ( ) . map ( |zone| zone. version . clone ( ) ) ) ;
254- let sp_versions = status. sps . values ( ) . flat_map ( |sp| {
255- [ sp. slot0_version . clone ( ) , sp. slot1_version . clone ( ) ]
252+ let sled_versions = status. sleds . into_iter ( ) . flat_map ( |sled| {
253+ let zone_versions = sled. zones . into_iter ( ) . map ( |zone| zone. version ) ;
254+
255+ // boot_disk tells you which slot is relevant
256+ let host_version =
257+ sled. host_phase_2 . boot_disk . ok ( ) . map ( |slot| match slot {
258+ M2Slot :: A => sled. host_phase_2 . slot_a_version . clone ( ) ,
259+ M2Slot :: B => sled. host_phase_2 . slot_b_version . clone ( ) ,
260+ } ) ;
261+
262+ zone_versions. chain ( host_version)
256263 } ) ;
257264
265+ let mgs_driven_versions =
266+ status. mgs_driven . into_iter ( ) . flat_map ( |status| {
267+ // for the SP, slot0_version is the active one
268+ let sp_version = status. sp . slot0_version . clone ( ) ;
269+
270+ // for the bootloader, stage0_version is the active one.
271+ let bootloader_version =
272+ status. rot_bootloader . stage0_version . clone ( ) ;
273+
274+ let rot_version =
275+ status. rot . active_slot . map ( |slot| match slot {
276+ RotSlot :: A => status. rot . slot_a_version . clone ( ) ,
277+ RotSlot :: B => status. rot . slot_b_version . clone ( ) ,
278+ } ) ;
279+
280+ let host_version = match & status. host_os_phase_1 {
281+ internal_views:: HostPhase1Status :: Sled {
282+ slot_a_version,
283+ slot_b_version,
284+ active_slot,
285+ ..
286+ } => active_slot. map ( |slot| match slot {
287+ M2Slot :: A => slot_a_version. clone ( ) ,
288+ M2Slot :: B => slot_b_version. clone ( ) ,
289+ } ) ,
290+ _ => None ,
291+ } ;
292+
293+ std:: iter:: once ( sp_version)
294+ . chain ( rot_version)
295+ . chain ( std:: iter:: once ( bootloader_version) )
296+ . chain ( host_version)
297+ } ) ;
298+
258299 let mut counts = BTreeMap :: new ( ) ;
259- for version in zone_versions . chain ( sp_versions ) {
300+ for version in sled_versions . chain ( mgs_driven_versions ) {
260301 * counts. entry ( version. to_string ( ) ) . or_insert ( 0 ) += 1 ;
261302 }
262303 Ok ( counts)
0 commit comments