Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 'disabling' physical disks to prevent future allocations #3526

Closed
wants to merge 13 commits into from
Closed
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ tufaceous-lib = { path = "tufaceous-lib" }
unicode-width = "0.1.11"
update-engine = { path = "update-engine" }
usdt = "0.3"
uuid = { version = "1.6.1", features = ["serde", "v4"] }
uuid = { version = "1.6.1", features = ["serde", "v4", "v5"] }
walkdir = "2.4"
wicket = { path = "wicket" }
wicket-common = { path = "wicket-common" }
Expand Down
13 changes: 13 additions & 0 deletions nexus/db-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ extern crate diesel;
#[macro_use]
extern crate newtype_derive;

use uuid::Uuid;

mod address_lot;
mod bgp;
mod block_size;
Expand Down Expand Up @@ -44,6 +46,7 @@ mod network_interface;
mod oximeter_info;
mod physical_disk;
mod physical_disk_kind;
mod physical_disk_state;
mod producer_endpoint;
mod project;
mod semver_version;
Expand Down Expand Up @@ -139,6 +142,7 @@ pub use network_interface::*;
pub use oximeter_info::*;
pub use physical_disk::*;
pub use physical_disk_kind::*;
pub use physical_disk_state::*;
pub use producer_endpoint::*;
pub use project::*;
pub use quota::*;
Expand Down Expand Up @@ -305,6 +309,15 @@ macro_rules! impl_enum_type {

pub(crate) use impl_enum_type;

/// This is an arbitrary UUID, but it's stable because it's embedded as a
/// constant. This defines a namespace, according to
/// <https://www.rfc-editor.org/rfc/rfc4122>, which allows generation of v5
/// UUIDs which are deterministic.
///
/// This UUID is used to identify hardware.
pub(crate) const HARDWARE_UUID_NAMESPACE: Uuid =
Uuid::from_u128(206230429496795504636731999500138461979);

/// Describes a type that's represented in the database using a String
///
/// If you're reaching for this type, consider whether it'd be better to use an
Expand Down
23 changes: 21 additions & 2 deletions nexus/db-model/src/physical_disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use super::{Generation, PhysicalDiskKind};
use super::{Generation, PhysicalDiskKind, PhysicalDiskState};
use crate::collection::DatastoreCollectionConfig;
use crate::schema::{physical_disk, zpool};
use chrono::{DateTime, Utc};
Expand All @@ -25,6 +25,7 @@ pub struct PhysicalDisk {

pub variant: PhysicalDiskKind,
pub sled_id: Uuid,
pub state: PhysicalDiskState,
}

impl PhysicalDisk {
Expand All @@ -35,15 +36,32 @@ impl PhysicalDisk {
variant: PhysicalDiskKind,
sled_id: Uuid,
) -> Self {
// NOTE: We may want to be more restrictive when parsing the vendor,
// serial, and model values, so that we can supply a separator
// distinguishing them.
//
// Theoretically, we could have the following problem:
//
// - A Disk vendor "Foo" makes a disk with serial "Bar", and model "Rev1".
// - This becomes: "FooBarRev1".
// - A Disk vendor "FooBar" makes a disk with serial "Rev", and model "1".
// - This becomes: "FooBarRev1", and conflicts.
let interpolated_name = format!("{vendor}{serial}{model}");
let disk_id = Uuid::new_v5(
&crate::HARDWARE_UUID_NAMESPACE,
interpolated_name.as_bytes(),
);
println!("Physical Disk ID: {disk_id}, from {interpolated_name}");
Self {
identity: PhysicalDiskIdentity::new(Uuid::new_v4()),
identity: PhysicalDiskIdentity::new(disk_id),
time_deleted: None,
rcgen: Generation::new(),
vendor,
serial,
model,
variant,
sled_id,
state: PhysicalDiskState::Active,
}
}

Expand Down Expand Up @@ -74,6 +92,7 @@ impl From<PhysicalDisk> for views::PhysicalDisk {
vendor: disk.vendor,
serial: disk.serial,
model: disk.model,
state: disk.state.into(),
form_factor: disk.variant.into(),
}
}
Expand Down
34 changes: 34 additions & 0 deletions nexus/db-model/src/physical_disk_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use super::impl_enum_type;
use nexus_types::external_api::views;
use serde::{Deserialize, Serialize};

impl_enum_type!(
#[derive(Clone, SqlType, Debug, QueryId)]
#[diesel(postgres_type(name = "physical_disk_state"))]
pub struct PhysicalDiskStateEnum;

#[derive(Clone, Copy, Debug, AsExpression, FromSqlRow, Serialize, Deserialize, PartialEq)]
#[diesel(sql_type = PhysicalDiskStateEnum)]
pub enum PhysicalDiskState;

// Enum values
Active => b"active"
Draining => b"draining"
Inactive => b"inactive"
);

impl From<PhysicalDiskState> for views::PhysicalDiskState {
fn from(state: PhysicalDiskState) -> Self {
use views::PhysicalDiskState as api;
use PhysicalDiskState as db;
match state {
db::Active => api::Active,
db::Draining => api::Draining,
db::Inactive => api::Inactive,
}
}
}
5 changes: 3 additions & 2 deletions nexus/db-model/src/queries/region_allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
// a CTE (where we want the alias name to come first).

use crate::schema::dataset;
use crate::schema::physical_disk;
use crate::schema::sled;
use crate::schema::zpool;

Expand Down Expand Up @@ -151,7 +152,9 @@ diesel::allow_tables_to_appear_in_same_query!(
diesel::allow_tables_to_appear_in_same_query!(
do_insert,
candidate_regions,
candidate_zpools,
dataset,
physical_disk,
zpool,
);

Expand All @@ -170,8 +173,6 @@ diesel::allow_tables_to_appear_in_same_query!(
updated_datasets,
);

diesel::allow_tables_to_appear_in_same_query!(candidate_zpools, dataset,);
diesel::allow_tables_to_appear_in_same_query!(candidate_zpools, zpool,);
diesel::allow_tables_to_appear_in_same_query!(candidate_datasets, dataset);

// == Needed for random region allocation ==
Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use omicron_common::api::external::SemverVersion;
///
/// This should be updated whenever the schema is changed. For more details,
/// refer to: schema/crdb/README.adoc
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(21, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(22, 0, 0);

table! {
disk (id) {
Expand Down Expand Up @@ -862,6 +862,7 @@ table! {

variant -> crate::PhysicalDiskKindEnum,
sled_id -> Uuid,
state -> crate::PhysicalDiskStateEnum,
}
}

Expand Down
Loading
Loading