Skip to content

Commit b867be7

Browse files
committed
OmicronSledConfig: add desired host phase 2 contents
1 parent 94dda3c commit b867be7

File tree

17 files changed

+157
-7
lines changed

17 files changed

+157
-7
lines changed

dev-tools/omdb/src/bin/omdb/db.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ use nexus_sled_agent_shared::inventory::BootPartitionDetails;
131131
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventory;
132132
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventoryResult;
133133
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventoryStatus;
134+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredContents;
134135
use nexus_sled_agent_shared::inventory::OmicronSledConfig;
135136
use nexus_sled_agent_shared::inventory::OmicronZoneImageSource;
136137
use nexus_sled_agent_shared::inventory::OrphanedDataset;
@@ -7567,12 +7568,30 @@ fn inv_collection_print_sled_config(label: &str, config: &OmicronSledConfig) {
75677568
datasets,
75687569
zones,
75697570
remove_mupdate_override,
7571+
host_phase_2,
75707572
} = config;
75717573

75727574
println!("\n{label} SLED CONFIG");
75737575
println!(" generation: {}", generation);
75747576
println!(" remove_mupdate_override: {remove_mupdate_override:?}");
75757577

7578+
let display_host_phase_2_desired = |desired| match desired {
7579+
HostPhase2DesiredContents::CurrentContents => {
7580+
Cow::Borrowed("keep existing current contents")
7581+
}
7582+
HostPhase2DesiredContents::Artifact(artifact) => {
7583+
Cow::Owned(format!("artifact {artifact}"))
7584+
}
7585+
};
7586+
println!(
7587+
" desired host phase 2 slot a: {}",
7588+
display_host_phase_2_desired(host_phase_2.slot_a)
7589+
);
7590+
println!(
7591+
" desired host phase 2 slot b: {}",
7592+
display_host_phase_2_desired(host_phase_2.slot_b)
7593+
);
7594+
75767595
if disks.is_empty() {
75777596
println!(" disk config empty");
75787597
} else {

nexus-sled-agent-shared/src/inventory.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,45 @@ pub enum SledRole {
576576
Scrimlet,
577577
}
578578

579+
/// Describes the desired contents of a host phase 2 slot (i.e., the boot
580+
/// partition on one of the internal M.2 drives).
581+
#[derive(
582+
Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq,
583+
)]
584+
pub enum HostPhase2DesiredContents {
585+
/// Do not change the current contents.
586+
///
587+
/// We use this value when we've detected a sled has been mupdated (and we
588+
/// don't want to overwrite phase 2 images until we understand how to
589+
/// recover from that mupdate) and as the default value when reading an
590+
/// [`OmicronSledConfig`] that was ledgered before this concept existed.
591+
CurrentContents,
592+
593+
/// Set the phase 2 slot to the given artifact.
594+
///
595+
/// The artifact will come from an unpacked and distributed TUF repo.
596+
Artifact(ArtifactHash),
597+
}
598+
599+
/// Describes the desired contents for both host phase 2 slots.
600+
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
601+
pub struct HostPhase2DesiredSlots {
602+
pub slot_a: HostPhase2DesiredContents,
603+
pub slot_b: HostPhase2DesiredContents,
604+
}
605+
606+
impl HostPhase2DesiredSlots {
607+
/// Return a `HostPhase2DesiredSlots` with both slots set to
608+
/// [`HostPhase2DesiredContents::CurrentContents`]; i.e., "make no changes
609+
/// to the current contents of either slot".
610+
pub const fn current_contents() -> Self {
611+
Self {
612+
slot_a: HostPhase2DesiredContents::CurrentContents,
613+
slot_b: HostPhase2DesiredContents::CurrentContents,
614+
}
615+
}
616+
}
617+
579618
/// Describes the set of Reconfigurator-managed configuration elements of a sled
580619
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
581620
pub struct OmicronSledConfig {
@@ -584,6 +623,8 @@ pub struct OmicronSledConfig {
584623
pub datasets: IdMap<DatasetConfig>,
585624
pub zones: IdMap<OmicronZoneConfig>,
586625
pub remove_mupdate_override: Option<MupdateOverrideUuid>,
626+
#[serde(default = "HostPhase2DesiredSlots::current_contents")]
627+
pub host_phase_2: HostPhase2DesiredSlots,
587628
}
588629

589630
impl Default for OmicronSledConfig {
@@ -594,6 +635,7 @@ impl Default for OmicronSledConfig {
594635
datasets: IdMap::default(),
595636
zones: IdMap::default(),
596637
remove_mupdate_override: None,
638+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
597639
}
598640
}
599641
}

