Skip to content

Commit 7a911ab

Browse files
Add support for re-adopting physical disks (#10221)
This change implements the determinations in RFD 663. It allows re-adopting physical disks in the control plane after the control plane level disk in the `physical_disk` table is expunged. It does this by forcing manual adoption of disks by an operator, where requests are placed in the `physical_disk_adoption_request` table. A disk will now only be adopted or re-adopted by the disk adoption background task if its physical vendor/model/serial information is present in a `physical_disk_adoption_request` row. The typical flow for an operator is to list uninitialized disks and then issue an adoption request via the external API. We also allow automatic re-adoption of disks if they have never been seen by the same sled. For instance, if a sled is expunged and zpools destroyed, re-adding the sled will give it a different id and therefore allow adoption of disks with the same physical id. --------- Co-authored-by: Andy Fiddaman <illumos@fiddaman.net>
1 parent 0cdc7b9 commit 7a911ab

37 files changed

Lines changed: 1816 additions & 179 deletions

File tree

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use nexus_types::internal_api::background::InstanceReincarnationStatus;
6565
use nexus_types::internal_api::background::InstanceUpdaterStatus;
6666
use nexus_types::internal_api::background::InventoryLoadStatus;
6767
use nexus_types::internal_api::background::LookupRegionPortStatus;
68+
use nexus_types::internal_api::background::PhysicalDiskAdoptionStatus;
6869
use nexus_types::internal_api::background::ProbeDistributorStatus;
6970
use nexus_types::internal_api::background::ReadOnlyRegionReplacementStartStatus;
7071
use nexus_types::internal_api::background::RegionReplacementDriverStatus;
@@ -1300,6 +1301,9 @@ fn print_task_details(bgtask: &BackgroundTask, details: &serde_json::Value) {
13001301
"phantom_disks" => {
13011302
print_task_phantom_disks(details);
13021303
}
1304+
"physical_disk_adoption" => {
1305+
print_task_physical_disk_adoption(details);
1306+
}
13031307
"probe_distributor" => {
13041308
print_task_probe_distributor(details);
13051309
}
@@ -3949,6 +3953,25 @@ fn print_task_trust_quorum_manager(details: &serde_json::Value) {
39493953
}
39503954
}
39513955

3956+
fn print_task_physical_disk_adoption(details: &serde_json::Value) {
3957+
let status = match serde_json::from_value::<PhysicalDiskAdoptionStatus>(
3958+
details.clone(),
3959+
) {
3960+
Ok(status) => status,
3961+
Err(error) => {
3962+
eprintln!(
3963+
"warning: failed to interpret task details: {:?}: {:#?}",
3964+
error, details
3965+
);
3966+
return;
3967+
}
3968+
};
3969+
println!("physical disks added: {}", status.disks_added);
3970+
for error in status.errors {
3971+
println!("{ERRICON} {error}");
3972+
}
3973+
}
3974+
39523975
const ERRICON: &str = "/!\\";
39533976

39543977
fn warn_if_nonzero(n: usize) -> &'static str {

dev-tools/omdb/tests/successes.out

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,8 @@ task: "physical_disk_adoption"
852852
configured period: every <REDACTED_DURATION>s
853853
last completed activation: <REDACTED ITERATIONS>, triggered by <TRIGGERED_BY_REDACTED>
854854
started at <REDACTED_TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
855-
last completion reported error: task disabled
855+
physical disks added: 0
856+
/!\ task disabled
856857

857858
task: "probe_distributor"
858859
configured period: every <REDACTED_DURATION>m
@@ -1534,7 +1535,8 @@ task: "physical_disk_adoption"
15341535
configured period: every <REDACTED_DURATION>s
15351536
last completed activation: <REDACTED ITERATIONS>, triggered by <TRIGGERED_BY_REDACTED>
15361537
started at <REDACTED_TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
1537-
last completion reported error: task disabled
1538+
physical disks added: 0
1539+
/!\ task disabled
15381540

15391541
task: "probe_distributor"
15401542
configured period: every <REDACTED_DURATION>m

nexus/db-model/src/physical_disk.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ use super::{
66
Generation, PhysicalDiskKind, PhysicalDiskPolicy, PhysicalDiskState,
77
};
88
use crate::DbTypedUuid;
9+
use crate::InvPhysicalDisk;
910
use crate::collection::DatastoreCollectionConfig;
1011
use chrono::{DateTime, Utc};
1112
use db_macros::Asset;
1213
use nexus_db_schema::schema::{physical_disk, zpool};
1314
use nexus_types::external_api::physical_disk as physical_disk_types;
15+
use nexus_types::external_api::physical_disk::PhysicalDiskManufacturerIdentity;
1416
use nexus_types::identity::Asset;
17+
use omicron_uuid_kinds::PhysicalDiskAdoptionRequestKind;
1518
use omicron_uuid_kinds::PhysicalDiskKind as PhysicalDiskUuidKind;
1619
use omicron_uuid_kinds::PhysicalDiskUuid;
1720
use omicron_uuid_kinds::SledKind;
@@ -38,8 +41,20 @@ pub struct PhysicalDisk {
3841
}
3942

4043
impl PhysicalDisk {
41-
/// Creates a new in-service, active disk
42-
pub fn new(
44+
/// Creates a new in-service, active disk from an inventory disk
45+
pub fn new(inv_disk: InvPhysicalDisk) -> Self {
46+
Self::from_parts(
47+
PhysicalDiskUuid::new_v4(),
48+
inv_disk.vendor,
49+
inv_disk.serial,
50+
inv_disk.model,
51+
inv_disk.variant,
52+
inv_disk.sled_id.into(),
53+
)
54+
}
55+
56+
/// Creates a new in-service, active disk from individual fields
57+
pub fn from_parts(
4358
id: PhysicalDiskUuid,
4459
vendor: String,
4560
serial: String,
@@ -74,6 +89,14 @@ impl PhysicalDisk {
7489
}
7590
}
7691

92+
impl From<PhysicalDisk>
93+
for physical_disk_types::PhysicalDiskManufacturerIdentity
94+
{
95+
fn from(value: PhysicalDisk) -> Self {
96+
Self { vendor: value.vendor, serial: value.serial, model: value.model }
97+
}
98+
}
99+
77100
impl From<PhysicalDisk> for physical_disk_types::PhysicalDisk {
78101
fn from(disk: PhysicalDisk) -> Self {
79102
Self {
@@ -89,6 +112,34 @@ impl From<PhysicalDisk> for physical_disk_types::PhysicalDisk {
89112
}
90113
}
91114

115+
/// A request to adopt a physical disk into the control plane.
116+
#[derive(Queryable, Insertable, Debug, Clone, Selectable)]
117+
#[diesel(table_name = nexus_db_schema::schema::physical_disk_adoption_request)]
118+
pub struct PhysicalDiskAdoptionRequest {
119+
pub id: DbTypedUuid<PhysicalDiskAdoptionRequestKind>,
120+
pub vendor: String,
121+
pub serial: String,
122+
pub model: String,
123+
pub time_created: DateTime<Utc>,
124+
pub time_deleted: Option<DateTime<Utc>>,
125+
}
126+
127+
impl From<PhysicalDiskAdoptionRequest>
128+
for physical_disk_types::PhysicalDiskAdoptionRequest
129+
{
130+
fn from(req: PhysicalDiskAdoptionRequest) -> Self {
131+
Self {
132+
id: req.id.into(),
133+
disk_id: PhysicalDiskManufacturerIdentity {
134+
vendor: req.vendor,
135+
serial: req.serial,
136+
model: req.model,
137+
},
138+
time_created: req.time_created,
139+
}
140+
}
141+
}
142+
92143
impl DatastoreCollectionConfig<super::Zpool> for PhysicalDisk {
93144
type CollectionId = DbTypedUuid<PhysicalDiskUuidKind>;
94145
type GenerationNumberColumn = physical_disk::dsl::rcgen;

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(256, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(257, 0, 0);
2020

2121
/// List of all past database schema versions, in *reverse* order
2222
///
@@ -28,6 +28,7 @@ pub 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(257, "add-disk-adoption-requests"),
3132
KnownVersion::new(256, "bgp-unnumbered-peer-cleanup"),
3233
KnownVersion::new(255, "blueprint-add-external-networking-generation"),
3334
KnownVersion::new(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ mod test {
10131013
kind: PhysicalDiskKind,
10141014
serial: String,
10151015
) -> PhysicalDiskUuid {
1016-
let physical_disk = PhysicalDisk::new(
1016+
let physical_disk = PhysicalDisk::from_parts(
10171017
PhysicalDiskUuid::new_v4(),
10181018
TEST_VENDOR.into(),
10191019
serial,

0 commit comments

Comments
 (0)