From 8fe589d628b13c76b96b492fd4f5cefd2b86d927 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Wed, 9 Aug 2023 15:15:35 -0400 Subject: [PATCH 01/11] Relocate limit constants to common --- common/src/api/external/mod.rs | 26 ++++++++++++++++++++++++- common/src/lib.rs | 1 + common/src/limits.rs | 19 ++++++++++++++++++ nexus/db-queries/src/db/queries/disk.rs | 8 +------- nexus/src/app/disk.rs | 5 ++--- nexus/src/app/instance.rs | 12 ++++++------ nexus/src/app/mod.rs | 18 ----------------- nexus/src/app/sagas/instance_create.rs | 8 ++++---- 8 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 common/src/limits.rs diff --git a/common/src/api/external/mod.rs b/common/src/api/external/mod.rs index 06a06ea52a..34463ed999 100644 --- a/common/src/api/external/mod.rs +++ b/common/src/api/external/mod.rs @@ -40,6 +40,8 @@ use std::num::{NonZeroU16, NonZeroU32}; use std::str::FromStr; use uuid::Uuid; +use crate::limits::MAX_VCPU_PER_INSTANCE; + // The type aliases below exist primarily to ensure consistency among return // types for functions in the `nexus::Nexus` and `nexus::DataStore`. The // type argument `T` generally implements `Object`. @@ -881,9 +883,31 @@ impl InstanceState { } /// The number of CPUs in an Instance -#[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub struct InstanceCpuCount(pub u16); +impl JsonSchema for InstanceCpuCount { + fn schema_name() -> String { + "InstanceCpuCount".to_string() + } + + fn json_schema( + _: &mut schemars::gen::SchemaGenerator, + ) -> schemars::schema::Schema { + schemars::schema::SchemaObject { + number: Some(Box::new(schemars::schema::NumberValidation { + multiple_of: None, + maximum: Some(MAX_VCPU_PER_INSTANCE.into()), + exclusive_maximum: None, + minimum: Some(1.0), + exclusive_minimum: None, + })), + ..Default::default() + } + .into() + } +} + impl TryFrom for InstanceCpuCount { type Error = anyhow::Error; diff --git a/common/src/lib.rs b/common/src/lib.rs index ced10abb1a..3d811e04a4 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -26,6 +26,7 @@ pub mod backoff; pub mod cmd; pub mod disk; pub mod ledger; +pub mod limits; pub mod nexus_config; pub mod postgres_config; pub mod update; diff --git a/common/src/limits.rs b/common/src/limits.rs new file mode 100644 index 0000000000..ef443f65c2 --- /dev/null +++ b/common/src/limits.rs @@ -0,0 +1,19 @@ +// 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/. + +// Contains constants that define the hard limits of Nexus + +pub const MAX_VCPU_PER_INSTANCE: u16 = 64; + +pub const MIN_MEMORY_BYTES_PER_INSTANCE: u32 = 1 << 30; // 1 GiB +pub const MAX_MEMORY_BYTES_PER_INSTANCE: u64 = 256 * (1 << 30); // 256 GiB + +pub const MAX_DISKS_PER_INSTANCE: u32 = 8; +pub const MIN_DISK_SIZE_BYTES: u32 = 1 << 30; // 1 GiB +pub const MAX_DISK_SIZE_BYTES: u64 = 1023 * (1 << 30); // 1023 GiB + +pub const MAX_NICS_PER_INSTANCE: usize = 8; + +// TODO-completeness: Support multiple external IPs +pub const MAX_EXTERNAL_IPS_PER_INSTANCE: usize = 1; diff --git a/nexus/db-queries/src/db/queries/disk.rs b/nexus/db-queries/src/db/queries/disk.rs index 9fd56c3ce8..64af650634 100644 --- a/nexus/db-queries/src/db/queries/disk.rs +++ b/nexus/db-queries/src/db/queries/disk.rs @@ -11,15 +11,9 @@ use diesel::{ query_builder::{AstPass, QueryFragment, QueryId}, sql_types, Column, QueryResult, }; +use omicron_common::limits::MAX_DISKS_PER_INSTANCE; use uuid::Uuid; -/// The maximum number of disks that can be attached to an instance. -// -// This is defined here for layering reasons: the main Nexus crate depends on -// the db-queries crate, so the disk-per-instance limit lives here and Nexus -// proper re-exports it. -pub const MAX_DISKS_PER_INSTANCE: u32 = 8; - /// A wrapper for the query that selects a PCI slot for a newly-attached disk. /// /// The general idea is to produce a query that left joins a single-column table diff --git a/nexus/src/app/disk.rs b/nexus/src/app/disk.rs index 1308784aa7..838e2c3178 100644 --- a/nexus/src/app/disk.rs +++ b/nexus/src/app/disk.rs @@ -24,13 +24,12 @@ use omicron_common::api::external::LookupResult; use omicron_common::api::external::NameOrId; use omicron_common::api::external::UpdateResult; use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::limits::MAX_DISK_SIZE_BYTES; +use omicron_common::limits::MIN_DISK_SIZE_BYTES; use sled_agent_client::Client as SledAgentClient; use std::sync::Arc; use uuid::Uuid; -use super::MAX_DISK_SIZE_BYTES; -use super::MIN_DISK_SIZE_BYTES; - impl super::Nexus { // Disks pub fn disk_lookup<'a>( diff --git a/nexus/src/app/instance.rs b/nexus/src/app/instance.rs index 2dc2bfb5bf..aa8ae24f6c 100644 --- a/nexus/src/app/instance.rs +++ b/nexus/src/app/instance.rs @@ -4,12 +4,6 @@ //! Virtual Machine Instances -use super::MAX_DISKS_PER_INSTANCE; -use super::MAX_EXTERNAL_IPS_PER_INSTANCE; -use super::MAX_MEMORY_BYTES_PER_INSTANCE; -use super::MAX_NICS_PER_INSTANCE; -use super::MAX_VCPU_PER_INSTANCE; -use super::MIN_MEMORY_BYTES_PER_INSTANCE; use crate::app::sagas; use crate::app::sagas::retry_until_known_result; use crate::authn; @@ -42,6 +36,12 @@ use omicron_common::api::external::UpdateResult; use omicron_common::api::external::Vni; use omicron_common::api::internal::nexus; use omicron_common::api::internal::shared::SwitchLocation; +use omicron_common::limits::MAX_DISKS_PER_INSTANCE; +use omicron_common::limits::MAX_EXTERNAL_IPS_PER_INSTANCE; +use omicron_common::limits::MAX_MEMORY_BYTES_PER_INSTANCE; +use omicron_common::limits::MAX_NICS_PER_INSTANCE; +use omicron_common::limits::MAX_VCPU_PER_INSTANCE; +use omicron_common::limits::MIN_MEMORY_BYTES_PER_INSTANCE; use propolis_client::support::tungstenite::protocol::frame::coding::CloseCode; use propolis_client::support::tungstenite::protocol::CloseFrame; use propolis_client::support::tungstenite::Message as WebSocketMessage; diff --git a/nexus/src/app/mod.rs b/nexus/src/app/mod.rs index 99ed75f14b..8af23b70d8 100644 --- a/nexus/src/app/mod.rs +++ b/nexus/src/app/mod.rs @@ -68,24 +68,6 @@ mod vpc_subnet; // application logic. pub mod sagas; -// TODO: When referring to API types, we should try to include -// the prefix unless it is unambiguous. - -pub(crate) use nexus_db_queries::db::queries::disk::MAX_DISKS_PER_INSTANCE; - -pub(crate) const MAX_NICS_PER_INSTANCE: usize = 8; - -// TODO-completeness: Support multiple external IPs -pub(crate) const MAX_EXTERNAL_IPS_PER_INSTANCE: usize = 1; - -pub const MAX_VCPU_PER_INSTANCE: u16 = 64; - -pub const MIN_MEMORY_BYTES_PER_INSTANCE: u32 = 1 << 30; // 1 GiB -pub const MAX_MEMORY_BYTES_PER_INSTANCE: u64 = 256 * (1 << 30); // 256 GiB - -pub const MIN_DISK_SIZE_BYTES: u32 = 1 << 30; // 1 GiB -pub const MAX_DISK_SIZE_BYTES: u64 = 1023 * (1 << 30); // 1023 GiB - /// Manages an Oxide fleet -- the heart of the control plane pub struct Nexus { /// uuid for this nexus instance. diff --git a/nexus/src/app/sagas/instance_create.rs b/nexus/src/app/sagas/instance_create.rs index ac684691aa..a8eabe343c 100644 --- a/nexus/src/app/sagas/instance_create.rs +++ b/nexus/src/app/sagas/instance_create.rs @@ -7,10 +7,6 @@ use crate::app::instance::WriteBackUpdatedInstance; use crate::app::sagas::declare_saga_actions; use crate::app::sagas::disk_create::{self, SagaDiskCreate}; use crate::app::sagas::retry_until_known_result; -use crate::app::{ - MAX_DISKS_PER_INSTANCE, MAX_EXTERNAL_IPS_PER_INSTANCE, - MAX_NICS_PER_INSTANCE, -}; use crate::db::identity::Resource; use crate::db::lookup::LookupPath; use crate::db::model::ByteCount as DbByteCount; @@ -29,6 +25,10 @@ use omicron_common::api::external::InstanceState; use omicron_common::api::external::Name; use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::shared::SwitchLocation; +use omicron_common::limits::{ + MAX_DISKS_PER_INSTANCE, MAX_EXTERNAL_IPS_PER_INSTANCE, + MAX_NICS_PER_INSTANCE, +}; use serde::Deserialize; use serde::Serialize; use sled_agent_client::types::InstanceStateRequested; From 6e76814a7dc01dcfad2c3465e6c71fc61e612685 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Wed, 9 Aug 2023 15:40:09 -0400 Subject: [PATCH 02/11] Update missed limit references --- nexus/tests/integration_tests/disks.rs | 3 ++- nexus/tests/integration_tests/instances.rs | 6 +++--- nexus/tests/integration_tests/snapshots.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/nexus/tests/integration_tests/disks.rs b/nexus/tests/integration_tests/disks.rs index 85174a74ab..1928a91aef 100644 --- a/nexus/tests/integration_tests/disks.rs +++ b/nexus/tests/integration_tests/disks.rs @@ -32,7 +32,8 @@ use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_common::api::external::Instance; use omicron_common::api::external::Name; use omicron_common::api::external::NameOrId; -use omicron_nexus::app::{MAX_DISK_SIZE_BYTES, MIN_DISK_SIZE_BYTES}; +use omicron_common::limits::MAX_DISK_SIZE_BYTES; +use omicron_common::limits::MIN_DISK_SIZE_BYTES; use omicron_nexus::db::fixed_data::{silo::SILO_ID, FLEET_ID}; use omicron_nexus::db::lookup::LookupPath; use omicron_nexus::TestInterfaces as _; diff --git a/nexus/tests/integration_tests/instances.rs b/nexus/tests/integration_tests/instances.rs index 411842f95e..b530066997 100644 --- a/nexus/tests/integration_tests/instances.rs +++ b/nexus/tests/integration_tests/instances.rs @@ -36,9 +36,9 @@ use omicron_common::api::external::InstanceState; use omicron_common::api::external::Ipv4Net; use omicron_common::api::external::Name; use omicron_common::api::external::Vni; -use omicron_nexus::app::MAX_MEMORY_BYTES_PER_INSTANCE; -use omicron_nexus::app::MAX_VCPU_PER_INSTANCE; -use omicron_nexus::app::MIN_MEMORY_BYTES_PER_INSTANCE; +use omicron_common::limits::MAX_MEMORY_BYTES_PER_INSTANCE; +use omicron_common::limits::MAX_VCPU_PER_INSTANCE; +use omicron_common::limits::MIN_MEMORY_BYTES_PER_INSTANCE; use omicron_nexus::db::fixed_data::silo::SILO_ID; use omicron_nexus::db::lookup::LookupPath; use omicron_nexus::external_api::shared::IpKind; diff --git a/nexus/tests/integration_tests/snapshots.rs b/nexus/tests/integration_tests/snapshots.rs index a26a9811a1..7b2ed69689 100644 --- a/nexus/tests/integration_tests/snapshots.rs +++ b/nexus/tests/integration_tests/snapshots.rs @@ -26,7 +26,7 @@ use omicron_common::api::external::IdentityMetadataCreateParams; 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_common::limits::MIN_DISK_SIZE_BYTES; use omicron_nexus::authz; use omicron_nexus::db; use omicron_nexus::db::identity::Resource; From b6f7530fed51897ba1f2b8db254b633c65e1c45f Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Wed, 9 Aug 2023 16:53:36 -0400 Subject: [PATCH 03/11] Add maximum to CPU count --- common/src/api/external/mod.rs | 8 ++++++++ nexus-client/src/lib.rs | 2 +- openapi/nexus-internal.json | 3 ++- openapi/nexus.json | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/common/src/api/external/mod.rs b/common/src/api/external/mod.rs index 34463ed999..48cd796967 100644 --- a/common/src/api/external/mod.rs +++ b/common/src/api/external/mod.rs @@ -895,6 +895,14 @@ impl JsonSchema for InstanceCpuCount { _: &mut schemars::gen::SchemaGenerator, ) -> schemars::schema::Schema { schemars::schema::SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + description: Some( + "The number of CPUs in an Instance".to_string(), + ), + ..Default::default() + })), + format: Some("uint16".to_string()), + instance_type: Some(schemars::schema::InstanceType::Integer.into()), number: Some(Box::new(schemars::schema::NumberValidation { multiple_of: None, maximum: Some(MAX_VCPU_PER_INSTANCE.into()), diff --git a/nexus-client/src/lib.rs b/nexus-client/src/lib.rs index e878775713..9c96b8dff3 100644 --- a/nexus-client/src/lib.rs +++ b/nexus-client/src/lib.rs @@ -128,7 +128,7 @@ impl From for types::InstanceCpuCount { fn from(s: omicron_common::api::external::InstanceCpuCount) -> Self { - Self(s.0) + Self(s.0.into()) } } diff --git a/openapi/nexus-internal.json b/openapi/nexus-internal.json index db276de5c0..b72a7b8420 100644 --- a/openapi/nexus-internal.json +++ b/openapi/nexus-internal.json @@ -1850,7 +1850,8 @@ "description": "The number of CPUs in an Instance", "type": "integer", "format": "uint16", - "minimum": 0 + "minimum": 1, + "maximum": 64 }, "InstanceRuntimeState": { "description": "Runtime state of the Instance, including the actual running state and minimal metadata\n\nThis state is owned by the sled agent running that Instance.", diff --git a/openapi/nexus.json b/openapi/nexus.json index 127f1309d0..b079afa06e 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -9601,7 +9601,8 @@ "description": "The number of CPUs in an Instance", "type": "integer", "format": "uint16", - "minimum": 0 + "minimum": 1, + "maximum": 64 }, "InstanceCreate": { "description": "Create-time parameters for an `Instance`", From 41f2384e3ecd10036162c33f2b6c517f28c3c956 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Fri, 11 Aug 2023 14:26:03 -0400 Subject: [PATCH 04/11] Add memory limits to instance --- nexus/types/src/external_api/params.rs | 32 +++++++++++++++++++++----- openapi/nexus.json | 6 ++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index 895746b785..f77245cdf2 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -8,20 +8,23 @@ use crate::external_api::shared; use base64::Engine; use chrono::{DateTime, Utc}; -use omicron_common::api::external::{ - AddressLotKind, ByteCount, IdentityMetadataCreateParams, - IdentityMetadataUpdateParams, InstanceCpuCount, IpNet, Ipv4Net, Ipv6Net, - Name, NameOrId, PaginationOrder, RouteDestination, RouteTarget, - SemverVersion, +use omicron_common::{ + api::external::{ + AddressLotKind, ByteCount, IdentityMetadataCreateParams, + IdentityMetadataUpdateParams, InstanceCpuCount, IpNet, Ipv4Net, + Ipv6Net, Name, NameOrId, PaginationOrder, RouteDestination, + RouteTarget, SemverVersion, + }, + limits::{MAX_MEMORY_BYTES_PER_INSTANCE, MIN_MEMORY_BYTES_PER_INSTANCE}, }; use schemars::JsonSchema; use serde::{ de::{self, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; -use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::HashMap; +use std::{char::MAX, collections::BTreeMap}; use std::{net::IpAddr, str::FromStr}; use uuid::Uuid; @@ -816,6 +819,7 @@ pub struct InstanceCreate { #[serde(flatten)] pub identity: IdentityMetadataCreateParams, pub ncpus: InstanceCpuCount, + #[schemars(schema_with = "memory_limits")] pub memory: ByteCount, pub hostname: String, // TODO-cleanup different type? @@ -859,6 +863,22 @@ fn bool_true() -> bool { true } +fn memory_limits( + gen: &mut schemars::gen::SchemaGenerator, +) -> schemars::schema::Schema { + let mut schema: schemars::schema::SchemaObject = + ::json_schema(gen).into(); + let min_mem = MIN_MEMORY_BYTES_PER_INSTANCE / (1 << 30); + let max_mem = MAX_MEMORY_BYTES_PER_INSTANCE / (1 << 30); + schema.metadata().description = Some( + format!("The amount of memory to allocate to the instance, in bytes.\n\nMust be between {min_mem} and {max_mem} GiB.") + .to_string(), + ); + schema.number().minimum = Some(MIN_MEMORY_BYTES_PER_INSTANCE as f64); + schema.number().maximum = Some(MAX_MEMORY_BYTES_PER_INSTANCE as f64); + schema.into() +} + // If you change this, also update the error message in // `UserData::deserialize()` below. pub const MAX_USER_DATA_BYTES: usize = 32 * 1024; // 32 KiB diff --git a/openapi/nexus.json b/openapi/nexus.json index b079afa06e..c4f77e8aca 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -9631,7 +9631,11 @@ "type": "string" }, "memory": { - "$ref": "#/components/schemas/ByteCount" + "description": "The amount of memory to allocate to the instance, in bytes.\n\nMust be between 1 and 256 GiB.", + "type": "integer", + "format": "uint64", + "minimum": 1073741824, + "maximum": 274877906944 }, "name": { "$ref": "#/components/schemas/Name" From 6f7c7e162104414f86fe6453c142984bd665b5dd Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Fri, 11 Aug 2023 14:41:03 -0400 Subject: [PATCH 05/11] Fix clippy issue --- nexus/types/src/external_api/params.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index f77245cdf2..78cf3692a5 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -22,9 +22,9 @@ use serde::{ de::{self, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; +use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::HashMap; -use std::{char::MAX, collections::BTreeMap}; use std::{net::IpAddr, str::FromStr}; use uuid::Uuid; @@ -872,7 +872,6 @@ fn memory_limits( let max_mem = MAX_MEMORY_BYTES_PER_INSTANCE / (1 << 30); schema.metadata().description = Some( format!("The amount of memory to allocate to the instance, in bytes.\n\nMust be between {min_mem} and {max_mem} GiB.") - .to_string(), ); schema.number().minimum = Some(MIN_MEMORY_BYTES_PER_INSTANCE as f64); schema.number().maximum = Some(MAX_MEMORY_BYTES_PER_INSTANCE as f64); From 9dd273700caf2bccf4dfca5c120e49e48492c200 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Fri, 11 Aug 2023 14:50:51 -0400 Subject: [PATCH 06/11] Add disk size limits --- nexus/types/src/external_api/params.rs | 23 +++++++++++++++++++++-- openapi/nexus.json | 20 +++++++++----------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index 78cf3692a5..e8dc1612f3 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -15,7 +15,10 @@ use omicron_common::{ Ipv6Net, Name, NameOrId, PaginationOrder, RouteDestination, RouteTarget, SemverVersion, }, - limits::{MAX_MEMORY_BYTES_PER_INSTANCE, MIN_MEMORY_BYTES_PER_INSTANCE}, + limits::{ + MAX_DISK_SIZE_BYTES, MAX_MEMORY_BYTES_PER_INSTANCE, + MIN_DISK_SIZE_BYTES, MIN_MEMORY_BYTES_PER_INSTANCE, + }, }; use schemars::JsonSchema; use serde::{ @@ -871,7 +874,7 @@ fn memory_limits( let min_mem = MIN_MEMORY_BYTES_PER_INSTANCE / (1 << 30); let max_mem = MAX_MEMORY_BYTES_PER_INSTANCE / (1 << 30); schema.metadata().description = Some( - format!("The amount of memory to allocate to the instance, in bytes.\n\nMust be between {min_mem} and {max_mem} GiB.") + format!("the amount of memory to allocate to the instance, in bytes.\n\nMust be between {min_mem} and {max_mem} GiB.") ); schema.number().minimum = Some(MIN_MEMORY_BYTES_PER_INSTANCE as f64); schema.number().maximum = Some(MAX_MEMORY_BYTES_PER_INSTANCE as f64); @@ -1170,9 +1173,25 @@ pub struct DiskCreate { /// initial source for this disk pub disk_source: DiskSource, /// total size of the Disk in bytes + #[schemars(schema_with = "disk_size_limits")] pub size: ByteCount, } +fn disk_size_limits( + gen: &mut schemars::gen::SchemaGenerator, +) -> schemars::schema::Schema { + let mut schema: schemars::schema::SchemaObject = + ByteCount::json_schema(gen).into(); + let min_disk = MIN_DISK_SIZE_BYTES / (1 << 30); + let max_disk = MAX_DISK_SIZE_BYTES / (1 << 30); + schema.metadata().description = Some( + format!("total size of the disk in bytes.\n\nMust be between {min_disk} and {max_disk} GiB.") + ); + schema.number().minimum = Some(MIN_DISK_SIZE_BYTES as f64); + schema.number().maximum = Some(MAX_DISK_SIZE_BYTES as f64); + schema.into() +} + // equivalent to crucible_pantry_client::types::ExpectedDigest #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] #[serde(rename_all = "snake_case")] diff --git a/openapi/nexus.json b/openapi/nexus.json index c4f77e8aca..5cbc5f2bf2 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -8544,11 +8544,10 @@ }, "size": { "description": "total size of the Disk in bytes", - "allOf": [ - { - "$ref": "#/components/schemas/ByteCount" - } - ] + "type": "integer", + "format": "uint64", + "minimum": 1073741824, + "maximum": 1098437885952 } }, "required": [ @@ -9631,7 +9630,7 @@ "type": "string" }, "memory": { - "description": "The amount of memory to allocate to the instance, in bytes.\n\nMust be between 1 and 256 GiB.", + "description": "the amount of memory to allocate to the instance, in bytes.\n\nMust be between 1 and 256 GiB.", "type": "integer", "format": "uint64", "minimum": 1073741824, @@ -9697,11 +9696,10 @@ }, "size": { "description": "total size of the Disk in bytes", - "allOf": [ - { - "$ref": "#/components/schemas/ByteCount" - } - ] + "type": "integer", + "format": "uint64", + "minimum": 1073741824, + "maximum": 1098437885952 }, "type": { "type": "string", From 6a5ae3c8488d69ac9a208f2b5b9a4c1bf4b921d8 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Fri, 11 Aug 2023 16:31:13 -0400 Subject: [PATCH 07/11] Update sled agent spec --- openapi/sled-agent.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openapi/sled-agent.json b/openapi/sled-agent.json index 5e34227a25..ab4bbb5cf8 100644 --- a/openapi/sled-agent.json +++ b/openapi/sled-agent.json @@ -1344,7 +1344,8 @@ "description": "The number of CPUs in an Instance", "type": "integer", "format": "uint16", - "minimum": 0 + "minimum": 1, + "maximum": 64 }, "InstanceEnsureBody": { "description": "The body of a request to ensure that an instance is known to a sled agent.", From 58503b2dead1223378ba884c1ea8afe98db0a8ea Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Fri, 11 Aug 2023 17:24:42 -0400 Subject: [PATCH 08/11] Fix clippy errors --- nexus/db-model/src/instance_cpu_count.rs | 2 +- sled-agent-client/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nexus/db-model/src/instance_cpu_count.rs b/nexus/db-model/src/instance_cpu_count.rs index 6c7debc6a5..8d676e0cac 100644 --- a/nexus/db-model/src/instance_cpu_count.rs +++ b/nexus/db-model/src/instance_cpu_count.rs @@ -47,6 +47,6 @@ where impl From for sled_agent_client::types::InstanceCpuCount { fn from(i: InstanceCpuCount) -> Self { - Self(i.0 .0) + Self((&i.0).try_into().unwrap()) } } diff --git a/sled-agent-client/src/lib.rs b/sled-agent-client/src/lib.rs index 98e7f207e3..c22aeef6c4 100644 --- a/sled-agent-client/src/lib.rs +++ b/sled-agent-client/src/lib.rs @@ -64,7 +64,7 @@ impl From for types::InstanceCpuCount { fn from(s: omicron_common::api::external::InstanceCpuCount) -> Self { - Self(s.0) + Self(s.0.try_into().unwrap()) } } @@ -125,7 +125,7 @@ impl From for omicron_common::api::external::InstanceCpuCount { fn from(s: types::InstanceCpuCount) -> Self { - Self(s.0) + Self(s.0.try_into().unwrap()) } } From 95c68375d9b0727be22ae3ec0bad0fdbc2a10694 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Tue, 12 Dec 2023 15:46:58 -0500 Subject: [PATCH 09/11] Fix broken import after main merge --- nexus/src/app/instance.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nexus/src/app/instance.rs b/nexus/src/app/instance.rs index 14bd83e6cc..b0e746c7a6 100644 --- a/nexus/src/app/instance.rs +++ b/nexus/src/app/instance.rs @@ -34,12 +34,14 @@ use omicron_common::api::external::NameOrId; use omicron_common::api::external::UpdateResult; use omicron_common::api::external::Vni; use omicron_common::api::internal::nexus; -use omicron_common::limits::MAX_DISKS_PER_INSTANCE; use omicron_common::limits::MAX_EXTERNAL_IPS_PER_INSTANCE; use omicron_common::limits::MAX_MEMORY_BYTES_PER_INSTANCE; use omicron_common::limits::MAX_NICS_PER_INSTANCE; use omicron_common::limits::MAX_VCPU_PER_INSTANCE; use omicron_common::limits::MIN_MEMORY_BYTES_PER_INSTANCE; +use omicron_common::limits::{ + MAX_DISKS_PER_INSTANCE, MAX_EPHEMERAL_IPS_PER_INSTANCE, +}; use propolis_client::support::tungstenite::protocol::frame::coding::CloseCode; use propolis_client::support::tungstenite::protocol::CloseFrame; use propolis_client::support::tungstenite::Message as WebSocketMessage; From 030211f3e4f9e82251157d2be28cf2cb49516e99 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Tue, 23 Jan 2024 23:24:12 -0500 Subject: [PATCH 10/11] Fix type error in e2e test --- end-to-end-tests/src/bin/bootstrap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end-to-end-tests/src/bin/bootstrap.rs b/end-to-end-tests/src/bin/bootstrap.rs index b02bed4265..9549210401 100644 --- a/end-to-end-tests/src/bin/bootstrap.rs +++ b/end-to-end-tests/src/bin/bootstrap.rs @@ -92,7 +92,7 @@ async fn main() -> Result<()> { disk_source: DiskSource::Blank { block_size: 512.try_into().unwrap(), }, - size: ByteCount(1024 * 1024 * 1024), + size: ByteCount::from(1024 * 1024 * 1024), }) .send() .await From 894041db7e0bf363d8e9eaf19a6eb3771ea9fa21 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Tue, 23 Jan 2024 23:24:33 -0500 Subject: [PATCH 11/11] Trial a (not working) fix for schema updates --- nexus/types/src/external_api/params.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index 4abeb00d4c..4c2b4bb9b0 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -1336,13 +1336,34 @@ fn disk_size_limits( ) -> schemars::schema::Schema { let mut schema: schemars::schema::SchemaObject = ByteCount::json_schema(gen).into(); + schema.instance_type = None; let min_disk = MIN_DISK_SIZE_BYTES / (1 << 30); let max_disk = MAX_DISK_SIZE_BYTES / (1 << 30); + + schema.subschemas = Some(Box::new(schemars::schema::SubschemaValidation { + all_of: Some(vec![ + schemars::schema::Schema::new_ref( + "#/components/schemas/ByteCount".to_string(), + ), + schemars::schema::SchemaObject { + number: Some(Box::new(schemars::schema::NumberValidation { + minimum: Some(MIN_DISK_SIZE_BYTES as f64), + maximum: Some(MAX_DISK_SIZE_BYTES as f64), + ..Default::default() + })), + ..ByteCount::json_schema(gen).into() + } + .into(), + ]), + ..Default::default() + })); + + // schema.reference = Some("#/components/schemas/ByteCount".to_string()); schema.metadata().description = Some( format!("total size of the disk in bytes.\n\nMust be between {min_disk} and {max_disk} GiB.") ); - schema.number().minimum = Some(MIN_DISK_SIZE_BYTES as f64); - schema.number().maximum = Some(MAX_DISK_SIZE_BYTES as f64); + // schema.number().minimum = Some(MIN_DISK_SIZE_BYTES as f64); + // schema.number().maximum = Some(MAX_DISK_SIZE_BYTES as f64); schema.into() }