@@ -93,13 +93,15 @@ use sled_agent_types::disk::SharedDatasetConfig;
9393use sled_agent_types:: inventory:: BootImageHeader ;
9494use sled_agent_types:: inventory:: BootPartitionDetails ;
9595use sled_agent_types:: inventory:: ConfigReconcilerInventoryStatus ;
96+ use sled_agent_types:: inventory:: CurrentUpdateDisposition ;
9697use sled_agent_types:: inventory:: ExternalDnsAddrs ;
9798use sled_agent_types:: inventory:: FmdHostCase ;
9899use sled_agent_types:: inventory:: FmdInventory ;
99100use sled_agent_types:: inventory:: FmdInventoryError ;
100101use sled_agent_types:: inventory:: FmdResource ;
101102use sled_agent_types:: inventory:: HostPhase2DesiredContents ;
102103use sled_agent_types:: inventory:: HostPhase2DesiredSlots ;
104+ use sled_agent_types:: inventory:: InstanceManagerStatus ;
103105use sled_agent_types:: inventory:: ManifestBootInventory ;
104106use sled_agent_types:: inventory:: ManifestInventory ;
105107use sled_agent_types:: inventory:: ManifestNonBootInventory ;
@@ -949,6 +951,71 @@ pub struct InvSledAgent {
949951
950952 #[ diesel( embed) ]
951953 pub file_source_resolver : InvOmicronFileSourceResolver ,
954+
955+ instance_manager_update_disposition : Option < DbInvSledUpdateDisposition > ,
956+ instance_manager_num_registered_vmms : SqlU32 ,
957+ }
958+
959+ /// Helper for breaking an [`InstanceManagerStatus`] up into its DB columns.
960+ #[ derive( Debug , Clone , Copy ) ]
961+ pub struct InvInstanceManagerStatusCols {
962+ pub update_disposition : Option < DbInvSledUpdateDisposition > ,
963+ pub num_registered_vmms : SqlU32 ,
964+ }
965+
966+ impl TryFrom < InstanceManagerStatus > for InvInstanceManagerStatusCols {
967+ type Error = anyhow:: Error ;
968+
969+ fn try_from ( status : InstanceManagerStatus ) -> Result < Self , Self :: Error > {
970+ let InstanceManagerStatus { update_disposition, num_registered_vmms } =
971+ status;
972+
973+ // "no config" becomes NULL; `Known(_)` becomes non-NULL.
974+ let update_disposition = match update_disposition {
975+ CurrentUpdateDisposition :: ConfigNotAvailable => None ,
976+ CurrentUpdateDisposition :: Known ( disposition) => {
977+ Some ( disposition. into ( ) )
978+ }
979+ } ;
980+
981+ // We never expect this to fail; there are many practial limits to the
982+ // number of VMMs registered on a sled far lower than `u32::MAX`.
983+ let num_registered_vmms =
984+ SqlU32 :: new ( u32:: try_from ( num_registered_vmms) . map_err ( |_| {
985+ anyhow ! (
986+ "inventory claims there are {num_registered_vmms} \
987+ on a sled; this doesn't fit in a SqlU32"
988+ )
989+ } ) ?) ;
990+
991+ Ok ( Self { update_disposition, num_registered_vmms } )
992+ }
993+ }
994+
995+ impl From < InvInstanceManagerStatusCols > for InstanceManagerStatus {
996+ fn from ( cols : InvInstanceManagerStatusCols ) -> Self {
997+ let InvInstanceManagerStatusCols {
998+ update_disposition,
999+ num_registered_vmms,
1000+ } = cols;
1001+
1002+ // See the comments in the `From<InstanceManagerStatus>` impl; we do the
1003+ // reverse here.
1004+ let update_disposition = match update_disposition {
1005+ None => CurrentUpdateDisposition :: ConfigNotAvailable ,
1006+ Some ( disposition) => {
1007+ CurrentUpdateDisposition :: Known ( disposition. into ( ) )
1008+ }
1009+ } ;
1010+
1011+ // usize can always contain a u32; saturate instead of unwrapping to
1012+ // suppress the error branch.
1013+ let num_registered_vmms: u32 = * num_registered_vmms;
1014+ let num_registered_vmms =
1015+ usize:: try_from ( num_registered_vmms) . unwrap_or ( usize:: MAX ) ;
1016+
1017+ InstanceManagerStatus { update_disposition, num_registered_vmms }
1018+ }
9521019}
9531020
9541021/// See [`sled_agent_types::inventory::ConfigReconcilerInventoryStatus`].
@@ -1338,6 +1405,11 @@ impl InvSledAgent {
13381405 non-null baseboard id"
13391406 ) )
13401407 } else {
1408+ let InvInstanceManagerStatusCols {
1409+ update_disposition : instance_manager_update_disposition,
1410+ num_registered_vmms : instance_manager_num_registered_vmms,
1411+ } = sled_agent. instance_manager_status . try_into ( ) ?;
1412+
13411413 Ok ( InvSledAgent {
13421414 inv_collection_id : collection_id. into ( ) ,
13431415 time_collected : sled_agent. time_collected ,
@@ -1360,9 +1432,21 @@ impl InvSledAgent {
13601432 ledgered_sled_config : ledgered_sled_config. map ( From :: from) ,
13611433 reconciler_status,
13621434 file_source_resolver,
1435+ instance_manager_update_disposition,
1436+ instance_manager_num_registered_vmms,
13631437 } )
13641438 }
13651439 }
1440+
1441+ /// Reassemble an [`InstanceManagerStatus`] from the database
1442+ /// representation held by `self`.
1443+ pub fn instance_manager_status ( & self ) -> InstanceManagerStatus {
1444+ InvInstanceManagerStatusCols {
1445+ update_disposition : self . instance_manager_update_disposition ,
1446+ num_registered_vmms : self . instance_manager_num_registered_vmms ,
1447+ }
1448+ . into ( )
1449+ }
13661450}
13671451
13681452#[ derive( Queryable , Clone , Debug , Selectable , Insertable ) ]
0 commit comments