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
14 changes: 10 additions & 4 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"pantry-api",
"pantry-client",
"pantry-types",
"pantry-types/versions",
"protocol",
"repair-client",
"smf",
Expand Down Expand Up @@ -157,6 +158,7 @@ crucible-pantry = { path = "./pantry" }
crucible-pantry-api = { path = "./pantry-api" }
crucible-pantry-client = { path = "./pantry-client" }
crucible-pantry-types = { path = "./pantry-types" }
crucible-pantry-types-versions = { path = "./pantry-types/versions" }
crucible-protocol = { path = "./protocol" }
crucible-raw-extent = { path = "./raw-extent" }
crucible-verify-raw = { path = "./verify-raw" }
Expand Down
5 changes: 1 addition & 4 deletions pantry-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ edition = "2024"
license = "MPL-2.0"

[dependencies]
crucible-client-types.workspace = true
crucible-pantry-types.workspace = true
crucible-pantry-types-versions.workspace = true
crucible-workspace-hack.workspace = true
dropshot.workspace = true
dropshot-api-manager-types.workspace = true
schemars.workspace = true
serde.workspace = true
162 changes: 33 additions & 129 deletions pantry-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use crucible_client_types::{ReplaceResult, VolumeConstructionRequest};
use crucible_pantry_types::*;
use crucible_pantry_types_versions::latest;
use dropshot::{
HttpError, HttpResponseDeleted, HttpResponseOk,
HttpResponseUpdatedNoContent, Path, RequestContext, TypedBody,
};
use dropshot_api_manager_types::api_versions;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

api_versions!([
// WHEN CHANGING THE API (part 1 of 2):
Expand Down Expand Up @@ -48,7 +45,7 @@ pub trait CruciblePantryApi {
}]
async fn pantry_status(
rqctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<PantryStatus>, HttpError>;
) -> Result<HttpResponseOk<latest::pantry::PantryStatus>, HttpError>;

/// Get a current Volume's status
#[endpoint {
Expand All @@ -57,8 +54,8 @@ pub trait CruciblePantryApi {
}]
async fn volume_status(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
) -> Result<HttpResponseOk<VolumeStatus>, HttpError>;
path: Path<latest::pantry::VolumePath>,
) -> Result<HttpResponseOk<latest::pantry::VolumeStatus>, HttpError>;

/// Construct a volume from a VolumeConstructionRequest, storing the result in
/// the Pantry.
Expand All @@ -68,9 +65,9 @@ pub trait CruciblePantryApi {
}]
async fn attach(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<AttachRequest>,
) -> Result<HttpResponseOk<AttachResult>, HttpError>;
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::AttachRequest>,
) -> Result<HttpResponseOk<latest::pantry::AttachResult>, HttpError>;

/// Construct a volume from a VolumeConstructionRequest, storing the result in
/// the Pantry. Activate in a separate job so as not to block the request.
Expand All @@ -80,8 +77,8 @@ pub trait CruciblePantryApi {
}]
async fn attach_activate_background(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<AttachBackgroundRequest>,
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::AttachBackgroundRequest>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// Call a volume's target_replace function
Expand All @@ -91,9 +88,9 @@ pub trait CruciblePantryApi {
}]
async fn replace(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<ReplaceRequest>,
) -> Result<HttpResponseOk<ReplaceResult>, HttpError>;
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::ReplaceRequest>,
) -> Result<HttpResponseOk<latest::pantry::ReplaceResult>, HttpError>;

/// Poll to see if a Pantry background job is done
#[endpoint {
Expand All @@ -102,8 +99,8 @@ pub trait CruciblePantryApi {
}]
async fn is_job_finished(
rqctx: RequestContext<Self::Context>,
path: Path<JobPath>,
) -> Result<HttpResponseOk<JobPollResponse>, HttpError>;
path: Path<latest::pantry::JobPath>,
) -> Result<HttpResponseOk<latest::pantry::JobPollResponse>, HttpError>;

/// Block on returning a Pantry background job result, then return 200 OK if the
/// job executed OK, 500 otherwise.
Expand All @@ -113,8 +110,8 @@ pub trait CruciblePantryApi {
}]
async fn job_result_ok(
rqctx: RequestContext<Self::Context>,
path: Path<JobPath>,
) -> Result<HttpResponseOk<JobResultOkResponse>, HttpError>;
path: Path<latest::pantry::JobPath>,
) -> Result<HttpResponseOk<latest::pantry::JobResultOkResponse>, HttpError>;

/// Import data from a URL into a volume
#[endpoint {
Expand All @@ -123,9 +120,9 @@ pub trait CruciblePantryApi {
}]
async fn import_from_url(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<ImportFromUrlRequest>,
) -> Result<HttpResponseOk<ImportFromUrlResponse>, HttpError>;
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::ImportFromUrlRequest>,
) -> Result<HttpResponseOk<latest::pantry::ImportFromUrlResponse>, HttpError>;

/// Take a snapshot of a volume
#[endpoint {
Expand All @@ -134,8 +131,8 @@ pub trait CruciblePantryApi {
}]
async fn snapshot(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<SnapshotRequest>,
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::SnapshotRequest>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// Bulk write data into a volume at a specified offset
Expand All @@ -145,8 +142,8 @@ pub trait CruciblePantryApi {
}]
async fn bulk_write(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<BulkWriteRequest>,
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::BulkWriteRequest>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// Bulk read data from a volume at a specified offset
Expand All @@ -156,9 +153,9 @@ pub trait CruciblePantryApi {
}]
async fn bulk_read(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<BulkReadRequest>,
) -> Result<HttpResponseOk<BulkReadResponse>, HttpError>;
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::BulkReadRequest>,
) -> Result<HttpResponseOk<latest::pantry::BulkReadResponse>, HttpError>;