nexus/db-model/src/inventory.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ use nexus_db_schema::schema::{
4444
use nexus_sled_agent_shared::inventory::BootImageHeader;
4545
use nexus_sled_agent_shared::inventory::BootPartitionDetails;
4646
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventoryStatus;
47+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredContents;
48+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredSlots;
4749
use nexus_sled_agent_shared::inventory::MupdateOverrideBootInventory;
4850
use nexus_sled_agent_shared::inventory::MupdateOverrideInventory;
4951
use nexus_sled_agent_shared::inventory::MupdateOverrideNonBootInventory;
@@ -1944,6 +1946,9 @@ pub struct InvOmicronSledConfig {
19441946
pub id: DbTypedUuid<OmicronSledConfigKind>,
19451947
pub generation: Generation,
19461948
pub remove_mupdate_override: Option<DbTypedUuid<MupdateOverrideKind>>,
1949+
1950+
#[diesel(embed)]
1951+
pub host_phase_2: DbHostPhase2DesiredSlots,
19471952
}
19481953

19491954
impl InvOmicronSledConfig {
@@ -1952,12 +1957,51 @@ impl InvOmicronSledConfig {
19521957
id: OmicronSledConfigUuid,
19531958
generation: external::Generation,
19541959
remove_mupdate_override: Option<MupdateOverrideUuid>,
1960+
host_phase_2: HostPhase2DesiredSlots,
19551961
) -> Self {
19561962
Self {
19571963
inv_collection_id: inv_collection_id.into(),
19581964
id: id.into(),
19591965
generation: Generation(generation),
19601966
remove_mupdate_override: remove_mupdate_override.map(From::from),
1967+
host_phase_2: host_phase_2.into(),
1968+
}
1969+
}
1970+
}
1971+
1972+
#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
1973+
#[diesel(table_name = inv_omicron_sled_config)]
1974+
pub struct DbHostPhase2DesiredSlots {
1975+
pub host_phase_2_desired_slot_a: Option<ArtifactHash>,
1976+
pub host_phase_2_desired_slot_b: Option<ArtifactHash>,
1977+
}
1978+
1979+
impl From<HostPhase2DesiredSlots> for DbHostPhase2DesiredSlots {
1980+
fn from(value: HostPhase2DesiredSlots) -> Self {
1981+
let remap = |desired| match desired {
1982+
HostPhase2DesiredContents::CurrentContents => None,
1983+
HostPhase2DesiredContents::Artifact(artifact) => {
1984+
Some(ArtifactHash(artifact))
1985+
}
1986+
};
1987+
Self {
1988+
host_phase_2_desired_slot_a: remap(value.slot_a),
1989+
host_phase_2_desired_slot_b: remap(value.slot_b),
1990+
}
1991+
}
1992+
}
1993+
1994+
impl From<DbHostPhase2DesiredSlots> for HostPhase2DesiredSlots {
1995+
fn from(value: DbHostPhase2DesiredSlots) -> Self {
1996+
let remap = |maybe_artifact| match maybe_artifact {
1997+
None => HostPhase2DesiredContents::CurrentContents,
1998+
Some(ArtifactHash(artifact)) => {
1999+
HostPhase2DesiredContents::Artifact(artifact)
2000+
}
2001+
};
2002+
Self {
2003+
slot_a: remap(value.host_phase_2_desired_slot_a),
2004+
slot_b: remap(value.host_phase_2_desired_slot_b),
19612005
}
19622006
}
19632007
}

nexus/db-model/src/schema_versions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
1616
///
1717
/// This must be updated when you change the database schema. Refer to
1818
/// schema/crdb/README.adoc in the root of this repository for details.
19-
pub const SCHEMA_VERSION: Version = Version::new(157, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(158, 0, 0);
2020

2121
/// List of all past database schema versions, in *reverse* order
2222
///
@@ -28,6 +28,7 @@ static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
2828
// | leaving the first copy as an example for the next person.
2929
// v
3030
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
31+
KnownVersion::new(158, "sled-config-desired-host-phase-2"),
3132
KnownVersion::new(157, "user-data-export"),
3233
KnownVersion::new(156, "boot-partitions-inventory"),
3334
KnownVersion::new(155, "vpc-firewall-icmp"),

nexus/db-queries/src/db/datastore/inventory.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,6 +2774,7 @@ impl DataStore {
27742774
disks: IdMap::default(),
27752775
datasets: IdMap::default(),
27762776
zones: IdMap::default(),
2777+
host_phase_2: sled_config.host_phase_2.into(),
27772778
},
27782779
});
27792780
}
@@ -3871,6 +3872,7 @@ impl ConfigReconcilerRows {
38713872
sled_config_id,
38723873
config.generation,
38733874
config.remove_mupdate_override,
3875+
config.host_phase_2.clone(),
38743876
));
38753877
self.disks.extend(config.disks.iter().map(|disk| {
38763878
InvOmicronSledConfigDisk::new(

nexus/db-schema/src/schema.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,6 +1788,8 @@ table! {
17881788

17891789
generation -> Int8,
17901790
remove_mupdate_override -> Nullable<Uuid>,
1791+
host_phase_2_desired_slot_a -> Nullable<Text>,
1792+
host_phase_2_desired_slot_b -> Nullable<Text>,
17911793
}
17921794
}
17931795

nexus/inventory/src/collector.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ mod test {
410410
use gateway_messages::SpPort;
411411
use id_map::IdMap;
412412
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventoryStatus;
413+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredSlots;
413414
use nexus_sled_agent_shared::inventory::OmicronSledConfig;
414415
use nexus_sled_agent_shared::inventory::OmicronZoneConfig;
415416
use nexus_sled_agent_shared::inventory::OmicronZoneImageSource;
@@ -434,6 +435,7 @@ mod test {
434435
datasets,
435436
zones,
436437
remove_mupdate_override,
438+
host_phase_2,
437439
} = config;
438440

439441
writeln!(s, " generation: {generation}").unwrap();
@@ -442,6 +444,11 @@ mod test {
442444
" remove_mupdate_override: {remove_mupdate_override:?}"
443445
)
444446
.unwrap();
447+
{
448+
let HostPhase2DesiredSlots { slot_a, slot_b } = host_phase_2;
449+
writeln!(s, " host_phase_2.slot_a: {slot_a:?}").unwrap();
450+
writeln!(s, " host_phase_2.slot_b: {slot_b:?}").unwrap();
451+
}
445452
for disk in disks {
446453
writeln!(
447454
s,
@@ -687,6 +694,7 @@ mod test {
687694
.into_iter()
688695
.collect(),
689696
remove_mupdate_override: None,
697+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
690698
})
691699
.await
692700
.expect("failed to write initial zone version to fake sled agent");

nexus/inventory/src/examples.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use nexus_sled_agent_shared::inventory::BootImageHeader;
2121
use nexus_sled_agent_shared::inventory::BootPartitionDetails;
2222
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventory;
2323
use nexus_sled_agent_shared::inventory::ConfigReconcilerInventoryStatus;
24+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredSlots;
2425
use nexus_sled_agent_shared::inventory::Inventory;
2526
use nexus_sled_agent_shared::inventory::InventoryDataset;
2627
use nexus_sled_agent_shared::inventory::InventoryDisk;
@@ -345,20 +346,23 @@ pub fn representative() -> Representative {
345346
datasets: Default::default(),
346347
zones: sled14.zones.into_iter().collect(),
347348
remove_mupdate_override: None,
349+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
348350
};
349351
let sled16 = OmicronSledConfig {
350352
generation: sled16.generation,
351353
disks: Default::default(),
352354
datasets: Default::default(),
353355
zones: sled16.zones.into_iter().collect(),
354356
remove_mupdate_override: None,
357+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
355358
};
356359
let sled17 = OmicronSledConfig {
357360
generation: sled17.generation,
358361
disks: Default::default(),
359362
datasets: Default::default(),
360363
zones: sled17.zones.into_iter().collect(),
361364
remove_mupdate_override: None,
365+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
362366
};
363367

364368
// Create iterator producing fixed IDs.

nexus/test-utils/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use nexus_config::MgdConfig;
3434
use nexus_config::NUM_INITIAL_RESERVED_IP_ADDRESSES;
3535
use nexus_config::NexusConfig;
3636
use nexus_db_queries::db::pub_test_utils::crdb;
37+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredSlots;
3738
use nexus_sled_agent_shared::inventory::OmicronSledConfig;
3839
use nexus_sled_agent_shared::inventory::OmicronZoneDataset;
3940
use nexus_sled_agent_shared::recovery_silo::RecoverySiloConfig;
@@ -1147,6 +1148,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> {
11471148
.map(From::from)
11481149
.collect(),
11491150
remove_mupdate_override: None,
1151+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
11501152
})
11511153
.await
11521154
.expect("Failed to configure sled agent with our zones");
@@ -1186,6 +1188,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> {
11861188
datasets: IdMap::default(),
11871189
zones: IdMap::default(),
11881190
remove_mupdate_override: None,
1191+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
11891192
})
11901193
.await
11911194
.expect("Failed to configure sled agent with our zones");

nexus/types/src/deployment.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use crate::inventory::ZpoolName;
2020
use blueprint_diff::ClickhouseClusterConfigDiffTablesForSingleBlueprint;
2121
use blueprint_display::BpDatasetsTableSchema;
2222
use daft::Diffable;
23+
use nexus_sled_agent_shared::inventory::HostPhase2DesiredSlots;
2324
use nexus_sled_agent_shared::inventory::OmicronSledConfig;
2425
use nexus_sled_agent_shared::inventory::OmicronZoneConfig;
2526
use nexus_sled_agent_shared::inventory::OmicronZoneImageSource;
@@ -743,6 +744,8 @@ impl BlueprintSledConfig {
743744
})
744745
.collect(),
745746
remove_mupdate_override: self.remove_mupdate_override,
747+
// TODO-john Open issue to add this to the blueprint
748+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
746749
}
747750
}
748751

0 commit comments

Comments
 (0)