55//! Facilities for making choices about MGS-managed updates
66
77mod rot;
8+ mod sp;
89
910use crate :: mgs_updates:: rot:: RotUpdateState ;
1011use crate :: mgs_updates:: rot:: mgs_update_status_rot;
1112use crate :: mgs_updates:: rot:: try_make_update_rot;
13+ use crate :: mgs_updates:: sp:: mgs_update_status_sp;
14+ use crate :: mgs_updates:: sp:: try_make_update_sp;
1215
1316use gateway_types:: rot:: RotSlot ;
1417use nexus_types:: deployment:: ExpectedActiveRotSlot ;
@@ -21,14 +24,13 @@ use nexus_types::inventory::BaseboardId;
2124use nexus_types:: inventory:: CabooseWhich ;
2225use nexus_types:: inventory:: Collection ;
2326use omicron_common:: api:: external:: TufRepoDescription ;
24- use slog:: { debug , error, info, warn} ;
27+ use slog:: { error, info, warn} ;
2528use slog_error_chain:: InlineErrorChain ;
2629use std:: collections:: BTreeSet ;
2730use std:: sync:: Arc ;
2831use thiserror:: Error ;
2932use tufaceous_artifact:: ArtifactVersion ;
3033use tufaceous_artifact:: ArtifactVersionError ;
31- use tufaceous_artifact:: KnownArtifactKind ;
3234
3335/// How to handle an MGS-driven update that has become impossible due to
3436/// unsatisfied preconditions.
@@ -365,39 +367,6 @@ fn mgs_update_status(
365367 }
366368}
367369
368- /// Compares a configured SP update with information from inventory and
369- /// determines the current status of the update. See `MgsUpdateStatus`.
370- fn mgs_update_status_sp (
371- desired_version : & ArtifactVersion ,
372- expected_active_version : & ArtifactVersion ,
373- expected_inactive_version : & ExpectedVersion ,
374- found_active_version : & str ,
375- found_inactive_version : Option < & str > ,
376- ) -> MgsUpdateStatus {
377- if found_active_version == desired_version. as_str ( ) {
378- // If we find the desired version in the active slot, we're done.
379- return MgsUpdateStatus :: Done ;
380- }
381-
382- // The update hasn't completed.
383- //
384- // Check to make sure the contents of the active slot are still what they
385- // were when we configured this update. If not, then this update cannot
386- // proceed as currently configured. It will fail its precondition check.
387- if found_active_version != expected_active_version. as_str ( ) {
388- return MgsUpdateStatus :: Impossible ;
389- }
390-
391- // Similarly, check the contents of the inactive slot to determine if it
392- // still matches what we saw when we configured this update. If not, then
393- // this update cannot proceed as currently configured. It will fail its
394- // precondition check.
395- mgs_update_status_inactive_versions (
396- found_inactive_version,
397- expected_inactive_version,
398- )
399- }
400-
401370fn mgs_update_status_inactive_versions (
402371 found_inactive_version : Option < & str > ,
403372 expected_inactive_version : & ExpectedVersion ,
@@ -465,141 +434,6 @@ fn try_make_update(
465434 } )
466435}
467436
468- /// Determine if the given baseboard needs an SP update and, if so, returns it.
469- fn try_make_update_sp (
470- log : & slog:: Logger ,
471- baseboard_id : & Arc < BaseboardId > ,
472- inventory : & Collection ,
473- current_artifacts : & TufRepoDescription ,
474- ) -> Option < PendingMgsUpdate > {
475- let Some ( sp_info) = inventory. sps . get ( baseboard_id) else {
476- warn ! (
477- log,
478- "cannot configure SP update for board \
479- (missing SP info from inventory)";
480- baseboard_id
481- ) ;
482- return None ;
483- } ;
484-
485- let Some ( active_caboose) =
486- inventory. caboose_for ( CabooseWhich :: SpSlot0 , baseboard_id)
487- else {
488- warn ! (
489- log,
490- "cannot configure SP update for board \
491- (missing active caboose from inventory)";
492- baseboard_id,
493- ) ;
494- return None ;
495- } ;
496-
497- let Ok ( expected_active_version) = active_caboose. caboose . version . parse ( )
498- else {
499- warn ! (
500- log,
501- "cannot configure SP update for board \
502- (cannot parse current active version as an ArtifactVersion)";
503- baseboard_id,
504- "found_version" => & active_caboose. caboose. version,
505- ) ;
506- return None ;
507- } ;
508-
509- let board = & active_caboose. caboose . board ;
510- let matching_artifacts: Vec < _ > = current_artifacts
511- . artifacts
512- . iter ( )
513- . filter ( |a| {
514- // A matching SP artifact will have:
515- //
516- // - "name" matching the board name (found above from caboose)
517- // - "kind" matching one of the known SP kinds
518-
519- if a. id . name != * board {
520- return false ;
521- }
522-
523- match a. id . kind . to_known ( ) {
524- None => false ,
525- Some (
526- KnownArtifactKind :: GimletSp
527- | KnownArtifactKind :: PscSp
528- | KnownArtifactKind :: SwitchSp ,
529- ) => true ,
530- Some (
531- KnownArtifactKind :: GimletRot
532- | KnownArtifactKind :: Host
533- | KnownArtifactKind :: Trampoline
534- | KnownArtifactKind :: InstallinatorDocument
535- | KnownArtifactKind :: ControlPlane
536- | KnownArtifactKind :: Zone
537- | KnownArtifactKind :: PscRot
538- | KnownArtifactKind :: SwitchRot
539- | KnownArtifactKind :: GimletRotBootloader
540- | KnownArtifactKind :: PscRotBootloader
541- | KnownArtifactKind :: SwitchRotBootloader ,
542- ) => false ,
543- }
544- } )
545- . collect ( ) ;
546- if matching_artifacts. is_empty ( ) {
547- warn ! (
548- log,
549- "cannot configure SP update for board (no matching artifact)" ;
550- baseboard_id,
551- ) ;
552- return None ;
553- }
554-
555- if matching_artifacts. len ( ) > 1 {
556- // This should be impossible unless we shipped a TUF repo with multiple
557- // artifacts for the same board. But it doesn't prevent us from picking
558- // one and proceeding. Make a note and proceed.
559- warn ! ( log, "found more than one matching artifact for SP update" ) ;
560- }
561-
562- let artifact = matching_artifacts[ 0 ] ;
563-
564- // If the artifact's version matches what's deployed, then no update is
565- // needed.
566- if artifact. id . version == expected_active_version {
567- debug ! ( log, "no SP update needed for board" ; baseboard_id) ;
568- return None ;
569- }
570-
571- // Begin configuring an update.
572- let expected_inactive_version = match inventory
573- . caboose_for ( CabooseWhich :: SpSlot1 , baseboard_id)
574- . map ( |c| c. caboose . version . parse :: < ArtifactVersion > ( ) )
575- . transpose ( )
576- {
577- Ok ( None ) => ExpectedVersion :: NoValidVersion ,
578- Ok ( Some ( v) ) => ExpectedVersion :: Version ( v) ,
579- Err ( _) => {
580- warn ! (
581- log,
582- "cannot configure SP update for board \
583- (found inactive slot contents but version was not valid)";
584- baseboard_id
585- ) ;
586- return None ;
587- }
588- } ;
589-
590- Some ( PendingMgsUpdate {
591- baseboard_id : baseboard_id. clone ( ) ,
592- sp_type : sp_info. sp_type ,
593- slot_id : sp_info. sp_slot ,
594- details : PendingMgsUpdateDetails :: Sp {
595- expected_active_version,
596- expected_inactive_version,
597- } ,
598- artifact_hash : artifact. hash ,
599- artifact_version : artifact. id . version . clone ( ) ,
600- } )
601- }
602-
603437#[ cfg( test) ]
604438mod test {
605439 use super :: ImpossibleUpdatePolicy ;
0 commit comments