/// Scrub the volume (copy blocks from read-only parent to subvolumes)
#[endpoint {
Expand All @@ -167,8 +164,8 @@ pub trait CruciblePantryApi {
}]
async fn scrub(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
) -> Result<HttpResponseOk<ScrubResponse>, HttpError>;
path: Path<latest::pantry::VolumePath>,
) -> Result<HttpResponseOk<latest::pantry::ScrubResponse>, HttpError>;

/// Validate the digest of a whole volume
#[endpoint {
Expand All @@ -177,9 +174,9 @@ pub trait CruciblePantryApi {
}]
async fn validate(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
body: TypedBody<ValidateRequest>,
) -> Result<HttpResponseOk<ValidateResponse>, HttpError>;
path: Path<latest::pantry::VolumePath>,
body: TypedBody<latest::pantry::ValidateRequest>,
) -> Result<HttpResponseOk<latest::pantry::ValidateResponse>, HttpError>;

/// Deactivate a volume, removing it from the Pantry
#[endpoint {
Expand All @@ -188,99 +185,6 @@ pub trait CruciblePantryApi {
}]
async fn detach(
rqctx: RequestContext<Self::Context>,
path: Path<VolumePath>,
path: Path<latest::pantry::VolumePath>,
) -> Result<HttpResponseDeleted, HttpError>;
}

#[derive(Deserialize, JsonSchema)]
pub struct VolumePath {
pub id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct AttachRequest {
pub volume_construction_request: VolumeConstructionRequest,
}

#[derive(Serialize, JsonSchema)]
pub struct AttachResult {
pub id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct AttachBackgroundRequest {
pub volume_construction_request: VolumeConstructionRequest,
pub job_id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct ReplaceRequest {
pub volume_construction_request: VolumeConstructionRequest,
}

#[derive(Deserialize, JsonSchema)]
pub struct JobPath {
pub id: String,
}

#[derive(Serialize, JsonSchema)]
pub struct JobPollResponse {
pub job_is_finished: bool,
}

#[derive(Serialize, JsonSchema)]
pub struct JobResultOkResponse {
pub job_result_ok: bool,
}

#[derive(Deserialize, JsonSchema)]
pub struct ImportFromUrlRequest {
pub url: String,
pub expected_digest: Option<ExpectedDigest>,
}

#[derive(Serialize, JsonSchema)]
pub struct ImportFromUrlResponse {
pub job_id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct SnapshotRequest {
pub snapshot_id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct BulkWriteRequest {
pub offset: u64,
pub base64_encoded_data: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct BulkReadRequest {
pub offset: u64,
pub size: usize,
}

#[derive(Serialize, JsonSchema)]
pub struct BulkReadResponse {
pub base64_encoded_data: String,
}

#[derive(Serialize, JsonSchema)]
pub struct ScrubResponse {
pub job_id: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct ValidateRequest {
pub expected_digest: ExpectedDigest,

// Size to validate in bytes, starting from offset 0. If not specified, the
// total volume size is used.
pub size_to_validate: Option<u64>,
}

#[derive(Serialize, JsonSchema)]
pub struct ValidateResponse {
pub job_id: String,
}
3 changes: 1 addition & 2 deletions pantry-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ edition = "2024"
license = "MPL-2.0"

[dependencies]
crucible-pantry-types-versions.workspace = true
crucible-workspace-hack.workspace = true
schemars.workspace = true
serde.workspace = true
33 changes: 2 additions & 31 deletions pantry-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Serialize, JsonSchema)]
pub struct PantryStatus {
/// Which volumes does this Pantry know about? Note this may include volumes
/// that are no longer active, and haven't been garbage collected yet.
pub volumes: Vec<String>,

/// How many job handles?
pub num_job_handles: usize,
}

#[derive(Serialize, JsonSchema)]
pub struct VolumeStatus {
/// Is the Volume currently active?
pub active: bool,

/// Has the Pantry ever seen this Volume active?
pub seen_active: bool,

/// How many job handles are there for this Volume?
pub num_job_handles: usize,
}

#[derive(Debug, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExpectedDigest {
Sha256(String),
}
pub mod pantry;
3 changes: 3 additions & 0 deletions pantry-types/src/pantry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Copyright 2026 Oxide Computer Company

pub use crucible_pantry_types_versions::latest::pantry::*;
11 changes: 11 additions & 0 deletions pantry-types/versions/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "crucible-pantry-types-versions"
version = "0.1.0"
license = "MPL-2.0"
edition = "2024"

[dependencies]
crucible-client-types.workspace = true
crucible-workspace-hack.workspace = true
schemars.workspace = true
serde.workspace = true
6 changes: 6 additions & 0 deletions pantry-types/versions/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2026 Oxide Computer Company

//! Functional code for the latest versions of types.

// Currently a placeholder. Remove this comment when functional code is added in
// a submodule.
5 changes: 5 additions & 0 deletions pantry-types/versions/src/initial/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright 2026 Oxide Computer Company

//! Version `INITIAL` of the Crucible Pantry API.

pub mod pantry;
Loading