Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions clients/sled-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ progenitor::generate_api!(
DatasetsConfig = omicron_common::disk::DatasetsConfig,
DatasetKind = omicron_common::api::internal::shared::DatasetKind,
DiskIdentity = omicron_common::disk::DiskIdentity,
DiskManagementStatus = omicron_common::disk::DiskManagementStatus,
DiskManagementError = omicron_common::disk::DiskManagementError,
DiskVariant = omicron_common::disk::DiskVariant,
Epoch = trust_quorum_types::types::Epoch,
ExternalIpGatewayMap = omicron_common::api::internal::shared::ExternalIpGatewayMap,
Expand Down
77 changes: 0 additions & 77 deletions common/src/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,83 +430,6 @@ impl From<ZpoolKind> for DiskVariant {
}
}

/// Identifies how a single disk management operation may have succeeded or
/// failed.
#[derive(Clone, Debug, JsonSchema, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct DiskManagementStatus {
pub identity: DiskIdentity,
pub err: Option<DiskManagementError>,
}

/// The result from attempting to manage underlying disks.
///
/// This is more complex than a simple "Error" type because it's possible
/// for some disks to be initialized correctly, while others can fail.
///
/// This structure provides a mechanism for callers to learn about partial
/// failures, and handle them appropriately on a per-disk basis.
#[derive(Default, Debug, JsonSchema, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[must_use = "this `DiskManagementResult` may contain errors, which should be handled"]
pub struct DisksManagementResult {
pub status: Vec<DiskManagementStatus>,
}

impl DisksManagementResult {
pub fn has_error(&self) -> bool {
for status in &self.status {
if status.err.is_some() {
return true;
}
}
false
}

pub fn has_retryable_error(&self) -> bool {
for status in &self.status {
if let Some(err) = &status.err {
if err.retryable() {
return true;
}
}
}
false
}
}

#[derive(
Clone, Debug, thiserror::Error, JsonSchema, Serialize, Deserialize,
)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum DiskManagementError {
#[error("Disk requested by control plane, but not found on device")]
NotFound,

#[error("Disk requested by control plane is an internal disk: {0}")]
InternalDiskControlPlaneRequest(PhysicalDiskUuid),

#[error("Expected zpool UUID of {expected}, but saw {observed}")]
ZpoolUuidMismatch { expected: ZpoolUuid, observed: ZpoolUuid },

#[error(
"Failed to access keys necessary to unlock storage. This error may be transient."
)]
KeyManager(String),

#[error("Other error starting disk management: {0}")]
Other(String),
}

impl DiskManagementError {
pub fn retryable(&self) -> bool {
match self {
DiskManagementError::KeyManager(_) => true,
_ => false,
}
}
}

/// Describes an M.2 slot, often in the context of writing a system image to
/// it.
#[derive(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use illumos_utils::zpool::Zpool;
use illumos_utils::zpool::ZpoolName;
use key_manager::StorageKeyRequester;
use omicron_common::api::external::ByteCount;
use omicron_common::disk::DiskManagementError;
use omicron_common::disk::DiskVariant;
use omicron_common::disk::OmicronPhysicalDiskConfig;
use omicron_uuid_kinds::PhysicalDiskUuid;
Expand Down Expand Up @@ -56,6 +55,39 @@ use crate::disks_common::update_properties_from_raw_disk;
use camino::Utf8PathBuf;
use illumos_utils::zfs::Mountpoint;

#[derive(Debug, thiserror::Error)]
enum DiskManagementError {
#[error("Disk requested by control plane, but not found on device")]
NotFound,

#[error("Disk requested by control plane is an internal disk: {0}")]
InternalDiskControlPlaneRequest(PhysicalDiskUuid),

#[error("Expected zpool UUID of {expected}, but saw {observed}")]
ZpoolUuidMismatch { expected: ZpoolUuid, observed: ZpoolUuid },

#[error(
"Failed to access keys necessary to unlock storage. \
This error may be transient."
)]
KeyManager(String),

#[error("Other error starting disk management: {0}")]
Other(String),
}

impl DiskManagementError {
fn retryable(&self) -> bool {
match self {
Self::KeyManager(_) => true,
Self::NotFound
| Self::InternalDiskControlPlaneRequest(_)
| Self::ZpoolUuidMismatch { .. }
| Self::Other(_) => false,
}
}
}

/// Set of currently managed zpools.
///
/// This handle should only be used to decide to _stop_ using a zpool (e.g., if
Expand Down
Loading