From e5d5317adbbd13879b38ee2e761b8298fa320192 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Wed, 14 Jul 2021 14:05:42 -0700 Subject: [PATCH 01/14] Adds basic types to represent VPCs, subnets, and NICs. - Adds the `VPC`, `VPCSubnet` and `VNIC` types, including internal control plane representations, client views, and database types. - Implements some required traits for generating JSON schema and serializing to/from PostgreSQL wire formats. Note that the MAC address type is serialized in the database as a string, as CockroachDB doesn't currently support the PostgreSQL MACADDR type. --- Cargo.lock | 19 ++- omicron-common/Cargo.toml | 9 + omicron-common/src/api/model.rs | 275 +++++++++++++++++++++++++++++- omicron-common/src/model_db.rs | 160 +++++++++++++++++ omicron-common/src/sql/dbinit.sql | 67 ++++++++ omicron-nexus/src/db/schema.rs | 59 +++++++ 6 files changed, 586 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5528109e62..2e8f3113913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -914,9 +914,12 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +dependencies = [ + "serde", +] [[package]] name = "itertools" @@ -978,6 +981,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "macaddr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baee0bbc17ce759db233beb01648088061bf678383130602a298e6998eedb2d8" +dependencies = [ + "serde", +] + [[package]] name = "maplit" version = "1.0.2" @@ -1210,7 +1222,10 @@ dependencies = [ "futures", "http", "hyper", + "ipnet", "libc", + "macaddr", + "postgres-protocol", "propolis-server", "rayon", "reqwest", diff --git a/omicron-common/Cargo.toml b/omicron-common/Cargo.toml index 97d28d175a7..e0cc6b74e27 100644 --- a/omicron-common/Cargo.toml +++ b/omicron-common/Cargo.toml @@ -11,6 +11,7 @@ http = "0.2.0" hyper = "0.14" libc = "0.2.98" propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "b6da043d" } +postgres-protocol = "0.6.1" rayon = "1.5" reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } ring = "0.16" @@ -41,6 +42,14 @@ features = [ "serde" ] git = "https://github.com/oxidecomputer/dropshot" branch = "main" +[dependencies.ipnet] +version = "2.3.1" +features = [ "serde" ] + +[dependencies.macaddr] +version = "1.0.1" +features = [ "serde_std" ] + [dependencies.schemars] version = "0.8" features = [ "chrono", "uuid" ] diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index d974748f308..cceb3b89928 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -24,7 +24,7 @@ use std::fmt::Debug; use std::fmt::Display; use std::fmt::Formatter; use std::fmt::Result as FormatResult; -use std::net::SocketAddr; +use std::net::{IpAddr, SocketAddr}; use std::num::NonZeroU32; use std::time::Duration; use uuid::Uuid; @@ -1313,6 +1313,279 @@ impl From for SagaStateView { } } +/// A Virtual Private Cloud (VPC) object. +#[derive(Clone, Debug)] +pub struct VPC { + /** common identifying metadata */ + pub identity: IdentityMetadata, + // TODO: Implement project-scoping + // /** id for the project containing this Instance */ + // pub project_id: Uuid, +} + +/// Client view onto a `VPC` object. +#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct VPCView { + #[serde(flatten)] + pub identity: IdentityMetadata, + // TODO: Implement project-scoping + // /** id for the project containing this Instance */ + // pub project_id: Uuid, +} + +impl Object for VPC { + type View = VPCView; + fn to_view(&self) -> Self::View { + VPCView { identity: self.identity.clone() } + } +} + +/// An `IpNet` represents a IP subnetwork (v4 or v6), including the address and network mask. +// NOTE: We're using the `ipnet` crate's implementation, but we wrap it in a newtype because that +// crate does not implement `JsonSchema` and Rust's orphan rules prevent us from implementing the +// trait directly on the type. +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub struct IpNet(pub ipnet::IpNet); + +impl std::ops::Deref for IpNet { + type Target = ipnet::IpNet; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::fmt::Display for IpNet { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl JsonSchema for IpNet { + fn schema_name() -> String { + "IpNet".to_string() + } + + fn json_schema( + _: &mut schemars::gen::SchemaGenerator, + ) -> schemars::schema::Schema { + schemars::schema::Schema::Object( + schemars::schema::SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + id: None, + title: Some("An IP subnet".to_string()), + description: Some("An IPv4 or IPv6 subnet, including prefix and subnet mask".to_string()), + default: None, + deprecated: false, + read_only: false, + write_only: false, + examples: vec!["192.168.1.0/24".into(), "fd12:3456::/64".into()], + })), + instance_type: Some(schemars::schema::SingleOrVec::Single(Box::new(schemars::schema::InstanceType::String))), + format: None, + enum_values: None, + const_value: None, + subschemas: None, + number: None, + string: Some(Box::new(schemars::schema::StringValidation { + max_length: Some(23), // fully-specified IPv6, slash and 3-digit mask + min_length: None, + // This regex validator is inspired by https://ihateregex.io/expr/ipv{4,6} + // Note that the regex is more permissive than we intend to be in the final + // API. This passes _any_ IPs, while we're likely going to restrict them to the + // private address space for v4 for example (RFD 21 sec 2.2). + pattern: Some( + r#"(^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$)"#.to_string() + ), + })), + array: None, + object: None, + reference: None, + extensions: BTreeMap::new(), + } + ) + } +} + +/// An IP subnet within a VPC. +#[derive(Clone, Debug)] +pub struct VPCSubnet { + /** common identifying metadata */ + pub identity: IdentityMetadata, + + // TODO: Implement project-scoping + // /** id for the project containing this Instance */ + // pub project_id: Uuid, + /** The VPC to which the subnet belongs. */ + pub vpc_id: Uuid, + + // TODO-correctness: RFD 21 sec 3.5 indicates that users may specify both v4 and v6 subnets in + // a single API call, but does not explicitly say if either is required. Clearly, one of them + // has to be specified, and most cloud providers require v4 and make v6 optional. However, RFD + // hints that users _might_ be able to specify v6 and not v4 (and maybe that the omitted block + // will be added by default). + /** The IPv4 subnet CIDR block. */ + pub ipv4_block: Option, + + /** The IPv4 subnet CIDR block. */ + pub ipv6_block: Option, +} + +impl Object for VPCSubnet { + type View = VPCSubnetView; + fn to_view(&self) -> Self::View { + VPCSubnetView { + identity: self.identity.clone(), + vpc_id: self.vpc_id, + ipv4_block: self.ipv4_block, + ipv6_block: self.ipv6_block, + } + } +} + +/// Client view onto a `VPCSubnet` object. +#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct VPCSubnetView { + #[serde(flatten)] + pub identity: IdentityMetadata, + + // TODO: Implement project-scoping + // /** id for the project containing this Instance */ + // pub project_id: Uuid, + /** The VPC to which the subnet belongs. */ + pub vpc_id: Uuid, + + /** The IPv4 subnetwork. */ + pub ipv4_block: Option, + + /** The IPv6 subnetwork. */ + pub ipv6_block: Option, +} + +/// The `MacAddr` represents a Media Access Control (MAC) address, used to uniquely identify +/// hardware devices on a network. +// NOTE: We're using the `macaddr` crate for the internal representation. But as with the `ipnet`, +// this crate does not implement `JsonSchema`, nor the the SQL conversion traits `FromSql` and +// `ToSql`. +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub struct MacAddr(pub macaddr::MacAddr6); + +impl std::ops::Deref for MacAddr { + type Target = macaddr::MacAddr6; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::fmt::Display for MacAddr { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl JsonSchema for MacAddr { + fn schema_name() -> String { + "MacAddr".to_string() + } + + fn json_schema( + _: &mut schemars::gen::SchemaGenerator, + ) -> schemars::schema::Schema { + schemars::schema::Schema::Object(schemars::schema::SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + id: None, + title: Some("A MAC address".to_string()), + description: Some( + "A Media Access Control address, in EUI-48 format" + .to_string(), + ), + default: None, + deprecated: false, + read_only: false, + write_only: false, + examples: vec!["ff:ff:ff:ff:ff:ff".into()], + })), + instance_type: Some(schemars::schema::SingleOrVec::Single( + Box::new(schemars::schema::InstanceType::String), + )), + format: None, + enum_values: None, + const_value: None, + subschemas: None, + number: None, + string: Some(Box::new(schemars::schema::StringValidation { + max_length: Some(17), // 12 hex characters and 5 ":"-separators + min_length: Some(17), + pattern: Some( + r#"^([0-8a-fA-F]{2}:){5}[0-8a-fA-F]{2}$"#.to_string(), + ), + })), + array: None, + object: None, + reference: None, + extensions: BTreeMap::new(), + }) + } +} + +/// A `VNIC` represents a virtual network interface device. +#[derive(Clone, Debug)] +pub struct VNIC { + /** common identifying metadata */ + pub identity: IdentityMetadata, + + // TODO: Implement project-scoping + // /** id for the project containing this Instance */ + // pub project_id: Uuid, + /** The VPC to which the NIC belongs. */ + pub vpc_id: Uuid, + + /** The subnet to which the NIC belongs. */ + pub subnet_id: Uuid, + + /** The MAC address assigned to this NIC. */ + pub mac: MacAddr, + + /** The IP address assigned to this NIC. */ + pub ip: IpAddr, +} + +impl Object for VNIC { + type View = VNICView; + fn to_view(&self) -> Self::View { + VNICView { + identity: self.identity.clone(), + vpc_id: self.vpc_id, + subnet_id: self.subnet_id, + mac: self.mac, + ip: self.ip, + } + } +} + +/// Client view onto a `VNIC` object. +#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct VNICView { + #[serde(flatten)] + pub identity: IdentityMetadata, + + // TODO: Implement project-scoping + // pub project_id: Uuid, + /** The VPC to which the NIC belongs. */ + pub vpc_id: Uuid, + + /** The subnet to which the NIC belongs. */ + pub subnet_id: Uuid, + + /** The MAC address assigned to this NIC. */ + pub mac: MacAddr, + + /** The IP address assigned to this NIC. */ + pub ip: IpAddr, +} + /* * Internal Control Plane API objects */ diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index fd35dedc922..7da347e9a5e 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -65,11 +65,16 @@ use crate::api::Instance; use crate::api::InstanceCpuCount; use crate::api::InstanceRuntimeState; use crate::api::InstanceState; +use crate::api::IpNet; +use crate::api::MacAddr; use crate::api::Name; use crate::api::OximeterAssignment; use crate::api::OximeterInfo; use crate::api::ProducerEndpoint; use crate::api::Project; +use crate::api::VPCSubnet; +use crate::api::VNIC; +use crate::api::VPC; use crate::bail_unless; use chrono::DateTime; use chrono::Utc; @@ -130,6 +135,82 @@ impl_sql_wrapping!(Generation, i64); impl_sql_wrapping!(InstanceCpuCount, i64); impl_sql_wrapping!(Name, &str); +// Conversion to/from SQL types for IpNet. +// +// Although there are implementations that convert an IP _address_ to and from PostgreSQL types, +// there does not appear to be any existing implementation that converts a _subnet_, including the +// address and mask, to and from SQL types. At least, not for the 3rd-party crate `ipnet` we're +// using to actually represent a subnet. +impl tokio_postgres::types::ToSql for IpNet { + fn to_sql( + &self, + _ty: &tokio_postgres::types::Type, + out: &mut tokio_postgres::types::private::BytesMut, + ) -> Result< + tokio_postgres::types::IsNull, + Box, + > { + postgres_protocol::types::inet_to_sql( + self.addr(), + self.prefix_len(), + out, + ); + Ok(tokio_postgres::types::IsNull::No) + } + + fn accepts(ty: &tokio_postgres::types::Type) -> bool { + matches!(ty, &tokio_postgres::types::Type::INET) + } + + tokio_postgres::types::to_sql_checked!(); +} + +impl<'a> tokio_postgres::types::FromSql<'a> for IpNet { + fn from_sql( + _ty: &tokio_postgres::types::Type, + raw: &'a [u8], + ) -> Result> { + let value = postgres_protocol::types::inet_from_sql(raw)?; + let (addr, mask) = (value.addr(), value.netmask()); + let subnet = match addr { + std::net::IpAddr::V4(addr) => { + ipnet::Ipv4Net::new(addr, mask)?.into() + } + std::net::IpAddr::V6(addr) => { + ipnet::Ipv6Net::new(addr, mask)?.into() + } + }; + Ok(IpNet(subnet)) + } + + fn accepts(ty: &tokio_postgres::types::Type) -> bool { + matches!(ty, &tokio_postgres::types::Type::INET) + } +} + +// Conversion to/from SQL types for MacAddr. +// +// As with the IP subnet above, there's no existing crate for MAC addresses that satisfies all our +// needs. The `eui48` crate implements SQL conversions, but not `Serialize`/`Deserialize` or +// `JsonSchema`. The `macaddr` crate implements serialization, but not the other two. Since +// serialization is more annoying that the others, we choose the latter, so we're implementing the +// SQL serialization here. CockroachDB does not currently support the Postgres MACADDR type, so +// we're storing it as a CHAR(17), 12 characters for the hexadecimal and 5 ":"-separators. +impl From<&MacAddr> for String { + fn from(addr: &MacAddr) -> String { + format!("{}", addr) + } +} + +impl TryFrom for MacAddr { + type Error = macaddr::ParseError; + + fn try_from(s: String) -> Result { + s.parse().map(|addr| MacAddr(addr)) + } +} +impl_sql_wrapping!(MacAddr, String); + /* * TryFrom impls used for more complex Rust types */ @@ -317,3 +398,82 @@ impl TryFrom<&tokio_postgres::Row> for OximeterAssignment { Ok(Self { oximeter_id, producer_id }) } } + +/// Load an [`VPC`] from a row in the `VPC` table. +impl TryFrom<&tokio_postgres::Row> for VPC { + type Error = Error; + + fn try_from(value: &tokio_postgres::Row) -> Result { + Ok(Self { identity: IdentityMetadata::try_from(value)? }) + } +} + +/// Load an [`VPCSubnet`] from a row in the `VPCSubnet` table. +impl TryFrom<&tokio_postgres::Row> for VPCSubnet { + type Error = Error; + + fn try_from(value: &tokio_postgres::Row) -> Result { + Ok(Self { + identity: IdentityMetadata::try_from(value)?, + vpc_id: sql_row_value(value, "vpc_id")?, + ipv4_block: sql_row_value(value, "ipv4_block")?, + ipv6_block: sql_row_value(value, "ipv6_block")?, + }) + } +} + +/// Load an [`VPC`] from a row in the `VNIC` table. +impl TryFrom<&tokio_postgres::Row> for VNIC { + type Error = Error; + + fn try_from(value: &tokio_postgres::Row) -> Result { + Ok(Self { + identity: IdentityMetadata::try_from(value)?, + vpc_id: sql_row_value(value, "vpc_id")?, + subnet_id: sql_row_value(value, "subnet_id")?, + mac: sql_row_value(value, "mac")?, + ip: sql_row_value(value, "ip")?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use tokio_postgres::types::private::BytesMut; + use tokio_postgres::types::{FromSql, ToSql}; + + #[test] + fn test_ipnet_conversion() { + let subnet = IpNet("192.168.1.0/24".parse().unwrap()); + let ty = tokio_postgres::types::Type::INET; + let mut buf = BytesMut::with_capacity(128); + let is_null = subnet.to_sql(&ty, &mut buf).unwrap(); + assert!(matches!(is_null, tokio_postgres::types::IsNull::No)); + let from_sql = IpNet::from_sql(&ty, &buf).unwrap(); + assert_eq!(subnet, from_sql); + assert_eq!( + from_sql.addr(), + "192.168.1.0".parse::().unwrap() + ); + assert_eq!(from_sql.prefix_len(), 24); + + let bad = b"some-bad-net"; + assert!(IpNet::from_sql(&ty, &bad[..]).is_err()); + } + + #[test] + fn test_macaddr_conversion() { + let mac = MacAddr([0xAFu8; 6].into()); + let ty = tokio_postgres::types::Type::MACADDR; + let mut buf = BytesMut::with_capacity(128); + let is_null = mac.to_sql(&ty, &mut buf).unwrap(); + assert!(matches!(is_null, tokio_postgres::types::IsNull::No)); + let from_sql = MacAddr::from_sql(&ty, &buf).unwrap(); + assert_eq!(mac, from_sql); + assert_eq!(from_sql.into_array(), [0xaf; 6]); + + let bad = b"not:a:mac:addr"; + assert!(MacAddr::from_sql(&ty, &bad[..]).is_err()); + } +} diff --git a/omicron-common/src/sql/dbinit.sql b/omicron-common/src/sql/dbinit.sql index d7693711d11..8ef61f628c2 100644 --- a/omicron-common/src/sql/dbinit.sql +++ b/omicron-common/src/sql/dbinit.sql @@ -245,6 +245,73 @@ CREATE TABLE omicron.public.OximeterAssignment ( CONSTRAINT "primary" PRIMARY KEY (oximeter_id, producer_id) ); +/* + * VPCs and networking primitives + */ + +CREATE TABLE omicron.public.VPC ( + /* Identity metadata */ + id UUID PRIMARY KEY, + name STRING(63) NOT NULL, + description STRING(512) NOT NULL, + time_created TIMESTAMPTZ NOT NULL, + time_modified TIMESTAMPTZ NOT NULL, + /* Indicates that the object has been deleted */ + time_deleted TIMESTAMPTZ + /* TODO: Add project-scoping. + * project_id UUID NOT NULL REFERENCES omicron.public.Project (id), + */ +); + +-- TODO: add project_id to index +CREATE UNIQUE INDEX ON omicron.public.VPC ( + name +) WHERE + time_deleted IS NULL; + +CREATE TABLE omicron.public.VPCSubnet ( + /* Identity metadata */ + id UUID PRIMARY KEY, + name STRING(63) NOT NULL, + description STRING(512) NOT NULL, + time_created TIMESTAMPTZ NOT NULL, + time_modified TIMESTAMPTZ NOT NULL, + /* Indicates that the object has been deleted */ + time_deleted TIMESTAMPTZ, + vpc_id UUID NOT NULL, + ipv4_block INET, + ipv6_block INET +); + +-- TODO: add project_id to index +CREATE UNIQUE INDEX ON omicron.public.VPCSubnet ( + name +) WHERE + time_deleted IS NULL; + +CREATE TABLE omicron.public.VNIC ( + /* Identity metadata */ + id UUID PRIMARY KEY, + name STRING(63) NOT NULL, + description STRING(512) NOT NULL, + time_created TIMESTAMPTZ NOT NULL, + time_modified TIMESTAMPTZ NOT NULL, + /* Indicates that the object has been deleted */ + time_deleted TIMESTAMPTZ, + /* FK into VPC table */ + vpc_id UUID NOT NULL, + /* FK into VPCSubnet table. */ + subnet_id UUID NOT NULL, + mac CHAR(17) NOT NULL, -- 6 octets in hex -> 12 characters, plus 5 ":" separators + ip INET NOT NULL +); + +-- TODO: add project_id to index +CREATE UNIQUE INDEX ON omicron.public.VNIC ( + name +) WHERE + time_deleted IS NULL; + /*******************************************************************/ /* diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index b289c03a912..13ca4342bb1 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -152,6 +152,61 @@ impl Table for OximeterAssignment { &["oximeter_id", "producer_id", "time_created"]; } +/** Describes the "VPC" table */ +pub struct VPC; +impl Table for VPC { + type ModelType = api::VPC; + const TABLE_NAME: &'static str = "VPC"; + const ALL_COLUMNS: &'static [&'static str] = &[ + "id", + "name", + "description", + "time_created", + "time_modified", + "time_deleted", + // TODO: Add project-scoping: "project_id", + ]; +} + +/** Describes the "VPCSubnet" table */ +pub struct VPCSubnet; +impl Table for VPCSubnet { + type ModelType = api::VPCSubnet; + const TABLE_NAME: &'static str = "VPCSubnet"; + const ALL_COLUMNS: &'static [&'static str] = &[ + "id", + "name", + "description", + "time_created", + "time_modified", + "time_deleted", + // TODO: Add project-scoping: "project_id", + "vpc_id", + "ipv4_block", + "ipv6_block", + ]; +} + +/** Describes the "VNIC" table */ +pub struct VNIC; +impl Table for VNIC { + type ModelType = api::VNIC; + const TABLE_NAME: &'static str = "VNIC"; + const ALL_COLUMNS: &'static [&'static str] = &[ + "id", + "name", + "description", + "time_created", + "time_modified", + "time_deleted", + // TODO: Add project-scoping: "project_id", + "vpc_id", + "subnet_id", + "mac", + "ip", + ]; +} + #[cfg(test)] mod test { use super::Disk; @@ -161,6 +216,7 @@ mod test { use super::SagaNodeEvent; use super::Table; use super::{MetricProducer, Oximeter, OximeterAssignment}; + use super::{VPCSubnet, VNIC, VPC}; use omicron_common::dev; use std::collections::BTreeSet; use tokio_postgres::types::ToSql; @@ -189,6 +245,9 @@ mod test { check_table_schema::(&client).await; check_table_schema::(&client).await; check_table_schema::(&client).await; + check_table_schema::(&client).await; + check_table_schema::(&client).await; + check_table_schema::(&client).await; database.cleanup().await.expect("failed to clean up database"); logctx.cleanup_successful(); From 8e3dc47532aacbf4a81d191fa91c9b3eb1c16320 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Mon, 19 Jul 2021 16:01:01 -0700 Subject: [PATCH 02/14] Splits IP v4 and v6 subnet types --- omicron-common/src/api/model.rs | 220 ++++++++++++-------------------- omicron-common/src/model_db.rs | 100 +++++++++++---- 2 files changed, 161 insertions(+), 159 deletions(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index cceb3b89928..1e59fc5065c 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -1323,47 +1323,82 @@ pub struct VPC { // pub project_id: Uuid, } -/// Client view onto a `VPC` object. -#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct VPCView { - #[serde(flatten)] - pub identity: IdentityMetadata, - // TODO: Implement project-scoping - // /** id for the project containing this Instance */ - // pub project_id: Uuid, +/// An `Ipv4Net` represents a IPv4 subnetwork, including the address and network mask. +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub struct Ipv4Net(pub ipnet::Ipv4Net); + +impl std::ops::Deref for Ipv4Net { + type Target = ipnet::Ipv4Net; + fn deref(&self) -> &Self::Target { + &self.0 + } } -impl Object for VPC { - type View = VPCView; - fn to_view(&self) -> Self::View { - VPCView { identity: self.identity.clone() } +impl std::fmt::Display for Ipv4Net { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) } } -/// An `IpNet` represents a IP subnetwork (v4 or v6), including the address and network mask. -// NOTE: We're using the `ipnet` crate's implementation, but we wrap it in a newtype because that -// crate does not implement `JsonSchema` and Rust's orphan rules prevent us from implementing the -// trait directly on the type. +impl JsonSchema for Ipv4Net { + fn schema_name() -> String { + "Ipv4Net".to_string() + } + + fn json_schema( + _: &mut schemars::gen::SchemaGenerator, + ) -> schemars::schema::Schema { + schemars::schema::Schema::Object( + schemars::schema::SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + title: Some("An IPv4 subnet".to_string()), + description: Some("An IPv4 subnet, including prefix and subnet mask".to_string()), + examples: vec!["192.168.1.0/24".into()], + ..Default::default() + })), + instance_type: Some(schemars::schema::SingleOrVec::Single(Box::new(schemars::schema::InstanceType::String))), + string: Some(Box::new(schemars::schema::StringValidation { + // Fully-specified IPv4 address. Up to 15 chars for address, plus slash and up to 2 subnet digits. + max_length: Some(18), + min_length: None, + // Addresses must be from an RFC 1918 private address space + pattern: Some( + concat!( + // 10.x.x.x/8 + r#"^(10\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9]\.){2}(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[0-9]|2[0-8]|[8-9]))$"#, + // 172.16.x.x/12 + r#"^(172\.16\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[2-9]|2[0-8]))$"#, + // 192.168.x.x/16 + r#"^(192\.168\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[6-9]|2[0-8]))$"#, + ).to_string(), + ), + })), + ..Default::default() + } + ) + } +} + +/// An `Ipv6Net` represents a IPv6 subnetwork, including the address and network mask. #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub struct IpNet(pub ipnet::IpNet); +pub struct Ipv6Net(pub ipnet::Ipv6Net); -impl std::ops::Deref for IpNet { - type Target = ipnet::IpNet; +impl std::ops::Deref for Ipv6Net { + type Target = ipnet::Ipv6Net; fn deref(&self) -> &Self::Target { &self.0 } } -impl std::fmt::Display for IpNet { +impl std::fmt::Display for Ipv6Net { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.0) } } -impl JsonSchema for IpNet { +impl JsonSchema for Ipv6Net { fn schema_name() -> String { - "IpNet".to_string() + "Ipv6Net".to_string() } fn json_schema( @@ -1372,42 +1407,32 @@ impl JsonSchema for IpNet { schemars::schema::Schema::Object( schemars::schema::SchemaObject { metadata: Some(Box::new(schemars::schema::Metadata { - id: None, - title: Some("An IP subnet".to_string()), - description: Some("An IPv4 or IPv6 subnet, including prefix and subnet mask".to_string()), - default: None, - deprecated: false, - read_only: false, - write_only: false, - examples: vec!["192.168.1.0/24".into(), "fd12:3456::/64".into()], + title: Some("An IPv6 subnet".to_string()), + description: Some("An IPv6 subnet, including prefix and subnet mask".to_string()), + examples: vec!["fd12:3456::/64".into()], + ..Default::default() })), instance_type: Some(schemars::schema::SingleOrVec::Single(Box::new(schemars::schema::InstanceType::String))), - format: None, - enum_values: None, - const_value: None, - subschemas: None, - number: None, string: Some(Box::new(schemars::schema::StringValidation { - max_length: Some(23), // fully-specified IPv6, slash and 3-digit mask + // Fully-specified IPv6 address. 4 hex chars per segment, 8 segments, 7 + // ":"-separators, slash and up to 3 subnet digits + max_length: Some(43), min_length: None, - // This regex validator is inspired by https://ihateregex.io/expr/ipv{4,6} - // Note that the regex is more permissive than we intend to be in the final - // API. This passes _any_ IPs, while we're likely going to restrict them to the - // private address space for v4 for example (RFD 21 sec 2.2). pattern: Some( - r#"(^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$)"#.to_string() + // Conforming to unique local addressing scheme, `fd00::/8` + concat!( + r#"^(fd|FD)00:((([0-8a-fA-F]{1,4}\:){6}[0-8a-fA-F]{1,4})|(([0-8a-fA-F]{1,4}:){1,6}:))/(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-6])$"#, + ).to_string(), ), })), - array: None, - object: None, - reference: None, - extensions: BTreeMap::new(), + ..Default::default() } ) } } -/// An IP subnet within a VPC. +/// A VPC subnet represents a logical grouping for instances that allows network traffic between +/// them, within a IPv4 subnetwork or optionall an IPv6 subnetwork. #[derive(Clone, Debug)] pub struct VPCSubnet { /** common identifying metadata */ @@ -1419,48 +1444,18 @@ pub struct VPCSubnet { /** The VPC to which the subnet belongs. */ pub vpc_id: Uuid, - // TODO-correctness: RFD 21 sec 3.5 indicates that users may specify both v4 and v6 subnets in - // a single API call, but does not explicitly say if either is required. Clearly, one of them - // has to be specified, and most cloud providers require v4 and make v6 optional. However, RFD - // hints that users _might_ be able to specify v6 and not v4 (and maybe that the omitted block - // will be added by default). - /** The IPv4 subnet CIDR block. */ - pub ipv4_block: Option, - + // TODO-design: RFD 21 says that V4 subnets are currently required, and V6 are optional. If a + // V6 address is _not_ specified, one is created with a prefix that depends on the VPC and a + // unique subnet-specific portion of the prefix (40 and 16 bits for each, respectively). + // + // We're leaving out the "view" types here for the external HTTP API for now, so it's not clear + // how to do the validation of user-specified CIDR blocks, or how to create a block if one is + // not given. /** The IPv4 subnet CIDR block. */ - pub ipv6_block: Option, -} + pub ipv4_block: Option, -impl Object for VPCSubnet { - type View = VPCSubnetView; - fn to_view(&self) -> Self::View { - VPCSubnetView { - identity: self.identity.clone(), - vpc_id: self.vpc_id, - ipv4_block: self.ipv4_block, - ipv6_block: self.ipv6_block, - } - } -} - -/// Client view onto a `VPCSubnet` object. -#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct VPCSubnetView { - #[serde(flatten)] - pub identity: IdentityMetadata, - - // TODO: Implement project-scoping - // /** id for the project containing this Instance */ - // pub project_id: Uuid, - /** The VPC to which the subnet belongs. */ - pub vpc_id: Uuid, - - /** The IPv4 subnetwork. */ - pub ipv4_block: Option, - - /** The IPv6 subnetwork. */ - pub ipv6_block: Option, + /** The IPv6 subnet CIDR block. */ + pub ipv6_block: Option, } /// The `MacAddr` represents a Media Access Control (MAC) address, used to uniquely identify @@ -1494,26 +1489,17 @@ impl JsonSchema for MacAddr { ) -> schemars::schema::Schema { schemars::schema::Schema::Object(schemars::schema::SchemaObject { metadata: Some(Box::new(schemars::schema::Metadata { - id: None, title: Some("A MAC address".to_string()), description: Some( "A Media Access Control address, in EUI-48 format" .to_string(), ), - default: None, - deprecated: false, - read_only: false, - write_only: false, examples: vec!["ff:ff:ff:ff:ff:ff".into()], + ..Default::default() })), instance_type: Some(schemars::schema::SingleOrVec::Single( Box::new(schemars::schema::InstanceType::String), )), - format: None, - enum_values: None, - const_value: None, - subschemas: None, - number: None, string: Some(Box::new(schemars::schema::StringValidation { max_length: Some(17), // 12 hex characters and 5 ":"-separators min_length: Some(17), @@ -1521,10 +1507,7 @@ impl JsonSchema for MacAddr { r#"^([0-8a-fA-F]{2}:){5}[0-8a-fA-F]{2}$"#.to_string(), ), })), - array: None, - object: None, - reference: None, - extensions: BTreeMap::new(), + ..Default::default() }) } } @@ -1551,41 +1534,6 @@ pub struct VNIC { pub ip: IpAddr, } -impl Object for VNIC { - type View = VNICView; - fn to_view(&self) -> Self::View { - VNICView { - identity: self.identity.clone(), - vpc_id: self.vpc_id, - subnet_id: self.subnet_id, - mac: self.mac, - ip: self.ip, - } - } -} - -/// Client view onto a `VNIC` object. -#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct VNICView { - #[serde(flatten)] - pub identity: IdentityMetadata, - - // TODO: Implement project-scoping - // pub project_id: Uuid, - /** The VPC to which the NIC belongs. */ - pub vpc_id: Uuid, - - /** The subnet to which the NIC belongs. */ - pub subnet_id: Uuid, - - /** The MAC address assigned to this NIC. */ - pub mac: MacAddr, - - /** The IP address assigned to this NIC. */ - pub ip: IpAddr, -} - /* * Internal Control Plane API objects */ diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 7da347e9a5e..ddfcb630055 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -65,7 +65,6 @@ use crate::api::Instance; use crate::api::InstanceCpuCount; use crate::api::InstanceRuntimeState; use crate::api::InstanceState; -use crate::api::IpNet; use crate::api::MacAddr; use crate::api::Name; use crate::api::OximeterAssignment; @@ -75,6 +74,7 @@ use crate::api::Project; use crate::api::VPCSubnet; use crate::api::VNIC; use crate::api::VPC; +use crate::api::{Ipv4Net, Ipv6Net}; use crate::bail_unless; use chrono::DateTime; use chrono::Utc; @@ -135,13 +135,8 @@ impl_sql_wrapping!(Generation, i64); impl_sql_wrapping!(InstanceCpuCount, i64); impl_sql_wrapping!(Name, &str); -// Conversion to/from SQL types for IpNet. -// -// Although there are implementations that convert an IP _address_ to and from PostgreSQL types, -// there does not appear to be any existing implementation that converts a _subnet_, including the -// address and mask, to and from SQL types. At least, not for the 3rd-party crate `ipnet` we're -// using to actually represent a subnet. -impl tokio_postgres::types::ToSql for IpNet { +// Conversion to/from SQL types for Ipv4Net. +impl tokio_postgres::types::ToSql for Ipv4Net { fn to_sql( &self, _ty: &tokio_postgres::types::Type, @@ -151,7 +146,7 @@ impl tokio_postgres::types::ToSql for IpNet { Box, > { postgres_protocol::types::inet_to_sql( - self.addr(), + self.addr().into(), self.prefix_len(), out, ); @@ -165,22 +160,62 @@ impl tokio_postgres::types::ToSql for IpNet { tokio_postgres::types::to_sql_checked!(); } -impl<'a> tokio_postgres::types::FromSql<'a> for IpNet { +impl<'a> tokio_postgres::types::FromSql<'a> for Ipv4Net { fn from_sql( _ty: &tokio_postgres::types::Type, raw: &'a [u8], ) -> Result> { let value = postgres_protocol::types::inet_from_sql(raw)?; let (addr, mask) = (value.addr(), value.netmask()); - let subnet = match addr { - std::net::IpAddr::V4(addr) => { - ipnet::Ipv4Net::new(addr, mask)?.into() - } - std::net::IpAddr::V6(addr) => { - ipnet::Ipv6Net::new(addr, mask)?.into() - } - }; - Ok(IpNet(subnet)) + if let std::net::IpAddr::V4(addr) = addr { + Ok(Ipv4Net(ipnet::Ipv4Net::new(addr, mask)?)) + } else { + panic!("Attempted to deserialize IPv6 subnet from database, expected IPv4 subnet"); + } + } + + fn accepts(ty: &tokio_postgres::types::Type) -> bool { + matches!(ty, &tokio_postgres::types::Type::INET) + } +} + +// Conversion to/from SQL types for Ipv6Net. +impl tokio_postgres::types::ToSql for Ipv6Net { + fn to_sql( + &self, + _ty: &tokio_postgres::types::Type, + out: &mut tokio_postgres::types::private::BytesMut, + ) -> Result< + tokio_postgres::types::IsNull, + Box, + > { + postgres_protocol::types::inet_to_sql( + self.addr().into(), + self.prefix_len(), + out, + ); + Ok(tokio_postgres::types::IsNull::No) + } + + fn accepts(ty: &tokio_postgres::types::Type) -> bool { + matches!(ty, &tokio_postgres::types::Type::INET) + } + + tokio_postgres::types::to_sql_checked!(); +} + +impl<'a> tokio_postgres::types::FromSql<'a> for Ipv6Net { + fn from_sql( + _ty: &tokio_postgres::types::Type, + raw: &'a [u8], + ) -> Result> { + let value = postgres_protocol::types::inet_from_sql(raw)?; + let (addr, mask) = (value.addr(), value.netmask()); + if let std::net::IpAddr::V6(addr) = addr { + Ok(Ipv6Net(ipnet::Ipv6Net::new(addr, mask)?)) + } else { + panic!("Attempted to deserialize IPv4 subnet from database, expected IPv6 subnet"); + } } fn accepts(ty: &tokio_postgres::types::Type) -> bool { @@ -444,13 +479,13 @@ mod tests { use tokio_postgres::types::{FromSql, ToSql}; #[test] - fn test_ipnet_conversion() { - let subnet = IpNet("192.168.1.0/24".parse().unwrap()); + fn test_ipv4net_conversion() { + let subnet = Ipv4Net("192.168.1.0/24".parse().unwrap()); let ty = tokio_postgres::types::Type::INET; let mut buf = BytesMut::with_capacity(128); let is_null = subnet.to_sql(&ty, &mut buf).unwrap(); assert!(matches!(is_null, tokio_postgres::types::IsNull::No)); - let from_sql = IpNet::from_sql(&ty, &buf).unwrap(); + let from_sql = Ipv4Net::from_sql(&ty, &buf).unwrap(); assert_eq!(subnet, from_sql); assert_eq!( from_sql.addr(), @@ -459,7 +494,26 @@ mod tests { assert_eq!(from_sql.prefix_len(), 24); let bad = b"some-bad-net"; - assert!(IpNet::from_sql(&ty, &bad[..]).is_err()); + assert!(Ipv4Net::from_sql(&ty, &bad[..]).is_err()); + } + + #[test] + fn test_ipv6net_conversion() { + let subnet = Ipv6Net("fd00:1234::/24".parse().unwrap()); + let ty = tokio_postgres::types::Type::INET; + let mut buf = BytesMut::with_capacity(256); + let is_null = subnet.to_sql(&ty, &mut buf).unwrap(); + assert!(matches!(is_null, tokio_postgres::types::IsNull::No)); + let from_sql = Ipv6Net::from_sql(&ty, &buf).unwrap(); + assert_eq!(subnet, from_sql); + assert_eq!( + from_sql.addr(), + "fd00:1234::".parse::().unwrap() + ); + assert_eq!(from_sql.prefix_len(), 24); + + let bad = b"some-bad-net"; + assert!(Ipv6Net::from_sql(&ty, &bad[..]).is_err()); } #[test] From 63b51d4b54c7216fcac852f13367854e816896ea Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Tue, 20 Jul 2021 09:44:28 -0700 Subject: [PATCH 03/14] Use STRING in MAC addr DB type for uniformity, and add TODO about NIC/IP table design --- omicron-common/src/sql/dbinit.sql | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/omicron-common/src/sql/dbinit.sql b/omicron-common/src/sql/dbinit.sql index 8ef61f628c2..c88df61cbd0 100644 --- a/omicron-common/src/sql/dbinit.sql +++ b/omicron-common/src/sql/dbinit.sql @@ -302,10 +302,18 @@ CREATE TABLE omicron.public.VNIC ( vpc_id UUID NOT NULL, /* FK into VPCSubnet table. */ subnet_id UUID NOT NULL, - mac CHAR(17) NOT NULL, -- 6 octets in hex -> 12 characters, plus 5 ":" separators + mac STRING(17) NOT NULL, -- e.g., "ff:ff:ff:ff:ff:ff" ip INET NOT NULL ); +/* TODO-completeness + + * We currently have a VNIC table with the IP and MAC addresses inline. + * Eventually, we'll probably want to move these to their own tables, and + * refer to them here, most notably to support multiple IPs per NIC, as well + * as moving IPs between NICs on different instances, etc. + */ + -- TODO: add project_id to index CREATE UNIQUE INDEX ON omicron.public.VNIC ( name From cef9eccdeb3969176ba917127a8fc30306ac5167 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Wed, 21 Jul 2021 08:03:42 -0700 Subject: [PATCH 04/14] Rename VNIC -> NetworkInterface --- omicron-common/src/api/model.rs | 12 ++++++------ omicron-common/src/model_db.rs | 6 +++--- omicron-common/src/sql/dbinit.sql | 6 +++--- omicron-nexus/src/db/schema.rs | 14 +++++++------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index 1e59fc5065c..f03ab8b3bf4 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -1512,25 +1512,25 @@ impl JsonSchema for MacAddr { } } -/// A `VNIC` represents a virtual network interface device. +/// A `NetworkInterface` represents a virtual network interface device. #[derive(Clone, Debug)] -pub struct VNIC { +pub struct NetworkInterface { /** common identifying metadata */ pub identity: IdentityMetadata, // TODO: Implement project-scoping // /** id for the project containing this Instance */ // pub project_id: Uuid, - /** The VPC to which the NIC belongs. */ + /** The VPC to which the interface belongs. */ pub vpc_id: Uuid, - /** The subnet to which the NIC belongs. */ + /** The subnet to which the interface belongs. */ pub subnet_id: Uuid, - /** The MAC address assigned to this NIC. */ + /** The MAC address assigned to this interface. */ pub mac: MacAddr, - /** The IP address assigned to this NIC. */ + /** The IP address assigned to this interface. */ pub ip: IpAddr, } diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index ddfcb630055..1674dd3a637 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -67,12 +67,12 @@ use crate::api::InstanceRuntimeState; use crate::api::InstanceState; use crate::api::MacAddr; use crate::api::Name; +use crate::api::NetworkInterface; use crate::api::OximeterAssignment; use crate::api::OximeterInfo; use crate::api::ProducerEndpoint; use crate::api::Project; use crate::api::VPCSubnet; -use crate::api::VNIC; use crate::api::VPC; use crate::api::{Ipv4Net, Ipv6Net}; use crate::bail_unless; @@ -457,8 +457,8 @@ impl TryFrom<&tokio_postgres::Row> for VPCSubnet { } } -/// Load an [`VPC`] from a row in the `VNIC` table. -impl TryFrom<&tokio_postgres::Row> for VNIC { +/// Load a [`NetworkInterface`] from a row in the `NetworkInterface` table. +impl TryFrom<&tokio_postgres::Row> for NetworkInterface { type Error = Error; fn try_from(value: &tokio_postgres::Row) -> Result { diff --git a/omicron-common/src/sql/dbinit.sql b/omicron-common/src/sql/dbinit.sql index c88df61cbd0..54b02890d7d 100644 --- a/omicron-common/src/sql/dbinit.sql +++ b/omicron-common/src/sql/dbinit.sql @@ -289,7 +289,7 @@ CREATE UNIQUE INDEX ON omicron.public.VPCSubnet ( ) WHERE time_deleted IS NULL; -CREATE TABLE omicron.public.VNIC ( +CREATE TABLE omicron.public.NetworkInterface ( /* Identity metadata */ id UUID PRIMARY KEY, name STRING(63) NOT NULL, @@ -308,14 +308,14 @@ CREATE TABLE omicron.public.VNIC ( /* TODO-completeness - * We currently have a VNIC table with the IP and MAC addresses inline. + * We currently have a NetworkInterface table with the IP and MAC addresses inline. * Eventually, we'll probably want to move these to their own tables, and * refer to them here, most notably to support multiple IPs per NIC, as well * as moving IPs between NICs on different instances, etc. */ -- TODO: add project_id to index -CREATE UNIQUE INDEX ON omicron.public.VNIC ( +CREATE UNIQUE INDEX ON omicron.public.NetworkInterface ( name ) WHERE time_deleted IS NULL; diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index 13ca4342bb1..b3b9893aa41 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -187,11 +187,11 @@ impl Table for VPCSubnet { ]; } -/** Describes the "VNIC" table */ -pub struct VNIC; -impl Table for VNIC { - type ModelType = api::VNIC; - const TABLE_NAME: &'static str = "VNIC"; +/** Describes the "NetworkInterface" table */ +pub struct NetworkInterface; +impl Table for NetworkInterface { + type ModelType = api::NetworkInterface; + const TABLE_NAME: &'static str = "NetworkInterface"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", "name", @@ -216,7 +216,7 @@ mod test { use super::SagaNodeEvent; use super::Table; use super::{MetricProducer, Oximeter, OximeterAssignment}; - use super::{VPCSubnet, VNIC, VPC}; + use super::{NetworkInterface, VPCSubnet, VPC}; use omicron_common::dev; use std::collections::BTreeSet; use tokio_postgres::types::ToSql; @@ -247,7 +247,7 @@ mod test { check_table_schema::(&client).await; check_table_schema::(&client).await; check_table_schema::(&client).await; - check_table_schema::(&client).await; + check_table_schema::(&client).await; database.cleanup().await.expect("failed to clean up database"); logctx.cleanup_successful(); From 7a4021bd306d1d925431f15d8aa33ab32d234780 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Wed, 21 Jul 2021 08:39:53 -0700 Subject: [PATCH 05/14] Add serialization derives to NetworkInterface --- omicron-common/src/api/model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index f03ab8b3bf4..816686f6a30 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -1513,7 +1513,7 @@ impl JsonSchema for MacAddr { } /// A `NetworkInterface` represents a virtual network interface device. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)] pub struct NetworkInterface { /** common identifying metadata */ pub identity: IdentityMetadata, From 32e2c7602ac47dfeb6c15f62af64a6f0a0c999ed Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 13:45:46 -0400 Subject: [PATCH 06/14] Split internal/external, though everything is external rn --- .../src/bootstrap_agent.rs | 4 +- .../src/bootstrap_agent_client.rs | 6 +- .../src/http_entrypoints.rs | 2 +- .../src/api/{ => external}/error.rs | 6 +- .../src/api/{ => external}/http_pagination.rs | 13 ++- .../src/api/{model.rs => external/mod.rs} | 8 +- omicron-common/src/api/internal/mod.rs | 4 + omicron-common/src/api/internal/nexus.rs | 0 omicron-common/src/api/internal/sled_agent.rs | 0 omicron-common/src/api/mod.rs | 8 +- omicron-common/src/collection.rs | 10 +- omicron-common/src/db.rs | 2 +- omicron-common/src/http_client.rs | 2 +- omicron-common/src/model_db.rs | 34 +++---- omicron-common/src/nexus_client.rs | 8 +- omicron-common/src/oximeter_client.rs | 4 +- omicron-common/src/sled_agent_client.rs | 14 +-- omicron-nexus/src/db/conversions.rs | 22 ++--- omicron-nexus/src/db/datastore.rs | 96 +++++++++---------- omicron-nexus/src/db/operations.rs | 2 +- omicron-nexus/src/db/pool.rs | 2 +- omicron-nexus/src/db/saga_recovery.rs | 2 +- omicron-nexus/src/db/saga_types.rs | 4 +- omicron-nexus/src/db/schema.rs | 16 ++-- omicron-nexus/src/db/sec_store.rs | 2 +- omicron-nexus/src/db/sql.rs | 6 +- omicron-nexus/src/db/sql_operations.rs | 10 +- .../src/http_entrypoints_external.rs | 56 +++++------ .../src/http_entrypoints_internal.rs | 10 +- omicron-nexus/src/nexus.rs | 62 ++++++------ omicron-nexus/src/saga_interface.rs | 4 +- omicron-nexus/src/sagas.rs | 12 +-- omicron-nexus/tests/common/mod.rs | 4 +- omicron-nexus/tests/test_basic.rs | 14 +-- omicron-nexus/tests/test_disks.rs | 24 ++--- omicron-nexus/tests/test_instances.rs | 18 ++-- omicron-sled-agent/src/common/disk.rs | 8 +- omicron-sled-agent/src/common/instance.rs | 12 +-- omicron-sled-agent/src/http_entrypoints.rs | 8 +- omicron-sled-agent/src/illumos/dladm.rs | 2 +- omicron-sled-agent/src/illumos/mod.rs | 2 +- omicron-sled-agent/src/illumos/svc.rs | 2 +- omicron-sled-agent/src/illumos/zfs.rs | 2 +- omicron-sled-agent/src/illumos/zone.rs | 2 +- omicron-sled-agent/src/instance.rs | 8 +- omicron-sled-agent/src/instance_manager.rs | 6 +- omicron-sled-agent/src/mocks/mod.rs | 6 +- omicron-sled-agent/src/server.rs | 2 +- omicron-sled-agent/src/sim/collection.rs | 20 ++-- omicron-sled-agent/src/sim/disk.rs | 10 +- .../src/sim/http_entrypoints.rs | 8 +- omicron-sled-agent/src/sim/instance.rs | 12 +-- omicron-sled-agent/src/sim/server.rs | 2 +- omicron-sled-agent/src/sim/simulatable.rs | 4 +- omicron-sled-agent/src/sim/sled_agent.rs | 10 +- omicron-sled-agent/src/sled_agent.rs | 4 +- oximeter/oximeter/examples/producer.rs | 2 +- oximeter/oximeter/src/oximeter_server.rs | 2 +- oximeter/oximeter/src/producer_server.rs | 2 +- 59 files changed, 315 insertions(+), 312 deletions(-) rename omicron-common/src/api/{ => external}/error.rs (98%) rename omicron-common/src/api/{ => external}/http_pagination.rs (99%) rename omicron-common/src/api/{model.rs => external/mod.rs} (99%) create mode 100644 omicron-common/src/api/internal/mod.rs create mode 100644 omicron-common/src/api/internal/nexus.rs create mode 100644 omicron-common/src/api/internal/sled_agent.rs diff --git a/omicron-bootstrap-agent/src/bootstrap_agent.rs b/omicron-bootstrap-agent/src/bootstrap_agent.rs index bf75de509ce..ec34d3b51af 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent.rs @@ -1,6 +1,6 @@ use crate::bootstrap_agent_client::Client as BootstrapClient; -use omicron_common::api::BootstrapAgentShareResponse; -use omicron_common::api::Error; +use omicron_common::api::external::BootstrapAgentShareResponse; +use omicron_common::api::external::Error; use omicron_common::packaging::sha256_digest; use slog::Logger; diff --git a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs index 28ebafae77a..6f62595e676 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs @@ -5,9 +5,9 @@ * generated by the server. */ -use omicron_common::api::BootstrapAgentShareRequest; -use omicron_common::api::BootstrapAgentShareResponse; -use omicron_common::api::Error; +use omicron_common::api::external::BootstrapAgentShareRequest; +use omicron_common::api::external::BootstrapAgentShareResponse; +use omicron_common::api::external::Error; use omicron_common::http_client::HttpClient; use http::Method; diff --git a/omicron-bootstrap-agent/src/http_entrypoints.rs b/omicron-bootstrap-agent/src/http_entrypoints.rs index 2c2cfe638d2..aff25cefafe 100644 --- a/omicron-bootstrap-agent/src/http_entrypoints.rs +++ b/omicron-bootstrap-agent/src/http_entrypoints.rs @@ -8,7 +8,7 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::{ +use omicron_common::api::external::{ BootstrapAgentShareRequest, BootstrapAgentShareResponse, }; use std::sync::Arc; diff --git a/omicron-common/src/api/error.rs b/omicron-common/src/api/external/error.rs similarity index 98% rename from omicron-common/src/api/error.rs rename to omicron-common/src/api/external/error.rs index 4344747e5b7..ae4e7b99b85 100644 --- a/omicron-common/src/api/error.rs +++ b/omicron-common/src/api/external/error.rs @@ -4,8 +4,8 @@ * For HTTP-level error handling, see Dropshot. */ -use crate::api::Name; -use crate::api::ResourceType; +use crate::api::external::Name; +use crate::api::external::ResourceType; use dropshot::HttpError; use dropshot::HttpErrorResponseBody; use serde::Deserialize; @@ -243,7 +243,7 @@ macro_rules! bail_unless { }; ($cond:expr, $($arg:tt)+) => { if !$cond { - return Err($crate::api::Error::internal_error(&format!( + return Err($crate::api::external::Error::internal_error(&format!( $($arg)*))) } }; diff --git a/omicron-common/src/api/http_pagination.rs b/omicron-common/src/api/external/http_pagination.rs similarity index 99% rename from omicron-common/src/api/http_pagination.rs rename to omicron-common/src/api/external/http_pagination.rs index 83d0d252690..d6d70d6f64f 100644 --- a/omicron-common/src/api/http_pagination.rs +++ b/omicron-common/src/api/external/http_pagination.rs @@ -38,10 +38,10 @@ * each resource paginated that way). Where possible, we should share code. */ -use crate::api::DataPageParams; -use crate::api::Name; -use crate::api::ObjectIdentity; -use crate::api::PaginationOrder; +use crate::api::external::DataPageParams; +use crate::api::external::Name; +use crate::api::external::ObjectIdentity; +use crate::api::external::PaginationOrder; use dropshot::HttpError; use dropshot::PaginationParams; use dropshot::RequestContext; @@ -505,9 +505,8 @@ mod test { use super::ScanByName; use super::ScanByNameOrId; use super::ScanParams; - use crate::api::IdentityMetadata; - use crate::api::ObjectIdentity; - use api_identity::ObjectIdentity; + use crate::api::external::IdentityMetadata; + use crate::api::external::ObjectIdentity; use chrono::Utc; use dropshot::PaginationOrder; use dropshot::PaginationParams; diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/external/mod.rs similarity index 99% rename from omicron-common/src/api/model.rs rename to omicron-common/src/api/external/mod.rs index d974748f308..fe3bd989d8d 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/external/mod.rs @@ -5,7 +5,11 @@ * internal APIs. The contents here are all HTTP-agnostic. */ -use crate::api::Error; +mod error; +pub mod http_pagination; +pub use error::*; + + use anyhow::anyhow; use anyhow::Context; use api_identity::ObjectIdentity; @@ -1422,7 +1426,7 @@ pub struct OximeterAssignment { mod test { use super::ByteCount; use super::Name; - use crate::api::Error; + use crate::api::external::Error; use std::convert::TryFrom; #[test] diff --git a/omicron-common/src/api/internal/mod.rs b/omicron-common/src/api/internal/mod.rs new file mode 100644 index 00000000000..34ee484c253 --- /dev/null +++ b/omicron-common/src/api/internal/mod.rs @@ -0,0 +1,4 @@ +//! Internally facing API + +mod nexus; +mod sled_agent; diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/omicron-common/src/api/mod.rs b/omicron-common/src/api/mod.rs index 1ce9cf3feac..d73d981abd6 100644 --- a/omicron-common/src/api/mod.rs +++ b/omicron-common/src/api/mod.rs @@ -1,8 +1,4 @@ //! Externally facing API -mod error; -pub mod http_pagination; -mod model; - -pub use error::*; -pub use model::*; +pub mod internal; +pub mod external; diff --git a/omicron-common/src/collection.rs b/omicron-common/src/collection.rs index bdb35619f06..9a46f57456f 100644 --- a/omicron-common/src/collection.rs +++ b/omicron-common/src/collection.rs @@ -2,11 +2,11 @@ * Functions for iterating pages from a collection */ -use crate::api::DataPageParams; -use crate::api::Error; -use crate::api::ListResult; -use crate::api::PaginationOrder::Ascending; -use crate::api::PaginationOrder::Descending; +use crate::api::external::DataPageParams; +use crate::api::external::Error; +use crate::api::external::ListResult; +use crate::api::external::PaginationOrder::Ascending; +use crate::api::external::PaginationOrder::Descending; use futures::StreamExt; use std::collections::BTreeMap; use std::convert::TryFrom; diff --git a/omicron-common/src/db.rs b/omicron-common/src/db.rs index 5b4e8d8c682..c5ddc13946c 100644 --- a/omicron-common/src/db.rs +++ b/omicron-common/src/db.rs @@ -5,7 +5,7 @@ * here is used by the model conversions, which have to live in this crate. */ -use crate::api::Error; +use crate::api::external::Error; use std::fmt; use thiserror::Error; use tokio_postgres::types::FromSql; diff --git a/omicron-common/src/http_client.rs b/omicron-common/src/http_client.rs index 07ef5f572ef..e30d4e35b02 100644 --- a/omicron-common/src/http_client.rs +++ b/omicron-common/src/http_client.rs @@ -2,7 +2,7 @@ * HTTP client used for internal control plane interfaces */ -use crate::api::Error; +use crate::api::external::Error; use dropshot::HttpErrorResponseBody; use http::Method; use hyper::client::HttpConnector; diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index fd35dedc922..64167df6290 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -53,23 +53,23 @@ use std::net::{IpAddr, SocketAddr}; use std::time::Duration; use super::db::sql_row_value; -use crate::api::ByteCount; -use crate::api::Disk; -use crate::api::DiskAttachment; -use crate::api::DiskRuntimeState; -use crate::api::DiskState; -use crate::api::Error; -use crate::api::Generation; -use crate::api::IdentityMetadata; -use crate::api::Instance; -use crate::api::InstanceCpuCount; -use crate::api::InstanceRuntimeState; -use crate::api::InstanceState; -use crate::api::Name; -use crate::api::OximeterAssignment; -use crate::api::OximeterInfo; -use crate::api::ProducerEndpoint; -use crate::api::Project; +use crate::api::external::Error; +use crate::api::external::ByteCount; +use crate::api::external::Disk; +use crate::api::external::DiskAttachment; +use crate::api::external::DiskRuntimeState; +use crate::api::external::DiskState; +use crate::api::external::Generation; +use crate::api::external::IdentityMetadata; +use crate::api::external::Instance; +use crate::api::external::InstanceCpuCount; +use crate::api::external::InstanceRuntimeState; +use crate::api::external::InstanceState; +use crate::api::external::Name; +use crate::api::external::OximeterAssignment; +use crate::api::external::OximeterInfo; +use crate::api::external::ProducerEndpoint; +use crate::api::external::Project; use crate::bail_unless; use chrono::DateTime; use chrono::Utc; diff --git a/omicron-common/src/nexus_client.rs b/omicron-common/src/nexus_client.rs index 31b3d657209..cc874afdaa5 100644 --- a/omicron-common/src/nexus_client.rs +++ b/omicron-common/src/nexus_client.rs @@ -6,10 +6,10 @@ * generated by the server. */ -use crate::api::DiskRuntimeState; -use crate::api::Error; -use crate::api::InstanceRuntimeState; -use crate::api::SledAgentStartupInfo; +use crate::api::external::Error; +use crate::api::external::DiskRuntimeState; +use crate::api::external::InstanceRuntimeState; +use crate::api::external::SledAgentStartupInfo; use crate::http_client::HttpClient; use http::Method; use hyper::Body; diff --git a/omicron-common/src/oximeter_client.rs b/omicron-common/src/oximeter_client.rs index f2ee254f5f4..0965e779fd1 100644 --- a/omicron-common/src/oximeter_client.rs +++ b/omicron-common/src/oximeter_client.rs @@ -8,8 +8,8 @@ use hyper::Body; use slog::Logger; use uuid::Uuid; -use crate::api::Error; -use crate::api::ProducerEndpoint; +use crate::api::external::Error; +use crate::api::external::ProducerEndpoint; use crate::http_client::HttpClient; /// Client of an oximeter server diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index f262f9c6d3d..18e654ae39b 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -5,13 +5,13 @@ * generated by the server. */ -use crate::api::DiskEnsureBody; -use crate::api::DiskRuntimeState; -use crate::api::DiskStateRequested; -use crate::api::Error; -use crate::api::InstanceEnsureBody; -use crate::api::InstanceRuntimeState; -use crate::api::InstanceRuntimeStateRequested; +use crate::api::external::Error; +use crate::api::external::DiskEnsureBody; +use crate::api::external::DiskRuntimeState; +use crate::api::external::DiskStateRequested; +use crate::api::external::InstanceEnsureBody; +use crate::api::external::InstanceRuntimeState; +use crate::api::external::InstanceRuntimeStateRequested; use crate::http_client::HttpClient; use async_trait::async_trait; use http::Method; diff --git a/omicron-nexus/src/db/conversions.rs b/omicron-nexus/src/db/conversions.rs index 4f1759df478..39109e58b2b 100644 --- a/omicron-nexus/src/db/conversions.rs +++ b/omicron-nexus/src/db/conversions.rs @@ -6,17 +6,17 @@ use chrono::DateTime; use chrono::Utc; -use omicron_common::api::DiskCreateParams; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::DiskState; -use omicron_common::api::IdentityMetadataCreateParams; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceState; -use omicron_common::api::OximeterAssignment; -use omicron_common::api::OximeterInfo; -use omicron_common::api::ProducerEndpoint; -use omicron_common::api::ProjectCreateParams; +use omicron_common::api::external::DiskCreateParams; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::DiskState; +use omicron_common::api::external::IdentityMetadataCreateParams; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::OximeterAssignment; +use omicron_common::api::external::OximeterInfo; +use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::external::ProjectCreateParams; use super::sql::SqlSerialize; use super::sql::SqlValueSet; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index df66f45cb4c..0bb8c137c77 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -21,19 +21,19 @@ use super::Pool; use chrono::Utc; use omicron_common::api; -use omicron_common::api::CreateResult; -use omicron_common::api::DataPageParams; -use omicron_common::api::DeleteResult; -use omicron_common::api::Error; -use omicron_common::api::Generation; -use omicron_common::api::ListResult; -use omicron_common::api::LookupResult; -use omicron_common::api::Name; -use omicron_common::api::OximeterAssignment; -use omicron_common::api::OximeterInfo; -use omicron_common::api::ProducerEndpoint; -use omicron_common::api::ResourceType; -use omicron_common::api::UpdateResult; +use omicron_common::api::external::CreateResult; +use omicron_common::api::external::DataPageParams; +use omicron_common::api::external::DeleteResult; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; +use omicron_common::api::external::ListResult; +use omicron_common::api::external::LookupResult; +use omicron_common::api::external::Name; +use omicron_common::api::external::OximeterAssignment; +use omicron_common::api::external::OximeterInfo; +use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::external::ResourceType; +use omicron_common::api::external::UpdateResult; use omicron_common::bail_unless; use omicron_common::db::sql_row_value; use std::convert::TryFrom; @@ -78,8 +78,8 @@ impl DataStore { pub async fn project_create_with_id( &self, new_id: &Uuid, - new_project: &api::ProjectCreateParams, - ) -> CreateResult { + new_project: &api::external::ProjectCreateParams, + ) -> CreateResult { let client = self.pool.acquire().await?; let now = Utc::now(); let mut values = SqlValueSet::new(); @@ -99,7 +99,7 @@ impl DataStore { pub async fn project_fetch( &self, project_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, @@ -154,7 +154,7 @@ impl DataStore { pub async fn projects_list_by_id( &self, pagparams: &DataPageParams<'_, Uuid>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_from_table::( &client, @@ -168,7 +168,7 @@ impl DataStore { pub async fn projects_list_by_name( &self, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueName, @@ -182,8 +182,8 @@ impl DataStore { pub async fn project_update( &self, project_name: &Name, - update_params: &api::ProjectUpdateParams, - ) -> UpdateResult { + update_params: &api::external::ProjectUpdateParams, + ) -> UpdateResult { let client = self.pool.acquire().await?; let now = Utc::now(); @@ -212,7 +212,7 @@ impl DataStore { Error::not_found_by_name(ResourceType::Project, project_name) }) .await?; - Ok(api::Project::try_from(&row)?) + Ok(api::external::Project::try_from(&row)?) } /* @@ -248,9 +248,9 @@ impl DataStore { &self, instance_id: &Uuid, project_id: &Uuid, - params: &api::InstanceCreateParams, - runtime_initial: &api::InstanceRuntimeState, - ) -> CreateResult { + params: &api::external::InstanceCreateParams, + runtime_initial: &api::external::InstanceRuntimeState, + ) -> CreateResult { let client = self.pool.acquire().await?; let now = runtime_initial.time_updated; let mut values = SqlValueSet::new(); @@ -274,7 +274,7 @@ impl DataStore { .await?; bail_unless!( - instance.runtime.run_state == api::InstanceState::Creating, + instance.runtime.run_state == api::external::InstanceState::Creating, "newly-created Instance has unexpected state: {:?}", instance.runtime.run_state ); @@ -290,7 +290,7 @@ impl DataStore { &self, project_id: &Uuid, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueNameInProject, @@ -303,7 +303,7 @@ impl DataStore { pub async fn instance_fetch( &self, instance_id: &Uuid, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::(&client, (), instance_id) .await @@ -313,7 +313,7 @@ impl DataStore { &self, project_id: &Uuid, instance_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, @@ -335,7 +335,7 @@ impl DataStore { pub async fn instance_update_runtime( &self, instance_id: &Uuid, - new_runtime: &api::InstanceRuntimeState, + new_runtime: &api::external::InstanceRuntimeState, ) -> Result { let client = self.pool.acquire().await?; @@ -378,14 +378,14 @@ impl DataStore { let now = Utc::now(); let mut values = SqlValueSet::new(); - api::InstanceState::Destroyed.sql_serialize(&mut values); + api::external::InstanceState::Destroyed.sql_serialize(&mut values); values.set("time_deleted", &now); let mut cond_sql = SqlString::new(); - let stopped = api::InstanceState::Stopped.to_string(); + let stopped = api::external::InstanceState::Stopped.to_string(); let p1 = cond_sql.next_param(&stopped); - let failed = api::InstanceState::Failed.to_string(); + let failed = api::external::InstanceState::Failed.to_string(); let p2 = cond_sql.next_param(&failed); cond_sql.push_str(&format!("instance_state in ({}, {})", p1, p2)); @@ -402,7 +402,7 @@ impl DataStore { let row = &update.found_state; let found_id: Uuid = sql_row_value(&row, "found_id")?; let variant: &str = sql_row_value(&row, "found_instance_state")?; - let instance_state = api::InstanceState::try_from(variant) + let instance_state = api::external::InstanceState::try_from(variant) .map_err(|e| Error::internal_error(&e))?; bail_unless!(found_id == *instance_id); @@ -429,9 +429,9 @@ impl DataStore { &self, instance_id: &Uuid, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; - sql_fetch_page_by::( + sql_fetch_page_by::( &client, (instance_id,), pagparams, @@ -444,9 +444,9 @@ impl DataStore { &self, disk_id: &Uuid, project_id: &Uuid, - params: &api::DiskCreateParams, - runtime_initial: &api::DiskRuntimeState, - ) -> CreateResult { + params: &api::external::DiskCreateParams, + runtime_initial: &api::external::DiskRuntimeState, + ) -> CreateResult { /* * See project_create_instance() for a discussion of how this function * works. The pattern here is nearly identical. @@ -473,7 +473,7 @@ impl DataStore { .await?; bail_unless!( - disk.runtime.disk_state == api::DiskState::Creating, + disk.runtime.disk_state == api::external::DiskState::Creating, "newly-created Disk has unexpected state: {:?}", disk.runtime.disk_state ); @@ -489,7 +489,7 @@ impl DataStore { &self, project_id: &Uuid, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueNameInProject, @@ -502,7 +502,7 @@ impl DataStore { pub async fn disk_update_runtime( &self, disk_id: &Uuid, - new_runtime: &api::DiskRuntimeState, + new_runtime: &api::external::DiskRuntimeState, ) -> Result { let client = self.pool.acquire().await?; @@ -528,7 +528,7 @@ impl DataStore { Ok(update.updated) } - pub async fn disk_fetch(&self, disk_id: &Uuid) -> LookupResult { + pub async fn disk_fetch(&self, disk_id: &Uuid) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::(&client, (), disk_id).await } @@ -537,7 +537,7 @@ impl DataStore { &self, project_id: &Uuid, disk_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, @@ -553,12 +553,12 @@ impl DataStore { let mut values = SqlValueSet::new(); values.set("time_deleted", &now); - api::DiskState::Destroyed.sql_serialize(&mut values); + api::external::DiskState::Destroyed.sql_serialize(&mut values); let mut cond_sql = SqlString::new(); - let disk_state_detached = api::DiskState::Detached.to_string(); + let disk_state_detached = api::external::DiskState::Detached.to_string(); let p1 = cond_sql.next_param(&disk_state_detached); - let disk_state_faulted = api::DiskState::Faulted.to_string(); + let disk_state_faulted = api::external::DiskState::Faulted.to_string(); let p2 = cond_sql.next_param(&disk_state_faulted); cond_sql.push_str(&format!("disk_state in ({}, {})", p1, p2)); @@ -577,13 +577,13 @@ impl DataStore { bail_unless!(found_id == *disk_id); // TODO-cleanup It would be nice to use - // api::DiskState::try_from(&tokio_postgres::Row), but the column names + // api::external::DiskState::try_from(&tokio_postgres::Row), but the column names // are different here. let disk_state_str: &str = sql_row_value(&row, "found_disk_state")?; let attach_instance_id: Option = sql_row_value(&row, "found_attach_instance_id")?; let found_disk_state = - api::DiskState::try_from((disk_state_str, attach_instance_id)) + api::external::DiskState::try_from((disk_state_str, attach_instance_id)) .map_err(|e| Error::internal_error(&e))?; if update.updated { diff --git a/omicron-nexus/src/db/operations.rs b/omicron-nexus/src/db/operations.rs index 5d3db1e8567..14cc7a8cebb 100644 --- a/omicron-nexus/src/db/operations.rs +++ b/omicron-nexus/src/db/operations.rs @@ -3,7 +3,7 @@ * and extract values */ -use omicron_common::api::Error; +use omicron_common::api::external::Error; use omicron_common::db::sql_error_generic; use omicron_common::db::DbError; use std::convert::TryFrom; diff --git a/omicron-nexus/src/db/pool.rs b/omicron-nexus/src/db/pool.rs index c71543f44f8..f66ac5fb185 100644 --- a/omicron-nexus/src/db/pool.rs +++ b/omicron-nexus/src/db/pool.rs @@ -26,7 +26,7 @@ use super::Config as DbConfig; use bb8_postgres::PostgresConnectionManager; -use omicron_common::api::Error; +use omicron_common::api::external::Error; use std::ops::Deref; #[derive(Debug)] diff --git a/omicron-nexus/src/db/saga_recovery.rs b/omicron-nexus/src/db/saga_recovery.rs index 5f1a98bdb31..862c84751bd 100644 --- a/omicron-nexus/src/db/saga_recovery.rs +++ b/omicron-nexus/src/db/saga_recovery.rs @@ -6,7 +6,7 @@ use crate::db; use crate::db::schema; use crate::db::sql::Table; use crate::db::sql_operations::sql_paginate; -use omicron_common::api::Error; +use omicron_common::api::external::Error; use omicron_common::backoff::internal_service_policy; use omicron_common::backoff::retry_notify; use omicron_common::backoff::BackoffError; diff --git a/omicron-nexus/src/db/saga_types.rs b/omicron-nexus/src/db/saga_types.rs index add148ea87a..0a3be7dd983 100644 --- a/omicron-nexus/src/db/saga_types.rs +++ b/omicron-nexus/src/db/saga_types.rs @@ -11,8 +11,8 @@ */ use crate::db; -use omicron_common::api::Error; -use omicron_common::api::Generation; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; use omicron_common::db::sql_row_value; use omicron_common::impl_sql_wrapping; use std::convert::TryFrom; diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index b289c03a912..54a15d35e9e 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -6,10 +6,10 @@ */ use omicron_common::api; -use omicron_common::api::Error; -use omicron_common::api::Name; -use omicron_common::api::ResourceType; -use omicron_common::api::{OximeterInfo, ProducerEndpoint}; +use omicron_common::api::external::Error; +use omicron_common::api::external::Name; +use omicron_common::api::external::ResourceType; +use omicron_common::api::external::{OximeterInfo, ProducerEndpoint}; use uuid::Uuid; use super::sql::LookupKey; @@ -20,7 +20,7 @@ use crate::db; /** Describes the "Project" table */ pub struct Project; impl Table for Project { - type ModelType = api::Project; + type ModelType = api::external::Project; const TABLE_NAME: &'static str = "Project"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", @@ -39,7 +39,7 @@ impl ResourceTable for Project { /** Describes the "Instance" table */ pub struct Instance; impl Table for Instance { - type ModelType = api::Instance; + type ModelType = api::external::Instance; const TABLE_NAME: &'static str = "Instance"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", @@ -66,7 +66,7 @@ impl ResourceTable for Instance { /** Describes the "Disk" table */ pub struct Disk; impl Table for Disk { - type ModelType = api::Disk; + type ModelType = api::external::Disk; const TABLE_NAME: &'static str = "Disk"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", @@ -146,7 +146,7 @@ impl Table for MetricProducer { /** Describes the "OximeterAssignment" table */ pub struct OximeterAssignment; impl Table for OximeterAssignment { - type ModelType = omicron_common::api::OximeterAssignment; + type ModelType = omicron_common::api::external::OximeterAssignment; const TABLE_NAME: &'static str = "OximeterAssignment"; const ALL_COLUMNS: &'static [&'static str] = &["oximeter_id", "producer_id", "time_created"]; diff --git a/omicron-nexus/src/db/sec_store.rs b/omicron-nexus/src/db/sec_store.rs index 1fac0579f71..aa829a85d4a 100644 --- a/omicron-nexus/src/db/sec_store.rs +++ b/omicron-nexus/src/db/sec_store.rs @@ -5,7 +5,7 @@ use crate::db; use anyhow::Context; use async_trait::async_trait; -use omicron_common::api::Generation; +use omicron_common::api::external::Generation; use slog::Logger; use std::fmt; use std::sync::Arc; diff --git a/omicron-nexus/src/db/sql.rs b/omicron-nexus/src/db/sql.rs index 56d08d5bbc1..000cf50f22a 100644 --- a/omicron-nexus/src/db/sql.rs +++ b/omicron-nexus/src/db/sql.rs @@ -5,9 +5,9 @@ * agnostic to the control plane. There is a bit of leakage in a few places. */ -use omicron_common::api::DataPageParams; -use omicron_common::api::Error; -use omicron_common::api::ResourceType; +use omicron_common::api::external::DataPageParams; +use omicron_common::api::external::Error; +use omicron_common::api::external::ResourceType; use std::collections::BTreeSet; use std::convert::TryFrom; use tokio_postgres::types::FromSql; diff --git a/omicron-nexus/src/db/sql_operations.rs b/omicron-nexus/src/db/sql_operations.rs index 9e1a7eaf510..70fd5e3bcee 100644 --- a/omicron-nexus/src/db/sql_operations.rs +++ b/omicron-nexus/src/db/sql_operations.rs @@ -3,11 +3,11 @@ */ use futures::StreamExt; -use omicron_common::api::DataPageParams; -use omicron_common::api::Error; -use omicron_common::api::ListResult; -use omicron_common::api::LookupResult; -use omicron_common::api::ResourceType; +use omicron_common::api::external::DataPageParams; +use omicron_common::api::external::Error; +use omicron_common::api::external::ListResult; +use omicron_common::api::external::LookupResult; +use omicron_common::api::external::ResourceType; use omicron_common::db::sql_error_generic; use omicron_common::db::sql_row_value; use omicron_common::db::DbError; diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index 92cf7ff733d..66ba5b2fa87 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -16,34 +16,34 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::TypedBody; -use omicron_common::api::http_pagination::data_page_params_for; -use omicron_common::api::http_pagination::data_page_params_nameid_id; -use omicron_common::api::http_pagination::data_page_params_nameid_name; -use omicron_common::api::http_pagination::pagination_field_for_scan_params; -use omicron_common::api::http_pagination::PagField; -use omicron_common::api::http_pagination::PaginatedById; -use omicron_common::api::http_pagination::PaginatedByName; -use omicron_common::api::http_pagination::PaginatedByNameOrId; -use omicron_common::api::http_pagination::ScanById; -use omicron_common::api::http_pagination::ScanByName; -use omicron_common::api::http_pagination::ScanByNameOrId; -use omicron_common::api::http_pagination::ScanParams; -use omicron_common::api::to_view_list; -use omicron_common::api::DataPageParams; -use omicron_common::api::DiskAttachment; -use omicron_common::api::DiskCreateParams; -use omicron_common::api::DiskView; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceView; -use omicron_common::api::Name; -use omicron_common::api::Object; -use omicron_common::api::PaginationOrder; -use omicron_common::api::ProjectCreateParams; -use omicron_common::api::ProjectUpdateParams; -use omicron_common::api::ProjectView; -use omicron_common::api::RackView; -use omicron_common::api::SagaView; -use omicron_common::api::SledView; +use omicron_common::api::external::http_pagination::data_page_params_for; +use omicron_common::api::external::http_pagination::data_page_params_nameid_id; +use omicron_common::api::external::http_pagination::data_page_params_nameid_name; +use omicron_common::api::external::http_pagination::pagination_field_for_scan_params; +use omicron_common::api::external::http_pagination::PagField; +use omicron_common::api::external::http_pagination::PaginatedById; +use omicron_common::api::external::http_pagination::PaginatedByName; +use omicron_common::api::external::http_pagination::PaginatedByNameOrId; +use omicron_common::api::external::http_pagination::ScanById; +use omicron_common::api::external::http_pagination::ScanByName; +use omicron_common::api::external::http_pagination::ScanByNameOrId; +use omicron_common::api::external::http_pagination::ScanParams; +use omicron_common::api::external::to_view_list; +use omicron_common::api::external::DataPageParams; +use omicron_common::api::external::DiskAttachment; +use omicron_common::api::external::DiskCreateParams; +use omicron_common::api::external::DiskView; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceView; +use omicron_common::api::external::Name; +use omicron_common::api::external::Object; +use omicron_common::api::external::PaginationOrder; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::external::ProjectUpdateParams; +use omicron_common::api::external::ProjectView; +use omicron_common::api::external::RackView; +use omicron_common::api::external::SagaView; +use omicron_common::api::external::SledView; use schemars::JsonSchema; use serde::Deserialize; use std::num::NonZeroU32; diff --git a/omicron-nexus/src/http_entrypoints_internal.rs b/omicron-nexus/src/http_entrypoints_internal.rs index 9dcb8833687..b77eeed5066 100644 --- a/omicron-nexus/src/http_entrypoints_internal.rs +++ b/omicron-nexus/src/http_entrypoints_internal.rs @@ -10,11 +10,11 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::OximeterInfo; -use omicron_common::api::ProducerEndpoint; -use omicron_common::api::SledAgentStartupInfo; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::OximeterInfo; +use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::external::SledAgentStartupInfo; use omicron_common::SledAgentClient; use schemars::JsonSchema; use serde::Deserialize; diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index f2816ed5619..aa5bba23452 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -11,37 +11,37 @@ use chrono::Utc; use futures::future::ready; use futures::lock::Mutex; use futures::StreamExt; -use omicron_common::api::CreateResult; -use omicron_common::api::DataPageParams; -use omicron_common::api::DeleteResult; -use omicron_common::api::Disk; -use omicron_common::api::DiskAttachment; -use omicron_common::api::DiskCreateParams; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::DiskState; -use omicron_common::api::DiskStateRequested; -use omicron_common::api::Error; -use omicron_common::api::Generation; -use omicron_common::api::IdentityMetadata; -use omicron_common::api::Instance; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; -use omicron_common::api::InstanceState; -use omicron_common::api::InstanceStateRequested; -use omicron_common::api::ListResult; -use omicron_common::api::LookupResult; -use omicron_common::api::Name; -use omicron_common::api::OximeterInfo; -use omicron_common::api::ProducerEndpoint; -use omicron_common::api::Project; -use omicron_common::api::ProjectCreateParams; -use omicron_common::api::ProjectUpdateParams; -use omicron_common::api::Rack; -use omicron_common::api::ResourceType; -use omicron_common::api::SagaView; -use omicron_common::api::Sled; -use omicron_common::api::UpdateResult; +use omicron_common::api::external::CreateResult; +use omicron_common::api::external::DataPageParams; +use omicron_common::api::external::DeleteResult; +use omicron_common::api::external::Disk; +use omicron_common::api::external::DiskAttachment; +use omicron_common::api::external::DiskCreateParams; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::DiskState; +use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; +use omicron_common::api::external::IdentityMetadata; +use omicron_common::api::external::Instance; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::InstanceStateRequested; +use omicron_common::api::external::ListResult; +use omicron_common::api::external::LookupResult; +use omicron_common::api::external::Name; +use omicron_common::api::external::OximeterInfo; +use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::external::Project; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::external::ProjectUpdateParams; +use omicron_common::api::external::Rack; +use omicron_common::api::external::ResourceType; +use omicron_common::api::external::SagaView; +use omicron_common::api::external::Sled; +use omicron_common::api::external::UpdateResult; use omicron_common::bail_unless; use omicron_common::collection::collection_page; use omicron_common::OximeterClient; diff --git a/omicron-nexus/src/saga_interface.rs b/omicron-nexus/src/saga_interface.rs index a6be04c7ec2..c9231308df7 100644 --- a/omicron-nexus/src/saga_interface.rs +++ b/omicron-nexus/src/saga_interface.rs @@ -4,8 +4,8 @@ use crate::db; use crate::Nexus; -use omicron_common::api::Error; -use omicron_common::api::InstanceCreateParams; +use omicron_common::api::external::Error; +use omicron_common::api::external::InstanceCreateParams; use omicron_common::SledAgentClient; use std::fmt; use std::sync::Arc; diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index aba8d055e7a..6b7af3d9994 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -12,12 +12,12 @@ use crate::saga_interface::SagaContext; use chrono::Utc; use lazy_static::lazy_static; -use omicron_common::api::Generation; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; -use omicron_common::api::InstanceState; -use omicron_common::api::InstanceStateRequested; +use omicron_common::api::external::Generation; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::InstanceStateRequested; use serde::Deserialize; use serde::Serialize; use std::collections::BTreeMap; diff --git a/omicron-nexus/tests/common/mod.rs b/omicron-nexus/tests/common/mod.rs index 0a51610e163..52ed506f7d0 100644 --- a/omicron-nexus/tests/common/mod.rs +++ b/omicron-nexus/tests/common/mod.rs @@ -7,8 +7,8 @@ use dropshot::test_util::LogContext; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; -use omicron_common::api::IdentityMetadata; -use omicron_common::api::ProducerEndpoint; +use omicron_common::api::external::IdentityMetadata; +use omicron_common::api::external::ProducerEndpoint; use omicron_common::dev; use slog::o; use slog::Logger; diff --git a/omicron-nexus/tests/test_basic.rs b/omicron-nexus/tests/test_basic.rs index 9f698bf4264..f1cdf819e5b 100644 --- a/omicron-nexus/tests/test_basic.rs +++ b/omicron-nexus/tests/test_basic.rs @@ -13,13 +13,13 @@ use dropshot::test_util::read_json; use dropshot::test_util::ClientTestContext; use http::method::Method; use http::StatusCode; -use omicron_common::api::IdentityMetadataCreateParams; -use omicron_common::api::IdentityMetadataUpdateParams; -use omicron_common::api::Name; -use omicron_common::api::ProjectCreateParams; -use omicron_common::api::ProjectUpdateParams; -use omicron_common::api::ProjectView; -use omicron_common::api::SledView; +use omicron_common::api::external::IdentityMetadataCreateParams; +use omicron_common::api::external::IdentityMetadataUpdateParams; +use omicron_common::api::external::Name; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::external::ProjectUpdateParams; +use omicron_common::api::external::ProjectView; +use omicron_common::api::external::SledView; use std::convert::TryFrom; use uuid::Uuid; diff --git a/omicron-nexus/tests/test_disks.rs b/omicron-nexus/tests/test_disks.rs index 2b1a5b0503e..bff98a49f54 100644 --- a/omicron-nexus/tests/test_disks.rs +++ b/omicron-nexus/tests/test_disks.rs @@ -4,18 +4,18 @@ use http::method::Method; use http::StatusCode; -use omicron_common::api::ByteCount; -use omicron_common::api::DiskAttachment; -use omicron_common::api::DiskCreateParams; -use omicron_common::api::DiskState; -use omicron_common::api::DiskView; -use omicron_common::api::IdentityMetadataCreateParams; -use omicron_common::api::InstanceCpuCount; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceView; -use omicron_common::api::Name; -use omicron_common::api::ProjectCreateParams; -use omicron_common::api::ProjectView; +use omicron_common::api::external::ByteCount; +use omicron_common::api::external::DiskAttachment; +use omicron_common::api::external::DiskCreateParams; +use omicron_common::api::external::DiskState; +use omicron_common::api::external::DiskView; +use omicron_common::api::external::IdentityMetadataCreateParams; +use omicron_common::api::external::InstanceCpuCount; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceView; +use omicron_common::api::external::Name; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::external::ProjectView; use omicron_common::SledAgentTestInterfaces as _; use omicron_nexus::Nexus; use omicron_nexus::TestInterfaces as _; diff --git a/omicron-nexus/tests/test_instances.rs b/omicron-nexus/tests/test_instances.rs index d9998e07cea..42fd893698c 100644 --- a/omicron-nexus/tests/test_instances.rs +++ b/omicron-nexus/tests/test_instances.rs @@ -4,15 +4,15 @@ use http::method::Method; use http::StatusCode; -use omicron_common::api::ByteCount; -use omicron_common::api::IdentityMetadataCreateParams; -use omicron_common::api::InstanceCpuCount; -use omicron_common::api::InstanceCreateParams; -use omicron_common::api::InstanceState; -use omicron_common::api::InstanceView; -use omicron_common::api::Name; -use omicron_common::api::ProjectCreateParams; -use omicron_common::api::ProjectView; +use omicron_common::api::external::ByteCount; +use omicron_common::api::external::IdentityMetadataCreateParams; +use omicron_common::api::external::InstanceCpuCount; +use omicron_common::api::external::InstanceCreateParams; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::InstanceView; +use omicron_common::api::external::Name; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::external::ProjectView; use omicron_common::SledAgentTestInterfaces as _; use omicron_nexus::Nexus; use omicron_nexus::TestInterfaces as _; diff --git a/omicron-sled-agent/src/common/disk.rs b/omicron-sled-agent/src/common/disk.rs index a97ca9690a1..e262982200c 100644 --- a/omicron-sled-agent/src/common/disk.rs +++ b/omicron-sled-agent/src/common/disk.rs @@ -1,10 +1,10 @@ //! Describes the states of network-attached storage. use chrono::Utc; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::DiskState; -use omicron_common::api::DiskStateRequested; -use omicron_common::api::Error; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::DiskState; +use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::external::Error; use propolis_client::api::DiskAttachmentState as PropolisDiskState; use uuid::Uuid; diff --git a/omicron-sled-agent/src/common/instance.rs b/omicron-sled-agent/src/common/instance.rs index 8705efbf0f8..839ae1f4925 100644 --- a/omicron-sled-agent/src/common/instance.rs +++ b/omicron-sled-agent/src/common/instance.rs @@ -1,11 +1,11 @@ //! Describes the states of VM instances. use chrono::Utc; -use omicron_common::api::Error; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; -use omicron_common::api::InstanceState; -use omicron_common::api::InstanceStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::InstanceStateRequested; use propolis_client::api::InstanceState as PropolisInstanceState; /// Action to be taken on behalf of state transition. @@ -261,7 +261,7 @@ impl InstanceStates { mod test { use super::{Action, InstanceStates}; use chrono::Utc; - use omicron_common::api::{ + use omicron_common::api::external::{ Generation, InstanceRuntimeState, InstanceState as State, InstanceStateRequested as Requested, }; diff --git a/omicron-sled-agent/src/http_entrypoints.rs b/omicron-sled-agent/src/http_entrypoints.rs index 837b15a21ce..3b059823216 100644 --- a/omicron-sled-agent/src/http_entrypoints.rs +++ b/omicron-sled-agent/src/http_entrypoints.rs @@ -7,10 +7,10 @@ use dropshot::HttpResponseOk; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::DiskEnsureBody; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::InstanceEnsureBody; -use omicron_common::api::InstanceRuntimeState; +use omicron_common::api::external::DiskEnsureBody; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::InstanceEnsureBody; +use omicron_common::api::external::InstanceRuntimeState; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index 6ca6e0871eb..504d4e8237b 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -1,7 +1,7 @@ //! Utilities for poking at data links. use crate::illumos::{execute, PFEXEC}; -use omicron_common::api::Error; +use omicron_common::api::external::Error; pub const VNIC_PREFIX: &str = "vnic_propolis"; diff --git a/omicron-sled-agent/src/illumos/mod.rs b/omicron-sled-agent/src/illumos/mod.rs index 7887dcf09b6..ddb0bb43992 100644 --- a/omicron-sled-agent/src/illumos/mod.rs +++ b/omicron-sled-agent/src/illumos/mod.rs @@ -5,7 +5,7 @@ pub mod svc; pub mod zfs; pub mod zone; -use omicron_common::api::Error; +use omicron_common::api::external::Error; const PFEXEC: &str = "/usr/bin/pfexec"; diff --git a/omicron-sled-agent/src/illumos/svc.rs b/omicron-sled-agent/src/illumos/svc.rs index ac2f50f3676..c2e873a3c49 100644 --- a/omicron-sled-agent/src/illumos/svc.rs +++ b/omicron-sled-agent/src/illumos/svc.rs @@ -2,7 +2,7 @@ use cfg_if::cfg_if; -use omicron_common::api::Error; +use omicron_common::api::external::Error; use omicron_common::dev::poll; use std::time::Duration; diff --git a/omicron-sled-agent/src/illumos/zfs.rs b/omicron-sled-agent/src/illumos/zfs.rs index 952569cf41b..8bff22bb8f6 100644 --- a/omicron-sled-agent/src/illumos/zfs.rs +++ b/omicron-sled-agent/src/illumos/zfs.rs @@ -1,7 +1,7 @@ //! Utilities for poking at ZFS. use crate::illumos::{execute, PFEXEC}; -use omicron_common::api::Error; +use omicron_common::api::external::Error; pub const ZONE_ZFS_DATASET_MOUNTPOINT: &str = "/zone"; pub const ZONE_ZFS_DATASET: &str = "rpool/zone"; diff --git a/omicron-sled-agent/src/illumos/zone.rs b/omicron-sled-agent/src/illumos/zone.rs index 4c3473ef5e4..c69dcd5fc7c 100644 --- a/omicron-sled-agent/src/illumos/zone.rs +++ b/omicron-sled-agent/src/illumos/zone.rs @@ -1,7 +1,7 @@ //! API for interacting with Zones running Propolis. use ipnet::IpNet; -use omicron_common::api::Error; +use omicron_common::api::external::Error; use slog::Logger; use std::net::SocketAddr; use uuid::Uuid; diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index a5f80c3fdda..f5579797ef9 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -5,9 +5,9 @@ use crate::illumos::svc::wait_for_service; use crate::illumos::{dladm::VNIC_PREFIX, zone::ZONE_PREFIX}; use crate::instance_manager::InstanceTicket; use futures::lock::Mutex; -use omicron_common::api::Error; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::dev::poll; use propolis_client::Client as PropolisClient; use slog::Logger; @@ -477,7 +477,7 @@ mod test { RequestContext, TypedBody, }; use futures::future::FutureExt; - use omicron_common::api::{ + use omicron_common::api::external::{ Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, }; use propolis_client::api; diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 76c45656eaa..391ec0d1e13 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -1,8 +1,8 @@ //! API for controlling multiple instances on a sled. use crate::illumos::zfs::ZONE_ZFS_DATASET; -use omicron_common::api::Error; -use omicron_common::api::{ +use omicron_common::api::external::Error; +use omicron_common::api::external::{ InstanceRuntimeState, InstanceRuntimeStateRequested, }; use slog::Logger; @@ -199,7 +199,7 @@ mod test { use crate::instance::MockInstance; use crate::mocks::MockNexusClient; use chrono::Utc; - use omicron_common::api::{ + use omicron_common::api::external::{ Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, }; diff --git a/omicron-sled-agent/src/mocks/mod.rs b/omicron-sled-agent/src/mocks/mod.rs index b06e55231c6..55c46f0de3e 100644 --- a/omicron-sled-agent/src/mocks/mod.rs +++ b/omicron-sled-agent/src/mocks/mod.rs @@ -1,9 +1,9 @@ //! Mock structures for testing. use mockall::mock; -use omicron_common::api::Error; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::SledAgentStartupInfo; +use omicron_common::api::external::Error; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::SledAgentStartupInfo; use slog::Logger; use std::net::SocketAddr; use uuid::Uuid; diff --git a/omicron-sled-agent/src/server.rs b/omicron-sled-agent/src/server.rs index 24a510b2e23..6c0a478ca88 100644 --- a/omicron-sled-agent/src/server.rs +++ b/omicron-sled-agent/src/server.rs @@ -4,7 +4,7 @@ use super::config::Config; use super::http_entrypoints::api as http_api; use super::sled_agent::SledAgent; -use omicron_common::api::SledAgentStartupInfo; +use omicron_common::api::external::SledAgentStartupInfo; use omicron_common::backoff::{ internal_service_policy, retry_notify, BackoffError, }; diff --git a/omicron-sled-agent/src/sim/collection.rs b/omicron-sled-agent/src/sim/collection.rs index 378c8953509..e9f303eae62 100644 --- a/omicron-sled-agent/src/sim/collection.rs +++ b/omicron-sled-agent/src/sim/collection.rs @@ -8,7 +8,7 @@ use futures::channel::mpsc::Receiver; use futures::channel::mpsc::Sender; use futures::lock::Mutex; use futures::stream::StreamExt; -use omicron_common::api::Error; +use omicron_common::api::external::Error; use omicron_common::NexusClient; use slog::Logger; use std::collections::BTreeMap; @@ -336,15 +336,15 @@ mod test { use chrono::Utc; use dropshot::test_util::LogContext; use futures::channel::mpsc::Receiver; - use omicron_common::api::DiskRuntimeState; - use omicron_common::api::DiskState; - use omicron_common::api::DiskStateRequested; - use omicron_common::api::Error; - use omicron_common::api::Generation; - use omicron_common::api::InstanceRuntimeState; - use omicron_common::api::InstanceRuntimeStateRequested; - use omicron_common::api::InstanceState; - use omicron_common::api::InstanceStateRequested; + use omicron_common::api::external::DiskRuntimeState; + use omicron_common::api::external::DiskState; + use omicron_common::api::external::DiskStateRequested; + use omicron_common::api::external::Error; + use omicron_common::api::external::Generation; + use omicron_common::api::external::InstanceRuntimeState; + use omicron_common::api::external::InstanceRuntimeStateRequested; + use omicron_common::api::external::InstanceState; + use omicron_common::api::external::InstanceStateRequested; use omicron_common::dev::test_setup_log; fn make_instance( diff --git a/omicron-sled-agent/src/sim/disk.rs b/omicron-sled-agent/src/sim/disk.rs index 080cf690baa..74d8ade310d 100644 --- a/omicron-sled-agent/src/sim/disk.rs +++ b/omicron-sled-agent/src/sim/disk.rs @@ -4,11 +4,11 @@ use crate::sim::simulatable::Simulatable; use async_trait::async_trait; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::DiskState; -use omicron_common::api::DiskStateRequested; -use omicron_common::api::Error; -use omicron_common::api::Generation; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::DiskState; +use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; use omicron_common::NexusClient; use propolis_client::api::DiskAttachmentState as PropolisDiskState; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index adb4172c68b..5d517e8842b 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -10,10 +10,10 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::DiskEnsureBody; -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::InstanceEnsureBody; -use omicron_common::api::InstanceRuntimeState; +use omicron_common::api::external::DiskEnsureBody; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::InstanceEnsureBody; +use omicron_common::api::external::InstanceRuntimeState; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/instance.rs b/omicron-sled-agent/src/sim/instance.rs index 00de0f7d94b..8f7e7072eb1 100644 --- a/omicron-sled-agent/src/sim/instance.rs +++ b/omicron-sled-agent/src/sim/instance.rs @@ -5,12 +5,12 @@ use super::simulatable::Simulatable; use async_trait::async_trait; -use omicron_common::api::Error; -use omicron_common::api::Generation; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; -use omicron_common::api::InstanceState; -use omicron_common::api::InstanceStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::external::InstanceState; +use omicron_common::api::external::InstanceStateRequested; use omicron_common::NexusClient; use propolis_client::api::InstanceState as PropolisInstanceState; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/server.rs b/omicron-sled-agent/src/sim/server.rs index b83de5c81b9..58896307243 100644 --- a/omicron-sled-agent/src/sim/server.rs +++ b/omicron-sled-agent/src/sim/server.rs @@ -6,7 +6,7 @@ use super::config::Config; use super::http_entrypoints::api as http_api; use super::sled_agent::SledAgent; -use omicron_common::api::SledAgentStartupInfo; +use omicron_common::api::external::SledAgentStartupInfo; use omicron_common::backoff::{ internal_service_policy, retry_notify, BackoffError, }; diff --git a/omicron-sled-agent/src/sim/simulatable.rs b/omicron-sled-agent/src/sim/simulatable.rs index b4ae48ea6ba..5999cb9d46b 100644 --- a/omicron-sled-agent/src/sim/simulatable.rs +++ b/omicron-sled-agent/src/sim/simulatable.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use omicron_common::api::Error; -use omicron_common::api::Generation; +use omicron_common::api::external::Error; +use omicron_common::api::external::Generation; use omicron_common::NexusClient; use std::fmt; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/sled_agent.rs b/omicron-sled-agent/src/sim/sled_agent.rs index 3c604f7365f..8144ea11046 100644 --- a/omicron-sled-agent/src/sim/sled_agent.rs +++ b/omicron-sled-agent/src/sim/sled_agent.rs @@ -2,11 +2,11 @@ * Simulated sled agent implementation */ -use omicron_common::api::DiskRuntimeState; -use omicron_common::api::DiskStateRequested; -use omicron_common::api::Error; -use omicron_common::api::InstanceRuntimeState; -use omicron_common::api::InstanceRuntimeStateRequested; +use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::external::Error; +use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::NexusClient; use slog::Logger; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 7f335c7a471..8750cf4c89b 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -1,7 +1,7 @@ //! Sled agent implementation -use omicron_common::api::Error; -use omicron_common::api::{ +use omicron_common::api::external::Error; +use omicron_common::api::external::{ DiskRuntimeState, DiskStateRequested, InstanceRuntimeState, InstanceRuntimeStateRequested, }; diff --git a/oximeter/oximeter/examples/producer.rs b/oximeter/oximeter/examples/producer.rs index b4ea73ba7af..d5428470d80 100644 --- a/oximeter/oximeter/examples/producer.rs +++ b/oximeter/oximeter/examples/producer.rs @@ -5,7 +5,7 @@ use std::time::Duration; use chrono::{DateTime, Utc}; use dropshot::{ConfigDropshot, ConfigLogging, ConfigLoggingLevel}; -use omicron_common::api::ProducerEndpoint; +use omicron_common::api::external::ProducerEndpoint; use oximeter::producer_server::{ ProducerServer, ProducerServerConfig, RegistrationInfo, }; diff --git a/oximeter/oximeter/src/oximeter_server.rs b/oximeter/oximeter/src/oximeter_server.rs index 4f86858d3cd..38fa51b3b8a 100644 --- a/oximeter/oximeter/src/oximeter_server.rs +++ b/oximeter/oximeter/src/oximeter_server.rs @@ -12,7 +12,7 @@ use dropshot::{ HttpResponseUpdatedNoContent, HttpServer, HttpServerStarter, RequestContext, TypedBody, }; -use omicron_common::api::{OximeterInfo, ProducerEndpoint}; +use omicron_common::api::external::{OximeterInfo, ProducerEndpoint}; use omicron_common::backoff; use reqwest::Client; use serde::{Deserialize, Serialize}; diff --git a/oximeter/oximeter/src/producer_server.rs b/oximeter/oximeter/src/producer_server.rs index 91561ede4b0..88b2508feb7 100644 --- a/oximeter/oximeter/src/producer_server.rs +++ b/oximeter/oximeter/src/producer_server.rs @@ -9,7 +9,7 @@ use dropshot::{ endpoint, ApiDescription, ConfigDropshot, ConfigLogging, HttpError, HttpResponseOk, HttpServer, HttpServerStarter, Path, RequestContext, }; -use omicron_common::api::ProducerEndpoint; +use omicron_common::api::external::ProducerEndpoint; use reqwest::Client; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; From 46e581bbda908560d8f6c93723b083c016be637d Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 14:44:53 -0400 Subject: [PATCH 07/14] Pull some disk stuff out of external --- omicron-common/src/api/external/mod.rs | 92 ++----------------- omicron-common/src/api/internal/mod.rs | 6 +- omicron-common/src/api/internal/nexus.rs | 42 +++++++++ omicron-common/src/api/internal/sled_agent.rs | 40 ++++++++ omicron-common/src/api/mod.rs | 2 +- omicron-common/src/model_db.rs | 4 +- omicron-common/src/nexus_client.rs | 2 +- omicron-common/src/sled_agent_client.rs | 6 +- omicron-nexus/src/db/conversions.rs | 2 +- omicron-nexus/src/db/datastore.rs | 14 +-- omicron-nexus/src/db/schema.rs | 2 +- .../src/http_entrypoints_external.rs | 14 ++- .../src/http_entrypoints_internal.rs | 2 +- omicron-nexus/src/nexus.rs | 6 +- omicron-sled-agent/src/common/disk.rs | 4 +- omicron-sled-agent/src/http_entrypoints.rs | 4 +- omicron-sled-agent/src/sim/collection.rs | 4 +- omicron-sled-agent/src/sim/disk.rs | 4 +- .../src/sim/http_entrypoints.rs | 4 +- omicron-sled-agent/src/sim/sled_agent.rs | 4 +- omicron-sled-agent/src/sled_agent.rs | 10 +- 21 files changed, 142 insertions(+), 126 deletions(-) diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index fe3bd989d8d..708e7c75e6e 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -932,26 +932,6 @@ pub struct InstanceUpdateParams { * DISKS */ -/** - * A Disk (network block device) in the external API - */ -#[derive(Clone, Debug)] -pub struct Disk { - /** common identifying metadata */ - pub identity: IdentityMetadata, - /** id for the project containing this Disk */ - pub project_id: Uuid, - /** - * id for the snapshot from which this Disk was created (None means a blank - * disk) - */ - pub create_snapshot_id: Option, - /** size of the Disk */ - pub size: ByteCount, - /** runtime state of the Disk */ - pub runtime: DiskRuntimeState, -} - /** * Client view of an [`Disk`] */ @@ -967,20 +947,19 @@ pub struct DiskView { pub device_path: String, } -impl Object for Disk { - type View = DiskView; - fn to_view(&self) -> DiskView { +impl From for DiskView { + fn from(disk: crate::api::internal::nexus::Disk) -> Self { /* * TODO-correctness: can the name always be used as a path like this * or might it need to be sanitized? */ - let device_path = format!("/mnt/{}", self.identity.name.as_str()); + let device_path = format!("/mnt/{}", disk.identity.name.as_str()); DiskView { - identity: self.identity.clone(), - project_id: self.project_id, - snapshot_id: self.create_snapshot_id, - size: self.size, - state: self.runtime.disk_state.clone(), + identity: disk.identity.clone(), + project_id: disk.project_id, + snapshot_id: disk.create_snapshot_id, + size: disk.size, + state: disk.runtime.disk_state.clone(), device_path, } } @@ -1088,20 +1067,6 @@ impl DiskState { } } -/** - * Runtime state of the Disk, which includes its attach state and some minimal - * metadata - */ -#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] -pub struct DiskRuntimeState { - /** runtime state of the Disk */ - pub disk_state: DiskState, - /** generation number for this state */ - pub gen: Generation, - /** timestamp for this information */ - pub time_updated: DateTime, -} - /** * Create-time parameters for an [`Disk`] */ @@ -1136,33 +1101,6 @@ impl Object for DiskAttachment { } } -/** - * Used to request a Disk state change - */ -#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, JsonSchema)] -#[serde(rename_all = "lowercase")] -pub enum DiskStateRequested { - Detached, - Attached(Uuid), - Destroyed, - Faulted, -} - -impl DiskStateRequested { - /** - * Returns whether the requested state is attached to an Instance or not. - */ - pub fn is_attached(&self) -> bool { - match self { - DiskStateRequested::Detached => false, - DiskStateRequested::Destroyed => false, - DiskStateRequested::Faulted => false, - - DiskStateRequested::Attached(_) => true, - } - } -} - /* * RACKS */ @@ -1344,20 +1282,6 @@ pub struct InstanceEnsureBody { pub target: InstanceRuntimeStateRequested, } -/** - * Sent from Nexus to a sled agent to establish the runtime state of a Disk - */ -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct DiskEnsureBody { - /** - * Last runtime state of the Disk known to Nexus (used if the agent has - * never seen this Disk before). - */ - pub initial_runtime: DiskRuntimeState, - /** requested runtime state of the Disk */ - pub target: DiskStateRequested, -} - /* * Bootstrap Agent objects */ diff --git a/omicron-common/src/api/internal/mod.rs b/omicron-common/src/api/internal/mod.rs index 34ee484c253..5578747942d 100644 --- a/omicron-common/src/api/internal/mod.rs +++ b/omicron-common/src/api/internal/mod.rs @@ -1,4 +1,4 @@ -//! Internally facing API +//! Internally facing APIs. -mod nexus; -mod sled_agent; +pub mod nexus; +pub mod sled_agent; diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index e69de29bb2d..1bd902ca788 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -0,0 +1,42 @@ +//! APIs exposed by Nexus. + +use crate::api::external::{ + ByteCount, + DiskState, + Generation, + IdentityMetadata, +}; +use chrono::{DateTime, Utc}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +/// A Disk (network block device). +#[derive(Clone, Debug)] +pub struct Disk { + /// common identifying metadata. + pub identity: IdentityMetadata, + /// id for the project containing this Disk + pub project_id: Uuid, + /// id for the snapshot from which this Disk was created (None means a blank + /// disk) + pub create_snapshot_id: Option, + /// size of the Disk + pub size: ByteCount, + /// runtime state of the Disk + pub runtime: DiskRuntimeState, +} + + +/// Runtime state of the Disk, which includes its attach state and some minimal +/// metadata +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] +pub struct DiskRuntimeState { + /// runtime state of the Disk + pub disk_state: DiskState, + /// generation number for this state + pub gen: Generation, + /// timestamp for this information + pub time_updated: DateTime, +} + diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index e69de29bb2d..0d156257531 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -0,0 +1,40 @@ +//! APIs exposed by Sled Agent. + +use crate::api::internal; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +/// Sent from to a sled agent to establish the runtime state of a Disk +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct DiskEnsureBody { + /// Last runtime state of the Disk known to Nexus (used if the agent has + /// never seen this Disk before). + pub initial_runtime: internal::nexus::DiskRuntimeState, + /// requested runtime state of the Disk + pub target: DiskStateRequested, +} + +///Used to request a Disk state change +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum DiskStateRequested { + Detached, + Attached(Uuid), + Destroyed, + Faulted, +} + +impl DiskStateRequested { + /// Returns whether the requested state is attached to an Instance or not. + pub fn is_attached(&self) -> bool { + match self { + DiskStateRequested::Detached => false, + DiskStateRequested::Destroyed => false, + DiskStateRequested::Faulted => false, + + DiskStateRequested::Attached(_) => true, + } + } +} + diff --git a/omicron-common/src/api/mod.rs b/omicron-common/src/api/mod.rs index d73d981abd6..679048ec777 100644 --- a/omicron-common/src/api/mod.rs +++ b/omicron-common/src/api/mod.rs @@ -1,4 +1,4 @@ -//! Externally facing API +//! APIs, both internal and external. pub mod internal; pub mod external; diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 64167df6290..4eddecae64c 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -55,9 +55,9 @@ use std::time::Duration; use super::db::sql_row_value; use crate::api::external::Error; use crate::api::external::ByteCount; -use crate::api::external::Disk; +use crate::api::internal::nexus::Disk; use crate::api::external::DiskAttachment; -use crate::api::external::DiskRuntimeState; +use crate::api::internal::nexus::DiskRuntimeState; use crate::api::external::DiskState; use crate::api::external::Generation; use crate::api::external::IdentityMetadata; diff --git a/omicron-common/src/nexus_client.rs b/omicron-common/src/nexus_client.rs index cc874afdaa5..c6a481c9390 100644 --- a/omicron-common/src/nexus_client.rs +++ b/omicron-common/src/nexus_client.rs @@ -7,7 +7,7 @@ */ use crate::api::external::Error; -use crate::api::external::DiskRuntimeState; +use crate::api::internal::nexus::DiskRuntimeState; use crate::api::external::InstanceRuntimeState; use crate::api::external::SledAgentStartupInfo; use crate::http_client::HttpClient; diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index 18e654ae39b..a448cecafff 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -6,9 +6,9 @@ */ use crate::api::external::Error; -use crate::api::external::DiskEnsureBody; -use crate::api::external::DiskRuntimeState; -use crate::api::external::DiskStateRequested; +use crate::api::internal::sled_agent::DiskEnsureBody; +use crate::api::internal::nexus::DiskRuntimeState; +use crate::api::internal::sled_agent::DiskStateRequested; use crate::api::external::InstanceEnsureBody; use crate::api::external::InstanceRuntimeState; use crate::api::external::InstanceRuntimeStateRequested; diff --git a/omicron-nexus/src/db/conversions.rs b/omicron-nexus/src/db/conversions.rs index 39109e58b2b..393e302ce2d 100644 --- a/omicron-nexus/src/db/conversions.rs +++ b/omicron-nexus/src/db/conversions.rs @@ -7,7 +7,7 @@ use chrono::DateTime; use chrono::Utc; use omicron_common::api::external::DiskCreateParams; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::DiskState; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_common::api::external::InstanceCreateParams; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index 0bb8c137c77..317f19a1032 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -445,8 +445,8 @@ impl DataStore { disk_id: &Uuid, project_id: &Uuid, params: &api::external::DiskCreateParams, - runtime_initial: &api::external::DiskRuntimeState, - ) -> CreateResult { + runtime_initial: &api::internal::nexus::DiskRuntimeState, + ) -> CreateResult { /* * See project_create_instance() for a discussion of how this function * works. The pattern here is nearly identical. @@ -461,7 +461,7 @@ impl DataStore { params.sql_serialize(&mut values); runtime_initial.sql_serialize(&mut values); - let disk = + let disk: api::internal::nexus::Disk = sql_insert_unique_idempotent_and_fetch::( &client, &mut values, @@ -489,7 +489,7 @@ impl DataStore { &self, project_id: &Uuid, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueNameInProject, @@ -502,7 +502,7 @@ impl DataStore { pub async fn disk_update_runtime( &self, disk_id: &Uuid, - new_runtime: &api::external::DiskRuntimeState, + new_runtime: &api::internal::nexus::DiskRuntimeState, ) -> Result { let client = self.pool.acquire().await?; @@ -528,7 +528,7 @@ impl DataStore { Ok(update.updated) } - pub async fn disk_fetch(&self, disk_id: &Uuid) -> LookupResult { + pub async fn disk_fetch(&self, disk_id: &Uuid) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::(&client, (), disk_id).await } @@ -537,7 +537,7 @@ impl DataStore { &self, project_id: &Uuid, disk_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index 54a15d35e9e..1b3efd6f2e6 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -66,7 +66,7 @@ impl ResourceTable for Instance { /** Describes the "Disk" table */ pub struct Disk; impl Table for Disk { - type ModelType = api::external::Disk; + type ModelType = api::internal::nexus::Disk; const TABLE_NAME: &'static str = "Disk"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index 66ba5b2fa87..4c296c4947f 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -16,6 +16,7 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::TypedBody; +use futures::stream::StreamExt; use omicron_common::api::external::http_pagination::data_page_params_for; use omicron_common::api::external::http_pagination::data_page_params_nameid_id; use omicron_common::api::external::http_pagination::data_page_params_nameid_name; @@ -289,8 +290,13 @@ async fn project_disks_get( &data_page_params_for(&rqctx, &query)?, ) .await?; - let view_list = to_view_list(disk_stream).await; - Ok(HttpResponseOk(ScanByName::results_page(&query, view_list)?)) + + let disk_list = disk_stream + .filter(|maybe_disk| futures::future::ready(maybe_disk.is_ok())) + .map(|maybe_disk| maybe_disk.unwrap().into()) + .collect::>() + .await; + Ok(HttpResponseOk(ScanByName::results_page(&query, disk_list)?)) } /** @@ -314,7 +320,7 @@ async fn project_disks_post( let new_disk_params = &new_disk.into_inner(); let disk = nexus.project_create_disk(&project_name, &new_disk_params).await?; - Ok(HttpResponseCreated(disk.to_view())) + Ok(HttpResponseCreated(disk.into())) } /** @@ -343,7 +349,7 @@ async fn project_disks_get_disk( let project_name = &path.project_name; let disk_name = &path.disk_name; let disk = nexus.project_lookup_disk(&project_name, &disk_name).await?; - Ok(HttpResponseOk(disk.to_view())) + Ok(HttpResponseOk(disk.into())) } /** diff --git a/omicron-nexus/src/http_entrypoints_internal.rs b/omicron-nexus/src/http_entrypoints_internal.rs index b77eeed5066..9183803bcf1 100644 --- a/omicron-nexus/src/http_entrypoints_internal.rs +++ b/omicron-nexus/src/http_entrypoints_internal.rs @@ -10,7 +10,7 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::InstanceRuntimeState; use omicron_common::api::external::OximeterInfo; use omicron_common::api::external::ProducerEndpoint; diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index aa5bba23452..900014667ed 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -11,15 +11,15 @@ use chrono::Utc; use futures::future::ready; use futures::lock::Mutex; use futures::StreamExt; +use omicron_common::api::internal::nexus::Disk; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DeleteResult; -use omicron_common::api::external::Disk; use omicron_common::api::external::DiskAttachment; use omicron_common::api::external::DiskCreateParams; -use omicron_common::api::external::DiskRuntimeState; use omicron_common::api::external::DiskState; -use omicron_common::api::external::DiskStateRequested; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; use omicron_common::api::external::IdentityMetadata; diff --git a/omicron-sled-agent/src/common/disk.rs b/omicron-sled-agent/src/common/disk.rs index e262982200c..657016ca1b2 100644 --- a/omicron-sled-agent/src/common/disk.rs +++ b/omicron-sled-agent/src/common/disk.rs @@ -1,9 +1,9 @@ //! Describes the states of network-attached storage. use chrono::Utc; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::DiskState; -use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::Error; use propolis_client::api::DiskAttachmentState as PropolisDiskState; use uuid::Uuid; diff --git a/omicron-sled-agent/src/http_entrypoints.rs b/omicron-sled-agent/src/http_entrypoints.rs index 3b059823216..cc33a48fdd7 100644 --- a/omicron-sled-agent/src/http_entrypoints.rs +++ b/omicron-sled-agent/src/http_entrypoints.rs @@ -7,8 +7,8 @@ use dropshot::HttpResponseOk; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::external::DiskEnsureBody; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskEnsureBody; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::InstanceEnsureBody; use omicron_common::api::external::InstanceRuntimeState; use schemars::JsonSchema; diff --git a/omicron-sled-agent/src/sim/collection.rs b/omicron-sled-agent/src/sim/collection.rs index e9f303eae62..f06afc70ac8 100644 --- a/omicron-sled-agent/src/sim/collection.rs +++ b/omicron-sled-agent/src/sim/collection.rs @@ -336,9 +336,9 @@ mod test { use chrono::Utc; use dropshot::test_util::LogContext; use futures::channel::mpsc::Receiver; - use omicron_common::api::external::DiskRuntimeState; + use omicron_common::api::internal::nexus::DiskRuntimeState; + use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::DiskState; - use omicron_common::api::external::DiskStateRequested; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceRuntimeState; diff --git a/omicron-sled-agent/src/sim/disk.rs b/omicron-sled-agent/src/sim/disk.rs index 74d8ade310d..da88d6720ea 100644 --- a/omicron-sled-agent/src/sim/disk.rs +++ b/omicron-sled-agent/src/sim/disk.rs @@ -4,9 +4,9 @@ use crate::sim::simulatable::Simulatable; use async_trait::async_trait; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::DiskState; -use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; use omicron_common::NexusClient; diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index 5d517e8842b..a70093c13ae 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -10,8 +10,8 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::external::DiskEnsureBody; -use omicron_common::api::external::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskEnsureBody; +use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::InstanceEnsureBody; use omicron_common::api::external::InstanceRuntimeState; use schemars::JsonSchema; diff --git a/omicron-sled-agent/src/sim/sled_agent.rs b/omicron-sled-agent/src/sim/sled_agent.rs index 8144ea11046..1782514dccd 100644 --- a/omicron-sled-agent/src/sim/sled_agent.rs +++ b/omicron-sled-agent/src/sim/sled_agent.rs @@ -2,8 +2,8 @@ * Simulated sled agent implementation */ -use omicron_common::api::external::DiskRuntimeState; -use omicron_common::api::external::DiskStateRequested; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::Error; use omicron_common::api::external::InstanceRuntimeState; use omicron_common::api::external::InstanceRuntimeStateRequested; diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 8750cf4c89b..aedf0a27034 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -1,10 +1,14 @@ //! Sled agent implementation use omicron_common::api::external::Error; -use omicron_common::api::external::{ - DiskRuntimeState, DiskStateRequested, InstanceRuntimeState, - InstanceRuntimeStateRequested, +use omicron_common::api::{ + external::{ + InstanceRuntimeState, InstanceRuntimeStateRequested, + }, + internal::nexus::DiskRuntimeState, + internal::sled_agent::DiskStateRequested, }; + use slog::Logger; use std::sync::Arc; use uuid::Uuid; From 26c187cb9e5450443e20cbbe722c81b054f657ea Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 15:03:56 -0400 Subject: [PATCH 08/14] Split project --- omicron-common/src/api/external/mod.rs | 36 +++++++++++-------- omicron-common/src/api/internal/nexus.rs | 6 ++++ omicron-common/src/model_db.rs | 2 +- omicron-nexus/src/db/datastore.rs | 12 +++---- omicron-nexus/src/db/schema.rs | 2 +- .../src/http_entrypoints_external.rs | 17 ++++----- omicron-nexus/src/nexus.rs | 2 +- 7 files changed, 43 insertions(+), 34 deletions(-) diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index 708e7c75e6e..efa1cdddaad 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -510,6 +510,19 @@ pub async fn to_view_list( .await } +pub async fn to_list( + object_stream: ObjectStream +) -> Vec +where + U: From, +{ + object_stream + .filter(|maybe_object| ready(maybe_object.is_ok())) + .map(|maybe_object| maybe_object.unwrap().into()) + .collect::>() + .await +} + /* * IDENTITY METADATA */ @@ -560,21 +573,6 @@ pub struct IdentityMetadataUpdateParams { * PROJECTS */ -/** - * A Project in the external API - */ -pub struct Project { - /** common identifying metadata */ - pub identity: IdentityMetadata, -} - -impl Object for Project { - type View = ProjectView; - fn to_view(&self) -> ProjectView { - ProjectView { identity: self.identity.clone() } - } -} - /** * Client view of an [`Project`] */ @@ -589,6 +587,14 @@ pub struct ProjectView { pub identity: IdentityMetadata, } +impl From for ProjectView { + fn from(project: crate::api::internal::nexus::Project) -> Self { + ProjectView { + identity: project.identity.clone() + } + } +} + /** * Create-time parameters for an [`Project`] */ diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index 1bd902ca788..dd92de73371 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -11,6 +11,12 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; +/// A collection of associated resources. +pub struct Project { + /// common identifying metadata. + pub identity: IdentityMetadata, +} + /// A Disk (network block device). #[derive(Clone, Debug)] pub struct Disk { diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 4eddecae64c..4fa6959528d 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -69,7 +69,7 @@ use crate::api::external::Name; use crate::api::external::OximeterAssignment; use crate::api::external::OximeterInfo; use crate::api::external::ProducerEndpoint; -use crate::api::external::Project; +use crate::api::internal::nexus::Project; use crate::bail_unless; use chrono::DateTime; use chrono::Utc; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index 317f19a1032..aed4338cedc 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -79,7 +79,7 @@ impl DataStore { &self, new_id: &Uuid, new_project: &api::external::ProjectCreateParams, - ) -> CreateResult { + ) -> CreateResult { let client = self.pool.acquire().await?; let now = Utc::now(); let mut values = SqlValueSet::new(); @@ -99,7 +99,7 @@ impl DataStore { pub async fn project_fetch( &self, project_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, @@ -154,7 +154,7 @@ impl DataStore { pub async fn projects_list_by_id( &self, pagparams: &DataPageParams<'_, Uuid>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_from_table::( &client, @@ -168,7 +168,7 @@ impl DataStore { pub async fn projects_list_by_name( &self, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueName, @@ -183,7 +183,7 @@ impl DataStore { &self, project_name: &Name, update_params: &api::external::ProjectUpdateParams, - ) -> UpdateResult { + ) -> UpdateResult { let client = self.pool.acquire().await?; let now = Utc::now(); @@ -212,7 +212,7 @@ impl DataStore { Error::not_found_by_name(ResourceType::Project, project_name) }) .await?; - Ok(api::external::Project::try_from(&row)?) + Ok(api::internal::nexus::Project::try_from(&row)?) } /* diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index 1b3efd6f2e6..6eec6ed70b1 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -20,7 +20,7 @@ use crate::db; /** Describes the "Project" table */ pub struct Project; impl Table for Project { - type ModelType = api::external::Project; + type ModelType = api::internal::nexus::Project; const TABLE_NAME: &'static str = "Project"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index 4c296c4947f..02e074b85a6 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -16,7 +16,7 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::TypedBody; -use futures::stream::StreamExt; +use omicron_common::api; use omicron_common::api::external::http_pagination::data_page_params_for; use omicron_common::api::external::http_pagination::data_page_params_nameid_id; use omicron_common::api::external::http_pagination::data_page_params_nameid_name; @@ -30,6 +30,7 @@ use omicron_common::api::external::http_pagination::ScanByName; use omicron_common::api::external::http_pagination::ScanByNameOrId; use omicron_common::api::external::http_pagination::ScanParams; use omicron_common::api::external::to_view_list; +use omicron_common::api::external::to_list; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DiskAttachment; use omicron_common::api::external::DiskCreateParams; @@ -167,7 +168,7 @@ async fn projects_get( } }; - let view_list = to_view_list(project_stream).await; + let view_list = to_list::(project_stream).await; Ok(HttpResponseOk(ScanByNameOrId::results_page(&query, view_list)?)) } @@ -185,7 +186,7 @@ async fn projects_post( let apictx = rqctx.context(); let nexus = &apictx.nexus; let project = nexus.project_create(&new_project.into_inner()).await?; - Ok(HttpResponseCreated(project.to_view())) + Ok(HttpResponseCreated(project.into())) } /** @@ -213,7 +214,7 @@ async fn projects_get_project( let path = path_params.into_inner(); let project_name = &path.project_name; let project = nexus.project_fetch(&project_name).await?; - Ok(HttpResponseOk(project.to_view())) + Ok(HttpResponseOk(project.into())) } /** @@ -260,7 +261,7 @@ async fn projects_put_project( let newproject = nexus .project_update(&project_name, &updated_project.into_inner()) .await?; - Ok(HttpResponseOk(newproject.to_view())) + Ok(HttpResponseOk(newproject.into())) } /* @@ -291,11 +292,7 @@ async fn project_disks_get( ) .await?; - let disk_list = disk_stream - .filter(|maybe_disk| futures::future::ready(maybe_disk.is_ok())) - .map(|maybe_disk| maybe_disk.unwrap().into()) - .collect::>() - .await; + let disk_list = to_list::(disk_stream).await; Ok(HttpResponseOk(ScanByName::results_page(&query, disk_list)?)) } diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 900014667ed..51a939944a7 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -13,6 +13,7 @@ use futures::lock::Mutex; use futures::StreamExt; use omicron_common::api::internal::nexus::Disk; use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::Project; use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; @@ -34,7 +35,6 @@ use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; use omicron_common::api::external::OximeterInfo; use omicron_common::api::external::ProducerEndpoint; -use omicron_common::api::external::Project; use omicron_common::api::external::ProjectCreateParams; use omicron_common::api::external::ProjectUpdateParams; use omicron_common::api::external::Rack; From 0d941fb739edcd07232db4ea889381688beaf7d6 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 15:43:46 -0400 Subject: [PATCH 09/14] Split up some instances --- omicron-common/src/api/external/mod.rs | 158 ++---------------- omicron-common/src/api/internal/nexus.rs | 40 +++++ omicron-common/src/api/internal/sled_agent.rs | 73 ++++++++ omicron-common/src/model_db.rs | 4 +- omicron-common/src/nexus_client.rs | 2 +- omicron-common/src/sled_agent_client.rs | 6 +- omicron-nexus/src/db/conversions.rs | 2 +- omicron-nexus/src/db/datastore.rs | 12 +- omicron-nexus/src/db/schema.rs | 2 +- .../src/http_entrypoints_external.rs | 12 +- .../src/http_entrypoints_internal.rs | 2 +- omicron-nexus/src/nexus.rs | 8 +- omicron-nexus/src/sagas.rs | 6 +- omicron-sled-agent/src/common/instance.rs | 13 +- omicron-sled-agent/src/http_entrypoints.rs | 6 +- omicron-sled-agent/src/instance.rs | 10 +- omicron-sled-agent/src/instance_manager.rs | 11 +- omicron-sled-agent/src/mocks/mod.rs | 2 +- omicron-sled-agent/src/sim/collection.rs | 6 +- .../src/sim/http_entrypoints.rs | 4 +- omicron-sled-agent/src/sim/instance.rs | 6 +- omicron-sled-agent/src/sim/sled_agent.rs | 6 +- omicron-sled-agent/src/sled_agent.rs | 5 +- 23 files changed, 197 insertions(+), 199 deletions(-) diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index efa1cdddaad..569a8d9440f 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -722,62 +722,6 @@ impl InstanceState { } } -/** - * Requestable running state of an Instance. - * - * A subset of [`InstanceState`]. - */ -#[derive( - Copy, - Clone, - Debug, - Deserialize, - Eq, - Ord, - PartialEq, - PartialOrd, - Serialize, - JsonSchema, -)] -#[serde(rename_all = "lowercase")] -pub enum InstanceStateRequested { - Running, - Stopped, - // Issues a reset command to the instance, such that it should - // stop and then immediately become running. - Reboot, - Destroyed, -} - -impl Display for InstanceStateRequested { - fn fmt(&self, f: &mut Formatter) -> FormatResult { - write!(f, "{}", self.label()) - } -} - -impl InstanceStateRequested { - fn label(&self) -> &str { - match self { - InstanceStateRequested::Running => "running", - InstanceStateRequested::Stopped => "stopped", - InstanceStateRequested::Reboot => "reboot", - InstanceStateRequested::Destroyed => "destroyed", - } - } - - /** - * Returns true if the state represents a stopped Instance. - */ - pub fn is_stopped(&self) -> bool { - match self { - InstanceStateRequested::Running => false, - InstanceStateRequested::Stopped => true, - InstanceStateRequested::Reboot => false, - InstanceStateRequested::Destroyed => true, - } - } -} - /** The number of CPUs in an Instance */ #[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct InstanceCpuCount(pub u16); @@ -796,72 +740,6 @@ impl From<&InstanceCpuCount> for i64 { } } -/** - * An Instance (VM) in the external API - */ -#[derive(Clone, Debug)] -pub struct Instance { - /** common identifying metadata */ - pub identity: IdentityMetadata, - - /** id for the project containing this Instance */ - pub project_id: Uuid, - - /** number of CPUs allocated for this Instance */ - pub ncpus: InstanceCpuCount, - /** memory allocated for this Instance */ - pub memory: ByteCount, - /** RFC1035-compliant hostname for the Instance. */ - pub hostname: String, /* TODO-cleanup different type? */ - - /** state owned by the data plane */ - pub runtime: InstanceRuntimeState, - /* TODO-completeness: add disks, network, tags, metrics */ -} - -impl Object for Instance { - type View = InstanceView; - fn to_view(&self) -> InstanceView { - InstanceView { - identity: self.identity.clone(), - project_id: self.project_id, - ncpus: self.ncpus, - memory: self.memory, - hostname: self.hostname.clone(), - runtime: self.runtime.to_view(), - } - } -} - -/** - * Runtime state of the Instance, including the actual running state and minimal - * metadata - * - * This state is owned by the sled agent running that Instance. - */ -#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] -pub struct InstanceRuntimeState { - /** runtime state of the Instance */ - pub run_state: InstanceState, - /** which sled is running this Instance */ - pub sled_uuid: Uuid, - /** generation number for this state */ - pub gen: Generation, - /** timestamp for this information */ - pub time_updated: DateTime, -} - -/** - * Used to request an Instance state change from a sled agent - * - * Right now, it's only the run state that can be changed, though we might want - * to support changing properties like "ncpus" here. - */ -#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] -pub struct InstanceRuntimeStateRequested { - pub run_state: InstanceStateRequested, -} - /** * Client view of an [`InstanceRuntimeState`] */ @@ -872,12 +750,11 @@ pub struct InstanceRuntimeStateView { pub time_run_state_updated: DateTime, } -impl Object for InstanceRuntimeState { - type View = InstanceRuntimeStateView; - fn to_view(&self) -> InstanceRuntimeStateView { +impl From for InstanceRuntimeStateView { + fn from(state: crate::api::internal::nexus::InstanceRuntimeState) -> Self { InstanceRuntimeStateView { - run_state: self.run_state, - time_run_state_updated: self.time_updated, + run_state: state.run_state, + time_run_state_updated: state.time_updated, } } } @@ -906,6 +783,19 @@ pub struct InstanceView { pub runtime: InstanceRuntimeStateView, } +impl From for InstanceView { + fn from(instance: crate::api::internal::nexus::Instance) -> Self { + InstanceView { + identity: instance.identity.clone(), + project_id: instance.project_id, + ncpus: instance.ncpus, + memory: instance.memory, + hostname: instance.hostname.clone(), + runtime: instance.runtime.into(), + } + } +} + /** * Create-time parameters for an [`Instance`] */ @@ -1274,20 +1164,6 @@ pub struct SledAgentStartupInfo { pub sa_address: SocketAddr, } -/** - * Sent from Nexus to a sled agent to establish the runtime state of an Instance - */ -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct InstanceEnsureBody { - /** - * Last runtime state of the Instance known to Nexus (used if the agent - * has never seen this Instance before). - */ - pub initial_runtime: InstanceRuntimeState, - /** requested runtime state of the Instance */ - pub target: InstanceRuntimeStateRequested, -} - /* * Bootstrap Agent objects */ diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index dd92de73371..3b2d2af7748 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -5,6 +5,8 @@ use crate::api::external::{ DiskState, Generation, IdentityMetadata, + InstanceCpuCount, + InstanceState, }; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -46,3 +48,41 @@ pub struct DiskRuntimeState { pub time_updated: DateTime, } +/// An Instance (VM). +#[derive(Clone, Debug)] +pub struct Instance { + /// common identifying metadata + pub identity: IdentityMetadata, + + /// id for the project containing this Instance + pub project_id: Uuid, + + /// number of CPUs allocated for this Instance + pub ncpus: InstanceCpuCount, + /// memory allocated for this Instance + pub memory: ByteCount, + /// RFC1035-compliant hostname for the Instance. + // TODO-cleanup different type? + pub hostname: String, + + /// state owned by the data plane + pub runtime: InstanceRuntimeState, + + // TODO-completeness: add disks, network, tags, metrics +} + +/// Runtime state of the Instance, including the actual running state and minimal +/// metadata +/// +/// This state is owned by the sled agent running that Instance. +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] +pub struct InstanceRuntimeState { + /// runtime state of the Instance + pub run_state: InstanceState, + /// which sled is running this Instance + pub sled_uuid: Uuid, + /// generation number for this state + pub gen: Generation, + /// timestamp for this information + pub time_updated: DateTime, +} diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index 0d156257531..238819e10ea 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -3,6 +3,7 @@ use crate::api::internal; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use std::fmt::{Debug, Display, Formatter, Result as FormatResult}; use uuid::Uuid; /// Sent from to a sled agent to establish the runtime state of a Disk @@ -38,3 +39,75 @@ impl DiskStateRequested { } } +/// Sent to a sled agent to establish the runtime state of an Instance +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct InstanceEnsureBody { + /// Last runtime state of the Instance known to Nexus (used if the agent + /// has never seen this Instance before). + pub initial_runtime: internal::nexus::InstanceRuntimeState, + /// requested runtime state of the Instance + pub target: InstanceRuntimeStateRequested, +} + + +/// Requestable running state of an Instance. +/// +/// A subset of [`InstanceState`]. +#[derive( + Copy, + Clone, + Debug, + Deserialize, + Eq, + Ord, + PartialEq, + PartialOrd, + Serialize, + JsonSchema, +)] +#[serde(rename_all = "lowercase")] +pub enum InstanceStateRequested { + Running, + Stopped, + // Issues a reset command to the instance, such that it should + // stop and then immediately become running. + Reboot, + Destroyed, +} + +impl Display for InstanceStateRequested { + fn fmt(&self, f: &mut Formatter) -> FormatResult { + write!(f, "{}", self.label()) + } +} + +impl InstanceStateRequested { + fn label(&self) -> &str { + match self { + InstanceStateRequested::Running => "running", + InstanceStateRequested::Stopped => "stopped", + InstanceStateRequested::Reboot => "reboot", + InstanceStateRequested::Destroyed => "destroyed", + } + } + + /// Returns true if the state represents a stopped Instance. + pub fn is_stopped(&self) -> bool { + match self { + InstanceStateRequested::Running => false, + InstanceStateRequested::Stopped => true, + InstanceStateRequested::Reboot => false, + InstanceStateRequested::Destroyed => true, + } + } +} + +/// Used to request an Instance state change from a sled agent +/// +/// Right now, it's only the run state that can be changed, though we might want +/// to support changing properties like "ncpus" here. +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] +pub struct InstanceRuntimeStateRequested { + pub run_state: InstanceStateRequested, +} + diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 4fa6959528d..e5a1c3669ad 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -61,9 +61,9 @@ use crate::api::internal::nexus::DiskRuntimeState; use crate::api::external::DiskState; use crate::api::external::Generation; use crate::api::external::IdentityMetadata; -use crate::api::external::Instance; +use crate::api::internal::nexus::Instance; use crate::api::external::InstanceCpuCount; -use crate::api::external::InstanceRuntimeState; +use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::external::InstanceState; use crate::api::external::Name; use crate::api::external::OximeterAssignment; diff --git a/omicron-common/src/nexus_client.rs b/omicron-common/src/nexus_client.rs index c6a481c9390..85bd2057051 100644 --- a/omicron-common/src/nexus_client.rs +++ b/omicron-common/src/nexus_client.rs @@ -8,7 +8,7 @@ use crate::api::external::Error; use crate::api::internal::nexus::DiskRuntimeState; -use crate::api::external::InstanceRuntimeState; +use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::external::SledAgentStartupInfo; use crate::http_client::HttpClient; use http::Method; diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index a448cecafff..66b43634db7 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -9,9 +9,9 @@ use crate::api::external::Error; use crate::api::internal::sled_agent::DiskEnsureBody; use crate::api::internal::nexus::DiskRuntimeState; use crate::api::internal::sled_agent::DiskStateRequested; -use crate::api::external::InstanceEnsureBody; -use crate::api::external::InstanceRuntimeState; -use crate::api::external::InstanceRuntimeStateRequested; +use crate::api::internal::sled_agent::InstanceEnsureBody; +use crate::api::internal::nexus::InstanceRuntimeState; +use crate::api::internal::sled_agent::InstanceRuntimeStateRequested; use crate::http_client::HttpClient; use async_trait::async_trait; use http::Method; diff --git a/omicron-nexus/src/db/conversions.rs b/omicron-nexus/src/db/conversions.rs index 393e302ce2d..6ee97f2d51a 100644 --- a/omicron-nexus/src/db/conversions.rs +++ b/omicron-nexus/src/db/conversions.rs @@ -8,10 +8,10 @@ use chrono::DateTime; use chrono::Utc; use omicron_common::api::external::DiskCreateParams; use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::external::DiskState; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_common::api::external::InstanceCreateParams; -use omicron_common::api::external::InstanceRuntimeState; use omicron_common::api::external::InstanceState; use omicron_common::api::external::OximeterAssignment; use omicron_common::api::external::OximeterInfo; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index aed4338cedc..54f6519918a 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -249,8 +249,8 @@ impl DataStore { instance_id: &Uuid, project_id: &Uuid, params: &api::external::InstanceCreateParams, - runtime_initial: &api::external::InstanceRuntimeState, - ) -> CreateResult { + runtime_initial: &api::internal::nexus::InstanceRuntimeState, + ) -> CreateResult { let client = self.pool.acquire().await?; let now = runtime_initial.time_updated; let mut values = SqlValueSet::new(); @@ -290,7 +290,7 @@ impl DataStore { &self, project_id: &Uuid, pagparams: &DataPageParams<'_, Name>, - ) -> ListResult { + ) -> ListResult { let client = self.pool.acquire().await?; sql_fetch_page_by::< LookupByUniqueNameInProject, @@ -303,7 +303,7 @@ impl DataStore { pub async fn instance_fetch( &self, instance_id: &Uuid, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::(&client, (), instance_id) .await @@ -313,7 +313,7 @@ impl DataStore { &self, project_id: &Uuid, instance_name: &Name, - ) -> LookupResult { + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::( &client, @@ -335,7 +335,7 @@ impl DataStore { pub async fn instance_update_runtime( &self, instance_id: &Uuid, - new_runtime: &api::external::InstanceRuntimeState, + new_runtime: &api::internal::nexus::InstanceRuntimeState, ) -> Result { let client = self.pool.acquire().await?; diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index 6eec6ed70b1..7ecb82409af 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -39,7 +39,7 @@ impl ResourceTable for Project { /** Describes the "Instance" table */ pub struct Instance; impl Table for Instance { - type ModelType = api::external::Instance; + type ModelType = api::internal::nexus::Instance; const TABLE_NAME: &'static str = "Instance"; const ALL_COLUMNS: &'static [&'static str] = &[ "id", diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index 02e074b85a6..58547717d4d 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -396,7 +396,7 @@ async fn project_instances_get( &data_page_params_for(&rqctx, &query)?, ) .await?; - let view_list = to_view_list(instance_stream).await; + let view_list = to_list::(instance_stream).await; Ok(HttpResponseOk(ScanByName::results_page(&query, view_list)?)) } @@ -428,7 +428,7 @@ async fn project_instances_post( let instance = nexus .project_create_instance(&project_name, &new_instance_params) .await?; - Ok(HttpResponseCreated(instance.to_view())) + Ok(HttpResponseCreated(instance.into())) } /** @@ -458,7 +458,7 @@ async fn project_instances_get_instance( let instance_name = &path.instance_name; let instance = nexus.project_lookup_instance(&project_name, &instance_name).await?; - Ok(HttpResponseOk(instance.to_view())) + Ok(HttpResponseOk(instance.into())) } /** @@ -498,7 +498,7 @@ async fn project_instances_instance_reboot( let project_name = &path.project_name; let instance_name = &path.instance_name; let instance = nexus.instance_reboot(&project_name, &instance_name).await?; - Ok(HttpResponseAccepted(instance.to_view())) + Ok(HttpResponseAccepted(instance.into())) } /** @@ -518,7 +518,7 @@ async fn project_instances_instance_start( let project_name = &path.project_name; let instance_name = &path.instance_name; let instance = nexus.instance_start(&project_name, &instance_name).await?; - Ok(HttpResponseAccepted(instance.to_view())) + Ok(HttpResponseAccepted(instance.into())) } /** @@ -539,7 +539,7 @@ async fn project_instances_instance_stop( let project_name = &path.project_name; let instance_name = &path.instance_name; let instance = nexus.instance_stop(&project_name, &instance_name).await?; - Ok(HttpResponseAccepted(instance.to_view())) + Ok(HttpResponseAccepted(instance.into())) } /** diff --git a/omicron-nexus/src/http_entrypoints_internal.rs b/omicron-nexus/src/http_entrypoints_internal.rs index 9183803bcf1..28f7362eadd 100644 --- a/omicron-nexus/src/http_entrypoints_internal.rs +++ b/omicron-nexus/src/http_entrypoints_internal.rs @@ -11,7 +11,7 @@ use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::external::OximeterInfo; use omicron_common::api::external::ProducerEndpoint; use omicron_common::api::external::SledAgentStartupInfo; diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 51a939944a7..dd98642cf20 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -13,8 +13,12 @@ use futures::lock::Mutex; use futures::StreamExt; use omicron_common::api::internal::nexus::Disk; use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::Instance; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::nexus::Project; use omicron_common::api::internal::sled_agent::DiskStateRequested; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; +use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DeleteResult; @@ -24,12 +28,8 @@ use omicron_common::api::external::DiskState; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; use omicron_common::api::external::IdentityMetadata; -use omicron_common::api::external::Instance; use omicron_common::api::external::InstanceCreateParams; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::api::external::InstanceState; -use omicron_common::api::external::InstanceStateRequested; use omicron_common::api::external::ListResult; use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index 6b7af3d9994..65604b926b5 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -14,10 +14,10 @@ use chrono::Utc; use lazy_static::lazy_static; use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceCreateParams; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::api::external::InstanceState; -use omicron_common::api::external::InstanceStateRequested; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; +use omicron_common::api::internal::sled_agent::InstanceStateRequested; use serde::Deserialize; use serde::Serialize; use std::collections::BTreeMap; diff --git a/omicron-sled-agent/src/common/instance.rs b/omicron-sled-agent/src/common/instance.rs index 839ae1f4925..f553dde2256 100644 --- a/omicron-sled-agent/src/common/instance.rs +++ b/omicron-sled-agent/src/common/instance.rs @@ -2,10 +2,10 @@ use chrono::Utc; use omicron_common::api::external::Error; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::api::external::InstanceState; -use omicron_common::api::external::InstanceStateRequested; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; +use omicron_common::api::internal::sled_agent::InstanceStateRequested; use propolis_client::api::InstanceState as PropolisInstanceState; /// Action to be taken on behalf of state transition. @@ -262,8 +262,11 @@ mod test { use super::{Action, InstanceStates}; use chrono::Utc; use omicron_common::api::external::{ - Generation, InstanceRuntimeState, InstanceState as State, - InstanceStateRequested as Requested, + Generation, InstanceState as State, + }; + use omicron_common::api::internal::{ + nexus::InstanceRuntimeState, + sled_agent::InstanceStateRequested as Requested, }; use propolis_client::api::InstanceState as Observed; diff --git a/omicron-sled-agent/src/http_entrypoints.rs b/omicron-sled-agent/src/http_entrypoints.rs index cc33a48fdd7..72ea0c0e5ad 100644 --- a/omicron-sled-agent/src/http_entrypoints.rs +++ b/omicron-sled-agent/src/http_entrypoints.rs @@ -7,10 +7,10 @@ use dropshot::HttpResponseOk; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::internal::sled_agent::DiskEnsureBody; use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::external::InstanceEnsureBody; -use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::DiskEnsureBody; +use omicron_common::api::internal::sled_agent::InstanceEnsureBody; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index f5579797ef9..947b59a2378 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -6,8 +6,8 @@ use crate::illumos::{dladm::VNIC_PREFIX, zone::ZONE_PREFIX}; use crate::instance_manager::InstanceTicket; use futures::lock::Mutex; use omicron_common::api::external::Error; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::dev::poll; use propolis_client::Client as PropolisClient; use slog::Logger; @@ -478,7 +478,11 @@ mod test { }; use futures::future::FutureExt; use omicron_common::api::external::{ - Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, + Generation, InstanceState, + }; + use omicron_common::api::internal::{ + nexus::InstanceRuntimeState, + sled_agent::InstanceStateRequested, }; use propolis_client::api; use tokio::sync::watch; diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 391ec0d1e13..d5d9810cdca 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -2,9 +2,8 @@ use crate::illumos::zfs::ZONE_ZFS_DATASET; use omicron_common::api::external::Error; -use omicron_common::api::external::{ - InstanceRuntimeState, InstanceRuntimeStateRequested, -}; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use slog::Logger; use std::collections::BTreeMap; use std::sync::{ @@ -200,7 +199,11 @@ mod test { use crate::mocks::MockNexusClient; use chrono::Utc; use omicron_common::api::external::{ - Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, + Generation, InstanceState, + }; + use omicron_common::api::internal::{ + nexus::InstanceRuntimeState, + sled_agent::InstanceStateRequested, }; static INST_UUID_STR: &str = "e398c5d5-5059-4e55-beac-3a1071083aaa"; diff --git a/omicron-sled-agent/src/mocks/mod.rs b/omicron-sled-agent/src/mocks/mod.rs index 55c46f0de3e..06eae04ec36 100644 --- a/omicron-sled-agent/src/mocks/mod.rs +++ b/omicron-sled-agent/src/mocks/mod.rs @@ -2,7 +2,7 @@ use mockall::mock; use omicron_common::api::external::Error; -use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::external::SledAgentStartupInfo; use slog::Logger; use std::net::SocketAddr; diff --git a/omicron-sled-agent/src/sim/collection.rs b/omicron-sled-agent/src/sim/collection.rs index f06afc70ac8..b9f785d6af1 100644 --- a/omicron-sled-agent/src/sim/collection.rs +++ b/omicron-sled-agent/src/sim/collection.rs @@ -341,10 +341,10 @@ mod test { use omicron_common::api::external::DiskState; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; - use omicron_common::api::external::InstanceRuntimeState; - use omicron_common::api::external::InstanceRuntimeStateRequested; use omicron_common::api::external::InstanceState; - use omicron_common::api::external::InstanceStateRequested; + use omicron_common::api::internal::nexus::InstanceRuntimeState; + use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; + use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::dev::test_setup_log; fn make_instance( diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index a70093c13ae..0c9de697cca 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -12,8 +12,8 @@ use dropshot::RequestContext; use dropshot::TypedBody; use omicron_common::api::internal::sled_agent::DiskEnsureBody; use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::external::InstanceEnsureBody; -use omicron_common::api::external::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceEnsureBody; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/instance.rs b/omicron-sled-agent/src/sim/instance.rs index 8f7e7072eb1..342423b0b47 100644 --- a/omicron-sled-agent/src/sim/instance.rs +++ b/omicron-sled-agent/src/sim/instance.rs @@ -7,10 +7,10 @@ use super::simulatable::Simulatable; use async_trait::async_trait; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::api::external::InstanceState; -use omicron_common::api::external::InstanceStateRequested; +use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::NexusClient; use propolis_client::api::InstanceState as PropolisInstanceState; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/sled_agent.rs b/omicron-sled-agent/src/sim/sled_agent.rs index 1782514dccd..da2cc48ba50 100644 --- a/omicron-sled-agent/src/sim/sled_agent.rs +++ b/omicron-sled-agent/src/sim/sled_agent.rs @@ -2,11 +2,11 @@ * Simulated sled agent implementation */ +use omicron_common::api::external::Error; use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::sled_agent::DiskStateRequested; -use omicron_common::api::external::Error; -use omicron_common::api::external::InstanceRuntimeState; -use omicron_common::api::external::InstanceRuntimeStateRequested; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::NexusClient; use slog::Logger; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index aedf0a27034..1cd29465ac6 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -2,11 +2,10 @@ use omicron_common::api::external::Error; use omicron_common::api::{ - external::{ - InstanceRuntimeState, InstanceRuntimeStateRequested, - }, internal::nexus::DiskRuntimeState, + internal::nexus::InstanceRuntimeState, internal::sled_agent::DiskStateRequested, + internal::sled_agent::InstanceRuntimeStateRequested, }; use slog::Logger; From 37aedcc728bde13029e35d5ecfda8735cafee559 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 20:13:18 -0400 Subject: [PATCH 10/14] Sagas, diskattachments, racks/sleds, bootstrap agent objects --- .../src/bin/bootstrap-agent.rs | 2 +- .../src/bootstrap_agent.rs | 6 +- .../src/bootstrap_agent_client.rs | 10 +- .../src/http_entrypoints.rs | 8 +- omicron-common/src/api/external/mod.rs | 151 ++---------------- .../src/api/internal/bootstrap_agent.rs | 18 +++ omicron-common/src/api/internal/mod.rs | 1 + omicron-common/src/api/internal/nexus.rs | 19 ++- omicron-common/src/nexus_client.rs | 2 +- .../src/http_entrypoints_external.rs | 18 +-- .../src/http_entrypoints_internal.rs | 2 +- omicron-nexus/src/nexus.rs | 4 +- omicron-sled-agent/src/mocks/mod.rs | 2 +- omicron-sled-agent/src/server.rs | 2 +- omicron-sled-agent/src/sim/server.rs | 2 +- 15 files changed, 82 insertions(+), 165 deletions(-) create mode 100644 omicron-common/src/api/internal/bootstrap_agent.rs diff --git a/omicron-bootstrap-agent/src/bin/bootstrap-agent.rs b/omicron-bootstrap-agent/src/bin/bootstrap-agent.rs index 506a67efa3d..19ab27e26ee 100644 --- a/omicron-bootstrap-agent/src/bin/bootstrap-agent.rs +++ b/omicron-bootstrap-agent/src/bin/bootstrap-agent.rs @@ -15,7 +15,7 @@ use uuid::Uuid; #[derive(Debug, StructOpt)] #[structopt( - name = "boostrap_agent", + name = "bootstrap_agent", about = "See README.adoc for more information" )] enum Args { diff --git a/omicron-bootstrap-agent/src/bootstrap_agent.rs b/omicron-bootstrap-agent/src/bootstrap_agent.rs index ec34d3b51af..278cba19008 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent.rs @@ -1,5 +1,5 @@ use crate::bootstrap_agent_client::Client as BootstrapClient; -use omicron_common::api::external::BootstrapAgentShareResponse; +use omicron_common::api::internal::bootstrap_agent::ShareResponse; use omicron_common::api::external::Error; use omicron_common::packaging::sha256_digest; @@ -49,14 +49,14 @@ impl BootstrapAgent { pub async fn request_share( &self, identity: Vec, - ) -> Result { + ) -> Result { // TODO-correctness: Validate identity, return whatever // information is necessary to establish trust quorum. // // This current implementation is a placeholder. info!(&self.log, "request_share, received identity: {:x?}", identity); - Ok(BootstrapAgentShareResponse { shared_secret: vec![] }) + Ok(ShareResponse { shared_secret: vec![] }) } /// Performs device initialization: diff --git a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs index 6f62595e676..61fdc340068 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs @@ -5,8 +5,8 @@ * generated by the server. */ -use omicron_common::api::external::BootstrapAgentShareRequest; -use omicron_common::api::external::BootstrapAgentShareResponse; +use omicron_common::api::internal::bootstrap_agent::ShareRequest; +use omicron_common::api::internal::bootstrap_agent::ShareResponse; use omicron_common::api::external::Error; use omicron_common::http_client::HttpClient; @@ -38,10 +38,10 @@ impl Client { pub async fn request_share( &self, identity: Vec, - ) -> Result { + ) -> Result { let path = "/request_share"; let body = Body::from( - serde_json::to_string(&BootstrapAgentShareRequest { identity }) + serde_json::to_string(&ShareRequest { identity }) .unwrap(), ); let mut response = self.client.request(Method::GET, path, body).await?; @@ -49,7 +49,7 @@ impl Client { assert!(response.status().is_success()); let value = self .client - .read_json::( + .read_json::( &self.client.error_message_base(&Method::GET, path), &mut response, ) diff --git a/omicron-bootstrap-agent/src/http_entrypoints.rs b/omicron-bootstrap-agent/src/http_entrypoints.rs index aff25cefafe..c157e3bf29c 100644 --- a/omicron-bootstrap-agent/src/http_entrypoints.rs +++ b/omicron-bootstrap-agent/src/http_entrypoints.rs @@ -8,8 +8,8 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::external::{ - BootstrapAgentShareRequest, BootstrapAgentShareResponse, +use omicron_common::api::internal::bootstrap_agent::{ + ShareRequest, ShareResponse, }; use std::sync::Arc; @@ -39,8 +39,8 @@ pub fn ba_api() -> ApiDescription> { }] async fn api_request_share( rqctx: Arc>>, - request: TypedBody, -) -> Result, HttpError> { + request: TypedBody, +) -> Result, HttpError> { let bootstrap_agent = rqctx.context(); let request = request.into_inner(); diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index 569a8d9440f..935c06a8209 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -457,59 +457,6 @@ impl Display for ResourceType { } } -/** - * Object represents a resource in the API and is implemented by concrete - * types representing specific API resources. - * - * Consider a Project, which is about as simple a resource as we have. The - * `Project` struct represents a project as understood by the API. It - * contains all the fields necessary to implement a Project. It has several - * related types: - * - * * `ProjectView` is what gets emitted by the API when a user asks for a - * Project - * * `ProjectCreateParams` is what must be provided to the API when a user - * wants to create a new project - * * `ProjectUpdateParams` is what must be provided to the API when a user - * wants to update a project. - * - * We also have Instances, Disks, Racks, Sleds, and many related types, and we - * expect to add many more types like images, networking abstractions, - * organizations, teams, users, system components, and the like. See RFD 4 for - * details. Some resources may not have analogs for all these types because - * they're immutable (e.g., the `Rack` resource doesn't define a - * "CreateParams" type). - * - * The only thing guaranteed by the `Object` trait is that the type can be - * converted to a View, which is something that can be serialized. - */ -/* - * TODO-coverage: each type could have unit tests for various invalid input - * types? - */ -pub trait Object { - type View: Serialize + Clone + Debug; - fn to_view(&self) -> Self::View; -} - -/** - * Given an `ObjectStream` (for some specific `Object` type), - * return a vector of the objects' views. Any failures are ignored. - */ -/* - * TODO-hardening: Consider how to better deal with these failures. We should - * probably at least log something. - */ -pub async fn to_view_list( - object_stream: ObjectStream, -) -> Vec { - object_stream - .filter(|maybe_object| ready(maybe_object.is_ok())) - .map(|maybe_object| maybe_object.unwrap().to_view()) - .collect::>() - .await -} - pub async fn to_list( object_stream: ObjectStream ) -> Vec @@ -990,31 +937,10 @@ pub struct DiskAttachment { pub disk_state: DiskState, } -impl Object for DiskAttachment { - type View = Self; - fn to_view(&self) -> Self::View { - self.clone() - } -} - /* * RACKS */ -/** - * A Rack in the external API - */ -pub struct Rack { - pub identity: IdentityMetadata, -} - -impl Object for Rack { - type View = RackView; - fn to_view(&self) -> RackView { - RackView { identity: self.identity.clone() } - } -} - /** * Client view of an [`Rack`] */ @@ -1024,28 +950,18 @@ pub struct RackView { pub identity: IdentityMetadata, } -/* - * SLEDS - */ - -/** - * A Sled in the external API - */ -pub struct Sled { - pub identity: IdentityMetadata, - pub service_address: SocketAddr, -} - -impl Object for Sled { - type View = SledView; - fn to_view(&self) -> SledView { - SledView { - identity: self.identity.clone(), - service_address: self.service_address, +impl From for RackView { + fn from(rack: crate::api::internal::nexus::Rack) -> Self { + RackView { + identity: rack.identity.clone() } } } +/* + * SLEDS + */ + /** * Client view of an [`Sled`] */ @@ -1057,6 +973,15 @@ pub struct SledView { pub service_address: SocketAddr, } +impl From for SledView { + fn from(sled: crate::api::internal::nexus::Sled) -> Self { + SledView { + identity: sled.identity.clone(), + service_address: sled.service_address, + } + } +} + /* * Sagas * @@ -1090,13 +1015,6 @@ pub struct SagaView { pub identity: IdentityMetadata, } -impl Object for SagaView { - type View = Self; - fn to_view(&self) -> Self::View { - self.clone() - } -} - impl From for SagaView { fn from(s: steno::SagaView) -> Self { SagaView { @@ -1151,41 +1069,6 @@ impl From for SagaStateView { } } -/* - * Internal Control Plane API objects - */ - -/** - * Sent by a sled agent on startup to Nexus to request further instruction - */ -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct SledAgentStartupInfo { - /** the address of the sled agent's API endpoint */ - pub sa_address: SocketAddr, -} - -/* - * Bootstrap Agent objects - */ - -/** - * Identity signed by local RoT and Oxide certificate chain. - */ -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct BootstrapAgentShareRequest { - // TODO-completeness: format TBD; currently opaque. - pub identity: Vec, -} - -/** - * Sent between bootstrap agents to establish trust quorum. - */ -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct BootstrapAgentShareResponse { - // TODO-completeness: format TBD; currently opaque. - pub shared_secret: Vec, -} - /* * Oximeter producer/collector objects. */ diff --git a/omicron-common/src/api/internal/bootstrap_agent.rs b/omicron-common/src/api/internal/bootstrap_agent.rs new file mode 100644 index 00000000000..dbf9c2af7a5 --- /dev/null +++ b/omicron-common/src/api/internal/bootstrap_agent.rs @@ -0,0 +1,18 @@ +//! APIs exposed by the bootstrap agent + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// Identity signed by local RoT and Oxide certificate chain. +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct ShareRequest { + // TODO-completeness: format TBD; currently opaque. + pub identity: Vec, +} + +/// Sent between bootstrap agents to establish trust quorum. +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct ShareResponse { + // TODO-completeness: format TBD; currently opaque. + pub shared_secret: Vec, +} diff --git a/omicron-common/src/api/internal/mod.rs b/omicron-common/src/api/internal/mod.rs index 5578747942d..72d0ede9af4 100644 --- a/omicron-common/src/api/internal/mod.rs +++ b/omicron-common/src/api/internal/mod.rs @@ -1,4 +1,5 @@ //! Internally facing APIs. +pub mod bootstrap_agent; pub mod nexus; pub mod sled_agent; diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index 3b2d2af7748..c8e43948619 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -11,8 +11,18 @@ use crate::api::external::{ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use std::net::SocketAddr; use uuid::Uuid; +pub struct Rack { + pub identity: IdentityMetadata, +} + +pub struct Sled { + pub identity: IdentityMetadata, + pub service_address: SocketAddr, +} + /// A collection of associated resources. pub struct Project { /// common identifying metadata. @@ -35,7 +45,6 @@ pub struct Disk { pub runtime: DiskRuntimeState, } - /// Runtime state of the Disk, which includes its attach state and some minimal /// metadata #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] @@ -86,3 +95,11 @@ pub struct InstanceRuntimeState { /// timestamp for this information pub time_updated: DateTime, } + +/// Sent by a sled agent on startup to Nexus to request further instruction +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct SledAgentStartupInfo { + /// the address of the sled agent's API endpoint + pub sa_address: SocketAddr, +} + diff --git a/omicron-common/src/nexus_client.rs b/omicron-common/src/nexus_client.rs index 85bd2057051..1ca7327c71c 100644 --- a/omicron-common/src/nexus_client.rs +++ b/omicron-common/src/nexus_client.rs @@ -9,7 +9,7 @@ use crate::api::external::Error; use crate::api::internal::nexus::DiskRuntimeState; use crate::api::internal::nexus::InstanceRuntimeState; -use crate::api::external::SledAgentStartupInfo; +use crate::api::internal::nexus::SledAgentStartupInfo; use crate::http_client::HttpClient; use http::Method; use hyper::Body; diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index 58547717d4d..b00ae32a0e4 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -29,7 +29,6 @@ use omicron_common::api::external::http_pagination::ScanById; use omicron_common::api::external::http_pagination::ScanByName; use omicron_common::api::external::http_pagination::ScanByNameOrId; use omicron_common::api::external::http_pagination::ScanParams; -use omicron_common::api::external::to_view_list; use omicron_common::api::external::to_list; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DiskAttachment; @@ -38,7 +37,6 @@ use omicron_common::api::external::DiskView; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceView; use omicron_common::api::external::Name; -use omicron_common::api::external::Object; use omicron_common::api::external::PaginationOrder; use omicron_common::api::external::ProjectCreateParams; use omicron_common::api::external::ProjectUpdateParams; @@ -567,7 +565,7 @@ async fn instance_disks_get( let disk_list = nexus .instance_list_disks(&project_name, &instance_name, &fake_query) .await?; - let view_list = to_view_list(disk_list).await; + let view_list = to_list(disk_list).await; Ok(HttpResponseOk(view_list)) } @@ -601,7 +599,7 @@ async fn instance_disks_get_disk( let attachment = nexus .instance_get_disk(&project_name, &instance_name, &disk_name) .await?; - Ok(HttpResponseOk(attachment.to_view())) + Ok(HttpResponseOk(attachment)) } /** @@ -624,7 +622,7 @@ async fn instance_disks_put_disk( let attachment = nexus .instance_attach_disk(&project_name, &instance_name, &disk_name) .await?; - Ok(HttpResponseCreated(attachment.to_view())) + Ok(HttpResponseCreated(attachment)) } /** @@ -670,7 +668,7 @@ async fn hardware_racks_get( let query = query_params.into_inner(); let rack_stream = nexus.racks_list(&data_page_params_for(&rqctx, &query)?).await?; - let view_list = to_view_list(rack_stream).await; + let view_list = to_list::(rack_stream).await; Ok(HttpResponseOk(ScanById::results_page(&query, view_list)?)) } @@ -698,7 +696,7 @@ async fn hardware_racks_get_rack( let nexus = &apictx.nexus; let path = path_params.into_inner(); let rack_info = nexus.rack_lookup(&path.rack_id).await?; - Ok(HttpResponseOk(rack_info.to_view())) + Ok(HttpResponseOk(rack_info.into())) } /* @@ -721,7 +719,7 @@ async fn hardware_sleds_get( let query = query_params.into_inner(); let sled_stream = nexus.sleds_list(&data_page_params_for(&rqctx, &query)?).await?; - let view_list = to_view_list(sled_stream).await; + let view_list = to_list::(sled_stream).await; Ok(HttpResponseOk(ScanById::results_page(&query, view_list)?)) } @@ -749,7 +747,7 @@ async fn hardware_sleds_get_sled( let nexus = &apictx.nexus; let path = path_params.into_inner(); let sled_info = nexus.sled_lookup(&path.sled_id).await?; - Ok(HttpResponseOk(sled_info.to_view())) + Ok(HttpResponseOk(sled_info.into())) } /* @@ -772,7 +770,7 @@ async fn sagas_get( let query = query_params.into_inner(); let pagparams = data_page_params_for(&rqctx, &query)?; let saga_stream = nexus.sagas_list(&pagparams).await?; - let view_list = to_view_list(saga_stream).await; + let view_list = to_list(saga_stream).await; Ok(HttpResponseOk(ScanById::results_page(&query, view_list)?)) } diff --git a/omicron-nexus/src/http_entrypoints_internal.rs b/omicron-nexus/src/http_entrypoints_internal.rs index 28f7362eadd..b4c59cdd26f 100644 --- a/omicron-nexus/src/http_entrypoints_internal.rs +++ b/omicron-nexus/src/http_entrypoints_internal.rs @@ -14,7 +14,7 @@ use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::external::OximeterInfo; use omicron_common::api::external::ProducerEndpoint; -use omicron_common::api::external::SledAgentStartupInfo; +use omicron_common::api::internal::nexus::SledAgentStartupInfo; use omicron_common::SledAgentClient; use schemars::JsonSchema; use serde::Deserialize; diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index dd98642cf20..8447f793d61 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -16,6 +16,8 @@ use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::internal::nexus::Instance; use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::nexus::Project; +use omicron_common::api::internal::nexus::Rack; +use omicron_common::api::internal::nexus::Sled; use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::api::internal::sled_agent::InstanceStateRequested; @@ -37,10 +39,8 @@ use omicron_common::api::external::OximeterInfo; use omicron_common::api::external::ProducerEndpoint; use omicron_common::api::external::ProjectCreateParams; use omicron_common::api::external::ProjectUpdateParams; -use omicron_common::api::external::Rack; use omicron_common::api::external::ResourceType; use omicron_common::api::external::SagaView; -use omicron_common::api::external::Sled; use omicron_common::api::external::UpdateResult; use omicron_common::bail_unless; use omicron_common::collection::collection_page; diff --git a/omicron-sled-agent/src/mocks/mod.rs b/omicron-sled-agent/src/mocks/mod.rs index 06eae04ec36..580eac58fd9 100644 --- a/omicron-sled-agent/src/mocks/mod.rs +++ b/omicron-sled-agent/src/mocks/mod.rs @@ -3,7 +3,7 @@ use mockall::mock; use omicron_common::api::external::Error; use omicron_common::api::internal::nexus::InstanceRuntimeState; -use omicron_common::api::external::SledAgentStartupInfo; +use omicron_common::api::internal::nexus::SledAgentStartupInfo; use slog::Logger; use std::net::SocketAddr; use uuid::Uuid; diff --git a/omicron-sled-agent/src/server.rs b/omicron-sled-agent/src/server.rs index 6c0a478ca88..71ff3949fc0 100644 --- a/omicron-sled-agent/src/server.rs +++ b/omicron-sled-agent/src/server.rs @@ -4,7 +4,7 @@ use super::config::Config; use super::http_entrypoints::api as http_api; use super::sled_agent::SledAgent; -use omicron_common::api::external::SledAgentStartupInfo; +use omicron_common::api::internal::nexus::SledAgentStartupInfo; use omicron_common::backoff::{ internal_service_policy, retry_notify, BackoffError, }; diff --git a/omicron-sled-agent/src/sim/server.rs b/omicron-sled-agent/src/sim/server.rs index 58896307243..4fdc454a478 100644 --- a/omicron-sled-agent/src/sim/server.rs +++ b/omicron-sled-agent/src/sim/server.rs @@ -6,7 +6,7 @@ use super::config::Config; use super::http_entrypoints::api as http_api; use super::sled_agent::SledAgent; -use omicron_common::api::external::SledAgentStartupInfo; +use omicron_common::api::internal::nexus::SledAgentStartupInfo; use omicron_common::backoff::{ internal_service_policy, retry_notify, BackoffError, }; From 2e0a0df3d9df07638f731b9c98d62a044f483b0f Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Thu, 22 Jul 2021 08:48:27 -0400 Subject: [PATCH 11/14] Oximeter structs --- omicron-common/src/api/external/mod.rs | 43 ------------------- omicron-common/src/api/internal/nexus.rs | 40 +++++++++++++++++ omicron-common/src/model_db.rs | 6 +-- omicron-common/src/oximeter_client.rs | 2 +- omicron-nexus/src/db/conversions.rs | 6 +-- omicron-nexus/src/db/datastore.rs | 6 +-- omicron-nexus/src/db/schema.rs | 4 +- .../src/http_entrypoints_internal.rs | 4 +- omicron-nexus/src/nexus.rs | 4 +- omicron-nexus/tests/common/mod.rs | 2 +- oximeter/oximeter/examples/producer.rs | 2 +- oximeter/oximeter/src/oximeter_server.rs | 2 +- oximeter/oximeter/src/producer_server.rs | 2 +- 13 files changed, 60 insertions(+), 63 deletions(-) diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index 935c06a8209..e0fa7fd4612 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -30,7 +30,6 @@ use std::fmt::Formatter; use std::fmt::Result as FormatResult; use std::net::SocketAddr; use std::num::NonZeroU32; -use std::time::Duration; use uuid::Uuid; /* @@ -1069,48 +1068,6 @@ impl From for SagaStateView { } } -/* - * Oximeter producer/collector objects. - */ - -/** - * Information announced by a metric server, used so that clients can contact it and collect - * available metric data from it. - */ -#[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] -pub struct ProducerEndpoint { - pub id: Uuid, - pub address: SocketAddr, - pub base_route: String, - pub interval: Duration, -} - -impl ProducerEndpoint { - /** - * Return the route that can be used to request metric data. - */ - pub fn collection_route(&self) -> String { - format!("{}/{}", &self.base_route, &self.id) - } -} - -/// Message used to notify Nexus that this oximeter instance is up and running. -#[derive(Debug, Clone, Copy, JsonSchema, Serialize, Deserialize)] -pub struct OximeterInfo { - /// The ID for this oximeter instance. - pub collector_id: Uuid, - - /// The address on which this oximeter instance listens for requests - pub address: SocketAddr, -} - -/// An assignment of an Oximeter instance to a metric producer for collection. -#[derive(Debug, Clone, Copy, JsonSchema, Serialize, Deserialize)] -pub struct OximeterAssignment { - pub oximeter_id: Uuid, - pub producer_id: Uuid, -} - #[cfg(test)] mod test { use super::ByteCount; diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index c8e43948619..efe11f55d1a 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -12,6 +12,7 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; +use std::time::Duration; use uuid::Uuid; pub struct Rack { @@ -103,3 +104,42 @@ pub struct SledAgentStartupInfo { pub sa_address: SocketAddr, } +// Oximeter producer/collector objects. + + +/// Information announced by a metric server, used so that clients can contact it and collect +/// available metric data from it. +#[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] +pub struct ProducerEndpoint { + pub id: Uuid, + pub address: SocketAddr, + pub base_route: String, + pub interval: Duration, +} + +impl ProducerEndpoint { + /** + * Return the route that can be used to request metric data. + */ + pub fn collection_route(&self) -> String { + format!("{}/{}", &self.base_route, &self.id) + } +} + +/// Message used to notify Nexus that this oximeter instance is up and running. +#[derive(Debug, Clone, Copy, JsonSchema, Serialize, Deserialize)] +pub struct OximeterInfo { + /// The ID for this oximeter instance. + pub collector_id: Uuid, + + /// The address on which this oximeter instance listens for requests + pub address: SocketAddr, +} + +/// An assignment of an Oximeter instance to a metric producer for collection. +// TODO: Goes to storage +#[derive(Debug, Clone, Copy, JsonSchema, Serialize, Deserialize)] +pub struct OximeterAssignment { + pub oximeter_id: Uuid, + pub producer_id: Uuid, +} diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index e5a1c3669ad..8b117dc6cc3 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -66,9 +66,9 @@ use crate::api::external::InstanceCpuCount; use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::external::InstanceState; use crate::api::external::Name; -use crate::api::external::OximeterAssignment; -use crate::api::external::OximeterInfo; -use crate::api::external::ProducerEndpoint; +use crate::api::internal::nexus::OximeterAssignment; +use crate::api::internal::nexus::OximeterInfo; +use crate::api::internal::nexus::ProducerEndpoint; use crate::api::internal::nexus::Project; use crate::bail_unless; use chrono::DateTime; diff --git a/omicron-common/src/oximeter_client.rs b/omicron-common/src/oximeter_client.rs index 0965e779fd1..befa53afe0d 100644 --- a/omicron-common/src/oximeter_client.rs +++ b/omicron-common/src/oximeter_client.rs @@ -9,7 +9,7 @@ use slog::Logger; use uuid::Uuid; use crate::api::external::Error; -use crate::api::external::ProducerEndpoint; +use crate::api::internal::nexus::ProducerEndpoint; use crate::http_client::HttpClient; /// Client of an oximeter server diff --git a/omicron-nexus/src/db/conversions.rs b/omicron-nexus/src/db/conversions.rs index 6ee97f2d51a..7c3556ecf33 100644 --- a/omicron-nexus/src/db/conversions.rs +++ b/omicron-nexus/src/db/conversions.rs @@ -13,9 +13,9 @@ use omicron_common::api::external::DiskState; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceState; -use omicron_common::api::external::OximeterAssignment; -use omicron_common::api::external::OximeterInfo; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::OximeterAssignment; +use omicron_common::api::internal::nexus::OximeterInfo; +use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::api::external::ProjectCreateParams; use super::sql::SqlSerialize; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index 54f6519918a..ace5ec4dee4 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -29,9 +29,9 @@ use omicron_common::api::external::Generation; use omicron_common::api::external::ListResult; use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; -use omicron_common::api::external::OximeterAssignment; -use omicron_common::api::external::OximeterInfo; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::OximeterAssignment; +use omicron_common::api::internal::nexus::OximeterInfo; +use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::api::external::ResourceType; use omicron_common::api::external::UpdateResult; use omicron_common::bail_unless; diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index 7ecb82409af..140ada25d8f 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -9,7 +9,7 @@ use omicron_common::api; use omicron_common::api::external::Error; use omicron_common::api::external::Name; use omicron_common::api::external::ResourceType; -use omicron_common::api::external::{OximeterInfo, ProducerEndpoint}; +use omicron_common::api::internal::nexus::{OximeterInfo, ProducerEndpoint}; use uuid::Uuid; use super::sql::LookupKey; @@ -146,7 +146,7 @@ impl Table for MetricProducer { /** Describes the "OximeterAssignment" table */ pub struct OximeterAssignment; impl Table for OximeterAssignment { - type ModelType = omicron_common::api::external::OximeterAssignment; + type ModelType = omicron_common::api::internal::nexus::OximeterAssignment; const TABLE_NAME: &'static str = "OximeterAssignment"; const ALL_COLUMNS: &'static [&'static str] = &["oximeter_id", "producer_id", "time_created"]; diff --git a/omicron-nexus/src/http_entrypoints_internal.rs b/omicron-nexus/src/http_entrypoints_internal.rs index b4c59cdd26f..9123b42ca00 100644 --- a/omicron-nexus/src/http_entrypoints_internal.rs +++ b/omicron-nexus/src/http_entrypoints_internal.rs @@ -12,8 +12,8 @@ use dropshot::RequestContext; use dropshot::TypedBody; use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::internal::nexus::InstanceRuntimeState; -use omicron_common::api::external::OximeterInfo; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::OximeterInfo; +use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::api::internal::nexus::SledAgentStartupInfo; use omicron_common::SledAgentClient; use schemars::JsonSchema; diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 8447f793d61..47be8c95202 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -35,8 +35,8 @@ use omicron_common::api::external::InstanceState; use omicron_common::api::external::ListResult; use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; -use omicron_common::api::external::OximeterInfo; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::OximeterInfo; +use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::api::external::ProjectCreateParams; use omicron_common::api::external::ProjectUpdateParams; use omicron_common::api::external::ResourceType; diff --git a/omicron-nexus/tests/common/mod.rs b/omicron-nexus/tests/common/mod.rs index 52ed506f7d0..7e3e1c91113 100644 --- a/omicron-nexus/tests/common/mod.rs +++ b/omicron-nexus/tests/common/mod.rs @@ -8,7 +8,7 @@ use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use omicron_common::api::external::IdentityMetadata; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::dev; use slog::o; use slog::Logger; diff --git a/oximeter/oximeter/examples/producer.rs b/oximeter/oximeter/examples/producer.rs index d5428470d80..2e147ad16e6 100644 --- a/oximeter/oximeter/examples/producer.rs +++ b/oximeter/oximeter/examples/producer.rs @@ -5,7 +5,7 @@ use std::time::Duration; use chrono::{DateTime, Utc}; use dropshot::{ConfigDropshot, ConfigLogging, ConfigLoggingLevel}; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::ProducerEndpoint; use oximeter::producer_server::{ ProducerServer, ProducerServerConfig, RegistrationInfo, }; diff --git a/oximeter/oximeter/src/oximeter_server.rs b/oximeter/oximeter/src/oximeter_server.rs index 38fa51b3b8a..c51a869a932 100644 --- a/oximeter/oximeter/src/oximeter_server.rs +++ b/oximeter/oximeter/src/oximeter_server.rs @@ -12,7 +12,7 @@ use dropshot::{ HttpResponseUpdatedNoContent, HttpServer, HttpServerStarter, RequestContext, TypedBody, }; -use omicron_common::api::external::{OximeterInfo, ProducerEndpoint}; +use omicron_common::api::internal::nexus::{OximeterInfo, ProducerEndpoint}; use omicron_common::backoff; use reqwest::Client; use serde::{Deserialize, Serialize}; diff --git a/oximeter/oximeter/src/producer_server.rs b/oximeter/oximeter/src/producer_server.rs index 88b2508feb7..5c50a07827c 100644 --- a/oximeter/oximeter/src/producer_server.rs +++ b/oximeter/oximeter/src/producer_server.rs @@ -9,7 +9,7 @@ use dropshot::{ endpoint, ApiDescription, ConfigDropshot, ConfigLogging, HttpError, HttpResponseOk, HttpServer, HttpServerStarter, Path, RequestContext, }; -use omicron_common::api::external::ProducerEndpoint; +use omicron_common::api::internal::nexus::ProducerEndpoint; use reqwest::Client; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; From 51f8624b87a57ffc0ed9d78f7413207cb5af7d06 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Thu, 22 Jul 2021 08:50:31 -0400 Subject: [PATCH 12/14] fmt --- .../src/bootstrap_agent.rs | 2 +- .../src/bootstrap_agent_client.rs | 5 ++-- omicron-common/src/api/external/mod.rs | 17 ++++------- omicron-common/src/api/internal/nexus.rs | 8 +---- omicron-common/src/api/internal/sled_agent.rs | 4 +-- omicron-common/src/api/mod.rs | 2 +- omicron-common/src/model_db.rs | 10 +++---- omicron-common/src/sled_agent_client.rs | 4 +-- omicron-nexus/src/db/conversions.rs | 6 ++-- omicron-nexus/src/db/datastore.rs | 29 +++++++++++++------ .../src/http_entrypoints_external.rs | 18 ++++++++---- omicron-nexus/src/nexus.rs | 24 +++++++-------- omicron-sled-agent/src/common/disk.rs | 4 +-- omicron-sled-agent/src/common/instance.rs | 4 +-- omicron-sled-agent/src/instance.rs | 7 ++--- omicron-sled-agent/src/instance_manager.rs | 7 ++--- omicron-sled-agent/src/sim/collection.rs | 4 +-- omicron-sled-agent/src/sim/disk.rs | 4 +-- .../src/sim/http_entrypoints.rs | 4 +-- omicron-sled-agent/src/sim/instance.rs | 2 +- omicron-sled-agent/src/sled_agent.rs | 3 +- 21 files changed, 82 insertions(+), 86 deletions(-) diff --git a/omicron-bootstrap-agent/src/bootstrap_agent.rs b/omicron-bootstrap-agent/src/bootstrap_agent.rs index 278cba19008..3e0b1b2cecf 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent.rs @@ -1,6 +1,6 @@ use crate::bootstrap_agent_client::Client as BootstrapClient; -use omicron_common::api::internal::bootstrap_agent::ShareResponse; use omicron_common::api::external::Error; +use omicron_common::api::internal::bootstrap_agent::ShareResponse; use omicron_common::packaging::sha256_digest; use slog::Logger; diff --git a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs index 61fdc340068..10d58889a3a 100644 --- a/omicron-bootstrap-agent/src/bootstrap_agent_client.rs +++ b/omicron-bootstrap-agent/src/bootstrap_agent_client.rs @@ -5,9 +5,9 @@ * generated by the server. */ +use omicron_common::api::external::Error; use omicron_common::api::internal::bootstrap_agent::ShareRequest; use omicron_common::api::internal::bootstrap_agent::ShareResponse; -use omicron_common::api::external::Error; use omicron_common::http_client::HttpClient; use http::Method; @@ -41,8 +41,7 @@ impl Client { ) -> Result { let path = "/request_share"; let body = Body::from( - serde_json::to_string(&ShareRequest { identity }) - .unwrap(), + serde_json::to_string(&ShareRequest { identity }).unwrap(), ); let mut response = self.client.request(Method::GET, path, body).await?; /* TODO-robustness handle 300-level? */ diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index e0fa7fd4612..39a9d120596 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -9,7 +9,6 @@ mod error; pub mod http_pagination; pub use error::*; - use anyhow::anyhow; use anyhow::Context; use api_identity::ObjectIdentity; @@ -456,9 +455,7 @@ impl Display for ResourceType { } } -pub async fn to_list( - object_stream: ObjectStream -) -> Vec +pub async fn to_list(object_stream: ObjectStream) -> Vec where U: From, { @@ -535,9 +532,7 @@ pub struct ProjectView { impl From for ProjectView { fn from(project: crate::api::internal::nexus::Project) -> Self { - ProjectView { - identity: project.identity.clone() - } + ProjectView { identity: project.identity.clone() } } } @@ -696,7 +691,9 @@ pub struct InstanceRuntimeStateView { pub time_run_state_updated: DateTime, } -impl From for InstanceRuntimeStateView { +impl From + for InstanceRuntimeStateView +{ fn from(state: crate::api::internal::nexus::InstanceRuntimeState) -> Self { InstanceRuntimeStateView { run_state: state.run_state, @@ -951,9 +948,7 @@ pub struct RackView { impl From for RackView { fn from(rack: crate::api::internal::nexus::Rack) -> Self { - RackView { - identity: rack.identity.clone() - } + RackView { identity: rack.identity.clone() } } } diff --git a/omicron-common/src/api/internal/nexus.rs b/omicron-common/src/api/internal/nexus.rs index efe11f55d1a..5da89257985 100644 --- a/omicron-common/src/api/internal/nexus.rs +++ b/omicron-common/src/api/internal/nexus.rs @@ -1,11 +1,7 @@ //! APIs exposed by Nexus. use crate::api::external::{ - ByteCount, - DiskState, - Generation, - IdentityMetadata, - InstanceCpuCount, + ByteCount, DiskState, Generation, IdentityMetadata, InstanceCpuCount, InstanceState, }; use chrono::{DateTime, Utc}; @@ -77,7 +73,6 @@ pub struct Instance { /// state owned by the data plane pub runtime: InstanceRuntimeState, - // TODO-completeness: add disks, network, tags, metrics } @@ -106,7 +101,6 @@ pub struct SledAgentStartupInfo { // Oximeter producer/collector objects. - /// Information announced by a metric server, used so that clients can contact it and collect /// available metric data from it. #[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index 238819e10ea..69fd9f6bc97 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -27,7 +27,7 @@ pub enum DiskStateRequested { } impl DiskStateRequested { - /// Returns whether the requested state is attached to an Instance or not. + /// Returns whether the requested state is attached to an Instance or not. pub fn is_attached(&self) -> bool { match self { DiskStateRequested::Detached => false, @@ -49,7 +49,6 @@ pub struct InstanceEnsureBody { pub target: InstanceRuntimeStateRequested, } - /// Requestable running state of an Instance. /// /// A subset of [`InstanceState`]. @@ -110,4 +109,3 @@ impl InstanceStateRequested { pub struct InstanceRuntimeStateRequested { pub run_state: InstanceStateRequested, } - diff --git a/omicron-common/src/api/mod.rs b/omicron-common/src/api/mod.rs index 679048ec777..6eea86d6df9 100644 --- a/omicron-common/src/api/mod.rs +++ b/omicron-common/src/api/mod.rs @@ -1,4 +1,4 @@ //! APIs, both internal and external. -pub mod internal; pub mod external; +pub mod internal; diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 8b117dc6cc3..d7663322ce9 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -53,19 +53,19 @@ use std::net::{IpAddr, SocketAddr}; use std::time::Duration; use super::db::sql_row_value; -use crate::api::external::Error; use crate::api::external::ByteCount; -use crate::api::internal::nexus::Disk; use crate::api::external::DiskAttachment; -use crate::api::internal::nexus::DiskRuntimeState; use crate::api::external::DiskState; +use crate::api::external::Error; use crate::api::external::Generation; use crate::api::external::IdentityMetadata; -use crate::api::internal::nexus::Instance; use crate::api::external::InstanceCpuCount; -use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::external::InstanceState; use crate::api::external::Name; +use crate::api::internal::nexus::Disk; +use crate::api::internal::nexus::DiskRuntimeState; +use crate::api::internal::nexus::Instance; +use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::internal::nexus::OximeterAssignment; use crate::api::internal::nexus::OximeterInfo; use crate::api::internal::nexus::ProducerEndpoint; diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index 66b43634db7..d2a7cb1a2e0 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -6,11 +6,11 @@ */ use crate::api::external::Error; -use crate::api::internal::sled_agent::DiskEnsureBody; use crate::api::internal::nexus::DiskRuntimeState; +use crate::api::internal::nexus::InstanceRuntimeState; +use crate::api::internal::sled_agent::DiskEnsureBody; use crate::api::internal::sled_agent::DiskStateRequested; use crate::api::internal::sled_agent::InstanceEnsureBody; -use crate::api::internal::nexus::InstanceRuntimeState; use crate::api::internal::sled_agent::InstanceRuntimeStateRequested; use crate::http_client::HttpClient; use async_trait::async_trait; diff --git a/omicron-nexus/src/db/conversions.rs b/omicron-nexus/src/db/conversions.rs index 7c3556ecf33..b49bca1c40a 100644 --- a/omicron-nexus/src/db/conversions.rs +++ b/omicron-nexus/src/db/conversions.rs @@ -7,16 +7,16 @@ use chrono::DateTime; use chrono::Utc; use omicron_common::api::external::DiskCreateParams; -use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::external::DiskState; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceState; +use omicron_common::api::external::ProjectCreateParams; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::nexus::OximeterAssignment; use omicron_common::api::internal::nexus::OximeterInfo; use omicron_common::api::internal::nexus::ProducerEndpoint; -use omicron_common::api::external::ProjectCreateParams; use super::sql::SqlSerialize; use super::sql::SqlValueSet; diff --git a/omicron-nexus/src/db/datastore.rs b/omicron-nexus/src/db/datastore.rs index ace5ec4dee4..e57e5719f54 100644 --- a/omicron-nexus/src/db/datastore.rs +++ b/omicron-nexus/src/db/datastore.rs @@ -29,11 +29,11 @@ use omicron_common::api::external::Generation; use omicron_common::api::external::ListResult; use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; +use omicron_common::api::external::ResourceType; +use omicron_common::api::external::UpdateResult; use omicron_common::api::internal::nexus::OximeterAssignment; use omicron_common::api::internal::nexus::OximeterInfo; use omicron_common::api::internal::nexus::ProducerEndpoint; -use omicron_common::api::external::ResourceType; -use omicron_common::api::external::UpdateResult; use omicron_common::bail_unless; use omicron_common::db::sql_row_value; use std::convert::TryFrom; @@ -274,7 +274,8 @@ impl DataStore { .await?; bail_unless!( - instance.runtime.run_state == api::external::InstanceState::Creating, + instance.runtime.run_state + == api::external::InstanceState::Creating, "newly-created Instance has unexpected state: {:?}", instance.runtime.run_state ); @@ -431,7 +432,11 @@ impl DataStore { pagparams: &DataPageParams<'_, Name>, ) -> ListResult { let client = self.pool.acquire().await?; - sql_fetch_page_by::( + sql_fetch_page_by::< + LookupByAttachedInstance, + Disk, + api::external::DiskAttachment, + >( &client, (instance_id,), pagparams, @@ -528,7 +533,10 @@ impl DataStore { Ok(update.updated) } - pub async fn disk_fetch(&self, disk_id: &Uuid) -> LookupResult { + pub async fn disk_fetch( + &self, + disk_id: &Uuid, + ) -> LookupResult { let client = self.pool.acquire().await?; sql_fetch_row_by::(&client, (), disk_id).await } @@ -556,7 +564,8 @@ impl DataStore { api::external::DiskState::Destroyed.sql_serialize(&mut values); let mut cond_sql = SqlString::new(); - let disk_state_detached = api::external::DiskState::Detached.to_string(); + let disk_state_detached = + api::external::DiskState::Detached.to_string(); let p1 = cond_sql.next_param(&disk_state_detached); let disk_state_faulted = api::external::DiskState::Faulted.to_string(); let p2 = cond_sql.next_param(&disk_state_faulted); @@ -582,9 +591,11 @@ impl DataStore { let disk_state_str: &str = sql_row_value(&row, "found_disk_state")?; let attach_instance_id: Option = sql_row_value(&row, "found_attach_instance_id")?; - let found_disk_state = - api::external::DiskState::try_from((disk_state_str, attach_instance_id)) - .map_err(|e| Error::internal_error(&e))?; + let found_disk_state = api::external::DiskState::try_from(( + disk_state_str, + attach_instance_id, + )) + .map_err(|e| Error::internal_error(&e))?; if update.updated { Ok(()) diff --git a/omicron-nexus/src/http_entrypoints_external.rs b/omicron-nexus/src/http_entrypoints_external.rs index b00ae32a0e4..83e232bc441 100644 --- a/omicron-nexus/src/http_entrypoints_external.rs +++ b/omicron-nexus/src/http_entrypoints_external.rs @@ -166,7 +166,9 @@ async fn projects_get( } }; - let view_list = to_list::(project_stream).await; + let view_list = + to_list::(project_stream) + .await; Ok(HttpResponseOk(ScanByNameOrId::results_page(&query, view_list)?)) } @@ -290,7 +292,8 @@ async fn project_disks_get( ) .await?; - let disk_list = to_list::(disk_stream).await; + let disk_list = + to_list::(disk_stream).await; Ok(HttpResponseOk(ScanByName::results_page(&query, disk_list)?)) } @@ -394,7 +397,10 @@ async fn project_instances_get( &data_page_params_for(&rqctx, &query)?, ) .await?; - let view_list = to_list::(instance_stream).await; + let view_list = to_list::( + instance_stream, + ) + .await; Ok(HttpResponseOk(ScanByName::results_page(&query, view_list)?)) } @@ -668,7 +674,8 @@ async fn hardware_racks_get( let query = query_params.into_inner(); let rack_stream = nexus.racks_list(&data_page_params_for(&rqctx, &query)?).await?; - let view_list = to_list::(rack_stream).await; + let view_list = + to_list::(rack_stream).await; Ok(HttpResponseOk(ScanById::results_page(&query, view_list)?)) } @@ -719,7 +726,8 @@ async fn hardware_sleds_get( let query = query_params.into_inner(); let sled_stream = nexus.sleds_list(&data_page_params_for(&rqctx, &query)?).await?; - let view_list = to_list::(sled_stream).await; + let view_list = + to_list::(sled_stream).await; Ok(HttpResponseOk(ScanById::results_page(&query, view_list)?)) } diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 47be8c95202..c6bb6c37ca9 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -11,16 +11,6 @@ use chrono::Utc; use futures::future::ready; use futures::lock::Mutex; use futures::StreamExt; -use omicron_common::api::internal::nexus::Disk; -use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::internal::nexus::Instance; -use omicron_common::api::internal::nexus::InstanceRuntimeState; -use omicron_common::api::internal::nexus::Project; -use omicron_common::api::internal::nexus::Rack; -use omicron_common::api::internal::nexus::Sled; -use omicron_common::api::internal::sled_agent::DiskStateRequested; -use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; -use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DeleteResult; @@ -35,13 +25,23 @@ use omicron_common::api::external::InstanceState; use omicron_common::api::external::ListResult; use omicron_common::api::external::LookupResult; use omicron_common::api::external::Name; -use omicron_common::api::internal::nexus::OximeterInfo; -use omicron_common::api::internal::nexus::ProducerEndpoint; use omicron_common::api::external::ProjectCreateParams; use omicron_common::api::external::ProjectUpdateParams; use omicron_common::api::external::ResourceType; use omicron_common::api::external::SagaView; use omicron_common::api::external::UpdateResult; +use omicron_common::api::internal::nexus::Disk; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::nexus::Instance; +use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::nexus::OximeterInfo; +use omicron_common::api::internal::nexus::ProducerEndpoint; +use omicron_common::api::internal::nexus::Project; +use omicron_common::api::internal::nexus::Rack; +use omicron_common::api::internal::nexus::Sled; +use omicron_common::api::internal::sled_agent::DiskStateRequested; +use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; +use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::bail_unless; use omicron_common::collection::collection_page; use omicron_common::OximeterClient; diff --git a/omicron-sled-agent/src/common/disk.rs b/omicron-sled-agent/src/common/disk.rs index 657016ca1b2..067aba9fb40 100644 --- a/omicron-sled-agent/src/common/disk.rs +++ b/omicron-sled-agent/src/common/disk.rs @@ -1,10 +1,10 @@ //! Describes the states of network-attached storage. use chrono::Utc; -use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::DiskState; -use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::Error; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use propolis_client::api::DiskAttachmentState as PropolisDiskState; use uuid::Uuid; diff --git a/omicron-sled-agent/src/common/instance.rs b/omicron-sled-agent/src/common/instance.rs index f553dde2256..cdd3391928d 100644 --- a/omicron-sled-agent/src/common/instance.rs +++ b/omicron-sled-agent/src/common/instance.rs @@ -261,9 +261,7 @@ impl InstanceStates { mod test { use super::{Action, InstanceStates}; use chrono::Utc; - use omicron_common::api::external::{ - Generation, InstanceState as State, - }; + use omicron_common::api::external::{Generation, InstanceState as State}; use omicron_common::api::internal::{ nexus::InstanceRuntimeState, sled_agent::InstanceStateRequested as Requested, diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index 947b59a2378..1ba59646901 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -477,12 +477,9 @@ mod test { RequestContext, TypedBody, }; use futures::future::FutureExt; - use omicron_common::api::external::{ - Generation, InstanceState, - }; + use omicron_common::api::external::{Generation, InstanceState}; use omicron_common::api::internal::{ - nexus::InstanceRuntimeState, - sled_agent::InstanceStateRequested, + nexus::InstanceRuntimeState, sled_agent::InstanceStateRequested, }; use propolis_client::api; use tokio::sync::watch; diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index d5d9810cdca..77e1f060fe6 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -198,12 +198,9 @@ mod test { use crate::instance::MockInstance; use crate::mocks::MockNexusClient; use chrono::Utc; - use omicron_common::api::external::{ - Generation, InstanceState, - }; + use omicron_common::api::external::{Generation, InstanceState}; use omicron_common::api::internal::{ - nexus::InstanceRuntimeState, - sled_agent::InstanceStateRequested, + nexus::InstanceRuntimeState, sled_agent::InstanceStateRequested, }; static INST_UUID_STR: &str = "e398c5d5-5059-4e55-beac-3a1071083aaa"; diff --git a/omicron-sled-agent/src/sim/collection.rs b/omicron-sled-agent/src/sim/collection.rs index b9f785d6af1..5ce37b3ef5c 100644 --- a/omicron-sled-agent/src/sim/collection.rs +++ b/omicron-sled-agent/src/sim/collection.rs @@ -336,13 +336,13 @@ mod test { use chrono::Utc; use dropshot::test_util::LogContext; use futures::channel::mpsc::Receiver; - use omicron_common::api::internal::nexus::DiskRuntimeState; - use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::DiskState; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceState; + use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::internal::nexus::InstanceRuntimeState; + use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::dev::test_setup_log; diff --git a/omicron-sled-agent/src/sim/disk.rs b/omicron-sled-agent/src/sim/disk.rs index da88d6720ea..4e627a203bc 100644 --- a/omicron-sled-agent/src/sim/disk.rs +++ b/omicron-sled-agent/src/sim/disk.rs @@ -4,11 +4,11 @@ use crate::sim::simulatable::Simulatable; use async_trait::async_trait; -use omicron_common::api::internal::nexus::DiskRuntimeState; use omicron_common::api::external::DiskState; -use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; +use omicron_common::api::internal::nexus::DiskRuntimeState; +use omicron_common::api::internal::sled_agent::DiskStateRequested; use omicron_common::NexusClient; use propolis_client::api::DiskAttachmentState as PropolisDiskState; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index 0c9de697cca..b553bc7dd21 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -10,10 +10,10 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use omicron_common::api::internal::sled_agent::DiskEnsureBody; use omicron_common::api::internal::nexus::DiskRuntimeState; -use omicron_common::api::internal::sled_agent::InstanceEnsureBody; use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::DiskEnsureBody; +use omicron_common::api::internal::sled_agent::InstanceEnsureBody; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; diff --git a/omicron-sled-agent/src/sim/instance.rs b/omicron-sled-agent/src/sim/instance.rs index 342423b0b47..ebb04f43d62 100644 --- a/omicron-sled-agent/src/sim/instance.rs +++ b/omicron-sled-agent/src/sim/instance.rs @@ -7,9 +7,9 @@ use super::simulatable::Simulatable; use async_trait::async_trait; use omicron_common::api::external::Error; use omicron_common::api::external::Generation; +use omicron_common::api::external::InstanceState; use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; -use omicron_common::api::external::InstanceState; use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::NexusClient; use propolis_client::api::InstanceState as PropolisInstanceState; diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 1cd29465ac6..5c5d6d0f12f 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -2,8 +2,7 @@ use omicron_common::api::external::Error; use omicron_common::api::{ - internal::nexus::DiskRuntimeState, - internal::nexus::InstanceRuntimeState, + internal::nexus::DiskRuntimeState, internal::nexus::InstanceRuntimeState, internal::sled_agent::DiskStateRequested, internal::sled_agent::InstanceRuntimeStateRequested, }; From 788e75b7c408b5eb82aae8ddee8707e9ad57f8cc Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Mon, 26 Jul 2021 17:59:42 -0400 Subject: [PATCH 13/14] Clippy --- omicron-common/src/api/external/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omicron-common/src/api/external/mod.rs b/omicron-common/src/api/external/mod.rs index 39a9d120596..d7579898c72 100644 --- a/omicron-common/src/api/external/mod.rs +++ b/omicron-common/src/api/external/mod.rs @@ -532,7 +532,7 @@ pub struct ProjectView { impl From for ProjectView { fn from(project: crate::api::internal::nexus::Project) -> Self { - ProjectView { identity: project.identity.clone() } + ProjectView { identity: project.identity } } } @@ -798,7 +798,7 @@ impl From for DiskView { project_id: disk.project_id, snapshot_id: disk.create_snapshot_id, size: disk.size, - state: disk.runtime.disk_state.clone(), + state: disk.runtime.disk_state, device_path, } } @@ -948,7 +948,7 @@ pub struct RackView { impl From for RackView { fn from(rack: crate::api::internal::nexus::Rack) -> Self { - RackView { identity: rack.identity.clone() } + RackView { identity: rack.identity } } } From 22d12f881783a7ccefb8b6eac8702865b496d7c1 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Tue, 27 Jul 2021 13:55:40 -0500 Subject: [PATCH 14/14] put project_id on VPC model, remove TODO on subnet and NIC --- omicron-common/src/api/model.rs | 11 ++--------- omicron-common/src/model_db.rs | 5 ++++- omicron-common/src/sql/dbinit.sql | 6 ++---- omicron-nexus/src/db/schema.rs | 4 +--- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index 816686f6a30..874d6c692a2 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -1318,9 +1318,8 @@ impl From for SagaStateView { pub struct VPC { /** common identifying metadata */ pub identity: IdentityMetadata, - // TODO: Implement project-scoping - // /** id for the project containing this Instance */ - // pub project_id: Uuid, + /** id for the project containing this Instance */ + pub project_id: Uuid, } /// An `Ipv4Net` represents a IPv4 subnetwork, including the address and network mask. @@ -1438,9 +1437,6 @@ pub struct VPCSubnet { /** common identifying metadata */ pub identity: IdentityMetadata, - // TODO: Implement project-scoping - // /** id for the project containing this Instance */ - // pub project_id: Uuid, /** The VPC to which the subnet belongs. */ pub vpc_id: Uuid, @@ -1518,9 +1514,6 @@ pub struct NetworkInterface { /** common identifying metadata */ pub identity: IdentityMetadata, - // TODO: Implement project-scoping - // /** id for the project containing this Instance */ - // pub project_id: Uuid, /** The VPC to which the interface belongs. */ pub vpc_id: Uuid, diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 1674dd3a637..638630a2f75 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -439,7 +439,10 @@ impl TryFrom<&tokio_postgres::Row> for VPC { type Error = Error; fn try_from(value: &tokio_postgres::Row) -> Result { - Ok(Self { identity: IdentityMetadata::try_from(value)? }) + Ok(Self { + identity: IdentityMetadata::try_from(value)?, + project_id: sql_row_value(value, "project_id")?, + }) } } diff --git a/omicron-common/src/sql/dbinit.sql b/omicron-common/src/sql/dbinit.sql index 54b02890d7d..12f842fd603 100644 --- a/omicron-common/src/sql/dbinit.sql +++ b/omicron-common/src/sql/dbinit.sql @@ -257,10 +257,8 @@ CREATE TABLE omicron.public.VPC ( time_created TIMESTAMPTZ NOT NULL, time_modified TIMESTAMPTZ NOT NULL, /* Indicates that the object has been deleted */ - time_deleted TIMESTAMPTZ - /* TODO: Add project-scoping. - * project_id UUID NOT NULL REFERENCES omicron.public.Project (id), - */ + time_deleted TIMESTAMPTZ, + project_id UUID NOT NULL ); -- TODO: add project_id to index diff --git a/omicron-nexus/src/db/schema.rs b/omicron-nexus/src/db/schema.rs index b3b9893aa41..79fba192cac 100644 --- a/omicron-nexus/src/db/schema.rs +++ b/omicron-nexus/src/db/schema.rs @@ -164,7 +164,7 @@ impl Table for VPC { "time_created", "time_modified", "time_deleted", - // TODO: Add project-scoping: "project_id", + "project_id", ]; } @@ -180,7 +180,6 @@ impl Table for VPCSubnet { "time_created", "time_modified", "time_deleted", - // TODO: Add project-scoping: "project_id", "vpc_id", "ipv4_block", "ipv6_block", @@ -199,7 +198,6 @@ impl Table for NetworkInterface { "time_created", "time_modified", "time_deleted", - // TODO: Add project-scoping: "project_id", "vpc_id", "subnet_id", "mac",