Skip to content

Commit 592e8b0

Browse files
authored
Nexus add/remove live test needs another blueprint round (#7823)
1 parent e8bfadf commit 592e8b0

File tree

1 file changed

+93
-3
lines changed

1 file changed

+93
-3
lines changed

live-tests/tests/test_nexus_add_remove.rs

+93-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ use common::LiveTestContext;
99
use common::reconfigurator::blueprint_edit_current_target;
1010
use futures::TryStreamExt;
1111
use live_tests_macros::live_test;
12+
use nexus_client::types::BackgroundTasksActivateRequest;
13+
use nexus_client::types::BlueprintTargetSet;
1214
use nexus_client::types::Saga;
1315
use nexus_client::types::SagaState;
1416
use nexus_inventory::CollectionBuilder;
1517
use nexus_reconfigurator_planning::blueprint_builder::BlueprintBuilder;
18+
use nexus_reconfigurator_planning::planner::Planner;
1619
use nexus_reconfigurator_preparation::PlanningInputFromDb;
1720
use nexus_sled_agent_shared::inventory::ZoneKind;
1821
use nexus_types::deployment::SledFilter;
@@ -156,7 +159,94 @@ async fn test_nexus_add_remove(lc: &LiveTestContext) {
156159
.await
157160
.unwrap();
158161

159-
// Wait for some other Nexus instance to pick up the saga.
162+
// We want to see another Nexus instance pick up the saga.
163+
//
164+
// For that to happen, inventory must first reflect that the Nexus we
165+
// expunged is really gone. Then we must run through another planning
166+
// round.
167+
//
168+
// First, kick one Nexus instance's inventory collector. Otherwise, it
169+
// might take a while for the system to notice this zone is gone. Having
170+
// activated the task, it shouldn't take too long to get an inventory
171+
info!(log, "activating inventory collector");
172+
nexus
173+
.bgtask_activate(&BackgroundTasksActivateRequest {
174+
bgtask_names: vec![String::from("inventory_collection")],
175+
})
176+
.await
177+
.expect("activating inventory background task");
178+
let latest_collection = wait_for_condition(
179+
|| async {
180+
let latest_collection = datastore
181+
.inventory_get_latest_collection(opctx)
182+
.await
183+
.expect("latest inventory collection")
184+
.expect("have a latest inventory collection");
185+
debug!(log, "got inventory"; "id" => %latest_collection.id);
186+
let agent = latest_collection.sled_agents.get(&sled_id).expect(
187+
"collection information for the sled we added a Nexus to",
188+
);
189+
if agent.omicron_zones.zones.iter().any(|z| z.id == new_zone.id) {
190+
debug!(log, "zone still present in inventory");
191+
return Err(CondCheckError::<()>::NotYet);
192+
}
193+
return Ok(latest_collection);
194+
},
195+
&Duration::from_millis(3000),
196+
&Duration::from_secs(90),
197+
)
198+
.await
199+
.expect("waiting for zone to be gone from inventory");
200+
201+
// Now run through the planner.
202+
info!(log, "running through planner");
203+
let planning_input = PlanningInputFromDb::assemble(&opctx, &datastore)
204+
.await
205+
.expect("planning input");
206+
let (_, parent_blueprint) = datastore
207+
.blueprint_target_get_current_full(opctx)
208+
.await
209+
.expect("getting latest target blueprint");
210+
let planner = Planner::new_based_on(
211+
log.clone(),
212+
&parent_blueprint,
213+
&planning_input,
214+
"live test suite",
215+
&latest_collection,
216+
)
217+
.expect("constructing planner");
218+
let new_blueprint = planner.plan().expect("creating blueprint");
219+
220+
// The new blueprint ought to have our zone expunged and ready for cleanup.
221+
// We don't need to check this here. It just provides a better error
222+
// message if something has gone wrong up to this point.
223+
let (_, expunged_zone_config) = new_blueprint
224+
.all_omicron_zones(|_| true)
225+
.find(|(_sled_id, zone_config)| zone_config.id == new_zone.id)
226+
.expect("expunged zone in new blueprint");
227+
assert!(expunged_zone_config.disposition.is_ready_for_cleanup());
228+
229+
// Now make this the current target.
230+
info!(
231+
log,
232+
"setting new blueprint target";
233+
"blueprint_id" => ?new_blueprint.id
234+
);
235+
nexus
236+
.blueprint_import(&new_blueprint)
237+
.await
238+
.expect("importing new blueprint");
239+
nexus
240+
.blueprint_target_set(&BlueprintTargetSet {
241+
enabled: true,
242+
target_id: new_blueprint.id,
243+
})
244+
.await
245+
.expect("setting target blueprint");
246+
247+
// At this point, blueprint execution should re-assign the saga.
248+
// Wait for that to happen and then for another Nexus instance to pick up
249+
// the saga.
160250
let nexus_found = wait_for_condition(
161251
|| async {
162252
for nexus_client in &initial_nexus_clients {
@@ -173,8 +263,8 @@ async fn test_nexus_add_remove(lc: &LiveTestContext) {
173263

174264
return Err(CondCheckError::<()>::NotYet);
175265
},
176-
&Duration::from_millis(50),
177-
&Duration::from_secs(60),
266+
&Duration::from_millis(1000),
267+
&Duration::from_secs(120),
178268
)
179269
.await
180270
.unwrap();

0 commit comments

Comments
 (0)