Skip to content

Commit efd37e9

Browse files
committed
Enforce ordering of planner steps in one place
1 parent 999169f commit efd37e9

File tree

1 file changed

+46
-28
lines changed

1 file changed

+46
-28
lines changed

nexus/reconfigurator/planning/src/planner.rs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,45 +83,63 @@ const NUM_CONCURRENT_MGS_UPDATES: usize = 1;
8383
/// The planner operates in distinct steps, and it is a compile-time error
8484
/// to skip or reorder them; see `Planner::do_plan`.
8585
trait PlannerStep {
86+
type Next: PlannerStep;
8687
fn new() -> Self;
87-
fn into_next<Next: PlannerStep>(self) -> Next;
88+
fn into_next(self) -> Self::Next;
8889
}
8990

9091
macro_rules! planner_step {
9192
($name: ident, $next: ident) => {
92-
/// Non-terminal step.
93+
// Non-terminal step.
9394
struct $name;
9495
impl PlannerStep for $name {
96+
type Next = $next;
97+
98+
fn new() -> Self {
99+
Self
100+
}
101+
102+
fn into_next(self) -> Self::Next {
103+
Self::Next::new()
104+
}
105+
}
106+
};
107+
($name: ident) => {
108+
// Terminal step.
109+
struct $name;
110+
impl PlannerStep for $name {
111+
type Next = Self;
112+
95113
fn new() -> Self {
96114
Self
97115
}
98116

99-
fn into_next<$next: PlannerStep>(self) -> $next {
100-
$next::new()
117+
fn into_next(self) -> Self::Next {
118+
unreachable!("terminal step has no next")
101119
}
102120
}
103121
};
104122
}
105123
planner_step!(ExpungeStep, AddStep);
106124
planner_step!(AddStep, DecommissionStep);
107-
planner_step!(DecommissionStep, MgsUpdateStep);
125+
planner_step!(DecommissionStep, MgsUpdatesStep);
108126
planner_step!(MgsUpdatesStep, UpdateZonesStep);
109127
planner_step!(UpdateZonesStep, CockroachDbSettingsStep);
110128
planner_step!(CockroachDbSettingsStep, TerminalStep);
111-
planner_step!(TerminalStep, Never);
129+
planner_step!(TerminalStep);
112130

113-
enum UpdateStepResult<Next> {
114-
ContinueToNextStep(Next),
131+
enum UpdateStepResult<Prev: PlannerStep> {
132+
ContinueToNextStep(Prev),
115133
PlanningComplete(TerminalStep),
116134
Waiting(Vec<WaitCondition>),
117135
}
118136

119-
impl<Next: PlannerStep> UpdateStepResult<Next> {
120-
fn continue_to_next_step<Prev: PlannerStep>(prev: Prev) -> Self {
121-
Self::ContinueToNextStep(prev.into_next())
137+
impl<Prev: PlannerStep> UpdateStepResult<Prev> {
138+
fn continue_to_next_step(prev: Prev) -> Self {
139+
Self::ContinueToNextStep(prev)
122140
}
123141

124-
fn planning_complete(prev: UpdateZonesStep) -> Self {
142+
fn planning_complete(prev: CockroachDbSettingsStep) -> Self {
125143
Self::PlanningComplete(prev.into_next())
126144
}
127145

@@ -212,18 +230,18 @@ impl<'a> Planner<'a> {
212230
}
213231
}};
214232
}
215-
let next = step!(self.do_plan_expunge()?);
216-
let next = step!(self.do_plan_add(next)?);
217-
let next = step!(self.do_plan_decommission(next)?);
218-
let next = step!(self.do_plan_mgs_updates(next));
219-
let next = step!(self.do_plan_zone_updates(next)?);
220-
step!(self.do_plan_cockroachdb_settings(next)?);
233+
let ready = step!(self.do_plan_expunge()?);
234+
let ready = step!(self.do_plan_add(ready.into_next())?);
235+
let ready = step!(self.do_plan_decommission(ready.into_next())?);
236+
let ready = step!(self.do_plan_mgs_updates(ready.into_next()));
237+
let ready = step!(self.do_plan_zone_updates(ready.into_next())?);
238+
step!(self.do_plan_cockroachdb_settings(ready.into_next())?);
221239
unreachable!("planning is complete!");
222240
}
223241

224242
fn do_plan_decommission(
225243
&mut self,
226-
prev: AddStep,
244+
ready: DecommissionStep,
227245
) -> Result<UpdateStepResult<DecommissionStep>, Error> {
228246
// Check for any sleds that are currently commissioned but can be
229247
// decommissioned. Our gates for decommissioning are:
@@ -307,7 +325,7 @@ impl<'a> Planner<'a> {
307325
}
308326
}
309327

310-
Ok(UpdateStepResult::continue_to_next_step(prev))
328+
Ok(UpdateStepResult::continue_to_next_step(ready))
311329
}
312330

313331
fn do_plan_decommission_expunged_disks_for_in_service_sled(
@@ -565,7 +583,7 @@ impl<'a> Planner<'a> {
565583

566584
fn do_plan_add(
567585
&mut self,
568-
prev: ExpungeStep,
586+
ready: AddStep,
569587
) -> Result<UpdateStepResult<AddStep>, Error> {
570588
// Internal DNS is a prerequisite for bringing up all other zones. At
571589
// this point, we assume that internal DNS (as a service) is already
@@ -753,7 +771,7 @@ impl<'a> Planner<'a> {
753771
// ensure that all sleds have the datasets they need to have.
754772
self.do_plan_datasets()?;
755773

756-
Ok(UpdateStepResult::continue_to_next_step(prev))
774+
Ok(UpdateStepResult::continue_to_next_step(ready))
757775
}
758776

759777
fn do_plan_datasets(&mut self) -> Result<(), Error> {
@@ -1014,7 +1032,7 @@ impl<'a> Planner<'a> {
10141032
/// date.
10151033
fn do_plan_mgs_updates(
10161034
&mut self,
1017-
prev: DecommissionStep,
1035+
ready: MgsUpdatesStep,
10181036
) -> UpdateStepResult<MgsUpdatesStep> {
10191037
// Determine which baseboards we will consider updating.
10201038
//
@@ -1063,7 +1081,7 @@ impl<'a> Planner<'a> {
10631081
// TODO This is not quite right. See oxidecomputer/omicron#8285.
10641082
self.blueprint.pending_mgs_updates_replace_all(next.clone());
10651083
if next.is_empty() {
1066-
UpdateStepResult::continue_to_next_step(prev)
1084+
UpdateStepResult::continue_to_next_step(ready)
10671085
} else {
10681086
UpdateStepResult::waiting(vec![WaitCondition::MgsUpdates {
10691087
pending: next.clone(),
@@ -1074,7 +1092,7 @@ impl<'a> Planner<'a> {
10741092
/// Update at most one existing zone to use a new image source.
10751093
fn do_plan_zone_updates(
10761094
&mut self,
1077-
prev: MgsUpdatesStep,
1095+
ready: UpdateZonesStep,
10781096
) -> Result<UpdateStepResult<UpdateZonesStep>, Error> {
10791097
// We are only interested in non-decommissioned sleds.
10801098
let sleds = self
@@ -1133,7 +1151,7 @@ impl<'a> Planner<'a> {
11331151
}
11341152

11351153
info!(self.log, "all zones up-to-date");
1136-
Ok(UpdateStepResult::continue_to_next_step(prev))
1154+
Ok(UpdateStepResult::continue_to_next_step(ready))
11371155
}
11381156

11391157
/// Update a zone to use a new image source, either in-place or by
@@ -1221,7 +1239,7 @@ impl<'a> Planner<'a> {
12211239

12221240
fn do_plan_cockroachdb_settings(
12231241
&mut self,
1224-
prev: UpdateZonesStep,
1242+
ready: CockroachDbSettingsStep,
12251243
) -> Result<UpdateStepResult<CockroachDbSettingsStep>, Error> {
12261244
// Figure out what we should set the CockroachDB "preserve downgrade
12271245
// option" setting to based on the planning input.
@@ -1315,7 +1333,7 @@ impl<'a> Planner<'a> {
13151333
//
13161334
// https://www.cockroachlabs.com/docs/stable/cluster-settings#change-a-cluster-setting
13171335

1318-
Ok(UpdateStepResult::planning_complete(prev.into_next()))
1336+
Ok(UpdateStepResult::planning_complete(ready))
13191337
}
13201338
}
13211339

0 commit comments

Comments
 (0)