From 924cf0d7ef2511f115459d7b9a9305374db420f1 Mon Sep 17 00:00:00 2001 From: Rain Date: Sun, 14 Apr 2024 19:23:19 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 --- Cargo.lock | 1 + clients/nexus-client/src/lib.rs | 1 + dev-tools/omdb/src/bin/omdb/db.rs | 23 +++++++----- nexus/db-model/src/dataset.rs | 4 ++- nexus/db-model/src/region_snapshot.rs | 5 +-- nexus/db-queries/src/db/datastore/dataset.rs | 19 ++++++---- nexus/db-queries/src/db/datastore/mod.rs | 22 ++++++------ nexus/db-queries/src/db/datastore/region.rs | 6 ++-- .../src/db/datastore/region_snapshot.rs | 10 +++--- nexus/db-queries/src/db/pagination.rs | 35 +++++++++++++++++-- .../reconfigurator/execution/src/datasets.rs | 4 ++- nexus/src/app/sagas/snapshot_create.rs | 2 +- nexus/src/app/sagas/volume_delete.rs | 2 +- nexus/src/app/sled.rs | 3 +- nexus/src/lib.rs | 3 +- nexus/test-interface/Cargo.toml | 1 + nexus/test-interface/src/lib.rs | 3 +- nexus/test-utils/src/lib.rs | 18 +++++----- nexus/test-utils/src/resource_helpers.rs | 7 ++-- nexus/tests/integration_tests/snapshots.rs | 3 +- nexus/tests/integration_tests/unauthorized.rs | 3 +- .../integration_tests/volume_management.rs | 4 +-- nexus/types/src/internal_api/params.rs | 3 +- openapi/nexus-internal.json | 7 ++-- sled-agent/src/rack_setup/service.rs | 5 +-- sled-agent/src/sim/server.rs | 7 ++-- sled-agent/src/sim/sled_agent.rs | 8 ++--- sled-agent/src/sim/storage.rs | 10 +++--- 28 files changed, 142 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2fc2b0ff6..8c10f9cc11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4827,6 +4827,7 @@ dependencies = [ "nexus-config", "nexus-types", "omicron-common", + "omicron-uuid-kinds", "omicron-workspace-hack", "slog", "uuid 1.8.0", diff --git a/clients/nexus-client/src/lib.rs b/clients/nexus-client/src/lib.rs index e083f5372e..c27f31da40 100644 --- a/clients/nexus-client/src/lib.rs +++ b/clients/nexus-client/src/lib.rs @@ -37,6 +37,7 @@ progenitor::generate_api!( NetworkInterfaceKind = omicron_common::api::internal::shared::NetworkInterfaceKind, TypedUuidForCollectionKind = omicron_uuid_kinds::CollectionUuid, TypedUuidForDownstairsKind = omicron_uuid_kinds::TypedUuid, + TypedUuidForOmicronZoneKind = omicron_uuid_kinds::OmicronZoneUuid, TypedUuidForUpstairsKind = omicron_uuid_kinds::TypedUuid, TypedUuidForUpstairsRepairKind = omicron_uuid_kinds::TypedUuid, TypedUuidForUpstairsSessionKind = omicron_uuid_kinds::TypedUuid, diff --git a/dev-tools/omdb/src/bin/omdb/db.rs b/dev-tools/omdb/src/bin/omdb/db.rs index a08fa9519c..95f334f4ad 100644 --- a/dev-tools/omdb/src/bin/omdb/db.rs +++ b/dev-tools/omdb/src/bin/omdb/db.rs @@ -39,6 +39,7 @@ use diesel::TextExpressionMethods; use gateway_client::types::SpType; use ipnetwork::IpNetwork; use nexus_config::PostgresConfigWithUrl; +use nexus_db_model::to_db_typed_uuid; use nexus_db_model::Dataset; use nexus_db_model::Disk; use nexus_db_model::DnsGroup; @@ -92,6 +93,7 @@ use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceState; use omicron_common::api::external::MacAddr; use omicron_uuid_kinds::CollectionUuid; +use omicron_uuid_kinds::OmicronZoneUuid; use sled_agent_client::types::VolumeConstructionRequest; use std::borrow::Cow; use std::cmp::Ordering; @@ -1144,7 +1146,7 @@ async fn cmd_db_disk_physical( for did in dataset_ids.clone().into_iter() { use db::schema::region::dsl as region_dsl; let regions = region_dsl::region - .filter(region_dsl::dataset_id.eq(did)) + .filter(region_dsl::dataset_id.eq(to_db_typed_uuid(did))) .select(Region::as_select()) .load_async(&*conn) .await @@ -1229,7 +1231,10 @@ async fn cmd_db_disk_physical( let limit = fetch_opts.fetch_limit; use db::schema::region_snapshot::dsl as region_snapshot_dsl; let region_snapshots = region_snapshot_dsl::region_snapshot - .filter(region_snapshot_dsl::dataset_id.eq_any(dataset_ids)) + .filter( + region_snapshot_dsl::dataset_id + .eq_any(dataset_ids.into_iter().map(to_db_typed_uuid)), + ) .limit(i64::from(u32::from(limit))) .select(RegionSnapshot::as_select()) .load_async(&*conn) @@ -2332,7 +2337,7 @@ async fn cmd_db_validate_volume_references( #[derive(Tabled)] struct Row { - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, region_id: Uuid, snapshot_id: Uuid, error: String, @@ -2394,7 +2399,7 @@ async fn cmd_db_validate_volume_references( if matching_volumes != region_snapshot.volume_references as usize { rows.push(Row { - dataset_id: region_snapshot.dataset_id, + dataset_id: region_snapshot.dataset_id.into(), region_id: region_snapshot.region_id, snapshot_id: region_snapshot.snapshot_id, error: format!( @@ -2412,7 +2417,7 @@ async fn cmd_db_validate_volume_references( if matching_volumes == 0 && !region_snapshot.deleting { rows.push(Row { - dataset_id: region_snapshot.dataset_id, + dataset_id: region_snapshot.dataset_id.into(), region_id: region_snapshot.region_id, snapshot_id: region_snapshot.snapshot_id, error: String::from( @@ -2470,7 +2475,7 @@ async fn cmd_db_validate_region_snapshots( #[derive(Tabled)] struct Row { - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, region_id: Uuid, snapshot_id: Uuid, dataset_addr: std::net::SocketAddrV6, @@ -2549,7 +2554,7 @@ async fn cmd_db_validate_region_snapshots( // This is ok - Nexus currently soft-deletes its // resource records. rows.push(Row { - dataset_id: region_snapshot.dataset_id, + dataset_id: region_snapshot.dataset_id.into(), region_id: region_snapshot.region_id, snapshot_id: region_snapshot.snapshot_id, dataset_addr: dataset.address(), @@ -2564,7 +2569,7 @@ async fn cmd_db_validate_region_snapshots( // higher level Snapshot was not deleted! rows.push(Row { - dataset_id: region_snapshot.dataset_id, + dataset_id: region_snapshot.dataset_id.into(), region_id: region_snapshot.region_id, snapshot_id: region_snapshot.snapshot_id, dataset_addr: dataset.address(), @@ -2593,7 +2598,7 @@ async fn cmd_db_validate_region_snapshots( // the Agent, so it's a bug. rows.push(Row { - dataset_id: region_snapshot.dataset_id, + dataset_id: region_snapshot.dataset_id.into(), region_id: region_snapshot.region_id, snapshot_id: region_snapshot.snapshot_id, dataset_addr: dataset.address(), diff --git a/nexus/db-model/src/dataset.rs b/nexus/db-model/src/dataset.rs index 65c0070509..4764c9d931 100644 --- a/nexus/db-model/src/dataset.rs +++ b/nexus/db-model/src/dataset.rs @@ -8,6 +8,7 @@ use crate::ipv6; use crate::schema::{dataset, region}; use chrono::{DateTime, Utc}; use db_macros::Asset; +use omicron_uuid_kinds::OmicronZoneUuid; use serde::{Deserialize, Serialize}; use std::net::{Ipv6Addr, SocketAddrV6}; use uuid::Uuid; @@ -28,6 +29,7 @@ use uuid::Uuid; PartialEq, )] #[diesel(table_name = dataset)] +#[asset(uuid_kind = OmicronZoneKind)] pub struct Dataset { #[diesel(embed)] identity: DatasetIdentity, @@ -45,7 +47,7 @@ pub struct Dataset { impl Dataset { pub fn new( - id: Uuid, + id: OmicronZoneUuid, pool_id: Uuid, addr: SocketAddrV6, kind: DatasetKind, diff --git a/nexus/db-model/src/region_snapshot.rs b/nexus/db-model/src/region_snapshot.rs index 2ea59f99f0..5d5bb9b183 100644 --- a/nexus/db-model/src/region_snapshot.rs +++ b/nexus/db-model/src/region_snapshot.rs @@ -2,7 +2,8 @@ // 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 crate::schema::region_snapshot; +use crate::{schema::region_snapshot, typed_uuid::DbTypedUuid}; +use omicron_uuid_kinds::OmicronZoneKind; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -23,7 +24,7 @@ use uuid::Uuid; #[diesel(table_name = region_snapshot)] pub struct RegionSnapshot { // unique identifier of this region snapshot - pub dataset_id: Uuid, + pub dataset_id: DbTypedUuid, pub region_id: Uuid, pub snapshot_id: Uuid, diff --git a/nexus/db-queries/src/db/datastore/dataset.rs b/nexus/db-queries/src/db/datastore/dataset.rs index 3617f6d7fc..b799921fb8 100644 --- a/nexus/db-queries/src/db/datastore/dataset.rs +++ b/nexus/db-queries/src/db/datastore/dataset.rs @@ -16,12 +16,13 @@ use crate::db::error::ErrorHandler; use crate::db::identity::Asset; use crate::db::model::Dataset; use crate::db::model::Zpool; -use crate::db::pagination::paginated; +use crate::db::pagination::paginated_mapped; use crate::db::pagination::Paginator; use async_bb8_diesel::AsyncRunQueryDsl; use chrono::Utc; use diesel::prelude::*; use diesel::upsert::excluded; +use nexus_db_model::to_db_typed_uuid; use nexus_db_model::DatasetKind; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; @@ -30,6 +31,7 @@ use omicron_common::api::external::ListResultVec; use omicron_common::api::external::LookupResult; use omicron_common::api::external::LookupType; use omicron_common::api::external::ResourceType; +use omicron_uuid_kinds::OmicronZoneUuid; use uuid::Uuid; impl DataStore { @@ -131,13 +133,18 @@ impl DataStore { &self, opctx: &OpContext, filter_kind: Option, - pagparams: &DataPageParams<'_, Uuid>, + pagparams: &DataPageParams<'_, OmicronZoneUuid>, ) -> ListResultVec { opctx.authorize(authz::Action::ListChildren, &authz::FLEET).await?; use db::schema::dataset::dsl; - let mut query = paginated(dsl::dataset, dsl::id, pagparams) - .filter(dsl::time_deleted.is_null()); + let mut query = paginated_mapped( + dsl::dataset, + dsl::id, + pagparams, + to_db_typed_uuid, + ) + .filter(dsl::time_deleted.is_null()); if let Some(kind) = filter_kind { query = query.filter(dsl::kind.eq(kind)); @@ -238,7 +245,7 @@ mod test { // Inserting a new dataset should succeed. let dataset1 = datastore .dataset_insert_if_not_exists(Dataset::new( - Uuid::new_v4(), + OmicronZoneUuid::new_v4(), zpool_id, "[::1]:0".parse().unwrap(), DatasetKind::Crucible, @@ -287,7 +294,7 @@ mod test { // We can can also upsert a different dataset... let dataset2 = datastore .dataset_upsert(Dataset::new( - Uuid::new_v4(), + OmicronZoneUuid::new_v4(), zpool_id, "[::1]:0".parse().unwrap(), DatasetKind::Cockroach, diff --git a/nexus/db-queries/src/db/datastore/mod.rs b/nexus/db-queries/src/db/datastore/mod.rs index 6e8eecb8ed..458c4491da 100644 --- a/nexus/db-queries/src/db/datastore/mod.rs +++ b/nexus/db-queries/src/db/datastore/mod.rs @@ -402,9 +402,9 @@ mod test { ByteCount, Error, IdentityMetadataCreateParams, LookupType, Name, }; use omicron_test_utils::dev; - use omicron_uuid_kinds::CollectionUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::SledUuid; + use omicron_uuid_kinds::{CollectionUuid, OmicronZoneUuid}; use std::collections::HashMap; use std::collections::HashSet; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV6}; @@ -751,12 +751,12 @@ mod test { ineligible: SledToDatasetMap, // A map from eligible dataset IDs to their corresponding sled IDs. - eligible_dataset_ids: HashMap, - ineligible_dataset_ids: HashMap, + eligible_dataset_ids: HashMap, + ineligible_dataset_ids: HashMap, } // Map of sled IDs to dataset IDs. - type SledToDatasetMap = HashMap>; + type SledToDatasetMap = HashMap>; impl TestDatasets { async fn create( @@ -892,7 +892,7 @@ mod test { let zpool_iter: Vec = (0..3).map(|_| zpool).collect(); stream::iter(zpool_iter).then(|zpool| { - let dataset_id = Uuid::new_v4(); + let dataset_id = OmicronZoneUuid::new_v4(); let dataset = Dataset::new( dataset_id, zpool.pool_id, @@ -982,8 +982,10 @@ mod test { // This is a little goofy, but it catches a bug that has // happened before. The returned columns share names (like // "id"), so we need to process them in-order. - assert!(regions.get(&dataset.id()).is_none()); - assert!(disk_datasets.get(®ion.id()).is_none()); + assert!(regions.get(dataset.id().as_untyped_uuid()).is_none()); + assert!(disk_datasets + .get(&OmicronZoneUuid::from_untyped_uuid(region.id())) + .is_none()); // Dataset must not be eligible for provisioning. if let Some(kind) = @@ -1263,7 +1265,7 @@ mod test { // 1 dataset per zpool stream::iter(zpool_ids.clone()) .then(|zpool_id| { - let id = Uuid::new_v4(); + let id = OmicronZoneUuid::new_v4(); let dataset = Dataset::new( id, zpool_id, @@ -1362,7 +1364,7 @@ mod test { // 1 dataset per zpool stream::iter(zpool_ids) .then(|zpool_id| { - let id = Uuid::new_v4(); + let id = OmicronZoneUuid::new_v4(); let dataset = Dataset::new( id, zpool_id, @@ -1438,7 +1440,7 @@ mod test { .await; let bogus_addr = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0); let dataset = Dataset::new( - Uuid::new_v4(), + OmicronZoneUuid::new_v4(), zpool_id, bogus_addr, DatasetKind::Crucible, diff --git a/nexus/db-queries/src/db/datastore/region.rs b/nexus/db-queries/src/db/datastore/region.rs index 113fc51ee5..e8d500faf6 100644 --- a/nexus/db-queries/src/db/datastore/region.rs +++ b/nexus/db-queries/src/db/datastore/region.rs @@ -18,10 +18,12 @@ use crate::transaction_retry::OptionalError; use async_bb8_diesel::AsyncRunQueryDsl; use diesel::prelude::*; use nexus_config::RegionAllocationStrategy; +use nexus_db_model::to_db_typed_uuid; use nexus_types::external_api::params; use omicron_common::api::external; use omicron_common::api::external::DeleteResult; use omicron_common::api::external::Error; +use omicron_uuid_kinds::OmicronZoneUuid; use slog::Logger; use uuid::Uuid; @@ -294,13 +296,13 @@ impl DataStore { /// Return the total occupied size for a dataset pub async fn regions_total_occupied_size( &self, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, ) -> Result { use db::schema::region::dsl as region_dsl; let total_occupied_size: Option = region_dsl::region - .filter(region_dsl::dataset_id.eq(dataset_id)) + .filter(region_dsl::dataset_id.eq(to_db_typed_uuid(dataset_id))) .select(diesel::dsl::sum( region_dsl::block_size * region_dsl::blocks_per_extent diff --git a/nexus/db-queries/src/db/datastore/region_snapshot.rs b/nexus/db-queries/src/db/datastore/region_snapshot.rs index 3d328a6206..b4f1178775 100644 --- a/nexus/db-queries/src/db/datastore/region_snapshot.rs +++ b/nexus/db-queries/src/db/datastore/region_snapshot.rs @@ -12,9 +12,11 @@ use crate::db::model::RegionSnapshot; use async_bb8_diesel::AsyncRunQueryDsl; use diesel::prelude::*; use diesel::OptionalExtension; +use nexus_db_model::to_db_typed_uuid; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DeleteResult; use omicron_common::api::external::LookupResult; +use omicron_uuid_kinds::OmicronZoneUuid; use uuid::Uuid; impl DataStore { @@ -35,14 +37,14 @@ impl DataStore { pub async fn region_snapshot_get( &self, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, region_id: Uuid, snapshot_id: Uuid, ) -> LookupResult> { use db::schema::region_snapshot::dsl; dsl::region_snapshot - .filter(dsl::dataset_id.eq(dataset_id)) + .filter(dsl::dataset_id.eq(to_db_typed_uuid(dataset_id))) .filter(dsl::region_id.eq(region_id)) .filter(dsl::snapshot_id.eq(snapshot_id)) .select(RegionSnapshot::as_select()) @@ -56,14 +58,14 @@ impl DataStore { pub async fn region_snapshot_remove( &self, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, region_id: Uuid, snapshot_id: Uuid, ) -> DeleteResult { use db::schema::region_snapshot::dsl; diesel::delete(dsl::region_snapshot) - .filter(dsl::dataset_id.eq(dataset_id)) + .filter(dsl::dataset_id.eq(to_db_typed_uuid(dataset_id))) .filter(dsl::region_id.eq(region_id)) .filter(dsl::snapshot_id.eq(snapshot_id)) .execute_async(&*self.pool_connection_unauthorized().await?) diff --git a/nexus/db-queries/src/db/pagination.rs b/nexus/db-queries/src/db/pagination.rs index 4fc1cf5966..1e89612f3d 100644 --- a/nexus/db-queries/src/db/pagination.rs +++ b/nexus/db-queries/src/db/pagination.rs @@ -51,19 +51,48 @@ where BoxedQuery: query_methods::OrderDsl, Output = BoxedQuery>, BoxedQuery: query_methods::FilterDsl, Output = BoxedQuery>, BoxedQuery: query_methods::FilterDsl, Output = BoxedQuery>, +{ + paginated_mapped(table, column, pagparams, std::convert::identity) +} + +/// Like [`paginated`], but also accepts a function that maps the parameter +/// type to the column type. +pub fn paginated_mapped( + table: T, + column: C, + pagparams: &DataPageParams<'_, M>, + mut map: F, +) -> BoxedQuery +where + // T is a table which can create a BoxedQuery. + T: diesel::Table, + T: query_methods::BoxedDsl<'static, Pg, Output = BoxedDslOutput>, + // C is a column which appears in T. + C: 'static + Column + Copy + ExpressionMethods + AppearsOnTable, + // Required to compare the column with the marker type. + C::SqlType: SqlType, + F: FnMut(M) -> N, + M: Clone, + N: AsExpression, + // Defines the methods which can be called on "query", and tells + // the compiler we're gonna output a BoxedQuery each time. + BoxedQuery: query_methods::OrderDsl, Output = BoxedQuery>, + BoxedQuery: query_methods::OrderDsl, Output = BoxedQuery>, + BoxedQuery: query_methods::FilterDsl, Output = BoxedQuery>, + BoxedQuery: query_methods::FilterDsl, Output = BoxedQuery>, { let mut query = table.into_boxed().limit(pagparams.limit.get().into()); - let marker = pagparams.marker.map(|m| m.clone()); + let marker = pagparams.marker.cloned(); match pagparams.direction { dropshot::PaginationOrder::Ascending => { if let Some(marker) = marker { - query = query.filter(column.gt(marker)); + query = query.filter(column.gt(map(marker))); } query.order(column.asc()) } dropshot::PaginationOrder::Descending => { if let Some(marker) = marker { - query = query.filter(column.lt(marker)); + query = query.filter(column.lt(map(marker))); } query.order(column.desc()) } diff --git a/nexus/reconfigurator/execution/src/datasets.rs b/nexus/reconfigurator/execution/src/datasets.rs index c22a56b1b4..077e6684db 100644 --- a/nexus/reconfigurator/execution/src/datasets.rs +++ b/nexus/reconfigurator/execution/src/datasets.rs @@ -14,6 +14,7 @@ use nexus_types::deployment::OmicronZoneConfig; use nexus_types::deployment::OmicronZoneType; use nexus_types::identity::Asset; use omicron_uuid_kinds::GenericUuid; +use omicron_uuid_kinds::OmicronZoneUuid; use slog::info; use slog::warn; use slog_error_chain::InlineErrorChain; @@ -57,7 +58,8 @@ pub(crate) async fn ensure_crucible_dataset_records_exist( continue; }; - let id = zone.id; + // TODO-cleanup use TypedUuid everywhere + let id = OmicronZoneUuid::from_untyped_uuid(zone.id); // If already present in the datastore, move on. if crucible_datasets.remove(&id) { diff --git a/nexus/src/app/sagas/snapshot_create.rs b/nexus/src/app/sagas/snapshot_create.rs index ff57470a5f..1a0c816c9e 100644 --- a/nexus/src/app/sagas/snapshot_create.rs +++ b/nexus/src/app/sagas/snapshot_create.rs @@ -1311,7 +1311,7 @@ async fn ssc_start_running_snapshot( osagactx .datastore() .region_snapshot_create(db::model::RegionSnapshot { - dataset_id: dataset.id(), + dataset_id: dataset.id().into(), region_id: region.id(), snapshot_id, snapshot_addr, diff --git a/nexus/src/app/sagas/volume_delete.rs b/nexus/src/app/sagas/volume_delete.rs index 22425a0b99..fa33f522d0 100644 --- a/nexus/src/app/sagas/volume_delete.rs +++ b/nexus/src/app/sagas/volume_delete.rs @@ -307,7 +307,7 @@ async fn svd_delete_crucible_snapshot_records( osagactx .datastore() .region_snapshot_remove( - region_snapshot.dataset_id, + region_snapshot.dataset_id.into(), region_snapshot.region_id, region_snapshot.snapshot_id, ) diff --git a/nexus/src/app/sled.rs b/nexus/src/app/sled.rs index 55a8c18910..dc15922b51 100644 --- a/nexus/src/app/sled.rs +++ b/nexus/src/app/sled.rs @@ -19,6 +19,7 @@ use omicron_common::api::external::DataPageParams; use omicron_common::api::external::Error; use omicron_common::api::external::ListResultVec; use omicron_common::api::external::LookupResult; +use omicron_uuid_kinds::OmicronZoneUuid; use sled_agent_client::Client as SledAgentClient; use std::net::SocketAddrV6; use std::sync::Arc; @@ -255,7 +256,7 @@ impl super::Nexus { /// Upserts a dataset into the database, updating it if it already exists. pub(crate) async fn upsert_dataset( &self, - id: Uuid, + id: OmicronZoneUuid, zpool_id: Uuid, address: SocketAddrV6, kind: DatasetKind, diff --git a/nexus/src/lib.rs b/nexus/src/lib.rs index 80c972363f..4a3349d479 100644 --- a/nexus/src/lib.rs +++ b/nexus/src/lib.rs @@ -39,6 +39,7 @@ use omicron_common::api::internal::shared::{ ExternalPortDiscovery, RackNetworkConfig, SwitchLocation, }; use omicron_common::FileKv; +use omicron_uuid_kinds::OmicronZoneUuid; use slog::Logger; use std::collections::HashMap; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV6}; @@ -351,7 +352,7 @@ impl nexus_test_interface::NexusServer for Server { &self, physical_disk: PhysicalDiskPutRequest, zpool: ZpoolPutRequest, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, address: SocketAddrV6, ) { let opctx = self.apictx.nexus.opctx_for_internal_api(); diff --git a/nexus/test-interface/Cargo.toml b/nexus/test-interface/Cargo.toml index 004ce28545..e31080b275 100644 --- a/nexus/test-interface/Cargo.toml +++ b/nexus/test-interface/Cargo.toml @@ -9,6 +9,7 @@ async-trait.workspace = true nexus-config.workspace = true nexus-types.workspace = true omicron-common.workspace = true +omicron-uuid-kinds.workspace = true slog.workspace = true uuid.workspace = true omicron-workspace-hack.workspace = true diff --git a/nexus/test-interface/src/lib.rs b/nexus/test-interface/src/lib.rs index 54478c0876..3fd3334128 100644 --- a/nexus/test-interface/src/lib.rs +++ b/nexus/test-interface/src/lib.rs @@ -39,6 +39,7 @@ use nexus_types::internal_api::params::{ }; use nexus_types::inventory::Collection; use omicron_common::api::external::Error; +use omicron_uuid_kinds::OmicronZoneUuid; use slog::Logger; use std::net::{SocketAddr, SocketAddrV6}; use uuid::Uuid; @@ -99,7 +100,7 @@ pub trait NexusServer: Send + Sync + 'static { &self, physical_disk: PhysicalDiskPutRequest, zpool: ZpoolPutRequest, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, address: SocketAddrV6, ); diff --git a/nexus/test-utils/src/lib.rs b/nexus/test-utils/src/lib.rs index 6392c729ce..8f2a302fb8 100644 --- a/nexus/test-utils/src/lib.rs +++ b/nexus/test-utils/src/lib.rs @@ -254,7 +254,7 @@ impl RackInitRequestBuilder { fn add_dataset( &mut self, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, address: SocketAddrV6, kind: DatasetKind, service_name: internal_dns::ServiceName, @@ -266,11 +266,7 @@ impl RackInitRequestBuilder { }); let zone = self .internal_dns_config - .host_zone( - // TODO-cleanup use TypedUuid everywhere - OmicronZoneUuid::from_untyped_uuid(dataset_id), - *address.ip(), - ) + .host_zone(dataset_id, *address.ip()) .expect("Failed to set up DNS for {kind}"); self.internal_dns_config .service_backend_zone(service_name, &zone, address.port()) @@ -430,7 +426,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { .expect("Failed to parse port"); let zpool_id = ZpoolUuid::new_v4(); - let dataset_id = Uuid::new_v4(); + let dataset_id = OmicronZoneUuid::new_v4(); eprintln!("DB address: {}", address); self.rack_init_builder.add_dataset( zpool_id, @@ -444,7 +440,8 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { .parse() .unwrap(); self.omicron_zones.push(OmicronZoneConfig { - id: dataset_id, + // TODO-cleanup use TypedUuid everywhere + id: dataset_id.into_untyped_uuid(), underlay_address: *address.ip(), zone_type: OmicronZoneType::CockroachDb { address: address.to_string(), @@ -467,7 +464,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { let port = clickhouse.port(); let zpool_id = ZpoolUuid::new_v4(); - let dataset_id = Uuid::new_v4(); + let dataset_id = OmicronZoneUuid::new_v4(); let address = SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0); self.rack_init_builder.add_dataset( zpool_id, @@ -493,7 +490,8 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { .parse() .unwrap(); self.omicron_zones.push(OmicronZoneConfig { - id: dataset_id, + // TODO-cleanup use TUuidypedUuid everywhere + id: dataset_id.into_untyped_uuid(), underlay_address: *address.ip(), zone_type: OmicronZoneType::Clickhouse { address: address.to_string(), diff --git a/nexus/test-utils/src/resource_helpers.rs b/nexus/test-utils/src/resource_helpers.rs index 2aef32d37c..eb4db1e89f 100644 --- a/nexus/test-utils/src/resource_helpers.rs +++ b/nexus/test-utils/src/resource_helpers.rs @@ -41,6 +41,7 @@ use omicron_sled_agent::sim::SledAgent; use omicron_test_utils::dev::poll::wait_for_condition; use omicron_test_utils::dev::poll::CondCheckError; use omicron_uuid_kinds::GenericUuid; +use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::ZpoolUuid; use slog::debug; use std::net::IpAddr; @@ -694,7 +695,7 @@ pub async fn projects_list( } pub struct TestDataset { - pub id: Uuid, + pub id: OmicronZoneUuid, } pub struct TestZpool { @@ -744,7 +745,7 @@ impl DiskTest { cptestctx, Uuid::new_v4(), ZpoolUuid::new_v4(), - Uuid::new_v4(), + OmicronZoneUuid::new_v4(), Self::DEFAULT_ZPOOL_SIZE_GIB, ) .await @@ -755,7 +756,7 @@ impl DiskTest { cptestctx: &ControlPlaneTestContext, physical_disk_id: Uuid, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, gibibytes: u32, ) { // To get a dataset, we actually need to create a new simulated physical diff --git a/nexus/tests/integration_tests/snapshots.rs b/nexus/tests/integration_tests/snapshots.rs index 251b729f98..1399226ff0 100644 --- a/nexus/tests/integration_tests/snapshots.rs +++ b/nexus/tests/integration_tests/snapshots.rs @@ -33,6 +33,7 @@ use omicron_common::api::external::Instance; use omicron_common::api::external::InstanceCpuCount; use omicron_common::api::external::Name; use omicron_nexus::app::MIN_DISK_SIZE_BYTES; +use omicron_uuid_kinds::OmicronZoneUuid; use uuid::Uuid; type ControlPlaneTestContext = @@ -1198,7 +1199,7 @@ async fn test_region_snapshot_create_idempotent( let datastore = nexus.datastore(); let region_snapshot = db::model::RegionSnapshot { - dataset_id: Uuid::new_v4(), + dataset_id: OmicronZoneUuid::new_v4().into(), region_id: Uuid::new_v4(), snapshot_id: Uuid::new_v4(), diff --git a/nexus/tests/integration_tests/unauthorized.rs b/nexus/tests/integration_tests/unauthorized.rs index 4f9f75c770..f088cc7e2c 100644 --- a/nexus/tests/integration_tests/unauthorized.rs +++ b/nexus/tests/integration_tests/unauthorized.rs @@ -20,6 +20,7 @@ use nexus_test_utils::http_testing::RequestBuilder; use nexus_test_utils::http_testing::TestResponse; use nexus_test_utils::resource_helpers::DiskTest; use nexus_test_utils_macros::nexus_test; +use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::ZpoolUuid; use once_cell::sync::Lazy; @@ -61,7 +62,7 @@ async fn test_unauthorized(cptestctx: &ControlPlaneTestContext) { cptestctx, nexus_test_utils::PHYSICAL_DISK_UUID.parse().unwrap(), ZpoolUuid::new_v4(), - uuid::Uuid::new_v4(), + OmicronZoneUuid::new_v4(), DiskTest::DEFAULT_ZPOOL_SIZE_GIB, ) .await; diff --git a/nexus/tests/integration_tests/volume_management.rs b/nexus/tests/integration_tests/volume_management.rs index ecfa7cf0f1..d5a00d3975 100644 --- a/nexus/tests/integration_tests/volume_management.rs +++ b/nexus/tests/integration_tests/volume_management.rs @@ -2215,7 +2215,7 @@ async fn test_keep_your_targets_straight(cptestctx: &ControlPlaneTestContext) { ®ion_snapshots[i]; datastore .region_snapshot_create(nexus_db_model::RegionSnapshot { - dataset_id: *dataset_id, + dataset_id: (*dataset_id).into(), region_id: *region_id, snapshot_id: *snapshot_id, snapshot_addr: snapshot_addr.clone(), @@ -2328,7 +2328,7 @@ async fn test_keep_your_targets_straight(cptestctx: &ControlPlaneTestContext) { ®ion_snapshots[i]; datastore .region_snapshot_create(nexus_db_model::RegionSnapshot { - dataset_id: *dataset_id, + dataset_id: (*dataset_id).into(), region_id: *region_id, snapshot_id: *snapshot_id, snapshot_addr: snapshot_addr.clone(), diff --git a/nexus/types/src/internal_api/params.rs b/nexus/types/src/internal_api/params.rs index a811106c2c..828f3595aa 100644 --- a/nexus/types/src/internal_api/params.rs +++ b/nexus/types/src/internal_api/params.rs @@ -16,6 +16,7 @@ use omicron_common::api::external::Name; use omicron_common::api::internal::shared::ExternalPortDiscovery; use omicron_common::api::internal::shared::RackNetworkConfig; use omicron_common::api::internal::shared::SourceNatConfig; +use omicron_uuid_kinds::OmicronZoneUuid; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt; @@ -210,7 +211,7 @@ pub struct ServicePutRequest { #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct DatasetCreateRequest { pub zpool_id: Uuid, - pub dataset_id: Uuid, + pub dataset_id: OmicronZoneUuid, pub request: DatasetPutRequest, } diff --git a/openapi/nexus-internal.json b/openapi/nexus-internal.json index c4eb89f0f9..ae4db9d4fa 100644 --- a/openapi/nexus-internal.json +++ b/openapi/nexus-internal.json @@ -3007,8 +3007,7 @@ "type": "object", "properties": { "dataset_id": { - "type": "string", - "format": "uuid" + "$ref": "#/components/schemas/TypedUuidForOmicronZoneKind" }, "request": { "$ref": "#/components/schemas/DatasetPutRequest" @@ -7533,6 +7532,10 @@ "type": "string", "format": "uuid" }, + "TypedUuidForOmicronZoneKind": { + "type": "string", + "format": "uuid" + }, "TypedUuidForUpstairsRepairKind": { "type": "string", "format": "uuid" diff --git a/sled-agent/src/rack_setup/service.rs b/sled-agent/src/rack_setup/service.rs index ce5cb3fa2d..fffc44d14c 100644 --- a/sled-agent/src/rack_setup/service.rs +++ b/sled-agent/src/rack_setup/service.rs @@ -103,8 +103,8 @@ use omicron_common::backoff::{ }; use omicron_common::ledger::{self, Ledger, Ledgerable}; use omicron_ddm_admin_client::{Client as DdmAdminClient, DdmError}; -use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::SledUuid; +use omicron_uuid_kinds::{GenericUuid, OmicronZoneUuid}; use serde::{Deserialize, Serialize}; use sled_agent_client::{ types as SledAgentTypes, Client as SledAgentClient, Error as SledAgentError, @@ -729,7 +729,8 @@ impl ServiceInner { { datasets.push(NexusTypes::DatasetCreateRequest { zpool_id: dataset_name.pool().id().into_untyped_uuid(), - dataset_id: zone.id, + // TODO-cleanup use TypedUuid everywhere + dataset_id: OmicronZoneUuid::from_untyped_uuid(zone.id), request: NexusTypes::DatasetPutRequest { address: dataset_address.to_string(), kind: dataset_name.dataset().clone().convert(), diff --git a/sled-agent/src/sim/server.rs b/sled-agent/src/sim/server.rs index 089760740a..157aaf15ee 100644 --- a/sled-agent/src/sim/server.rs +++ b/sled-agent/src/sim/server.rs @@ -34,6 +34,7 @@ use omicron_common::backoff::{ use omicron_common::disk::DiskIdentity; use omicron_common::FileKv; use omicron_uuid_kinds::GenericUuid; +use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::ZpoolUuid; use slog::{info, Drain, Logger}; use std::collections::BTreeMap; @@ -185,13 +186,13 @@ impl Server { sled_agent .create_zpool(zpool_id, physical_disk_id, zpool.size) .await; - let dataset_id = Uuid::new_v4(); + let dataset_id = OmicronZoneUuid::new_v4(); let address = sled_agent.create_crucible_dataset(zpool_id, dataset_id).await; datasets.push(NexusTypes::DatasetCreateRequest { zpool_id: zpool_id.into_untyped_uuid(), - dataset_id, + dataset_id: dataset_id, request: NexusTypes::DatasetPutRequest { address: address.to_string(), kind: NexusTypes::DatasetKind::Crucible, @@ -486,7 +487,7 @@ pub async fn run_standalone_server( { datasets.push(NexusTypes::DatasetCreateRequest { zpool_id: zpool.id, - dataset_id, + dataset_id: dataset_id, request: NexusTypes::DatasetPutRequest { address: address.to_string(), kind: NexusTypes::DatasetKind::Crucible, diff --git a/sled-agent/src/sim/sled_agent.rs b/sled-agent/src/sim/sled_agent.rs index 900265ad0d..71dc2e1860 100644 --- a/sled-agent/src/sim/sled_agent.rs +++ b/sled-agent/src/sim/sled_agent.rs @@ -36,7 +36,7 @@ use omicron_common::api::internal::nexus::{ InstanceRuntimeState, VmmRuntimeState, }; use omicron_common::disk::DiskIdentity; -use omicron_uuid_kinds::ZpoolUuid; +use omicron_uuid_kinds::{OmicronZoneUuid, ZpoolUuid}; use propolis_client::{ types::VolumeConstructionRequest, Client as PropolisClient, }; @@ -549,7 +549,7 @@ impl SledAgent { pub async fn get_datasets( &self, zpool_id: ZpoolUuid, - ) -> Vec<(Uuid, SocketAddr)> { + ) -> Vec<(OmicronZoneUuid, SocketAddr)> { self.storage.lock().await.get_all_datasets(zpool_id) } @@ -571,7 +571,7 @@ impl SledAgent { pub async fn create_crucible_dataset( &self, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, ) -> SocketAddr { self.storage.lock().await.insert_dataset(zpool_id, dataset_id).await } @@ -580,7 +580,7 @@ impl SledAgent { pub async fn get_crucible_dataset( &self, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, ) -> Arc { self.storage.lock().await.get_dataset(zpool_id, dataset_id).await } diff --git a/sled-agent/src/sim/storage.rs b/sled-agent/src/sim/storage.rs index 56cf771b2a..b2bfdf9a55 100644 --- a/sled-agent/src/sim/storage.rs +++ b/sled-agent/src/sim/storage.rs @@ -485,7 +485,7 @@ pub(crate) struct Zpool { id: ZpoolUuid, physical_disk_id: Uuid, total_size: u64, - datasets: HashMap, + datasets: HashMap, } impl Zpool { @@ -496,7 +496,7 @@ impl Zpool { fn insert_dataset( &mut self, log: &Logger, - id: Uuid, + id: OmicronZoneUuid, crucible_ip: IpAddr, crucible_port: u16, ) -> &CrucibleServer { @@ -644,7 +644,7 @@ impl Storage { pub async fn insert_dataset( &mut self, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, ) -> SocketAddr { // Update our local data let dataset = self @@ -704,7 +704,7 @@ impl Storage { pub fn get_all_datasets( &self, zpool_id: ZpoolUuid, - ) -> Vec<(Uuid, SocketAddr)> { + ) -> Vec<(OmicronZoneUuid, SocketAddr)> { let zpool = self.zpools.get(&zpool_id).expect("Zpool does not exist"); zpool @@ -717,7 +717,7 @@ impl Storage { pub async fn get_dataset( &self, zpool_id: ZpoolUuid, - dataset_id: Uuid, + dataset_id: OmicronZoneUuid, ) -> Arc { self.zpools .get(&zpool_id)