From 0cd0f4b29315a5465cb09cbdfe0592516c49df1a Mon Sep 17 00:00:00 2001 From: Alan Hanson Date: Thu, 10 Aug 2023 17:24:46 +0000 Subject: [PATCH] Update crucible with new Volume and VCR related changes New crucible, which has updated Volume structure with Logger field. New VolumeConstructionRequest format which has sub-structures for all the fields. This also adds support for the VCR replacement, which can be used to replace a downstairs as well as validate a VCR for migration. --- Cargo.lock | 8 +-- Cargo.toml | 5 +- bin/propolis-server/src/lib/initializer.rs | 28 ++++++---- bin/propolis-server/src/lib/spec.rs | 22 ++++---- lib/propolis-client/src/handmade/api.rs | 4 +- .../src/instance_spec/openapi_impls.rs | 18 +++--- lib/propolis/src/block/crucible.rs | 5 +- phd-tests/framework/src/disk/crucible.rs | 56 ++++++++++--------- 8 files changed, 80 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53d65c443..5b69a5b5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -674,7 +674,7 @@ dependencies = [ [[package]] name = "crucible" version = "0.0.1" -source = "git+https://github.com/oxidecomputer/crucible?rev=84507ed89aced20920de73342666a8abcb8237c1#84507ed89aced20920de73342666a8abcb8237c1" +source = "git+https://github.com/oxidecomputer/crucible?rev=b5949e169277d657e32fdfb95d5affb2cb497e86#b5949e169277d657e32fdfb95d5affb2cb497e86" dependencies = [ "aes-gcm-siv", "anyhow", @@ -717,7 +717,7 @@ dependencies = [ [[package]] name = "crucible-client-types" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/crucible?rev=84507ed89aced20920de73342666a8abcb8237c1#84507ed89aced20920de73342666a8abcb8237c1" +source = "git+https://github.com/oxidecomputer/crucible?rev=b5949e169277d657e32fdfb95d5affb2cb497e86#b5949e169277d657e32fdfb95d5affb2cb497e86" dependencies = [ "base64 0.21.2", "schemars", @@ -729,7 +729,7 @@ dependencies = [ [[package]] name = "crucible-common" version = "0.0.1" -source = "git+https://github.com/oxidecomputer/crucible?rev=84507ed89aced20920de73342666a8abcb8237c1#84507ed89aced20920de73342666a8abcb8237c1" +source = "git+https://github.com/oxidecomputer/crucible?rev=b5949e169277d657e32fdfb95d5affb2cb497e86#b5949e169277d657e32fdfb95d5affb2cb497e86" dependencies = [ "anyhow", "atty", @@ -756,7 +756,7 @@ dependencies = [ [[package]] name = "crucible-protocol" version = "0.0.0" -source = "git+https://github.com/oxidecomputer/crucible?rev=84507ed89aced20920de73342666a8abcb8237c1#84507ed89aced20920de73342666a8abcb8237c1" +source = "git+https://github.com/oxidecomputer/crucible?rev=b5949e169277d657e32fdfb95d5affb2cb497e86#b5949e169277d657e32fdfb95d5affb2cb497e86" dependencies = [ "anyhow", "bincode", diff --git a/Cargo.toml b/Cargo.toml index b7de4a827..f90e14b93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,8 +92,8 @@ chrono = "0.4.19" clap = "4.2" const_format = "0.2" crossbeam-channel = "0.5" -crucible = { git = "https://github.com/oxidecomputer/crucible", rev = "84507ed89aced20920de73342666a8abcb8237c1" } -crucible-client-types = { git = "https://github.com/oxidecomputer/crucible", rev = "84507ed89aced20920de73342666a8abcb8237c1" } +crucible = { git = "https://github.com/oxidecomputer/crucible", rev = "b5949e169277d657e32fdfb95d5affb2cb497e86" } +crucible-client-types = { git = "https://github.com/oxidecomputer/crucible", rev = "b5949e169277d657e32fdfb95d5affb2cb497e86" } ctrlc = "3.2" dropshot = { git = "https://github.com/oxidecomputer/dropshot", branch = "main" } enum-iterator = "1.4.1" @@ -143,4 +143,3 @@ tracing-subscriber = "0.3.14" usdt = { version = "0.3.5", default-features = false } uuid = "1.3.2" vte = "0.10.1" - diff --git a/bin/propolis-server/src/lib/initializer.rs b/bin/propolis-server/src/lib/initializer.rs index cc5dc2fd5..f0cd1727a 100644 --- a/bin/propolis-server/src/lib/initializer.rs +++ b/bin/propolis-server/src/lib/initializer.rs @@ -25,6 +25,7 @@ use propolis::hw::{nvme, virtio}; use propolis::instance::Instance; use propolis::inventory::{self, EntityID, Inventory}; use propolis::vmm::{self, Builder, Machine}; +use propolis_client::handmade::api::{VcrFile, VcrRegion, VcrUrl, VcrVolume}; use propolis_client::instance_spec::{self, *}; use slog::info; @@ -312,18 +313,21 @@ impl<'a> MachineInitializer<'a> { "Creating Crucible disk from request {:?}", req ); let cru_id = match req { - VolumeConstructionRequest::Volume { - id, .. - } => id.to_string(), - VolumeConstructionRequest::File { id, .. } => { - id.to_string() - } - VolumeConstructionRequest::Url { id, .. } => { - id.to_string() - } - VolumeConstructionRequest::Region { .. } => { - "Region".to_string() - } + VolumeConstructionRequest::Volume(VcrVolume { + id, + .. + }) => id.to_string(), + VolumeConstructionRequest::File(VcrFile { + id, + .. + }) => id.to_string(), + VolumeConstructionRequest::Url(VcrUrl { + id, + .. + }) => id.to_string(), + VolumeConstructionRequest::Region(VcrRegion { + .. + }) => "Region".to_string(), }; let be = propolis::block::CrucibleBackend::create( req.clone(), diff --git a/bin/propolis-server/src/lib/spec.rs b/bin/propolis-server/src/lib/spec.rs index 34b3cabb1..b38ebb10b 100644 --- a/bin/propolis-server/src/lib/spec.rs +++ b/bin/propolis-server/src/lib/spec.rs @@ -538,7 +538,7 @@ impl ServerSpecBuilder { mod test { use std::{collections::BTreeMap, path::PathBuf}; - use propolis_client::handmade::api::Slot; + use propolis_client::handmade::api::{Slot, VcrFile}; use uuid::Uuid; use crate::config::{self, Config}; @@ -583,11 +583,13 @@ mod test { slot: Slot(0), read_only: true, device: "nvme".to_string(), - volume_construction_request: VolumeConstructionRequest::File { - id: Uuid::new_v4(), - block_size: 512, - path: "disk1.img".to_string() - }, + volume_construction_request: VolumeConstructionRequest::File( + VcrFile { + id: Uuid::new_v4(), + block_size: 512, + path: "disk1.img".to_string() + } + ), }) .is_ok()); assert!(matches!( @@ -598,11 +600,11 @@ mod test { read_only: true, device: "virtio".to_string(), volume_construction_request: - VolumeConstructionRequest::File { + VolumeConstructionRequest::File(VcrFile { id: Uuid::new_v4(), block_size: 512, path: "disk2.img".to_string() - }, + }), }) .err(), Some(ServerSpecBuilderError::InnerBuilderError( @@ -637,11 +639,11 @@ mod test { read_only: true, device: "virtio-scsi".to_string(), volume_construction_request: - VolumeConstructionRequest::File { + VolumeConstructionRequest::File(VcrFile { id: Uuid::new_v4(), block_size: 512, path: "disk3.img".to_string() - }, + }), }) .err(), Some(ServerSpecBuilderError::UnrecognizedStorageDevice(_)) diff --git a/lib/propolis-client/src/handmade/api.rs b/lib/propolis-client/src/handmade/api.rs index 3bf1a47c3..6752acc02 100644 --- a/lib/propolis-client/src/handmade/api.rs +++ b/lib/propolis-client/src/handmade/api.rs @@ -16,7 +16,9 @@ use std::net::SocketAddr; use uuid::Uuid; // Re-export types that are of a public struct -pub use crucible_client_types::VolumeConstructionRequest; +pub use crucible_client_types::{ + VcrFile, VcrRegion, VcrUrl, VcrVolume, VolumeConstructionRequest, +}; #[derive(Clone, Deserialize, Serialize, JsonSchema)] pub struct InstanceNameParams { diff --git a/lib/propolis-client/src/instance_spec/openapi_impls.rs b/lib/propolis-client/src/instance_spec/openapi_impls.rs index fba913842..1769bc091 100644 --- a/lib/propolis-client/src/instance_spec/openapi_impls.rs +++ b/lib/propolis-client/src/instance_spec/openapi_impls.rs @@ -184,39 +184,40 @@ impl From for api::PciPath { use crate::types::VolumeConstructionRequest as GenVCR; use crucible_client_types::VolumeConstructionRequest as CrucibleVCR; +use crucible_client_types::{VcrFile, VcrRegion, VcrUrl, VcrVolume}; impl From for GenVCR { fn from(vcr: CrucibleVCR) -> Self { match vcr { - CrucibleVCR::Volume { + CrucibleVCR::Volume(VcrVolume { id, block_size, sub_volumes, read_only_parent, - } => GenVCR::Volume { + }) => GenVCR::Volume { id, block_size, sub_volumes: sub_volumes.into_iter().map(Into::into).collect(), read_only_parent: read_only_parent .map(|rop| Box::new((*rop).into())), }, - CrucibleVCR::Url { id, block_size, url } => { + CrucibleVCR::Url(VcrUrl { id, block_size, url }) => { GenVCR::Url { id, block_size, url } } - CrucibleVCR::Region { + CrucibleVCR::Region(VcrRegion { block_size, blocks_per_extent, extent_count, opts, gen, - } => GenVCR::Region { + }) => GenVCR::Region { block_size, blocks_per_extent, extent_count, opts: opts.into(), gen, }, - CrucibleVCR::File { id, block_size, path } => { + CrucibleVCR::File(VcrFile { id, block_size, path }) => { GenVCR::File { id, block_size, path } } } @@ -255,6 +256,7 @@ impl From for crate::types::CrucibleOpts { #[cfg(test)] mod tests { use super::*; + use crucible_client_types::VcrRegion; #[test] fn device_specs_are_convertible() { @@ -270,7 +272,7 @@ mod tests { "disk1_be".to_string(), StorageBackend { kind: StorageBackendKind::Crucible { - req: VolumeConstructionRequest::Region { + req: VolumeConstructionRequest::Region(VcrRegion { block_size: 512, blocks_per_extent: 20, extent_count: 40, @@ -287,7 +289,7 @@ mod tests { read_only: true, }, gen: 1, - }, + }), }, readonly: true, }, diff --git a/lib/propolis/src/block/crucible.rs b/lib/propolis/src/block/crucible.rs index 3623d5a54..f19e1a1d9 100644 --- a/lib/propolis/src/block/crucible.rs +++ b/lib/propolis/src/block/crucible.rs @@ -62,8 +62,7 @@ impl CrucibleBackend { ) -> Result, crucible::CrucibleError> { // Construct the volume. let volume = - Volume::construct(request, producer_registry, Some(log.clone())) - .await?; + Volume::construct(request, producer_registry, log.clone()).await?; // Decide if we need to scrub this volume or not. if volume.has_read_only_parent() { @@ -72,7 +71,7 @@ impl CrucibleBackend { let volume_id = vclone.get_uuid().await.unwrap(); // This does the actual scrub. - match vclone.scrub(&log, Some(120), Some(25)).await { + match vclone.scrub(Some(120), Some(25)).await { Ok(()) => { if let Some(nexus_client) = nexus_client { info!( diff --git a/phd-tests/framework/src/disk/crucible.rs b/phd-tests/framework/src/disk/crucible.rs index ed878d2e7..ade9d93d8 100644 --- a/phd-tests/framework/src/disk/crucible.rs +++ b/phd-tests/framework/src/disk/crucible.rs @@ -11,7 +11,9 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; -use crucible_client_types::{CrucibleOpts, VolumeConstructionRequest}; +use crucible_client_types::{ + CrucibleOpts, VcrFile, VcrRegion, VcrVolume, VolumeConstructionRequest, +}; use rand::{rngs::StdRng, RngCore, SeedableRng}; use tracing::{error, info}; use uuid::Uuid; @@ -240,37 +242,41 @@ impl super::DiskConfig for CrucibleDisk { propolis_client::instance_spec::StorageBackend { kind: propolis_client::instance_spec::StorageBackendKind::Crucible { - req: VolumeConstructionRequest::Volume { + req: VolumeConstructionRequest::Volume(VcrVolume { id: self.id, block_size: self.block_size.bytes(), - sub_volumes: vec![VolumeConstructionRequest::Region { - block_size: self.block_size.bytes(), - blocks_per_extent: self.blocks_per_extent, - extent_count: self.extent_count, - opts: CrucibleOpts { - id: Uuid::new_v4(), - target: downstairs_addrs, - lossy: false, - flush_timeout: None, - key: Some(self.encryption_key.clone()), - cert_pem: None, - key_pem: None, - root_cert_pem: None, - control: None, - read_only: false, + sub_volumes: vec![VolumeConstructionRequest::Region( + VcrRegion { + block_size: self.block_size.bytes(), + blocks_per_extent: self.blocks_per_extent, + extent_count: self.extent_count, + opts: CrucibleOpts { + id: Uuid::new_v4(), + target: downstairs_addrs, + lossy: false, + flush_timeout: None, + key: Some(self.encryption_key.clone()), + cert_pem: None, + key_pem: None, + root_cert_pem: None, + control: None, + read_only: false, + }, + gen, }, - gen, - }], + )], read_only_parent: self.read_only_parent.as_ref().map( |p| { - Box::new(VolumeConstructionRequest::File { - id: Uuid::new_v4(), - block_size: self.block_size.bytes(), - path: p.to_string_lossy().to_string(), - }) + Box::new(VolumeConstructionRequest::File( + VcrFile { + id: Uuid::new_v4(), + block_size: self.block_size.bytes(), + path: p.to_string_lossy().to_string(), + }, + )) }, ), - }, + }), }, readonly: false, }