Skip to content

Commit 2f8d2cd

Browse files
authored
[18/n] add target release generation to planning input (#8401)
Add a new `TufRepoPolicy` struct that currently consists of the target release generation plus the `TufRepoDescription`, and use it for both `tuf_repo` and `old_repo`. We're going to need `tuf_repo.generation` for MUPdate override work (RFD 556). We don't anticipate needing `old_repo.generation` for now but logically it makes sense to have.
1 parent 9d63409 commit 2f8d2cd

File tree

12 files changed

+190
-90
lines changed

12 files changed

+190
-90
lines changed

dev-tools/reconfigurator-cli/src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,11 +1672,12 @@ fn cmd_show(sim: &mut ReconfiguratorSim) -> anyhow::Result<Option<String>> {
16721672
);
16731673

16741674
let target_release = state.system().description().target_release();
1675-
match target_release {
1675+
match target_release.description() {
16761676
Some(tuf_desc) => {
16771677
swriteln!(
16781678
s,
1679-
"target release: {} ({})",
1679+
"target release (generation {}): {} ({})",
1680+
target_release.target_release_generation,
16801681
tuf_desc.repo.system_version,
16811682
tuf_desc.repo.file_name
16821683
);
@@ -1692,7 +1693,11 @@ fn cmd_show(sim: &mut ReconfiguratorSim) -> anyhow::Result<Option<String>> {
16921693
}
16931694
}
16941695
None => {
1695-
swriteln!(s, "target release: unset");
1696+
swriteln!(
1697+
s,
1698+
"target release (generation {}): unset",
1699+
target_release.target_release_generation,
1700+
);
16961701
}
16971702
}
16981703

dev-tools/reconfigurator-cli/tests/output/cmds-example-stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ configured silo names: example-silo
1616
internal DNS generations: 1
1717
external DNS generations: 1
1818
target number of Nexus instances: default
19-
target release: unset
19+
target release (generation 1): unset
2020

2121

2222

dev-tools/reconfigurator-cli/tests/output/target-release-stdout

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ configured silo names: example-silo
1313
internal DNS generations: 1
1414
external DNS generations: 1
1515
target number of Nexus instances: default
16-
target release: unset
16+
target release (generation 1): unset
1717

1818

1919

@@ -51,7 +51,7 @@ configured silo names: example-silo
5151
internal DNS generations: 1
5252
external DNS generations: 1
5353
target number of Nexus instances: default
54-
target release: 1.0.0 (system-update-v1.0.0.zip)
54+
target release (generation 2): 1.0.0 (system-update-v1.0.0.zip)
5555
artifact: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670 gimlet_sp (SimGimletSp version 1.0.0)
5656
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_a (fake-gimlet-rot version 1.0.0)
5757
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_b (fake-gimlet-rot version 1.0.0)
@@ -89,7 +89,7 @@ configured silo names: example-silo
8989
internal DNS generations:
9090
external DNS generations:
9191
target number of Nexus instances: default
92-
target release: unset
92+
target release (generation 1): unset
9393

9494

9595
> load saved.out
@@ -115,7 +115,7 @@ configured silo names: example-silo
115115
internal DNS generations: 1
116116
external DNS generations: 1
117117
target number of Nexus instances: default
118-
target release: 1.0.0 (system-update-v1.0.0.zip)
118+
target release (generation 2): 1.0.0 (system-update-v1.0.0.zip)
119119
artifact: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670 gimlet_sp (SimGimletSp version 1.0.0)
120120
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_a (fake-gimlet-rot version 1.0.0)
121121
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_b (fake-gimlet-rot version 1.0.0)

nexus/reconfigurator/execution/src/dns.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ mod test {
349349
use nexus_types::deployment::OximeterReadPolicy;
350350
use nexus_types::deployment::PendingMgsUpdates;
351351
use nexus_types::deployment::SledFilter;
352+
use nexus_types::deployment::TufRepoPolicy;
352353
use nexus_types::deployment::blueprint_zone_type;
353354
use nexus_types::external_api::params;
354355
use nexus_types::external_api::shared;
@@ -1495,7 +1496,7 @@ mod test {
14951496
target_crucible_pantry_zone_count: CRUCIBLE_PANTRY_REDUNDANCY,
14961497
clickhouse_policy: None,
14971498
oximeter_read_policy: OximeterReadPolicy::new(1),
1498-
tuf_repo: None,
1499+
tuf_repo: TufRepoPolicy::initial(),
14991500
old_repo: None,
15001501
log,
15011502
}

nexus/reconfigurator/planning/src/blueprint_builder/builder.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,8 +2003,9 @@ impl<'a> BlueprintBuilder<'a> {
20032003
&self,
20042004
zone_kind: ZoneKind,
20052005
) -> BlueprintZoneImageSource {
2006-
let new_repo = self.input.tuf_repo();
2007-
let old_repo = self.input.old_repo();
2006+
let new_repo = self.input.tuf_repo().description();
2007+
let old_repo =
2008+
self.input.old_repo().and_then(|repo| repo.description());
20082009
Self::zone_image_artifact(
20092010
if self.zone_is_ready_for_update(zone_kind, new_repo) {
20102011
new_repo

nexus/reconfigurator/planning/src/planner.rs

Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ impl<'a> Planner<'a> {
974974
// Compute the new set of PendingMgsUpdates.
975975
let current_updates =
976976
&self.blueprint.parent_blueprint().pending_mgs_updates;
977-
let current_artifacts = self.input.tuf_repo();
977+
let current_artifacts = self.input.tuf_repo().description();
978978
let next = plan_mgs_updates(
979979
&self.log,
980980
&self.inventory,
@@ -1255,6 +1255,7 @@ pub(crate) mod test {
12551255
use nexus_types::deployment::ClickhouseMode;
12561256
use nexus_types::deployment::ClickhousePolicy;
12571257
use nexus_types::deployment::SledDisk;
1258+
use nexus_types::deployment::TufRepoPolicy;
12581259
use nexus_types::deployment::blueprint_zone_type;
12591260
use nexus_types::deployment::blueprint_zone_type::InternalDns;
12601261
use nexus_types::external_api::views::PhysicalDiskState;
@@ -4705,7 +4706,7 @@ pub(crate) mod test {
47054706
verify_blueprint(&blueprint1);
47064707

47074708
// We should start with no specified TUF repo and nothing to do.
4708-
assert!(example.input.tuf_repo().is_none());
4709+
assert!(example.input.tuf_repo().description().is_none());
47094710
assert_planning_makes_no_changes(
47104711
&logctx.log,
47114712
&blueprint1,
@@ -4724,18 +4725,28 @@ pub(crate) mod test {
47244725
))
47254726
);
47264727

4728+
// This generation is successively incremented for each TUF repo. We use
4729+
// generation 2 to represent the first generation with a TUF repo
4730+
// attached.
4731+
let target_release_generation = Generation::from_u32(2);
4732+
47274733
// Manually specify a trivial TUF repo.
47284734
let mut input_builder = example.input.clone().into_builder();
4729-
input_builder.policy_mut().tuf_repo = Some(TufRepoDescription {
4730-
repo: TufRepoMeta {
4731-
hash: ArtifactHash([0; 32]),
4732-
targets_role_version: 0,
4733-
valid_until: Utc::now(),
4734-
system_version: Version::new(0, 0, 0),
4735-
file_name: String::from(""),
4736-
},
4737-
artifacts: vec![],
4738-
});
4735+
input_builder.policy_mut().tuf_repo = TufRepoPolicy {
4736+
// We use generation 2 to represent the first generation set to a
4737+
// target TUF repo.
4738+
target_release_generation,
4739+
description: Some(TufRepoDescription {
4740+
repo: TufRepoMeta {
4741+
hash: ArtifactHash([0; 32]),
4742+
targets_role_version: 0,
4743+
valid_until: Utc::now(),
4744+
system_version: Version::new(0, 0, 0),
4745+
file_name: String::from(""),
4746+
},
4747+
artifacts: vec![],
4748+
}),
4749+
};
47394750
let input = input_builder.build();
47404751
let blueprint2 = Planner::new_based_on(
47414752
log.clone(),
@@ -4776,16 +4787,20 @@ pub(crate) mod test {
47764787
fake_zone_artifact!(CruciblePantry, version.clone()),
47774788
fake_zone_artifact!(Nexus, version.clone()),
47784789
];
4779-
input_builder.policy_mut().tuf_repo = Some(TufRepoDescription {
4780-
repo: TufRepoMeta {
4781-
hash: fake_hash,
4782-
targets_role_version: 0,
4783-
valid_until: Utc::now(),
4784-
system_version: Version::new(1, 0, 0),
4785-
file_name: String::from(""),
4786-
},
4787-
artifacts,
4788-
});
4790+
let target_release_generation = target_release_generation.next();
4791+
input_builder.policy_mut().tuf_repo = TufRepoPolicy {
4792+
target_release_generation,
4793+
description: Some(TufRepoDescription {
4794+
repo: TufRepoMeta {
4795+
hash: fake_hash,
4796+
targets_role_version: 0,
4797+
valid_until: Utc::now(),
4798+
system_version: Version::new(1, 0, 0),
4799+
file_name: String::from(""),
4800+
},
4801+
artifacts,
4802+
}),
4803+
};
47894804

47904805
// Some helper predicates for the assertions below.
47914806
let is_old_nexus = |zone: &BlueprintZoneConfig| -> bool {
@@ -5023,30 +5038,36 @@ pub(crate) mod test {
50235038
},
50245039
hash: fake_hash,
50255040
};
5026-
let tuf_repo = TufRepoDescription {
5027-
repo: TufRepoMeta {
5028-
hash: fake_hash,
5029-
targets_role_version: 0,
5030-
valid_until: Utc::now(),
5031-
system_version: Version::new(1, 0, 0),
5032-
file_name: String::from(""),
5033-
},
5034-
artifacts: vec![
5035-
fake_zone_artifact!(BoundaryNtp, version.clone()),
5036-
fake_zone_artifact!(Clickhouse, version.clone()),
5037-
fake_zone_artifact!(ClickhouseKeeper, version.clone()),
5038-
fake_zone_artifact!(ClickhouseServer, version.clone()),
5039-
fake_zone_artifact!(CockroachDb, version.clone()),
5040-
fake_zone_artifact!(Crucible, version.clone()),
5041-
fake_zone_artifact!(CruciblePantry, version.clone()),
5042-
fake_zone_artifact!(ExternalDns, version.clone()),
5043-
fake_zone_artifact!(InternalDns, version.clone()),
5044-
fake_zone_artifact!(InternalNtp, version.clone()),
5045-
fake_zone_artifact!(Nexus, version.clone()),
5046-
fake_zone_artifact!(Oximeter, version.clone()),
5047-
],
5041+
// We use generation 2 to represent the first generation with a TUF repo
5042+
// attached.
5043+
let target_release_generation = Generation::new().next();
5044+
let tuf_repo = TufRepoPolicy {
5045+
target_release_generation,
5046+
description: Some(TufRepoDescription {
5047+
repo: TufRepoMeta {
5048+
hash: fake_hash,
5049+
targets_role_version: 0,
5050+
valid_until: Utc::now(),
5051+
system_version: Version::new(1, 0, 0),
5052+
file_name: String::from(""),
5053+
},
5054+
artifacts: vec![
5055+
fake_zone_artifact!(BoundaryNtp, version.clone()),
5056+
fake_zone_artifact!(Clickhouse, version.clone()),
5057+
fake_zone_artifact!(ClickhouseKeeper, version.clone()),
5058+
fake_zone_artifact!(ClickhouseServer, version.clone()),
5059+
fake_zone_artifact!(CockroachDb, version.clone()),
5060+
fake_zone_artifact!(Crucible, version.clone()),
5061+
fake_zone_artifact!(CruciblePantry, version.clone()),
5062+
fake_zone_artifact!(ExternalDns, version.clone()),
5063+
fake_zone_artifact!(InternalDns, version.clone()),
5064+
fake_zone_artifact!(InternalNtp, version.clone()),
5065+
fake_zone_artifact!(Nexus, version.clone()),
5066+
fake_zone_artifact!(Oximeter, version.clone()),
5067+
],
5068+
}),
50485069
};
5049-
input_builder.policy_mut().tuf_repo = Some(tuf_repo);
5070+
input_builder.policy_mut().tuf_repo = tuf_repo;
50505071
let input = input_builder.build();
50515072

50525073
/// Expected number of planner iterations required to converge.

nexus/reconfigurator/planning/src/system.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use nexus_types::deployment::Policy;
3434
use nexus_types::deployment::SledDetails;
3535
use nexus_types::deployment::SledDisk;
3636
use nexus_types::deployment::SledResources;
37+
use nexus_types::deployment::TufRepoPolicy;
3738
use nexus_types::external_api::views::PhysicalDiskPolicy;
3839
use nexus_types::external_api::views::PhysicalDiskState;
3940
use nexus_types::external_api::views::SledPolicy;
@@ -107,8 +108,8 @@ pub struct SystemDescription {
107108
external_dns_version: Generation,
108109
clickhouse_policy: Option<ClickhousePolicy>,
109110
oximeter_read_policy: OximeterReadPolicy,
110-
tuf_repo: Option<TufRepoDescription>,
111-
old_repo: Option<TufRepoDescription>,
111+
tuf_repo: TufRepoPolicy,
112+
old_repo: Option<TufRepoPolicy>,
112113
}
113114

114115
impl SystemDescription {
@@ -188,7 +189,7 @@ impl SystemDescription {
188189
external_dns_version: Generation::new(),
189190
clickhouse_policy: None,
190191
oximeter_read_policy: OximeterReadPolicy::new(1),
191-
tuf_repo: None,
192+
tuf_repo: TufRepoPolicy::initial(),
192193
old_repo: None,
193194
}
194195
}
@@ -468,16 +469,38 @@ impl SystemDescription {
468469
Ok(sled.sp_inactive_caboose().map(|c| c.version.as_ref()))
469470
}
470471

472+
pub fn set_tuf_repo(&mut self, tuf_repo: TufRepoPolicy) {
473+
self.tuf_repo = tuf_repo;
474+
}
475+
471476
pub fn set_target_release(
472477
&mut self,
473478
tuf_repo: Option<TufRepoDescription>,
474479
) -> &mut Self {
475-
self.tuf_repo = tuf_repo;
480+
// Create a new TufRepoPolicy by bumping the generation.
481+
let new_repo = TufRepoPolicy {
482+
target_release_generation: self
483+
.tuf_repo
484+
.target_release_generation
485+
.next(),
486+
description: tuf_repo,
487+
};
488+
489+
self.tuf_repo = new_repo;
490+
491+
// It's tempting to consider setting old_repo to the current tuf_repo,
492+
// but that requires the invariant that old_repo is always the current
493+
// target release and that an update isn't currently in progress. See
494+
// https://github.com/oxidecomputer/omicron/issues/8056 for some
495+
// discussion.
496+
//
497+
// We may want a more explicit operation to set the old repo, though.
498+
476499
self
477500
}
478501

479-
pub fn target_release(&self) -> Option<&TufRepoDescription> {
480-
self.tuf_repo.as_ref()
502+
pub fn target_release(&self) -> &TufRepoPolicy {
503+
&self.tuf_repo
481504
}
482505

483506
pub fn to_collection_builder(&self) -> anyhow::Result<CollectionBuilder> {

0 commit comments

Comments
 (0)