Skip to content

Commit 77d097a

Browse files
authored
Add desired host phase 2 contents to OmicronSledConfig (PR 1/4) (#8538)
`HostPhase2DesiredContents` is analogous to `OmicronZoneImageSource`, but for OS images: either keep the current contents of the boot disk or set it to a specific artifact from the TUF repo depot. "Keep the current contents" should show up in three cases, just like `OmicronZoneImageSource::InstallDataset`: 1. It's the default value for deserializing, so we can load old configs that didn't have this value 2. RSS uses it (no TUF repo depot involved at this point) 3. The planner will use this variant as a part of removing a mupdate override (this work is still in PR itself: #8456 (comment))
1 parent b7b24d5 commit 77d097a

File tree

23 files changed

+320
-87
lines changed

23 files changed

+320
-87
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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 current contents")
7581+
}
7582+
HostPhase2DesiredContents::Artifact { hash } => {
7583+
Cow::Owned(format!("artifact {hash}"))
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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,47 @@ 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+
#[serde(tag = "type", rename_all = "snake_case")]
585+
pub enum HostPhase2DesiredContents {
586+
/// Do not change the current contents.
587+
///
588+
/// We use this value when we've detected a sled has been mupdated (and we
589+
/// don't want to overwrite phase 2 images until we understand how to
590+
/// recover from that mupdate) and as the default value when reading an
591+
/// [`OmicronSledConfig`] that was ledgered before this concept existed.
592+
CurrentContents,
593+
594+
/// Set the phase 2 slot to the given artifact.
595+
///
596+
/// The artifact will come from an unpacked and distributed TUF repo.
597+
Artifact { hash: ArtifactHash },
598+
}
599+
600+
/// Describes the desired contents for both host phase 2 slots.
601+
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
602+
#[serde(rename_all = "snake_case")]
603+
pub struct HostPhase2DesiredSlots {
604+
pub slot_a: HostPhase2DesiredContents,
605+
pub slot_b: HostPhase2DesiredContents,
606+
}
607+
608+
impl HostPhase2DesiredSlots {
609+
/// Return a `HostPhase2DesiredSlots` with both slots set to
610+
/// [`HostPhase2DesiredContents::CurrentContents`]; i.e., "make no changes
611+
/// to the current contents of either slot".
612+
pub const fn current_contents() -> Self {
613+
Self {
614+
slot_a: HostPhase2DesiredContents::CurrentContents,
615+
slot_b: HostPhase2DesiredContents::CurrentContents,
616+
}
617+
}
618+
}
619+
579620
/// Describes the set of Reconfigurator-managed configuration elements of a sled
580621
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
581622
pub struct OmicronSledConfig {
@@ -584,6 +625,8 @@ pub struct OmicronSledConfig {
584625
pub datasets: IdMap<DatasetConfig>,
585626
pub zones: IdMap<OmicronZoneConfig>,
586627
pub remove_mupdate_override: Option<MupdateOverrideUuid>,
628+
#[serde(default = "HostPhase2DesiredSlots::current_contents")]
629+
pub host_phase_2: HostPhase2DesiredSlots,
587630
}
588631

589632
impl Default for OmicronSledConfig {
@@ -594,6 +637,7 @@ impl Default for OmicronSledConfig {
594637
datasets: IdMap::default(),
595638
zones: IdMap::default(),
596639
remove_mupdate_override: None,
640+
host_phase_2: HostPhase2DesiredSlots::current_contents(),
597641
}
598642
}
599643
}

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 { hash } => {
1984+
Some(ArtifactHash(hash))
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(hash)) => {
1999+
HostPhase2DesiredContents::Artifact { hash }
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(158, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(159, 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(159, "sled-config-desired-host-phase-2"),
3132
KnownVersion::new(158, "drop-builtin-roles"),
3233
KnownVersion::new(157, "user-data-export"),
3334
KnownVersion::new(156, "boot-partitions-inventory"),

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
@@ -1780,6 +1780,8 @@ table! {
17801780

17811781
generation -> Int8,
17821782
remove_mupdate_override -> Nullable<Uuid>,
1783+
host_phase_2_desired_slot_a -> Nullable<Text>,
1784+
host_phase_2_desired_slot_b -> Nullable<Text>,
17831785
}
17841786
}
17851787

nexus/inventory/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ sled-agent-types.workspace = true
3232
sled-agent-zone-images-examples.workspace = true
3333
slog.workspace = true
3434
strum.workspace = true
35+
swrite.workspace = true
3536
thiserror.workspace = true
3637
tufaceous-artifact.workspace = true
3738
typed-rng.workspace = true

0 commit comments

Comments
 (0)