55//! Background task for realizing a plan blueprint
66
77use crate :: app:: {
8- background:: { Activator , BackgroundTask } ,
8+ background:: { Activator , BackgroundTask , LoadedTargetBlueprint } ,
99 quiesce:: NexusQuiesceHandle ,
1010} ;
1111use futures:: FutureExt ;
@@ -16,22 +16,20 @@ use nexus_db_queries::db::DataStore;
1616use nexus_reconfigurator_execution:: {
1717 RealizeBlueprintOutput , RequiredRealizeArgs ,
1818} ;
19- use nexus_types:: deployment:: {
20- Blueprint , BlueprintTarget , PendingMgsUpdates , execution:: EventBuffer ,
21- } ;
19+ use nexus_types:: deployment:: { PendingMgsUpdates , execution:: EventBuffer } ;
2220use omicron_uuid_kinds:: OmicronZoneUuid ;
2321use serde_json:: json;
2422use slog_error_chain:: InlineErrorChain ;
2523use std:: sync:: Arc ;
2624use tokio:: sync:: watch;
2725use update_engine:: NestedError ;
2826
29- /// Background task that takes a [ `Blueprint`] and realizes the change to
27+ /// Background task that takes a `Blueprint` and realizes the change to
3028/// the state of the system based on the `Blueprint`.
3129pub struct BlueprintExecutor {
3230 datastore : Arc < DataStore > ,
3331 resolver : Resolver ,
34- rx_blueprint : watch:: Receiver < Option < ( BlueprintTarget , Arc < Blueprint > ) > > ,
32+ rx_blueprint : watch:: Receiver < Option < LoadedTargetBlueprint > > ,
3533 nexus_id : OmicronZoneUuid ,
3634 tx : watch:: Sender < usize > ,
3735 saga_recovery : Activator ,
@@ -43,9 +41,7 @@ impl BlueprintExecutor {
4341 pub fn new (
4442 datastore : Arc < DataStore > ,
4543 resolver : Resolver ,
46- rx_blueprint : watch:: Receiver <
47- Option < ( BlueprintTarget , Arc < Blueprint > ) > ,
48- > ,
44+ rx_blueprint : watch:: Receiver < Option < LoadedTargetBlueprint > > ,
4945 nexus_id : OmicronZoneUuid ,
5046 saga_recovery : Activator ,
5147 mgs_update_tx : watch:: Sender < PendingMgsUpdates > ,
@@ -79,7 +75,7 @@ impl BlueprintExecutor {
7975 // on the watch.
8076 let update = self . rx_blueprint . borrow_and_update ( ) . clone ( ) ;
8177
82- let Some ( ( bp_target , blueprint) ) = update else {
78+ let Some ( LoadedTargetBlueprint { target , blueprint } ) = update else {
8379 warn ! (
8480 & opctx. log, "Blueprint execution: skipped" ;
8581 "reason" => "no blueprint" ,
@@ -127,11 +123,13 @@ impl BlueprintExecutor {
127123 }
128124 } ;
129125
130- if !bp_target. enabled {
131- warn ! ( & opctx. log,
132- "Blueprint execution: skipped" ;
133- "reason" => "blueprint disabled" ,
134- "target_id" => %blueprint. id) ;
126+ if !target. enabled {
127+ warn ! (
128+ & opctx. log,
129+ "Blueprint execution: skipped" ;
130+ "reason" => "blueprint disabled" ,
131+ "target_id" => %blueprint. id,
132+ ) ;
135133 return json ! ( {
136134 "target_id" : blueprint. id. to_string( ) ,
137135 "enabled" : false ,
@@ -220,7 +218,9 @@ impl BackgroundTask for BlueprintExecutor {
220218#[ cfg( test) ]
221219mod test {
222220 use super :: BlueprintExecutor ;
223- use crate :: app:: background:: { Activator , BackgroundTask } ;
221+ use crate :: app:: background:: {
222+ Activator , BackgroundTask , LoadedTargetBlueprint ,
223+ } ;
224224 use crate :: app:: quiesce:: NexusQuiesceHandle ;
225225 use httptest:: Expectation ;
226226 use httptest:: matchers:: { not, request} ;
@@ -274,7 +274,7 @@ mod test {
274274 opctx : & OpContext ,
275275 blueprint_zones : BTreeMap < SledUuid , IdOrdMap < BlueprintZoneConfig > > ,
276276 dns_version : Generation ,
277- ) -> ( BlueprintTarget , Blueprint ) {
277+ ) -> LoadedTargetBlueprint {
278278 let id = BlueprintUuid :: new_v4 ( ) ;
279279 // Assume all sleds are active with no disks or datasets.
280280 let blueprint_sleds = blueprint_zones
@@ -310,7 +310,7 @@ mod test {
310310 enabled : true ,
311311 time_made_target : chrono:: Utc :: now ( ) ,
312312 } ;
313- let blueprint = Blueprint {
313+ let blueprint = Arc :: new ( Blueprint {
314314 id,
315315 sleds : blueprint_sleds,
316316 pending_mgs_updates : PendingMgsUpdates :: new ( ) ,
@@ -329,7 +329,7 @@ mod test {
329329 creator : "test" . to_string ( ) ,
330330 comment : "test blueprint" . to_string ( ) ,
331331 source : BlueprintSource :: Test ,
332- } ;
332+ } ) ;
333333
334334 datastore
335335 . blueprint_insert ( opctx, & blueprint)
@@ -340,7 +340,7 @@ mod test {
340340 . await
341341 . expect ( "set new blueprint as current target" ) ;
342342
343- ( target, blueprint)
343+ LoadedTargetBlueprint { target, blueprint }
344344 }
345345
346346 #[ nexus_test( server = crate :: Server ) ]
@@ -450,18 +450,11 @@ mod test {
450450 // With a target blueprint having no zones, the task should trivially
451451 // complete and report a successful (empty) summary.
452452 let generation = Generation :: new ( ) ;
453- let blueprint = {
454- let ( target, blueprint) = create_blueprint (
455- & datastore,
456- & opctx,
457- BTreeMap :: new ( ) ,
458- generation,
459- )
460- . await ;
461- ( target, Arc :: new ( blueprint) )
462- } ;
463- let blueprint_id = blueprint. 1 . id ;
464- blueprint_tx. send ( Some ( blueprint) ) . unwrap ( ) ;
453+ let loaded =
454+ create_blueprint ( & datastore, & opctx, BTreeMap :: new ( ) , generation)
455+ . await ;
456+ let blueprint_id = loaded. blueprint . id ;
457+ blueprint_tx. send ( Some ( loaded) ) . unwrap ( ) ;
465458 let mut value = task. activate ( & opctx) . await ;
466459
467460 let event_buffer = extract_event_buffer ( & mut value) ;
@@ -515,7 +508,7 @@ mod test {
515508 // In-service zones should be deployed.
516509 //
517510 // TODO: add expunged zones to the test (should not be deployed).
518- let mut blueprint = create_blueprint (
511+ let mut loaded = create_blueprint (
519512 & datastore,
520513 & opctx,
521514 BTreeMap :: from ( [
@@ -528,7 +521,7 @@ mod test {
528521
529522 // Insert records for the zpools backing the datasets in these zones.
530523 for ( sled_id, config) in
531- blueprint . 1 . all_omicron_zones ( BlueprintZoneDisposition :: any)
524+ loaded . blueprint . all_omicron_zones ( BlueprintZoneDisposition :: any)
532525 {
533526 let Some ( dataset) = config. zone_type . durable_dataset ( ) else {
534527 continue ;
@@ -547,9 +540,7 @@ mod test {
547540 . expect ( "failed to upsert zpool" ) ;
548541 }
549542
550- blueprint_tx
551- . send ( Some ( ( blueprint. 0 , Arc :: new ( blueprint. 1 . clone ( ) ) ) ) )
552- . unwrap ( ) ;
543+ blueprint_tx. send ( Some ( loaded. clone ( ) ) ) . unwrap ( ) ;
553544
554545 // Make sure that requests get made to the sled agent.
555546 for s in [ & mut s1, & mut s2] {
@@ -568,7 +559,7 @@ mod test {
568559 assert_eq ! (
569560 value,
570561 json!( {
571- "target_id" : blueprint . 1 . id. to_string( ) ,
562+ "target_id" : loaded . blueprint . id. to_string( ) ,
572563 "execution_error" : null,
573564 "enabled" : true ,
574565 "needs_saga_recovery" : false ,
@@ -589,19 +580,20 @@ mod test {
589580 // Now, disable the target and make sure that we _don't_ invoke the sled
590581 // agent. It's enough to just not set expectations on
591582 // match_put_omicron_config().
592- blueprint. 1 . internal_dns_version =
593- blueprint. 1 . internal_dns_version . next ( ) ;
594- blueprint. 0 . enabled = false ;
595- blueprint_tx
596- . send ( Some ( ( blueprint. 0 , Arc :: new ( blueprint. 1 . clone ( ) ) ) ) )
597- . unwrap ( ) ;
583+ {
584+ let blueprint = Arc :: make_mut ( & mut loaded. blueprint ) ;
585+ blueprint. internal_dns_version =
586+ blueprint. internal_dns_version . next ( ) ;
587+ }
588+ loaded. target . enabled = false ;
589+ blueprint_tx. send ( Some ( loaded. clone ( ) ) ) . unwrap ( ) ;
598590 let value = task. activate ( & opctx) . await ;
599591 println ! ( "when disabled: {:?}" , value) ;
600592 assert_eq ! (
601593 value,
602594 json!( {
603595 "enabled" : false ,
604- "target_id" : blueprint . 1 . id. to_string( )
596+ "target_id" : loaded . blueprint . id. to_string( )
605597 } )
606598 ) ;
607599 s1. verify_and_clear ( ) ;
@@ -616,10 +608,8 @@ mod test {
616608
617609 // Do it all again, but configure one of the servers to fail so we can
618610 // verify the task's returned summary of what happened.
619- blueprint. 0 . enabled = true ;
620- blueprint_tx
621- . send ( Some ( ( blueprint. 0 , Arc :: new ( blueprint. 1 . clone ( ) ) ) ) )
622- . unwrap ( ) ;
611+ loaded. target . enabled = true ;
612+ blueprint_tx. send ( Some ( loaded. clone ( ) ) ) . unwrap ( ) ;
623613 s1. expect (
624614 Expectation :: matching ( match_put_omicron_config ( ) )
625615 . respond_with ( status_code ( 204 ) ) ,
0 commit comments