From e5d5317adbbd13879b38ee2e761b8298fa320192 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Wed, 14 Jul 2021 14:05:42 -0700 Subject: [PATCH 01/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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", From 07a1b7b6b02cbf45aa798807e130eda187bd2d73 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Tue, 20 Jul 2021 18:14:14 -0400 Subject: [PATCH 15/28] [api][instance] Relocate instance hardware info to InstanceRuntimeState --- omicron-common/src/api/model.rs | 26 ++++++++--------------- omicron-common/src/model_db.rs | 6 +++--- omicron-nexus/src/sagas.rs | 3 +++ omicron-sled-agent/src/common/instance.rs | 9 +++----- omicron-sled-agent/src/instance.rs | 8 ++++--- 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index 874d6c692a2..d233a75397b 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -797,13 +797,6 @@ pub struct Instance { /** 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 */ @@ -815,9 +808,6 @@ impl Object for Instance { 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(), } } @@ -835,6 +825,15 @@ pub struct InstanceRuntimeState { pub run_state: InstanceState, /** which sled is running this Instance */ pub sled_uuid: 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? */ + + /* TODO-completeness: add disks, network, tags, metrics */ /** generation number for this state */ pub gen: Generation, /** timestamp for this information */ @@ -885,13 +884,6 @@ pub struct InstanceView { /** id for the project containing this Instance */ pub project_id: Uuid, - /** number of CPUs allocated for this Instance */ - pub ncpus: InstanceCpuCount, - /** memory, in gigabytes, allocated for this Instance */ - pub memory: ByteCount, - /** RFC1035-compliant hostname for the Instance. */ - pub hostname: String, /* TODO-cleanup different type? */ - #[serde(flatten)] pub runtime: InstanceRuntimeStateView, } diff --git a/omicron-common/src/model_db.rs b/omicron-common/src/model_db.rs index 638630a2f75..d80a82ed16b 100644 --- a/omicron-common/src/model_db.rs +++ b/omicron-common/src/model_db.rs @@ -307,9 +307,6 @@ impl TryFrom<&tokio_postgres::Row> for Instance { Ok(Instance { identity: IdentityMetadata::try_from(value)?, project_id: sql_row_value(value, "project_id")?, - ncpus: sql_row_value(value, "ncpus")?, - memory: sql_row_value(value, "memory")?, - hostname: sql_row_value(value, "hostname")?, runtime: InstanceRuntimeState::try_from(value)?, }) } @@ -325,6 +322,9 @@ impl TryFrom<&tokio_postgres::Row> for InstanceRuntimeState { Ok(InstanceRuntimeState { run_state: InstanceState::try_from(value)?, sled_uuid: sql_row_value(value, "active_server_id")?, + ncpus: sql_row_value(value, "ncpus")?, + memory: sql_row_value(value, "memory")?, + hostname: sql_row_value(value, "hostname")?, gen: sql_row_value(value, "state_generation")?, time_updated: sql_row_value(value, "time_state_updated")?, }) diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index aba8d055e7a..58201ae4ab7 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -134,6 +134,9 @@ async fn sic_create_instance_record( let runtime = InstanceRuntimeState { run_state: InstanceState::Creating, sled_uuid: sled_uuid?, + hostname: params.create_params.hostname.clone(), + memory: params.create_params.memory, + ncpus: params.create_params.ncpus, gen: Generation::new(), time_updated: Utc::now(), }; diff --git a/omicron-sled-agent/src/common/instance.rs b/omicron-sled-agent/src/common/instance.rs index 8705efbf0f8..d39b72f8d07 100644 --- a/omicron-sled-agent/src/common/instance.rs +++ b/omicron-sled-agent/src/common/instance.rs @@ -143,12 +143,9 @@ impl InstanceStates { next: InstanceState, desired: Option, ) { - self.current = InstanceRuntimeState { - run_state: next, - sled_uuid: self.current.sled_uuid, - gen: self.current.gen.next(), - time_updated: Utc::now(), - }; + self.current.run_state = next; + self.current.gen = self.current.gen.next(); + self.current.time_updated = Utc::now(); self.desired = desired .map(|run_state| InstanceRuntimeStateRequested { run_state }); } diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index a5f80c3fdda..b0cdb025208 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -281,12 +281,14 @@ impl Instance { // NOTE: Mostly lies. properties: propolis_client::api::InstanceProperties { id, - name: "Test instance".to_string(), + name: initial_runtime.hostname.clone(), description: "Test description".to_string(), image_id: Uuid::nil(), bootrom_id: Uuid::nil(), - memory: 256, - vcpus: 2, + memory: initial_runtime.memory.to_bytes(), + // TODO: we should probably make propolis aligned with + // InstanceCpuCount here, to avoid any casting... + vcpus: initial_runtime.ncpus.0 as u8, }, state: InstanceStates::new(initial_runtime), nexus_client, From ac9ebb0c95e28cd2b62843df6c100f197529a462 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 21 Jul 2021 09:47:10 -0400 Subject: [PATCH 16/28] Fix tests, leave view object unchanged --- omicron-common/src/api/model.rs | 10 ++++++++++ omicron-sled-agent/src/common/instance.rs | 7 +++++-- omicron-sled-agent/src/instance.rs | 6 +++++- omicron-sled-agent/src/instance_manager.rs | 6 +++++- omicron-sled-agent/src/sim/collection.rs | 5 +++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/omicron-common/src/api/model.rs b/omicron-common/src/api/model.rs index d233a75397b..25e05c0fe08 100644 --- a/omicron-common/src/api/model.rs +++ b/omicron-common/src/api/model.rs @@ -808,6 +808,9 @@ impl Object for Instance { InstanceView { identity: self.identity.clone(), project_id: self.project_id, + ncpus: self.runtime.ncpus, + memory: self.runtime.memory, + hostname: self.runtime.hostname.clone(), runtime: self.runtime.to_view(), } } @@ -884,6 +887,13 @@ pub struct InstanceView { /** 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? */ + #[serde(flatten)] pub runtime: InstanceRuntimeStateView, } diff --git a/omicron-sled-agent/src/common/instance.rs b/omicron-sled-agent/src/common/instance.rs index d39b72f8d07..2067a0181ef 100644 --- a/omicron-sled-agent/src/common/instance.rs +++ b/omicron-sled-agent/src/common/instance.rs @@ -259,8 +259,8 @@ mod test { use super::{Action, InstanceStates}; use chrono::Utc; use omicron_common::api::{ - Generation, InstanceRuntimeState, InstanceState as State, - InstanceStateRequested as Requested, + ByteCount, Generation, InstanceCpuCount, InstanceRuntimeState, + InstanceState as State, InstanceStateRequested as Requested, }; use propolis_client::api::InstanceState as Observed; @@ -268,6 +268,9 @@ mod test { InstanceStates::new(InstanceRuntimeState { run_state: State::Creating, sled_uuid: uuid::Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), gen: Generation::new(), time_updated: Utc::now(), }) diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index b0cdb025208..648750e05f0 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -480,7 +480,8 @@ mod test { }; use futures::future::FutureExt; use omicron_common::api::{ - Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, + ByteCount, Generation, InstanceCpuCount, InstanceRuntimeState, + InstanceState, InstanceStateRequested, }; use propolis_client::api; use tokio::sync::watch; @@ -809,6 +810,9 @@ mod test { InstanceRuntimeState { run_state: InstanceState::Creating, sled_uuid: Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), gen: Generation::new(), time_updated: Utc::now(), } diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 76c45656eaa..0c786acaa65 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -200,7 +200,8 @@ mod test { use crate::mocks::MockNexusClient; use chrono::Utc; use omicron_common::api::{ - Generation, InstanceRuntimeState, InstanceState, InstanceStateRequested, + ByteCount, Generation, InstanceCpuCount, InstanceRuntimeState, + InstanceState, InstanceStateRequested, }; static INST_UUID_STR: &str = "e398c5d5-5059-4e55-beac-3a1071083aaa"; @@ -221,6 +222,9 @@ mod test { InstanceRuntimeState { run_state: InstanceState::Creating, sled_uuid: Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), gen: Generation::new(), time_updated: Utc::now(), } diff --git a/omicron-sled-agent/src/sim/collection.rs b/omicron-sled-agent/src/sim/collection.rs index 378c8953509..f21141d9ead 100644 --- a/omicron-sled-agent/src/sim/collection.rs +++ b/omicron-sled-agent/src/sim/collection.rs @@ -336,11 +336,13 @@ mod test { use chrono::Utc; use dropshot::test_util::LogContext; use futures::channel::mpsc::Receiver; + use omicron_common::api::ByteCount; 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::InstanceCpuCount; use omicron_common::api::InstanceRuntimeState; use omicron_common::api::InstanceRuntimeStateRequested; use omicron_common::api::InstanceState; @@ -354,6 +356,9 @@ mod test { InstanceRuntimeState { run_state: InstanceState::Creating, sled_uuid: uuid::Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), gen: Generation::new(), time_updated: Utc::now(), } From 6ed0a48bbc0241bfebe9251646761f95ef443d17 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Thu, 29 Jul 2021 14:25:19 -0400 Subject: [PATCH 17/28] Start plumbing nics through sled agent -> Propolis --- omicron-common/Cargo.toml | 2 +- omicron-common/src/api/internal/sled_agent.rs | 11 ++++-- omicron-common/src/sled_agent_client.rs | 3 +- omicron-nexus/src/nexus.rs | 21 ++++++++++- omicron-nexus/src/sagas.rs | 10 ++++-- omicron-sled-agent/Cargo.toml | 2 +- omicron-sled-agent/src/http_entrypoints.rs | 4 +-- omicron-sled-agent/src/illumos/dladm.rs | 2 +- omicron-sled-agent/src/illumos/zone.rs | 18 ++++++++++ omicron-sled-agent/src/instance.rs | 36 ++++++++++++++----- omicron-sled-agent/src/instance_manager.rs | 7 ++-- .../src/sim/http_entrypoints.rs | 4 +-- omicron-sled-agent/src/sim/sled_agent.rs | 5 +-- omicron-sled-agent/src/sled_agent.rs | 8 +++-- smf/propolis-server/manifest.xml | 2 +- 15 files changed, 103 insertions(+), 32 deletions(-) diff --git a/omicron-common/Cargo.toml b/omicron-common/Cargo.toml index e0cc6b74e27..abd5e52079a 100644 --- a/omicron-common/Cargo.toml +++ b/omicron-common/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.15" http = "0.2.0" hyper = "0.14" libc = "0.2.98" -propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "b6da043d" } +propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "e4d83b1fe8" } postgres-protocol = "0.6.1" rayon = "1.5" reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index 69fd9f6bc97..4aa67bdf249 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -1,6 +1,6 @@ //! APIs exposed by Sled Agent. -use crate::api::internal; +use crate::api::{external, internal}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::{Debug, Display, Formatter, Result as FormatResult}; @@ -39,12 +39,19 @@ impl DiskStateRequested { } } +/// Describes the instance hardware. +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct InstanceHardware { + pub runtime: internal::nexus::InstanceRuntimeState, + pub nics: Vec, +} + /// 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, + pub initial_runtime: InstanceHardware, /// requested runtime state of the Instance pub target: InstanceRuntimeStateRequested, } diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index d2a7cb1a2e0..fef174049c5 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -11,6 +11,7 @@ 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::sled_agent::InstanceHardware; use crate::api::internal::sled_agent::InstanceRuntimeStateRequested; use crate::http_client::HttpClient; use async_trait::async_trait; @@ -54,7 +55,7 @@ impl Client { pub async fn instance_ensure( self: &Arc, instance_id: Uuid, - initial_runtime: InstanceRuntimeState, + initial_runtime: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { let path = format!("/instances/{}", instance_id); diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index c6bb6c37ca9..678ae0fbbeb 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -40,6 +40,7 @@ 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::InstanceHardware; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::api::internal::sled_agent::InstanceStateRequested; use omicron_common::bail_unless; @@ -484,6 +485,19 @@ impl Nexus { let project_id = self.db_datastore.project_lookup_id_by_name(project_name).await?; + // TODO TODO TODO TODO TODO TODO + // + // 1) (not here) Create a default VPC for the project when it is created + // RFD21: "When a project is created, a default VPC is created as well." + // 1a) (not here) Create a default subnet for a VPC when created + // 2) Look up the VPC subnet here, unless one is specified (?). + // 2a) Allocate an address within that range. + // 2b) Allocate a mac address (?). + // 3) Create a network interface from all the allocated stats. + // 4) Pass it alongside the "hw info". + // + // TODO TODO TODO TODO TODO TODO + let saga_params = Arc::new(sagas::ParamsInstanceCreate { project_id, create_params: params.clone(), @@ -739,10 +753,15 @@ impl Nexus { * not the newest one, that's fine. That might just mean the sled agent * beat us to it. */ + let instance_hardware = InstanceHardware { + runtime: instance.runtime.clone(), + nics: vec![], + }; + let new_runtime = sa .instance_ensure( instance.identity.id, - instance.runtime.clone(), + instance_hardware, requested, ) .await?; diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index 4a8701a7910..8f5da08b0c2 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -16,6 +16,7 @@ use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceState; use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceHardware; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::api::internal::sled_agent::InstanceStateRequested; use serde::Deserialize; @@ -125,7 +126,7 @@ async fn sic_alloc_server( async fn sic_create_instance_record( sagactx: ActionContext, -) -> Result { +) -> Result { let osagactx = sagactx.user_data(); let params = sagactx.saga_params(); let sled_uuid = sagactx.lookup::("server_id"); @@ -151,7 +152,10 @@ async fn sic_create_instance_record( ) .await .map_err(ActionError::action_failed)?; - Ok(instance.runtime) + Ok(InstanceHardware { + runtime: instance.runtime, + nics: vec![], + }) } async fn sic_instance_ensure( @@ -167,7 +171,7 @@ async fn sic_instance_ensure( let instance_id = sagactx.lookup::("instance_id")?; let sled_uuid = sagactx.lookup::("server_id")?; let initial_runtime = - sagactx.lookup::("initial_runtime")?; + sagactx.lookup::("initial_runtime")?; let sa = osagactx .sled_client(&sled_uuid) .await diff --git a/omicron-sled-agent/Cargo.toml b/omicron-sled-agent/Cargo.toml index 55eca82ea97..20c096b8acd 100644 --- a/omicron-sled-agent/Cargo.toml +++ b/omicron-sled-agent/Cargo.toml @@ -13,7 +13,7 @@ http = "0.2.0" hyper = "0.14" ipnet = "2.3" omicron-common = { path = "../omicron-common" } -propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "3d58a6398" } +propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "e4d83b1fe8" } schemars = { version = "0.8", features = [ "chrono", "uuid" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" diff --git a/omicron-sled-agent/src/http_entrypoints.rs b/omicron-sled-agent/src/http_entrypoints.rs index 72ea0c0e5ad..fba41df2abb 100644 --- a/omicron-sled-agent/src/http_entrypoints.rs +++ b/omicron-sled-agent/src/http_entrypoints.rs @@ -56,8 +56,8 @@ async fn instance_put( Ok(HttpResponseOk( sa.instance_ensure( instance_id, - body_args.initial_runtime.clone(), - body_args.target.clone(), + body_args.initial_runtime, + body_args.target, ) .await?, )) diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index 504d4e8237b..d8edb7a3579 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -5,7 +5,7 @@ use omicron_common::api::external::Error; pub const VNIC_PREFIX: &str = "vnic_propolis"; -const DLADM: &str = "/usr/sbin/dladm"; +pub const DLADM: &str = "/usr/sbin/dladm"; /// Wraps commands for interacting with data links. pub struct Dladm {} diff --git a/omicron-sled-agent/src/illumos/zone.rs b/omicron-sled-agent/src/illumos/zone.rs index c69dcd5fc7c..84f34bbb0b6 100644 --- a/omicron-sled-agent/src/illumos/zone.rs +++ b/omicron-sled-agent/src/illumos/zone.rs @@ -6,6 +6,7 @@ use slog::Logger; use std::net::SocketAddr; use uuid::Uuid; +use crate::illumos::dladm::DLADM; use crate::illumos::zfs::ZONE_ZFS_DATASET_MOUNTPOINT; use crate::illumos::{execute, PFEXEC}; @@ -184,6 +185,23 @@ impl Zones { .collect()) } + /// Creates a VNIC within a zone. + // TODO: de-dup with "fn create_vnic" in dladm.rs? + pub fn create_vnic(zone: &str, physical: &str, vnic_name: &str) -> Result<(), Error> { + let mut command = std::process::Command::new(PFEXEC); + let cmd = command.args(&[ + ZLOGIN, + zone, + DLADM, + "create-vnic", + "-l", + physical, + vnic_name + ]); + execute(cmd)?; + Ok(()) + } + /// Creates an IP address within a Zone. pub fn create_address(zone: &str, interface: &str) -> Result { let mut command = std::process::Command::new(PFEXEC); diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index 1c352de3880..9256c763815 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -6,7 +6,9 @@ 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::NetworkInterface; use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceHardware; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::dev::poll; use propolis_client::Client as PropolisClient; @@ -130,6 +132,7 @@ struct InstanceInner { log: Logger, runtime_id: u64, properties: propolis_client::api::InstanceProperties, + nics: Vec, state: InstanceStates, nexus_client: Arc, running_state: Option, @@ -157,7 +160,7 @@ impl InstanceInner { // Notify Nexus of the state change. self.nexus_client - .notify_instance_updated(&self.properties.id, self.state.current()) + .notify_instance_updated(self.id(), self.state.current()) .await?; // Take the next action, if any. @@ -176,7 +179,7 @@ impl InstanceInner { .as_ref() .expect("Propolis client should be initialized before usage") .client - .instance_state_put(self.properties.id, request) + .instance_state_put(*self.id(), request) .await .map_err(|e| Error::InternalError { message: format!("Failed to set state of instance: {}", e), @@ -186,7 +189,10 @@ impl InstanceInner { async fn ensure(&self) -> Result<(), Error> { let request = propolis_client::api::InstanceEnsureRequest { properties: self.properties.clone(), + nics: vec![], // TODO TODO }; + println!("Ensuring instance: {:?}", request.properties); + self.running_state .as_ref() .expect("Propolis client should be initialized before usage") @@ -243,7 +249,7 @@ mockall::mock! { log: Logger, id: Uuid, runtime_id: u64, - initial_runtime: InstanceRuntimeState, + initial: InstanceHardware, nexus_client: Arc, ) -> Result; pub async fn start(&self, ticket: InstanceTicket) -> Result<(), Error>; @@ -266,13 +272,13 @@ impl Instance { /// * `runtime_id`: A unique (to the sled) numeric ID which may be used to /// refer to a VNIC. (This exists because of a restriction on VNIC name /// lengths, otherwise the UUID would be used instead). - /// * `initial_runtime`: State of the instance at initialization time. + /// * `initial`: State of the instance at initialization time. /// * `nexus_client`: Connection to Nexus, used for sending notifications. pub fn new( log: Logger, id: Uuid, runtime_id: u64, - initial_runtime: InstanceRuntimeState, + initial: InstanceHardware, nexus_client: Arc, ) -> Result { let instance = InstanceInner { @@ -281,16 +287,18 @@ impl Instance { // NOTE: Mostly lies. properties: propolis_client::api::InstanceProperties { id, - name: initial_runtime.hostname.clone(), + name: initial.runtime.hostname.clone(), description: "Test description".to_string(), image_id: Uuid::nil(), bootrom_id: Uuid::nil(), - memory: initial_runtime.memory.to_bytes(), + // TODO: aligning the byte type would be handy + memory: initial.runtime.memory.to_whole_mebibytes(), // TODO: we should probably make propolis aligned with // InstanceCpuCount here, to avoid any casting... - vcpus: initial_runtime.ncpus.0 as u8, + vcpus: initial.runtime.ncpus.0 as u8, }, - state: InstanceStates::new(initial_runtime), + nics: initial.nics, + state: InstanceStates::new(initial.runtime), nexus_client, running_state: None, }; @@ -365,6 +373,15 @@ impl Instance { inner.running_state = Some(RunningState { client, ticket, monitor_task: None }); + // Instantiate all requested VNICs within the zone. + // Note that Propolis could theoretically do this itself. + // + // TODO: Prevent collision here with the other VNIC types? + // Sanitize the name? + for nic in &inner.nics { + Zones::create_vnic(&zname, &vnic_name, &format!("vnic-{}", nic.mac.to_string()))?; + } + // Ensure the instance exists in the Propolis Server before we start // using it. inner.ensure().await?; @@ -535,6 +552,7 @@ mod test { if let Some(server) = server.as_ref() { if server.id == id { + // TODO: Patch this up with real values let instance_info = api::Instance { properties: api::InstanceProperties { id, diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 3173ed9a27f..2ba8397cbb8 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -3,6 +3,7 @@ use crate::illumos::zfs::ZONE_ZFS_DATASET; use omicron_common::api::external::Error; use omicron_common::api::internal::nexus::InstanceRuntimeState; +use omicron_common::api::internal::sled_agent::InstanceHardware; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use slog::Logger; use std::collections::BTreeMap; @@ -97,12 +98,12 @@ impl InstanceManager { } /// Idempotently ensures that the given Instance (described by - /// `initial_runtime`) exists on this server in the given runtime state + /// `initial_hardware`) exists on this server in the given runtime state /// (described by `target`). pub async fn ensure( &self, instance_id: Uuid, - initial_runtime: InstanceRuntimeState, + initial_hardware: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { info!( @@ -129,7 +130,7 @@ impl InstanceManager { instance_log, instance_id, self.inner.next_id.fetch_add(1, Ordering::SeqCst), - initial_runtime, + initial_hardware, self.inner.nexus_client.clone(), )?, ); diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index b553bc7dd21..9c62b95d878 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -65,8 +65,8 @@ async fn instance_put( Ok(HttpResponseOk( sa.instance_ensure( instance_id, - body_args.initial_runtime.clone(), - body_args.target.clone(), + body_args.initial_runtime, + body_args.target, ) .await?, )) diff --git a/omicron-sled-agent/src/sim/sled_agent.rs b/omicron-sled-agent/src/sim/sled_agent.rs index da2cc48ba50..13bf5430dc9 100644 --- a/omicron-sled-agent/src/sim/sled_agent.rs +++ b/omicron-sled-agent/src/sim/sled_agent.rs @@ -6,6 +6,7 @@ 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::internal::sled_agent::InstanceHardware; use omicron_common::api::internal::sled_agent::InstanceRuntimeStateRequested; use omicron_common::NexusClient; use slog::Logger; @@ -76,12 +77,12 @@ impl SledAgent { pub async fn instance_ensure( self: &Arc, instance_id: Uuid, - initial_runtime: InstanceRuntimeState, + initial_hardware: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { Ok(self .instances - .sim_ensure(&instance_id, initial_runtime, target) + .sim_ensure(&instance_id, initial_hardware.runtime, target) .await?) } diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 5c5d6d0f12f..7ca4effa86f 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -1,9 +1,11 @@ //! Sled agent implementation -use omicron_common::api::external::Error; use omicron_common::api::{ - internal::nexus::DiskRuntimeState, internal::nexus::InstanceRuntimeState, + external::Error, + internal::nexus::DiskRuntimeState, + internal::nexus::InstanceRuntimeState, internal::sled_agent::DiskStateRequested, + internal::sled_agent::InstanceHardware, internal::sled_agent::InstanceRuntimeStateRequested, }; @@ -43,7 +45,7 @@ impl SledAgent { pub async fn instance_ensure( &self, instance_id: Uuid, - initial_runtime: InstanceRuntimeState, + initial_runtime: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { self.instances.ensure(instance_id, initial_runtime, target).await diff --git a/smf/propolis-server/manifest.xml b/smf/propolis-server/manifest.xml index 8ec7c82757d..0ab039c65a1 100644 --- a/smf/propolis-server/manifest.xml +++ b/smf/propolis-server/manifest.xml @@ -10,7 +10,7 @@ From 0bab62b5aef4dc7602f76951f2759f27bd42d358 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Thu, 29 Jul 2021 20:59:05 -0400 Subject: [PATCH 18/28] Theoretically, guest nics should be allocated when requested --- Cargo.lock | 32 ++--- omicron-common/src/api/internal/sled_agent.rs | 2 +- omicron-sled-agent/src/instance.rs | 124 ++++++++++-------- omicron-sled-agent/src/instance_manager.rs | 68 ++++++---- 4 files changed, 126 insertions(+), 100 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7994441554f..2abe900392a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "bhyve_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" dependencies = [ "libc", "num_enum", @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "dladm" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" dependencies = [ "libc", "num_enum", @@ -1304,7 +1304,7 @@ dependencies = [ "ipnet", "mockall", "omicron-common", - "propolis-client 0.1.0 (git+https://github.com/oxidecomputer/propolis?rev=3d58a6398)", + "propolis-client", "schemars", "serde", "serde_json", @@ -1686,7 +1686,7 @@ dependencies = [ [[package]] name = "propolis" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" dependencies = [ "bhyve_api", "bitflags", @@ -1703,23 +1703,7 @@ dependencies = [ [[package]] name = "propolis-client" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=3d58a6398#3d58a6398e08b88db5e9fe60e50ecb5e43a31c82" -dependencies = [ - "reqwest", - "ring", - "schemars", - "serde", - "serde_json", - "slog", - "structopt", - "thiserror", - "uuid", -] - -[[package]] -name = "propolis-client" -version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" dependencies = [ "reqwest", "ring", @@ -1735,14 +1719,14 @@ dependencies = [ [[package]] name = "propolis-server" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" dependencies = [ "anyhow", "dropshot", "futures", "hyper", "propolis", - "propolis-client 0.1.0 (git+https://github.com/oxidecomputer/propolis?rev=b6da043d)", + "propolis-client", "serde", "serde_derive", "slog", @@ -2889,7 +2873,7 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "viona_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=b6da043d#b6da043dd8c2a3aef44f84aed1f43c6a7369e77f" +source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" [[package]] name = "walkdir" diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index 4aa67bdf249..f48b95435cd 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -40,7 +40,7 @@ impl DiskStateRequested { } /// Describes the instance hardware. -#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct InstanceHardware { pub runtime: internal::nexus::InstanceRuntimeState, pub nics: Vec, diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index 9256c763815..ced9eb11f78 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -3,7 +3,7 @@ use crate::common::instance::{Action as InstanceAction, InstanceStates}; use crate::illumos::svc::wait_for_service; use crate::illumos::{dladm::VNIC_PREFIX, zone::ZONE_PREFIX}; -use crate::instance_manager::InstanceTicket; +use crate::instance_manager::{IdAllocator, InstanceTicket}; use futures::lock::Mutex; use omicron_common::api::external::Error; use omicron_common::api::external::NetworkInterface; @@ -81,8 +81,12 @@ fn zone_name(id: &Uuid) -> String { format!("{}{}", ZONE_PREFIX, id) } -fn vnic_name(runtime_id: u64) -> String { - format!("{}{}", VNIC_PREFIX, runtime_id) +fn vnic_name(id: u64) -> String { + format!("{}{}", VNIC_PREFIX, id) +} + +fn guest_vnic_name(id: u64) -> String { + format!("{}_guest{}", VNIC_PREFIX, id) } fn interface_name(vnic_name: &str) -> String { @@ -130,9 +134,10 @@ impl Drop for RunningState { struct InstanceInner { log: Logger, - runtime_id: u64, + nic_id_allocator: IdAllocator, properties: propolis_client::api::InstanceProperties, nics: Vec, + allocated_nics: Vec, state: InstanceStates, nexus_client: Arc, running_state: Option, @@ -143,6 +148,12 @@ impl InstanceInner { &self.properties.id } + fn allocate_nic_id(&mut self) -> u64 { + let id = self.nic_id_allocator.next(); + self.allocated_nics.push(vnic_name(id)); + id + } + async fn observe_state( &mut self, state: propolis_client::api::InstanceState, @@ -186,12 +197,19 @@ impl InstanceInner { }) } - async fn ensure(&self) -> Result<(), Error> { + async fn ensure(&self, guest_nics: Vec) -> Result<(), Error> { + // TODO: Store slot in NetworkInterface, make this more stable. + let nics = self.nics.iter().enumerate().map(|(i, _)| { + propolis_client::api::NetworkInterfaceRequest { + name: guest_nics[i].clone(), + slot: propolis_client::api::Slot(i as u8), + } + }).collect(); + let request = propolis_client::api::InstanceEnsureRequest { properties: self.properties.clone(), - nics: vec![], // TODO TODO + nics, }; - println!("Ensuring instance: {:?}", request.properties); self.running_state .as_ref() @@ -248,7 +266,7 @@ mockall::mock! { pub fn new( log: Logger, id: Uuid, - runtime_id: u64, + nic_id_allocator: IdAllocator, initial: InstanceHardware, nexus_client: Arc, ) -> Result; @@ -265,11 +283,11 @@ mockall::mock! { impl Instance { /// Creates a new (not yet running) instance object. - + /// /// Arguments: /// * `log`: Logger for dumping debug information. /// * `id`: UUID of the instance to be created. - /// * `runtime_id`: A unique (to the sled) numeric ID which may be used to + /// * `nic_id_allocator`: A unique (to the sled) ID generator to /// refer to a VNIC. (This exists because of a restriction on VNIC name /// lengths, otherwise the UUID would be used instead). /// * `initial`: State of the instance at initialization time. @@ -277,13 +295,13 @@ impl Instance { pub fn new( log: Logger, id: Uuid, - runtime_id: u64, + nic_id_allocator: IdAllocator, initial: InstanceHardware, nexus_client: Arc, ) -> Result { let instance = InstanceInner { log: log.new(o!("instance id" => id.to_string())), - runtime_id, + nic_id_allocator, // NOTE: Mostly lies. properties: propolis_client::api::InstanceProperties { id, @@ -298,6 +316,7 @@ impl Instance { vcpus: initial.runtime.ncpus.0 as u8, }, nics: initial.nics, + allocated_nics: vec![], state: InstanceStates::new(initial.runtime), nexus_client, running_state: None, @@ -311,11 +330,10 @@ impl Instance { /// Begins the execution of the instance's service (Propolis). pub async fn start(&self, ticket: InstanceTicket) -> Result<(), Error> { let mut inner = self.inner.lock().await; - let log = &inner.log; // Create the VNIC which will be attached to the zone. let physical_dl = Dladm::find_physical()?; - info!(log, "Saw physical DL: {}", physical_dl); + info!(inner.log, "Saw physical DL: {}", physical_dl); // It would be preferable to use the UUID of the instance as a component // of the "per-Zone, control plane VNIC", but VNIC names are somewhat @@ -323,36 +341,36 @@ impl Instance { // 32 characters. // // Instead, we just use a per-agent incrementing number. - let vnic_name = vnic_name(inner.runtime_id); - Dladm::create_vnic(&physical_dl, &vnic_name)?; - info!(log, "Created vnic: {}", vnic_name); + let propolis_nic = vnic_name(inner.allocate_nic_id()); + Dladm::create_vnic(&physical_dl, &propolis_nic)?; + info!(inner.log, "Created vnic: {}", propolis_nic); // Create a zone for the propolis instance, using the previously // configured VNIC. let zname = zone_name(inner.id()); - Zones::configure_child_zone(&log, &zname, &vnic_name)?; - info!(log, "Configured child zone: {}", zname); + Zones::configure_child_zone(&inner.log, &zname, &propolis_nic)?; + info!(inner.log, "Configured child zone: {}", zname); // Clone the zone from a base zone (faster than installing) and // boot it up. Zones::clone_from_base(&zname)?; - info!(log, "Cloned child zone: {}", zname); + info!(inner.log, "Cloned child zone: {}", zname); Zones::boot(&zname)?; - info!(log, "Booted zone: {}", zname); + info!(inner.log, "Booted zone: {}", zname); // Wait for the network services to come online, then create an address. wait_for_service(Some(&zname), "svc:/milestone/network:default") .await?; - info!(log, "Network milestone ready for {}", zname); + info!(inner.log, "Network milestone ready for {}", zname); - let ip = Zones::create_address(&zname, &interface_name(&vnic_name))?; - info!(log, "Created address {} for zone: {}", ip, zname); + let ip = Zones::create_address(&zname, &interface_name(&propolis_nic))?; + info!(inner.log, "Created address {} for zone: {}", ip, zname); // Run Propolis in the Zone. let port = 12400; let server_addr = SocketAddr::new(ip.addr(), port); Zones::run_propolis(&zname, inner.id(), &server_addr)?; - info!(log, "Started propolis in zone: {}", zname); + info!(inner.log, "Started propolis in zone: {}", zname); // This isn't strictly necessary - we wait for the HTTP server below - // but it helps distinguish "online in SMF" from "responding to HTTP @@ -362,29 +380,27 @@ impl Instance { let client = Arc::new(PropolisClient::new( server_addr, - log.new(o!("component" => "propolis-client")), + inner.log.new(o!("component" => "propolis-client")), )); // Although the instance is online, the HTTP server may not be running // yet. Wait for it to respond to requests, so users of the instance // don't need to worry about initialization races. - wait_for_http_server(&log, &client).await?; + wait_for_http_server(&inner.log, &client).await?; inner.running_state = Some(RunningState { client, ticket, monitor_task: None }); // Instantiate all requested VNICs within the zone. - // Note that Propolis could theoretically do this itself. - // - // TODO: Prevent collision here with the other VNIC types? - // Sanitize the name? - for nic in &inner.nics { - Zones::create_vnic(&zname, &vnic_name, &format!("vnic-{}", nic.mac.to_string()))?; - } + let guest_nics = (0..inner.nics.len()).into_iter().map(|_| { + let nic = guest_vnic_name(inner.allocate_nic_id()); + Zones::create_vnic(&zname, &physical_dl, &nic)?; + Ok(nic) + }).collect::, Error>>()?; // Ensure the instance exists in the Propolis Server before we start // using it. - inner.ensure().await?; + inner.ensure(guest_nics).await?; // Monitor propolis for state changes in the background. let self_clone = self.clone(); @@ -408,8 +424,9 @@ impl Instance { let zname = zone_name(inner.id()); warn!(inner.log, "Halting and removing zone: {}", zname); Zones::halt_and_remove(&inner.log, &zname).unwrap(); - let vnic_name = vnic_name(inner.runtime_id); - Dladm::delete_vnic(&vnic_name)?; + for nic in &inner.allocated_nics { + Dladm::delete_vnic(&nic)?; + } inner.running_state.as_mut().unwrap().ticket.terminate(); Ok(()) @@ -826,15 +843,18 @@ mod test { .unwrap() } - fn new_runtime_state() -> InstanceRuntimeState { - InstanceRuntimeState { - run_state: InstanceState::Creating, - sled_uuid: Uuid::new_v4(), - ncpus: InstanceCpuCount(2), - memory: ByteCount::from_mebibytes_u32(512), - hostname: "myvm".to_string(), - gen: Generation::new(), - time_updated: Utc::now(), + fn new_initial_instance() -> InstanceHardware { + InstanceHardware { + runtime: InstanceRuntimeState { + run_state: InstanceState::Creating, + sled_uuid: Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), + gen: Generation::new(), + time_updated: Utc::now(), + }, + nics: vec![], } } @@ -854,7 +874,7 @@ mod test { #[serial_test::serial] async fn start_then_stop() { let log = logger(); - let runtime_id = 0; + let nic_id_allocator = IdAllocator::new(); let mut nexus_client = MockNexusClient::default(); // Set expectations about what will be seen (and when) by Nexus before @@ -883,8 +903,8 @@ mod test { let inst = Instance::new( log.clone(), test_uuid(), - runtime_id, - new_runtime_state(), + nic_id_allocator, + new_initial_instance(), Arc::new(nexus_client), ) .unwrap(); @@ -931,14 +951,14 @@ mod test { )] async fn transition_before_start() { let log = logger(); - let runtime_id = 0; + let nic_id_allocator = IdAllocator::new(); let nexus_client = MockNexusClient::default(); let inst = Instance::new( log.clone(), test_uuid(), - runtime_id, - new_runtime_state(), + nic_id_allocator, + new_initial_instance(), Arc::new(nexus_client), ) .unwrap(); diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 2ba8397cbb8..8bf900e3ba5 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -32,6 +32,25 @@ use crate::{ instance::MockInstance as Instance, }; +/// A shareable wrapper around an atomic counter. +/// May be used to allocate runtime-unique IDs. +#[derive(Clone, Debug)] +pub struct IdAllocator { + value: Arc, +} + +impl IdAllocator { + pub fn new() -> Self { + Self { + value: Arc::new(AtomicU64::new(0)), + } + } + + pub fn next(&self) -> u64 { + self.value.fetch_add(1, Ordering::SeqCst) + } +} + struct InstanceManagerInternal { log: Logger, nexus_client: Arc, @@ -41,7 +60,7 @@ struct InstanceManagerInternal { // if the Propolis client hasn't been initialized. instances: Mutex>, - next_id: AtomicU64, + nic_id_allocator: IdAllocator, } /// All instances currently running on the sled. @@ -92,7 +111,7 @@ impl InstanceManager { log, nexus_client, instances: Mutex::new(BTreeMap::new()), - next_id: AtomicU64::new(1), + nic_id_allocator: IdAllocator::new(), }), }) } @@ -129,7 +148,7 @@ impl InstanceManager { Instance::new( instance_log, instance_id, - self.inner.next_id.fetch_add(1, Ordering::SeqCst), + self.inner.nic_id_allocator.clone(), initial_hardware, self.inner.nexus_client.clone(), )?, @@ -220,15 +239,18 @@ mod test { .unwrap() } - fn new_runtime_state() -> InstanceRuntimeState { - InstanceRuntimeState { - run_state: InstanceState::Creating, - sled_uuid: Uuid::new_v4(), - ncpus: InstanceCpuCount(2), - memory: ByteCount::from_mebibytes_u32(512), - hostname: "myvm".to_string(), - gen: Generation::new(), - time_updated: Utc::now(), + fn new_initial_instance() -> InstanceHardware { + InstanceHardware { + runtime: InstanceRuntimeState { + run_state: InstanceState::Creating, + sled_uuid: Uuid::new_v4(), + ncpus: InstanceCpuCount(2), + memory: ByteCount::from_mebibytes_u32(512), + hostname: "myvm".to_string(), + gen: Generation::new(), + time_updated: Utc::now(), + }, + nics: vec![], } } @@ -286,9 +308,9 @@ mod test { Ok(()) }); inst.expect_transition().return_once(|_| { - let mut rt_state = new_runtime_state(); - rt_state.run_state = InstanceState::Running; - Ok(rt_state) + let mut rt_state = new_initial_instance(); + rt_state.runtime.run_state = InstanceState::Running; + Ok(rt_state.runtime) }); inst }); @@ -297,7 +319,7 @@ mod test { let rt_state = im .ensure( test_uuid(), - new_runtime_state(), + new_initial_instance(), InstanceRuntimeStateRequested { run_state: InstanceStateRequested::Running, }, @@ -357,9 +379,9 @@ mod test { Ok(()) }); inst.expect_transition().return_once(|_| { - let mut rt_state = new_runtime_state(); - rt_state.run_state = InstanceState::Running; - Ok(rt_state) + let mut rt_state = new_initial_instance(); + rt_state.runtime.run_state = InstanceState::Running; + Ok(rt_state.runtime) }); inst }, @@ -369,9 +391,9 @@ mod test { move || { let mut inst = MockInstance::default(); inst.expect_transition().returning(|_| { - let mut rt_state = new_runtime_state(); - rt_state.run_state = InstanceState::Running; - Ok(rt_state) + let mut rt_state = new_initial_instance(); + rt_state.runtime.run_state = InstanceState::Running; + Ok(rt_state.runtime) }); inst }, @@ -380,7 +402,7 @@ mod test { }); let id = test_uuid(); - let rt = new_runtime_state(); + let rt = new_initial_instance(); let target = InstanceRuntimeStateRequested { run_state: InstanceStateRequested::Running, }; From 54149b80aca5dfa339faf5b7fff819ef30f0a6a0 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Fri, 30 Jul 2021 09:58:55 -0400 Subject: [PATCH 19/28] Macs maybe? --- omicron-sled-agent/src/illumos/dladm.rs | 19 ++++++++++-- omicron-sled-agent/src/illumos/zone.rs | 30 +++++------------- omicron-sled-agent/src/instance.rs | 41 ++++++++++++++++--------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index d8edb7a3579..160941b1d7c 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -2,6 +2,7 @@ use crate::illumos::{execute, PFEXEC}; use omicron_common::api::external::Error; +use omicron_common::api::external::MacAddr; pub const VNIC_PREFIX: &str = "vnic_propolis"; @@ -34,10 +35,24 @@ impl Dladm { } /// Creates a new VNIC atop a physical device. - pub fn create_vnic(physical: &str, vnic_name: &str) -> Result<(), Error> { + pub fn create_vnic(physical: &str, vnic_name: &str, mac: Option) -> Result<(), Error> { let mut command = std::process::Command::new(PFEXEC); + let mut args = vec![ + DLADM.to_string(), + "create-vnic".to_string(), + "-t".to_string(), + "-l".to_string(), + physical.to_string(), + ]; + + if let Some(mac) = mac { + args.push("-m".to_string()); + args.push(mac.0.to_string()); + } + + args.push(vnic_name.to_string()); let cmd = - command.args(&[DLADM, "create-vnic", "-l", physical, vnic_name]); + command.args(&args); execute(cmd)?; Ok(()) } diff --git a/omicron-sled-agent/src/illumos/zone.rs b/omicron-sled-agent/src/illumos/zone.rs index 84f34bbb0b6..bc5ee961e2a 100644 --- a/omicron-sled-agent/src/illumos/zone.rs +++ b/omicron-sled-agent/src/illumos/zone.rs @@ -6,7 +6,6 @@ use slog::Logger; use std::net::SocketAddr; use uuid::Uuid; -use crate::illumos::dladm::DLADM; use crate::illumos::zfs::ZONE_ZFS_DATASET_MOUNTPOINT; use crate::illumos::{execute, PFEXEC}; @@ -123,7 +122,7 @@ impl Zones { pub fn configure_child_zone( log: &Logger, name: &str, - vnic: &str, + vnics: Vec, ) -> Result<(), Error> { info!(log, "Creating child zone: {}", name); let mut cfg = zone::Config::create( @@ -142,10 +141,12 @@ impl Zones { options: vec!["ro".to_string()], ..Default::default() }); - cfg.add_net(&zone::Net { - physical: vnic.to_string(), - ..Default::default() - }); + for vnic in &vnics { + cfg.add_net(&zone::Net { + physical: vnic.to_string(), + ..Default::default() + }); + } cfg.add_device(&zone::Device { name: "/dev/vmm/*".to_string() }); cfg.add_device(&zone::Device { name: "/dev/vmmctl".to_string() }); cfg.add_device(&zone::Device { name: "/dev/viona".to_string() }); @@ -185,23 +186,6 @@ impl Zones { .collect()) } - /// Creates a VNIC within a zone. - // TODO: de-dup with "fn create_vnic" in dladm.rs? - pub fn create_vnic(zone: &str, physical: &str, vnic_name: &str) -> Result<(), Error> { - let mut command = std::process::Command::new(PFEXEC); - let cmd = command.args(&[ - ZLOGIN, - zone, - DLADM, - "create-vnic", - "-l", - physical, - vnic_name - ]); - execute(cmd)?; - Ok(()) - } - /// Creates an IP address within a Zone. pub fn create_address(zone: &str, interface: &str) -> Result { let mut command = std::process::Command::new(PFEXEC); diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index ced9eb11f78..c5d86031fc8 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -332,23 +332,41 @@ impl Instance { let mut inner = self.inner.lock().await; // Create the VNIC which will be attached to the zone. - let physical_dl = Dladm::find_physical()?; - info!(inner.log, "Saw physical DL: {}", physical_dl); - + // // It would be preferable to use the UUID of the instance as a component // of the "per-Zone, control plane VNIC", but VNIC names are somewhat // restrictive. They must end with numerics, and they must be less than // 32 characters. // - // Instead, we just use a per-agent incrementing number. + // Instead, we just use a per-agent incrementing number. We do the same + // for the guest-accessible NICs too. + let physical_dl = Dladm::find_physical()?; + info!(inner.log, "Saw physical DL: {}", physical_dl); let propolis_nic = vnic_name(inner.allocate_nic_id()); - Dladm::create_vnic(&physical_dl, &propolis_nic)?; + Dladm::create_vnic(&physical_dl, &propolis_nic, None)?; info!(inner.log, "Created vnic: {}", propolis_nic); + // Instantiate all guest-requested VNICs. + // + // TODO: Ideally, we'd allocate VNICs directly within the Zone. + // However, this seems to have been a SmartOS feature which + // doesn't exist in illumos. + // + // https://github.com/illumos/ipd/blob/master/ipd/0003/README.md + let guest_nics = inner.nics.clone().into_iter().map(|nic| { + let nic_name = guest_vnic_name(inner.allocate_nic_id()); + // TODO: IP allocation? + Dladm::create_vnic(&physical_dl, &nic_name, Some(nic.mac))?; + Ok(nic_name) + }).collect::, Error>>()?; + // Create a zone for the propolis instance, using the previously - // configured VNIC. + // configured VNICs. let zname = zone_name(inner.id()); - Zones::configure_child_zone(&inner.log, &zname, &propolis_nic)?; + + let mut nics_to_put_in_zone = guest_nics.clone(); + nics_to_put_in_zone.push(propolis_nic.clone()); + Zones::configure_child_zone(&inner.log, &zname, nics_to_put_in_zone)?; info!(inner.log, "Configured child zone: {}", zname); // Clone the zone from a base zone (faster than installing) and @@ -391,13 +409,6 @@ impl Instance { inner.running_state = Some(RunningState { client, ticket, monitor_task: None }); - // Instantiate all requested VNICs within the zone. - let guest_nics = (0..inner.nics.len()).into_iter().map(|_| { - let nic = guest_vnic_name(inner.allocate_nic_id()); - Zones::create_vnic(&zname, &physical_dl, &nic)?; - Ok(nic) - }).collect::, Error>>()?; - // Ensure the instance exists in the Propolis Server before we start // using it. inner.ensure(guest_nics).await?; @@ -721,7 +732,7 @@ mod test { .expect() .times(1) .in_sequence(&mut seq) - .returning(|phys, vnic| { + .returning(|phys, vnic, maybe_mac| { assert_eq!(phys, "physical"); assert_eq!(vnic, vnic_name(0)); Ok(()) From 5e67a833b0a64f2562d1bf524f1d882a28c83ece Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 4 Aug 2021 14:03:59 -0400 Subject: [PATCH 20/28] Conjuring a NIC in Nexus, throwing it around --- Cargo.lock | 13 +- omicron-common/Cargo.toml | 2 +- omicron-common/src/api/internal/sled_agent.rs | 2 +- omicron-common/src/sled_agent_client.rs | 4 +- omicron-nexus/Cargo.toml | 1 + omicron-nexus/src/nexus.rs | 6 + omicron-nexus/src/sagas.rs | 19 ++- omicron-sled-agent/Cargo.toml | 2 +- omicron-sled-agent/src/http_entrypoints.rs | 2 +- omicron-sled-agent/src/illumos/dladm.rs | 15 ++- omicron-sled-agent/src/instance.rs | 125 ++++++++++++++---- .../src/sim/http_entrypoints.rs | 2 +- omicron-sled-agent/src/sled_agent.rs | 4 +- 13 files changed, 148 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2abe900392a..8cd8097a57a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "bhyve_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" dependencies = [ "libc", "num_enum", @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "dladm" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" dependencies = [ "libc", "num_enum", @@ -1269,6 +1269,7 @@ dependencies = [ "hyper", "lazy_static", "libc", + "macaddr", "newtype_derive", "omicron-common", "omicron-sled-agent", @@ -1686,7 +1687,7 @@ dependencies = [ [[package]] name = "propolis" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" dependencies = [ "bhyve_api", "bitflags", @@ -1703,7 +1704,7 @@ dependencies = [ [[package]] name = "propolis-client" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" dependencies = [ "reqwest", "ring", @@ -1719,7 +1720,7 @@ dependencies = [ [[package]] name = "propolis-server" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" dependencies = [ "anyhow", "dropshot", @@ -2873,7 +2874,7 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "viona_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=e4d83b1fe8#e4d83b1fe8f49c3d79088d6f115f6ecde0fe4b49" +source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" [[package]] name = "walkdir" diff --git a/omicron-common/Cargo.toml b/omicron-common/Cargo.toml index abd5e52079a..3e6f852e2fb 100644 --- a/omicron-common/Cargo.toml +++ b/omicron-common/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.15" http = "0.2.0" hyper = "0.14" libc = "0.2.98" -propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "e4d83b1fe8" } +propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "a0d1abc2" } postgres-protocol = "0.6.1" rayon = "1.5" reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } diff --git a/omicron-common/src/api/internal/sled_agent.rs b/omicron-common/src/api/internal/sled_agent.rs index f48b95435cd..6aa7fcc9a85 100644 --- a/omicron-common/src/api/internal/sled_agent.rs +++ b/omicron-common/src/api/internal/sled_agent.rs @@ -51,7 +51,7 @@ pub struct InstanceHardware { 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: InstanceHardware, + pub initial: InstanceHardware, /// requested runtime state of the Instance pub target: InstanceRuntimeStateRequested, } diff --git a/omicron-common/src/sled_agent_client.rs b/omicron-common/src/sled_agent_client.rs index fef174049c5..561dbde4982 100644 --- a/omicron-common/src/sled_agent_client.rs +++ b/omicron-common/src/sled_agent_client.rs @@ -55,13 +55,13 @@ impl Client { pub async fn instance_ensure( self: &Arc, instance_id: Uuid, - initial_runtime: InstanceHardware, + initial: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { let path = format!("/instances/{}", instance_id); let body = Body::from( serde_json::to_string(&InstanceEnsureBody { - initial_runtime, + initial, target, }) .unwrap(), diff --git a/omicron-nexus/Cargo.toml b/omicron-nexus/Cargo.toml index 8800c06e71e..2be5d0ddba8 100644 --- a/omicron-nexus/Cargo.toml +++ b/omicron-nexus/Cargo.toml @@ -13,6 +13,7 @@ http = "0.2.0" hyper = "0.14" lazy_static = "1.4.0" libc = "0.2.98" +macaddr = { version = "1.0.1", features = [ "serde_std" ]} newtype_derive = "0.1.6" serde_json = "1.0" serde_with = "1.9.4" diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 678ae0fbbeb..12a8d78593e 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -11,6 +11,7 @@ use chrono::Utc; use futures::future::ready; use futures::lock::Mutex; use futures::StreamExt; +use omicron_common::api::external; use omicron_common::api::external::CreateResult; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::DeleteResult; @@ -753,8 +754,13 @@ impl Nexus { * not the newest one, that's fine. That might just mean the sled agent * beat us to it. */ + let instance_hardware = InstanceHardware { runtime: instance.runtime.clone(), + // TODO TODO TODO: Avoid hard-coding this NIC! + // + // TODO: also, this same thing is called in sagas.rs. + // When is one used vs the other? nics: vec![], }; diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index 8f5da08b0c2..a034feac21c 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -12,6 +12,7 @@ use crate::saga_interface::SagaContext; use chrono::Utc; use lazy_static::lazy_static; +use omicron_common::api::external; use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceState; @@ -22,6 +23,7 @@ use omicron_common::api::internal::sled_agent::InstanceStateRequested; use serde::Deserialize; use serde::Serialize; use std::collections::BTreeMap; +use std::convert::TryFrom; use std::sync::Arc; use steno::new_action_noop_undo; use steno::ActionContext; @@ -154,7 +156,22 @@ async fn sic_create_instance_record( .map_err(ActionError::action_failed)?; Ok(InstanceHardware { runtime: instance.runtime, - nics: vec![], + // TODO TODO TODO: Avoid hard-coding! + nics: vec![ + external::NetworkInterface { + identity: external::IdentityMetadata { + id: Uuid::new_v4(), + name: external::Name::try_from("my-nic".to_string()).unwrap(), + description: "Look a VNIC".to_string(), + time_created: Utc::now(), + time_modified: Utc::now(), + }, + vpc_id: Uuid::new_v4(), + subnet_id: Uuid::new_v4(), + mac: external::MacAddr(macaddr::MacAddr6::new(2, 8, 20, 1, 6, 24)), + ip: std::net::IpAddr::V4(std::net::Ipv4Addr::new(10, 0, 0, 8)), + } + ], }) } diff --git a/omicron-sled-agent/Cargo.toml b/omicron-sled-agent/Cargo.toml index 20c096b8acd..7e34f48309f 100644 --- a/omicron-sled-agent/Cargo.toml +++ b/omicron-sled-agent/Cargo.toml @@ -13,7 +13,7 @@ http = "0.2.0" hyper = "0.14" ipnet = "2.3" omicron-common = { path = "../omicron-common" } -propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "e4d83b1fe8" } +propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "a0d1abc2" } schemars = { version = "0.8", features = [ "chrono", "uuid" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" diff --git a/omicron-sled-agent/src/http_entrypoints.rs b/omicron-sled-agent/src/http_entrypoints.rs index fba41df2abb..06a1abbbb24 100644 --- a/omicron-sled-agent/src/http_entrypoints.rs +++ b/omicron-sled-agent/src/http_entrypoints.rs @@ -56,7 +56,7 @@ async fn instance_put( Ok(HttpResponseOk( sa.instance_ensure( instance_id, - body_args.initial_runtime, + body_args.initial, body_args.target, ) .await?, diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index 160941b1d7c..399abb2f0bf 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -8,17 +8,21 @@ pub const VNIC_PREFIX: &str = "vnic_propolis"; pub const DLADM: &str = "/usr/sbin/dladm"; +/// The name of a physical datalink. +#[derive(Debug)] +pub struct PhysicalLink(String); + /// Wraps commands for interacting with data links. pub struct Dladm {} #[cfg_attr(test, mockall::automock, allow(dead_code))] impl Dladm { /// Returns the name of the first observed physical data link. - pub fn find_physical() -> Result { + pub fn find_physical() -> Result { let mut command = std::process::Command::new(PFEXEC); let cmd = command.args(&[DLADM, "show-phys", "-p", "-o", "LINK"]); let output = execute(cmd)?; - Ok(String::from_utf8(output.stdout) + let name = String::from_utf8(output.stdout) .map_err(|e| Error::InternalError { message: format!("Cannot parse dladm output as UTF-8: {}", e), })? @@ -31,18 +35,19 @@ impl Dladm { .ok_or_else(|| Error::InternalError { message: "No physical devices found".to_string(), })? - .to_string()) + .to_string(); + Ok(PhysicalLink(name)) } /// Creates a new VNIC atop a physical device. - pub fn create_vnic(physical: &str, vnic_name: &str, mac: Option) -> Result<(), Error> { + pub fn create_vnic(physical: &PhysicalLink, vnic_name: &str, mac: Option) -> Result<(), Error> { let mut command = std::process::Command::new(PFEXEC); let mut args = vec![ DLADM.to_string(), "create-vnic".to_string(), "-t".to_string(), "-l".to_string(), - physical.to_string(), + physical.0.to_string(), ]; if let Some(mac) = mac { diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index c5d86031fc8..d6d8f0fb121 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -2,10 +2,14 @@ use crate::common::instance::{Action as InstanceAction, InstanceStates}; use crate::illumos::svc::wait_for_service; -use crate::illumos::{dladm::VNIC_PREFIX, zone::ZONE_PREFIX}; +use crate::illumos::{ + dladm::{PhysicalLink, VNIC_PREFIX}, + zone::ZONE_PREFIX +}; use crate::instance_manager::{IdAllocator, InstanceTicket}; use futures::lock::Mutex; use omicron_common::api::external::Error; +use omicron_common::api::external::MacAddr; use omicron_common::api::external::NetworkInterface; use omicron_common::api::internal::nexus::InstanceRuntimeState; use omicron_common::api::internal::sled_agent::InstanceHardware; @@ -132,12 +136,71 @@ impl Drop for RunningState { } } +/// Represents an allocated VNIC on the system. +/// The VNIC is de-allocated when it goes out of scope. +/// +/// Note that the "ownership" of the VNIC is based on convention; +/// another process in the global zone could also modify / destroy +/// the VNIC while this object is alive. +#[derive(Debug)] +struct Vnic { + name: String, + deleted: bool, +} + +impl Vnic { + // Creates a new NIC, intended for usage by the guest. + fn new_guest( + allocator: &IdAllocator, + physical_dl: &PhysicalLink, + mac: Option + ) -> Result { + let name = guest_vnic_name(allocator.next()); + Dladm::create_vnic(physical_dl, &name, mac)?; + Ok(Vnic { + name, + deleted: false, + }) + } + + // Creates a new NIC, intended for allowing Propolis to communicate + // with the control plane. + fn new_control( + allocator: &IdAllocator, + physical_dl: &PhysicalLink, + mac: Option + ) -> Result { + let name = vnic_name(allocator.next()); + Dladm::create_vnic(physical_dl, &name, mac)?; + Ok(Vnic { + name, + deleted: false, + }) + } + + // Deletes a NIC (if it has not already been deleted). + fn delete(&mut self) -> Result<(), Error> { + if self.deleted { + Ok(()) + } else { + self.deleted = true; + Dladm::delete_vnic(&self.name) + } + } +} + +impl Drop for Vnic { + fn drop(&mut self) { + let _ = self.delete(); + } +} + struct InstanceInner { log: Logger, nic_id_allocator: IdAllocator, properties: propolis_client::api::InstanceProperties, - nics: Vec, - allocated_nics: Vec, + requested_nics: Vec, + allocated_nics: Vec, state: InstanceStates, nexus_client: Arc, running_state: Option, @@ -148,12 +211,6 @@ impl InstanceInner { &self.properties.id } - fn allocate_nic_id(&mut self) -> u64 { - let id = self.nic_id_allocator.next(); - self.allocated_nics.push(vnic_name(id)); - id - } - async fn observe_state( &mut self, state: propolis_client::api::InstanceState, @@ -197,11 +254,11 @@ impl InstanceInner { }) } - async fn ensure(&self, guest_nics: Vec) -> Result<(), Error> { + async fn ensure(&self, guest_nics: &Vec) -> Result<(), Error> { // TODO: Store slot in NetworkInterface, make this more stable. - let nics = self.nics.iter().enumerate().map(|(i, _)| { + let nics = self.requested_nics.iter().enumerate().map(|(i, _)| { propolis_client::api::NetworkInterfaceRequest { - name: guest_nics[i].clone(), + name: guest_nics[i].name.clone(), slot: propolis_client::api::Slot(i as u8), } }).collect(); @@ -211,6 +268,7 @@ impl InstanceInner { nics, }; + info!(self.log, "Sending ensure request to propolis: {:?}", request); self.running_state .as_ref() .expect("Propolis client should be initialized before usage") @@ -299,6 +357,7 @@ impl Instance { initial: InstanceHardware, nexus_client: Arc, ) -> Result { + info!(log, "Instance::new w/initial HW: {:?}", initial); let instance = InstanceInner { log: log.new(o!("instance id" => id.to_string())), nic_id_allocator, @@ -315,7 +374,7 @@ impl Instance { // InstanceCpuCount here, to avoid any casting... vcpus: initial.runtime.ncpus.0 as u8, }, - nics: initial.nics, + requested_nics: initial.nics, allocated_nics: vec![], state: InstanceStates::new(initial.runtime), nexus_client, @@ -341,10 +400,7 @@ impl Instance { // Instead, we just use a per-agent incrementing number. We do the same // for the guest-accessible NICs too. let physical_dl = Dladm::find_physical()?; - info!(inner.log, "Saw physical DL: {}", physical_dl); - let propolis_nic = vnic_name(inner.allocate_nic_id()); - Dladm::create_vnic(&physical_dl, &propolis_nic, None)?; - info!(inner.log, "Created vnic: {}", propolis_nic); + let control_nic = Vnic::new_control(&inner.nic_id_allocator, &physical_dl, None)?; // Instantiate all guest-requested VNICs. // @@ -353,19 +409,19 @@ impl Instance { // doesn't exist in illumos. // // https://github.com/illumos/ipd/blob/master/ipd/0003/README.md - let guest_nics = inner.nics.clone().into_iter().map(|nic| { - let nic_name = guest_vnic_name(inner.allocate_nic_id()); - // TODO: IP allocation? - Dladm::create_vnic(&physical_dl, &nic_name, Some(nic.mac))?; - Ok(nic_name) + let guest_nics = inner.requested_nics.clone().into_iter().map(|nic| { + Vnic::new_guest(&inner.nic_id_allocator, &physical_dl, Some(nic.mac)) }).collect::, Error>>()?; // Create a zone for the propolis instance, using the previously // configured VNICs. let zname = zone_name(inner.id()); - let mut nics_to_put_in_zone = guest_nics.clone(); - nics_to_put_in_zone.push(propolis_nic.clone()); + let nics_to_put_in_zone: Vec = guest_nics.iter() + .map(|nic| nic.name.clone()) + .chain(std::iter::once(control_nic.name.clone())) + .collect(); + Zones::configure_child_zone(&inner.log, &zname, nics_to_put_in_zone)?; info!(inner.log, "Configured child zone: {}", zname); @@ -381,7 +437,7 @@ impl Instance { .await?; info!(inner.log, "Network milestone ready for {}", zname); - let ip = Zones::create_address(&zname, &interface_name(&propolis_nic))?; + let ip = Zones::create_address(&zname, &interface_name(&control_nic.name))?; info!(inner.log, "Created address {} for zone: {}", ip, zname); // Run Propolis in the Zone. @@ -411,7 +467,7 @@ impl Instance { // Ensure the instance exists in the Propolis Server before we start // using it. - inner.ensure(guest_nics).await?; + inner.ensure(&guest_nics).await?; // Monitor propolis for state changes in the background. let self_clone = self.clone(); @@ -425,6 +481,10 @@ impl Instance { } })); + // Store the VNICs while the instance is running. + inner.allocated_nics = + guest_nics.into_iter().chain(std::iter::once(control_nic)).collect(); + Ok(()) } @@ -435,8 +495,17 @@ impl Instance { let zname = zone_name(inner.id()); warn!(inner.log, "Halting and removing zone: {}", zname); Zones::halt_and_remove(&inner.log, &zname).unwrap(); - for nic in &inner.allocated_nics { - Dladm::delete_vnic(&nic)?; + + // Explicitly remove NICs. + // + // The NICs would self-delete on drop anyway, but this allows us + // to explicitly record errors. + let mut nics = vec![]; + std::mem::swap(&mut inner.allocated_nics, &mut nics); + for mut nic in nics { + if let Err(e) = nic.delete() { + error!(inner.log, "Failed to delete NIC {:?}: {}", nic, e); + } } inner.running_state.as_mut().unwrap().ticket.terminate(); diff --git a/omicron-sled-agent/src/sim/http_entrypoints.rs b/omicron-sled-agent/src/sim/http_entrypoints.rs index 9c62b95d878..78200d18075 100644 --- a/omicron-sled-agent/src/sim/http_entrypoints.rs +++ b/omicron-sled-agent/src/sim/http_entrypoints.rs @@ -65,7 +65,7 @@ async fn instance_put( Ok(HttpResponseOk( sa.instance_ensure( instance_id, - body_args.initial_runtime, + body_args.initial, body_args.target, ) .await?, diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 7ca4effa86f..cea9aa116ee 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -45,10 +45,10 @@ impl SledAgent { pub async fn instance_ensure( &self, instance_id: Uuid, - initial_runtime: InstanceHardware, + initial: InstanceHardware, target: InstanceRuntimeStateRequested, ) -> Result { - self.instances.ensure(instance_id, initial_runtime, target).await + self.instances.ensure(instance_id, initial, target).await } /// Idempotently ensures that the given Disk is attached (or not) as From 2eca04ce333dd35b4e3849fa64975f13aabc0203 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 4 Aug 2021 14:12:09 -0400 Subject: [PATCH 21/28] pass tests pls thank u --- omicron-sled-agent/src/illumos/dladm.rs | 2 +- omicron-sled-agent/src/instance.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index 399abb2f0bf..99e1be1c2f5 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -10,7 +10,7 @@ pub const DLADM: &str = "/usr/sbin/dladm"; /// The name of a physical datalink. #[derive(Debug)] -pub struct PhysicalLink(String); +pub struct PhysicalLink(pub String); /// Wraps commands for interacting with data links. pub struct Dladm {} diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index d6d8f0fb121..b71605c7106 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -794,15 +794,15 @@ mod test { .expect() .times(1) .in_sequence(&mut seq) - .returning(|| Ok("physical".to_string())); + .returning(|| Ok(PhysicalLink("physical".to_string()))); let dladm_create_vnic_ctx = MockDladm::create_vnic_context(); dladm_create_vnic_ctx .expect() .times(1) .in_sequence(&mut seq) - .returning(|phys, vnic, maybe_mac| { - assert_eq!(phys, "physical"); + .returning(|phys, vnic, _maybe_mac| { + assert_eq!(phys.0, "physical"); assert_eq!(vnic, vnic_name(0)); Ok(()) }); @@ -813,9 +813,10 @@ mod test { .expect() .times(1) .in_sequence(&mut seq) - .returning(|_, zone, vnic| { + .returning(|_, zone, vnics| { assert_eq!(zone, zone_name(&test_uuid())); - assert_eq!(vnic, vnic_name(0)); + assert_eq!(vnics.len(), 1); + assert_eq!(vnics[0], vnic_name(0)); Ok(()) }); From 005966750b33176de88fd6a0fd82c637e4257c35 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 1 Sep 2021 16:43:14 -0400 Subject: [PATCH 22/28] Workaround for libpq --- README.adoc | 8 ++++++++ smf/bootstrap-agent/manifest.xml | 2 +- smf/nexus/manifest.xml | 2 +- smf/oximeter/manifest.xml | 2 +- smf/propolis-server/manifest.xml | 2 +- smf/sled-agent/manifest.xml | 2 +- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.adoc b/README.adoc index 7d988f91078..335450d9227 100644 --- a/README.adoc +++ b/README.adoc @@ -56,6 +56,14 @@ However, once these have been provided, the codebase should be buildable with `c **Prerequisites:** +. Postgres + +(See https://github.com/oxidecomputer/omicron/issues/213 ; we may be able to remove this dependency long-term) + +Linux: `sudo apt-get install libpq-dev` +Mac: `brew install postgresql` +Helios: `pkg install library/postgresql-13` + . CockroachDB v20.2.5. + The test suite expects to be able to start a single-node CockroachDB cluster using the `cockroach` executable on your PATH. diff --git a/smf/bootstrap-agent/manifest.xml b/smf/bootstrap-agent/manifest.xml index d7da9b7fd26..8fac04129f5 100644 --- a/smf/bootstrap-agent/manifest.xml +++ b/smf/bootstrap-agent/manifest.xml @@ -30,7 +30,7 @@ diff --git a/smf/nexus/manifest.xml b/smf/nexus/manifest.xml index 5021d79f34a..1f8d113a9d9 100644 --- a/smf/nexus/manifest.xml +++ b/smf/nexus/manifest.xml @@ -13,7 +13,7 @@ diff --git a/smf/oximeter/manifest.xml b/smf/oximeter/manifest.xml index a588bd84466..23b7cb743a6 100644 --- a/smf/oximeter/manifest.xml +++ b/smf/oximeter/manifest.xml @@ -13,7 +13,7 @@ diff --git a/smf/propolis-server/manifest.xml b/smf/propolis-server/manifest.xml index 8ec7c82757d..f24eaa66201 100644 --- a/smf/propolis-server/manifest.xml +++ b/smf/propolis-server/manifest.xml @@ -10,7 +10,7 @@ diff --git a/smf/sled-agent/manifest.xml b/smf/sled-agent/manifest.xml index 51376acb8ab..2be3f13b029 100644 --- a/smf/sled-agent/manifest.xml +++ b/smf/sled-agent/manifest.xml @@ -13,7 +13,7 @@ From bc54efbe6f540662537688dd5ed612e2e78ee05c Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 1 Sep 2021 16:46:37 -0400 Subject: [PATCH 23/28] Update readme --- README.adoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.adoc b/README.adoc index 335450d9227..2a5d5d606ad 100644 --- a/README.adoc +++ b/README.adoc @@ -58,12 +58,21 @@ However, once these have been provided, the codebase should be buildable with `c . Postgres +Postgres is required to link against libpq for access to the database. + (See https://github.com/oxidecomputer/omicron/issues/213 ; we may be able to remove this dependency long-term) Linux: `sudo apt-get install libpq-dev` Mac: `brew install postgresql` Helios: `pkg install library/postgresql-13` +Additionally, to help all cargo build commands find this library, we recommend the following: + +[source,text] +---- +export LD_LIBRARY_PATH="$(pg_config --libdir)" +---- + . CockroachDB v20.2.5. + The test suite expects to be able to start a single-node CockroachDB cluster using the `cockroach` executable on your PATH. From 7c5c848f21b6a3691edd51de6540e35415d3cd62 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 1 Sep 2021 17:10:18 -0400 Subject: [PATCH 24/28] Review feedback --- README.adoc | 3 +-- smf/propolis-server/manifest.xml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index 2a5d5d606ad..1eb2f039154 100644 --- a/README.adoc +++ b/README.adoc @@ -66,8 +66,7 @@ Linux: `sudo apt-get install libpq-dev` Mac: `brew install postgresql` Helios: `pkg install library/postgresql-13` -Additionally, to help all cargo build commands find this library, we recommend the following: - +Additionally, to help all runtime commands find this library, we recommend the following: [source,text] ---- export LD_LIBRARY_PATH="$(pg_config --libdir)" diff --git a/smf/propolis-server/manifest.xml b/smf/propolis-server/manifest.xml index f24eaa66201..592cbeab15a 100644 --- a/smf/propolis-server/manifest.xml +++ b/smf/propolis-server/manifest.xml @@ -10,7 +10,7 @@ From d881b90368d5a27a062bde658a3c49d7e6b1fc76 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 1 Sep 2021 17:27:00 -0400 Subject: [PATCH 25/28] rm feedback --- smf/bootstrap-agent/manifest.xml | 7 ++++++- smf/nexus/manifest.xml | 7 ++++++- smf/oximeter/manifest.xml | 7 ++++++- smf/propolis-server/manifest.xml | 7 ++++++- smf/sled-agent/manifest.xml | 7 ++++++- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/smf/bootstrap-agent/manifest.xml b/smf/bootstrap-agent/manifest.xml index 8fac04129f5..97d4a75ce13 100644 --- a/smf/bootstrap-agent/manifest.xml +++ b/smf/bootstrap-agent/manifest.xml @@ -29,8 +29,13 @@ + + + + + diff --git a/smf/nexus/manifest.xml b/smf/nexus/manifest.xml index 1f8d113a9d9..2f3905dc779 100644 --- a/smf/nexus/manifest.xml +++ b/smf/nexus/manifest.xml @@ -12,8 +12,13 @@ + + + + + diff --git a/smf/oximeter/manifest.xml b/smf/oximeter/manifest.xml index 23b7cb743a6..9801c467ed3 100644 --- a/smf/oximeter/manifest.xml +++ b/smf/oximeter/manifest.xml @@ -12,8 +12,13 @@ + + + + + diff --git a/smf/propolis-server/manifest.xml b/smf/propolis-server/manifest.xml index 592cbeab15a..f838f4b89ec 100644 --- a/smf/propolis-server/manifest.xml +++ b/smf/propolis-server/manifest.xml @@ -9,8 +9,13 @@ + + + + + diff --git a/smf/sled-agent/manifest.xml b/smf/sled-agent/manifest.xml index 2be3f13b029..d3063a8e2db 100644 --- a/smf/sled-agent/manifest.xml +++ b/smf/sled-agent/manifest.xml @@ -12,8 +12,13 @@ + + + + + From 430f4dbddb208f9555c8d316ac6b1a79e5314d6e Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 1 Sep 2021 18:01:17 -0400 Subject: [PATCH 26/28] Avoid actually sending fake NICs from Nexus --- omicron-nexus/src/nexus.rs | 20 +++----------------- omicron-nexus/src/sagas.rs | 23 ++++------------------- 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/omicron-nexus/src/nexus.rs b/omicron-nexus/src/nexus.rs index 46db1e162ab..4524f8bb754 100644 --- a/omicron-nexus/src/nexus.rs +++ b/omicron-nexus/src/nexus.rs @@ -508,19 +508,6 @@ impl Nexus { let project_id = self.db_datastore.project_lookup_id_by_name(project_name).await?; - // TODO TODO TODO TODO TODO TODO - // - // 1) (not here) Create a default VPC for the project when it is created - // RFD21: "When a project is created, a default VPC is created as well." - // 1a) (not here) Create a default subnet for a VPC when created - // 2) Look up the VPC subnet here, unless one is specified (?). - // 2a) Allocate an address within that range. - // 2b) Allocate a mac address (?). - // 3) Create a network interface from all the allocated stats. - // 4) Pass it alongside the "hw info". - // - // TODO TODO TODO TODO TODO TODO - let saga_params = Arc::new(sagas::ParamsInstanceCreate { project_id, create_params: params.clone(), @@ -777,12 +764,11 @@ impl Nexus { * beat us to it. */ + // TODO: Populate this with an appropriate NIC. + // See also: sic_create_instance_record in sagas.rs for a similar + // construction. let instance_hardware = InstanceHardware { runtime: instance.runtime().into(), - // TODO TODO TODO: Avoid hard-coding this NIC! - // - // TODO: also, this same thing is called in sagas.rs. - // When is one used vs the other? nics: vec![], }; diff --git a/omicron-nexus/src/sagas.rs b/omicron-nexus/src/sagas.rs index ebf2a2ccba9..53047a466d0 100644 --- a/omicron-nexus/src/sagas.rs +++ b/omicron-nexus/src/sagas.rs @@ -12,7 +12,6 @@ use crate::saga_interface::SagaContext; use chrono::Utc; use lazy_static::lazy_static; -use omicron_common::api::external; use omicron_common::api::external::Generation; use omicron_common::api::external::InstanceCreateParams; use omicron_common::api::external::InstanceState; @@ -23,7 +22,6 @@ use omicron_common::api::internal::sled_agent::InstanceStateRequested; use serde::Deserialize; use serde::Serialize; use std::collections::BTreeMap; -use std::convert::TryFrom; use std::sync::Arc; use steno::new_action_noop_undo; use steno::ActionContext; @@ -154,23 +152,10 @@ async fn sic_create_instance_record( ) .await .map_err(ActionError::action_failed)?; - Ok(InstanceHardware { - runtime: instance.runtime().into(), - // TODO TODO TODO: Avoid hard-coding! - nics: vec![external::NetworkInterface { - identity: external::IdentityMetadata { - id: Uuid::new_v4(), - name: external::Name::try_from("my-nic".to_string()).unwrap(), - description: "Look a VNIC".to_string(), - time_created: Utc::now(), - time_modified: Utc::now(), - }, - vpc_id: Uuid::new_v4(), - subnet_id: Uuid::new_v4(), - mac: external::MacAddr(macaddr::MacAddr6::new(2, 8, 20, 1, 6, 24)), - ip: std::net::IpAddr::V4(std::net::Ipv4Addr::new(10, 0, 0, 8)), - }], - }) + + // TODO: Populate this with an appropriate NIC. + // See also: instance_set_runtime in nexus.rs for a similar construction. + Ok(InstanceHardware { runtime: instance.runtime().into(), nics: vec![] }) } async fn sic_instance_ensure( From 6bcc2ff0f27a3c2f61cd27950974e2cc4b944109 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Tue, 7 Sep 2021 11:25:48 -0400 Subject: [PATCH 27/28] Plumb VLAN tagging through API --- omicron-sled-agent/src/bin/sled-agent.rs | 7 +++- omicron-sled-agent/src/common/mod.rs | 1 + omicron-sled-agent/src/common/vlan.rs | 41 ++++++++++++++++++++++ omicron-sled-agent/src/config.rs | 7 ++-- omicron-sled-agent/src/illumos/dladm.rs | 16 +++++++-- omicron-sled-agent/src/instance.rs | 37 ++++++++++++++----- omicron-sled-agent/src/instance_manager.rs | 13 ++++--- omicron-sled-agent/src/server.rs | 10 ++++-- omicron-sled-agent/src/sled_agent.rs | 4 ++- 9 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 omicron-sled-agent/src/common/vlan.rs diff --git a/omicron-sled-agent/src/bin/sled-agent.rs b/omicron-sled-agent/src/bin/sled-agent.rs index 101aa5ad096..2df5f8381ab 100644 --- a/omicron-sled-agent/src/bin/sled-agent.rs +++ b/omicron-sled-agent/src/bin/sled-agent.rs @@ -5,6 +5,7 @@ use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use omicron_common::cmd::fatal; use omicron_common::cmd::CmdError; +use omicron_sled_agent::common::vlan::VlanID; use omicron_sled_agent::config::Config; use omicron_sled_agent::server::{run_openapi, run_server}; use std::net::SocketAddr; @@ -29,6 +30,9 @@ enum Args { #[structopt(name = "NEXUS_IP:PORT", parse(try_from_str))] nexus_addr: SocketAddr, + + #[structopt(long = "vlan")] + vlan: Option, }, } @@ -46,7 +50,7 @@ async fn do_run() -> Result<(), CmdError> { match args { Args::OpenApi => run_openapi().map_err(CmdError::Failure), - Args::Run { uuid, sled_agent_addr, nexus_addr } => { + Args::Run { uuid, sled_agent_addr, nexus_addr, vlan } => { let config = Config { id: uuid, nexus_address: nexus_addr, @@ -57,6 +61,7 @@ async fn do_run() -> Result<(), CmdError> { log: ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info, }, + vlan, }; run_server(&config).await.map_err(CmdError::Failure) } diff --git a/omicron-sled-agent/src/common/mod.rs b/omicron-sled-agent/src/common/mod.rs index 3834c63549d..a419e2329c1 100644 --- a/omicron-sled-agent/src/common/mod.rs +++ b/omicron-sled-agent/src/common/mod.rs @@ -2,3 +2,4 @@ pub mod disk; pub mod instance; +pub mod vlan; diff --git a/omicron-sled-agent/src/common/vlan.rs b/omicron-sled-agent/src/common/vlan.rs new file mode 100644 index 00000000000..49db81bbe70 --- /dev/null +++ b/omicron-sled-agent/src/common/vlan.rs @@ -0,0 +1,41 @@ +//! VLAN ID wrapper. + +use omicron_common::api::external::Error; +use std::fmt; +use std::str::FromStr; + +/// The maximum VLAN value (inclusive), as specified by IEEE 802.1Q. +pub const VLAN_MAX: u16 = 4094; + +/// Wrapper around a VLAN ID, ensuring it is valid. +#[derive(Debug, Clone, Copy)] +pub struct VlanID(u16); + +impl VlanID { + /// Creates a new VLAN ID, returning an error if it is out of range. + pub fn new(id: u16) -> Result { + if VLAN_MAX < id { + return Err(Error::InvalidValue { + label: id.to_string(), + message: "Invalid VLAN value".to_string(), + }); + } + Ok(Self(id)) + } +} + +impl fmt::Display for VlanID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0.to_string()) + } +} + +impl FromStr for VlanID { + type Err = Error; + fn from_str(s: &str) -> Result { + Self::new(s.parse().map_err(|e| Error::InvalidValue { + label: s.to_string(), + message: format!("{}", e), + })?) + } +} diff --git a/omicron-sled-agent/src/config.rs b/omicron-sled-agent/src/config.rs index b3e5e9f4775..3ae08e50ef2 100644 --- a/omicron-sled-agent/src/config.rs +++ b/omicron-sled-agent/src/config.rs @@ -1,14 +1,13 @@ //! Interfaces for working with sled agent configuration +use crate::common::vlan::VlanID; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; -use serde::Deserialize; -use serde::Serialize; use std::net::SocketAddr; use uuid::Uuid; /// Configuration for a sled agent -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug)] pub struct Config { /// Unique id for the sled pub id: Uuid, @@ -18,4 +17,6 @@ pub struct Config { pub dropshot: ConfigDropshot, /// Configuration for the sled agent debug log pub log: ConfigLogging, + /// Optional VLAN ID to be used for tagging guest VNICs. + pub vlan: Option, } diff --git a/omicron-sled-agent/src/illumos/dladm.rs b/omicron-sled-agent/src/illumos/dladm.rs index fe6562ab972..8e91319ed9d 100644 --- a/omicron-sled-agent/src/illumos/dladm.rs +++ b/omicron-sled-agent/src/illumos/dladm.rs @@ -1,15 +1,15 @@ //! Utilities for poking at data links. +use crate::common::vlan::VlanID; use crate::illumos::{execute, PFEXEC}; use omicron_common::api::external::Error; use omicron_common::api::external::MacAddr; pub const VNIC_PREFIX: &str = "vnic_propolis"; - pub const DLADM: &str = "/usr/sbin/dladm"; /// The name of a physical datalink. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PhysicalLink(pub String); /// Wraps commands for interacting with data links. @@ -40,10 +40,17 @@ impl Dladm { } /// Creates a new VNIC atop a physical device. + /// + /// * `physical`: The physical link on top of which a device will be + /// created. + /// * `vnic_name`: Exact name of the VNIC to be created. + /// * `mac`: An optional unicast MAC address for the newly created NIC. + /// * `vlan`: An optional VLAN ID for VLAN tagging. pub fn create_vnic( physical: &PhysicalLink, vnic_name: &str, mac: Option, + vlan: Option, ) -> Result<(), Error> { let mut command = std::process::Command::new(PFEXEC); let mut args = vec![ @@ -59,6 +66,11 @@ impl Dladm { args.push(mac.0.to_string()); } + if let Some(vlan) = vlan { + args.push("-v".to_string()); + args.push(vlan.to_string()); + } + args.push(vnic_name.to_string()); let cmd = command.args(&args); execute(cmd)?; diff --git a/omicron-sled-agent/src/instance.rs b/omicron-sled-agent/src/instance.rs index 9052a21d4e5..f15aa62df77 100644 --- a/omicron-sled-agent/src/instance.rs +++ b/omicron-sled-agent/src/instance.rs @@ -1,6 +1,9 @@ //! API for controlling a single instance. -use crate::common::instance::{Action as InstanceAction, InstanceStates}; +use crate::common::{ + instance::{Action as InstanceAction, InstanceStates}, + vlan::VlanID, +}; use crate::illumos::svc::wait_for_service; use crate::illumos::{ dladm::{PhysicalLink, VNIC_PREFIX}, @@ -154,9 +157,10 @@ impl Vnic { allocator: &IdAllocator, physical_dl: &PhysicalLink, mac: Option, + vlan: Option, ) -> Result { let name = guest_vnic_name(allocator.next()); - Dladm::create_vnic(physical_dl, &name, mac)?; + Dladm::create_vnic(physical_dl, &name, mac, vlan)?; Ok(Vnic { name, deleted: false }) } @@ -168,7 +172,7 @@ impl Vnic { mac: Option, ) -> Result { let name = vnic_name(allocator.next()); - Dladm::create_vnic(physical_dl, &name, mac)?; + Dladm::create_vnic(physical_dl, &name, mac, None)?; Ok(Vnic { name, deleted: false }) } @@ -191,13 +195,22 @@ impl Drop for Vnic { struct InstanceInner { log: Logger, - nic_id_allocator: IdAllocator, + + // Properties visible to Propolis properties: propolis_client::api::InstanceProperties, + + // NIC-related properties + nic_id_allocator: IdAllocator, requested_nics: Vec, allocated_nics: Vec, + vlan: Option, + + // Internal State management state: InstanceStates, - nexus_client: Arc, running_state: Option, + + // Connection to Nexus + nexus_client: Arc, } impl InstanceInner { @@ -323,6 +336,7 @@ mockall::mock! { id: Uuid, nic_id_allocator: IdAllocator, initial: InstanceHardware, + vlan: Option, nexus_client: Arc, ) -> Result; pub async fn start(&self, ticket: InstanceTicket) -> Result<(), Error>; @@ -347,17 +361,19 @@ impl Instance { /// lengths, otherwise the UUID would be used instead). /// * `initial`: State of the instance at initialization time. /// * `nexus_client`: Connection to Nexus, used for sending notifications. + /// * `vlan`: An optional VLAN ID for tagging guest VNICs. + // TODO: This arg list is getting a little long; can we clean this up? pub fn new( log: Logger, id: Uuid, nic_id_allocator: IdAllocator, initial: InstanceHardware, + vlan: Option, nexus_client: Arc, ) -> Result { info!(log, "Instance::new w/initial HW: {:?}", initial); let instance = InstanceInner { log: log.new(o!("instance id" => id.to_string())), - nic_id_allocator, // NOTE: Mostly lies. properties: propolis_client::api::InstanceProperties { id, @@ -371,11 +387,13 @@ impl Instance { // InstanceCpuCount here, to avoid any casting... vcpus: initial.runtime.ncpus.0 as u8, }, + nic_id_allocator, requested_nics: initial.nics, allocated_nics: vec![], + vlan, state: InstanceStates::new(initial.runtime), - nexus_client, running_state: None, + nexus_client, }; let inner = Arc::new(Mutex::new(instance)); @@ -416,6 +434,7 @@ impl Instance { &inner.nic_id_allocator, &physical_dl, Some(nic.mac), + inner.vlan, ) }) .collect::, Error>>()?; @@ -812,7 +831,7 @@ mod test { .expect() .times(1) .in_sequence(&mut seq) - .returning(|phys, vnic, _maybe_mac| { + .returning(|phys, vnic, _maybe_mac, _maybe_vlan| { assert_eq!(phys.0, "physical"); assert_eq!(vnic, vnic_name(0)); Ok(()) @@ -997,6 +1016,7 @@ mod test { test_uuid(), nic_id_allocator, new_initial_instance(), + None, Arc::new(nexus_client), ) .unwrap(); @@ -1051,6 +1071,7 @@ mod test { test_uuid(), nic_id_allocator, new_initial_instance(), + None, Arc::new(nexus_client), ) .unwrap(); diff --git a/omicron-sled-agent/src/instance_manager.rs b/omicron-sled-agent/src/instance_manager.rs index 8af94477943..0f7be0f8cf6 100644 --- a/omicron-sled-agent/src/instance_manager.rs +++ b/omicron-sled-agent/src/instance_manager.rs @@ -1,5 +1,6 @@ //! API for controlling multiple instances on a sled. +use crate::common::vlan::VlanID; use crate::illumos::zfs::ZONE_ZFS_DATASET; use omicron_common::api::external::Error; use omicron_common::api::internal::nexus::InstanceRuntimeState; @@ -58,6 +59,7 @@ struct InstanceManagerInternal { // if the Propolis client hasn't been initialized. instances: Mutex>, + vlan: Option, nic_id_allocator: IdAllocator, } @@ -70,6 +72,7 @@ impl InstanceManager { /// Initializes a new [`InstanceManager`] object. pub fn new( log: Logger, + vlan: Option, nexus_client: Arc, ) -> Result { // Before we start creating instances, we need to ensure that the @@ -109,6 +112,7 @@ impl InstanceManager { log, nexus_client, instances: Mutex::new(BTreeMap::new()), + vlan, nic_id_allocator: IdAllocator::new(), }), }) @@ -148,6 +152,7 @@ impl InstanceManager { instance_id, self.inner.nic_id_allocator.clone(), initial_hardware, + self.inner.vlan, self.inner.nexus_client.clone(), )?, ); @@ -277,7 +282,7 @@ mod test { let dladm_get_vnics_ctx = MockDladm::get_vnics_context(); dladm_get_vnics_ctx.expect().return_once(|| Ok(vec![])); - let im = InstanceManager::new(log, nexus_client).unwrap(); + let im = InstanceManager::new(log, None, nexus_client).unwrap(); // Verify that no instances exist. assert!(im.inner.instances.lock().unwrap().is_empty()); @@ -294,7 +299,7 @@ mod test { let ticket = Arc::new(std::sync::Mutex::new(None)); let ticket_clone = ticket.clone(); let instance_new_ctx = MockInstance::new_context(); - instance_new_ctx.expect().return_once(move |_, _, _, _, _| { + instance_new_ctx.expect().return_once(move |_, _, _, _, _, _| { let mut inst = MockInstance::default(); inst.expect_clone().return_once(move || { let mut inst = MockInstance::default(); @@ -359,13 +364,13 @@ mod test { let dladm_get_vnics_ctx = MockDladm::get_vnics_context(); dladm_get_vnics_ctx.expect().return_once(|| Ok(vec![])); - let im = InstanceManager::new(log, nexus_client).unwrap(); + let im = InstanceManager::new(log, None, nexus_client).unwrap(); let ticket = Arc::new(std::sync::Mutex::new(None)); let ticket_clone = ticket.clone(); let instance_new_ctx = MockInstance::new_context(); let mut seq = mockall::Sequence::new(); - instance_new_ctx.expect().return_once(move |_, _, _, _, _| { + instance_new_ctx.expect().return_once(move |_, _, _, _, _, _| { let mut inst = MockInstance::default(); // First call to ensure (start + transition). inst.expect_clone().times(1).in_sequence(&mut seq).return_once( diff --git a/omicron-sled-agent/src/server.rs b/omicron-sled-agent/src/server.rs index 71ff3949fc0..b670f34caf5 100644 --- a/omicron-sled-agent/src/server.rs +++ b/omicron-sled-agent/src/server.rs @@ -39,9 +39,13 @@ impl Server { "component" => "SledAgent", "server" => config.id.clone().to_string() )); - let sled_agent = - SledAgent::new(&config.id, sa_log, nexus_client.clone()) - .map_err(|e| e.to_string())?; + let sled_agent = SledAgent::new( + &config.id, + sa_log, + config.vlan, + nexus_client.clone(), + ) + .map_err(|e| e.to_string())?; let dropshot_log = log.new(o!("component" => "dropshot")); let http_server = dropshot::HttpServerStarter::new( diff --git a/omicron-sled-agent/src/sled_agent.rs b/omicron-sled-agent/src/sled_agent.rs index 30967eabfb1..f19056512d5 100644 --- a/omicron-sled-agent/src/sled_agent.rs +++ b/omicron-sled-agent/src/sled_agent.rs @@ -17,6 +17,7 @@ use crate::mocks::MockNexusClient as NexusClient; #[cfg(not(test))] use omicron_common::NexusClient; +use crate::common::vlan::VlanID; use crate::instance_manager::InstanceManager; /// Describes an executing Sled Agent object. @@ -31,12 +32,13 @@ impl SledAgent { pub fn new( id: &Uuid, log: Logger, + vlan: Option, nexus_client: Arc, ) -> Result { info!(&log, "created sled agent"; "id" => ?id); Ok(SledAgent { - instances: InstanceManager::new(log.clone(), nexus_client)?, + instances: InstanceManager::new(log.clone(), vlan, nexus_client)?, }) } From 772c4da8cbb3775491eb2a61b76f0ac384eb45da Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Tue, 7 Sep 2021 14:24:45 -0400 Subject: [PATCH 28/28] uprev propolis version --- Cargo.lock | 475 +++++++++++++++++----------------- omicron-common/Cargo.toml | 2 +- omicron-sled-agent/Cargo.toml | 2 +- 3 files changed, 241 insertions(+), 238 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 968a7bece93..2cab2ab5c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" [[package]] name = "api_identity" @@ -64,7 +64,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "winapi", ] @@ -110,17 +110,17 @@ dependencies = [ [[package]] name = "bhyve_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "num_enum", ] [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -172,18 +172,18 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.68" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" [[package]] name = "cfg-if" @@ -197,7 +197,7 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer", "num-traits", "serde", @@ -227,7 +227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -238,11 +238,11 @@ checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "cpufeatures" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -291,9 +291,9 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" dependencies = [ "generic-array 0.14.4", "subtle", @@ -356,7 +356,7 @@ dependencies = [ "diesel_derives", "ipnetwork", "itoa", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "pq-sys", "r2d2", "serde_json", @@ -413,7 +413,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users", "winapi", ] @@ -421,9 +421,9 @@ dependencies = [ [[package]] name = "dladm" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "num_enum", ] @@ -446,7 +446,7 @@ checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d" [[package]] name = "dropshot" version = "0.5.2-dev" -source = "git+https://github.com/oxidecomputer/dropshot?branch=main#1c6f4d156c670edc6476ca5bcdffc33a7001cbc7" +source = "git+https://github.com/oxidecomputer/dropshot?branch=main#28b04efe999fc6344c39d70225885a86b2de49e2" dependencies = [ "async-trait", "base64", @@ -480,7 +480,7 @@ dependencies = [ [[package]] name = "dropshot_endpoint" version = "0.5.2-dev" -source = "git+https://github.com/oxidecomputer/dropshot?branch=main#1c6f4d156c670edc6476ca5bcdffc33a7001cbc7" +source = "git+https://github.com/oxidecomputer/dropshot?branch=main#28b04efe999fc6344c39d70225885a86b2de49e2" dependencies = [ "proc-macro2", "quote", @@ -551,12 +551,12 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "filetime" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ "cfg-if", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall", "winapi", ] @@ -615,9 +615,9 @@ checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" [[package]] name = "futures" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" dependencies = [ "futures-channel", "futures-core", @@ -630,9 +630,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" +checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" dependencies = [ "futures-core", "futures-sink", @@ -640,15 +640,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" dependencies = [ "futures-core", "futures-task", @@ -657,15 +657,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" +checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" [[package]] name = "futures-macro" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" +checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg", "proc-macro-hack", @@ -676,21 +676,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" +checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" dependencies = [ "autocfg", "futures-channel", @@ -733,7 +733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "wasi", ] @@ -745,9 +745,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" +checksum = "d7f3675cfef6a30c8031cf9e6493ebdc3bb3272a3fea3923c4210d1830e6a472" dependencies = [ "bytes", "fnv", @@ -764,9 +764,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "heck" @@ -779,11 +779,11 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -802,7 +802,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "match_cfg", "winapi", ] @@ -820,9 +820,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" dependencies = [ "bytes", "http", @@ -831,9 +831,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" @@ -843,9 +843,9 @@ checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" [[package]] name = "hyper" -version = "0.14.10" +version = "0.14.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03" +checksum = "13f67199e765030fa08fe0bd581af683f0d5bc04ea09c2b1102012c5fb90e7fd" dependencies = [ "bytes", "futures-channel", @@ -912,9 +912,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", "hashbrown", @@ -932,9 +932,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ "cfg-if", ] @@ -968,15 +968,15 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d" dependencies = [ "wasm-bindgen", ] @@ -989,9 +989,14 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.101" +source = "git+https://github.com/rust-lang/libc.git?rev=796459785#796459785e5190a02fdf7c223fc8aa91d04306f7" + +[[package]] +name = "libc" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] name = "linked-hash-map" @@ -1001,9 +1006,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -1040,9 +1045,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "md-5" @@ -1057,9 +1062,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" @@ -1078,11 +1083,11 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "log", "miow", "ntapi", @@ -1127,12 +1132,12 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "log", "openssl", "openssl-probe", @@ -1199,14 +1204,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_enum" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066" +checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" dependencies = [ "derivative", "num_enum_derive", @@ -1214,9 +1219,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" +checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1260,7 +1265,7 @@ dependencies = [ "http", "hyper", "ipnet", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "macaddr", "postgres-protocol", "propolis-server", @@ -1307,7 +1312,7 @@ dependencies = [ "hyper", "ipnetwork", "lazy_static", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "macaddr", "newtype_derive", "omicron-common", @@ -1361,9 +1366,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "opaque-debug" @@ -1380,7 +1385,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openapi-lint" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/openapi-lint?branch=main#cbf584bac7a0eefae46ffc4a0f75bd3c680775f4" +source = "git+https://github.com/oxidecomputer/openapi-lint?branch=main#ca2947b52139b58a3f07cfb17f2257b3ebd50b63" dependencies = [ "indexmap", "openapiv3", @@ -1400,14 +1405,14 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.34" +version = "0.10.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8" +checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" dependencies = [ "bitflags", "cfg-if", "foreign-types", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell", "openssl-sys", ] @@ -1420,13 +1425,13 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.63" +version = "0.9.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98" +checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" dependencies = [ "autocfg", "cc", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config", "vcpkg", ] @@ -1470,9 +1475,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -1481,13 +1486,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall", "smallvec", "winapi", @@ -1578,18 +1583,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ "proc-macro2", "quote", @@ -1598,9 +1603,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pin-utils" @@ -1683,9 +1688,9 @@ checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" [[package]] name = "predicates-tree" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2" +checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d" dependencies = [ "predicates-core", "treeline", @@ -1693,10 +1698,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92" dependencies = [ + "thiserror", "toml", ] @@ -1738,9 +1744,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" dependencies = [ "unicode-xid", ] @@ -1748,14 +1754,14 @@ dependencies = [ [[package]] name = "propolis" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" dependencies = [ "bhyve_api", "bitflags", "byteorder", "dladm", "lazy_static", - "libc", + "libc 0.2.101 (git+https://github.com/rust-lang/libc.git?rev=796459785)", "num_enum", "thiserror", "usdt", @@ -1765,7 +1771,7 @@ dependencies = [ [[package]] name = "propolis-client" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" dependencies = [ "reqwest", "ring", @@ -1781,7 +1787,7 @@ dependencies = [ [[package]] name = "propolis-server" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" dependencies = [ "anyhow", "dropshot", @@ -1822,11 +1828,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha", "rand_core", "rand_hc", @@ -1834,9 +1840,9 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -1844,18 +1850,18 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] [[package]] name = "rand_hc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ "rand_core", ] @@ -1887,9 +1893,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -1976,7 +1982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell", "spin", "untrusted", @@ -2091,25 +2097,25 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.3.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" +checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "2.3.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" +checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" dependencies = [ "core-foundation-sys", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2120,18 +2126,18 @@ checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" [[package]] name = "serde" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -2151,9 +2157,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950" dependencies = [ "itoa", "ryu", @@ -2185,9 +2191,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.9.4" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad9fdbb69badc8916db738c25efd04f0a65297d26c2f8de4b62e57b8c12bc72" +checksum = "062b87e45d8f26714eacfaef0ed9a583e2bfd50ebd96bdd3c200733bd5758e2c" dependencies = [ "rustversion", "serde", @@ -2196,9 +2202,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1569374bd54623ec8bd592cf22ba6e03c0f177ff55fbc8c29a49e296e7adecf" +checksum = "98c1fcca18d55d1763e1c16873c4bde0ac3ef75179a28c7b372917e0494625be" dependencies = [ "darling", "proc-macro2", @@ -2208,12 +2214,12 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.17" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +checksum = "ad104641f3c958dab30eb3010e834c2622d1f3f4c530fef1dee20ad9485f3c09" dependencies = [ "dtoa", - "linked-hash-map", + "indexmap", "serde", "yaml-rust", ] @@ -2254,9 +2260,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", "cfg-if", @@ -2267,9 +2273,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3" dependencies = [ "block-buffer 0.9.0", "cfg-if", @@ -2280,11 +2286,11 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" +checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry", ] @@ -2294,7 +2300,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2304,22 +2310,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6c5d32165ff8b94e68e7b3bdecb1b082e958c22434b363482cfb89dcd6f3ff8" dependencies = [ "futures-core", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook", "tokio", ] [[package]] name = "siphasher" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" [[package]] name = "slab" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" [[package]] name = "slog" @@ -2329,9 +2335,9 @@ checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" [[package]] name = "slog-async" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c60813879f820c85dbc4eabf3269befe374591289019775898d56a81a804fbdc" +checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe" dependencies = [ "crossbeam-channel", "slog", @@ -2353,9 +2359,9 @@ dependencies = [ [[package]] name = "slog-json" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" +checksum = "52e9b96fb6b5e80e371423b4aca6656eb537661ce8f82c2697e619f8ca85d043" dependencies = [ "chrono", "serde", @@ -2393,11 +2399,11 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "winapi", ] @@ -2451,9 +2457,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71" +checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" dependencies = [ "clap", "lazy_static", @@ -2462,9 +2468,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10" +checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" dependencies = [ "heck", "proc-macro-error", @@ -2479,21 +2485,21 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "334b801f9ca2529ba9605109f1d2835f15aff94cd6cfe5afe6ce8cf71e5fd3c4" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "winapi", ] [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" dependencies = [ "proc-macro2", "quote", @@ -2502,9 +2508,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" dependencies = [ "proc-macro2", "quote", @@ -2520,12 +2526,12 @@ checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" [[package]] name = "tar" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80" +checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" dependencies = [ "filetime", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "xattr", ] @@ -2536,7 +2542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "rand", "redox_syscall", "remove_dir_all", @@ -2574,18 +2580,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" dependencies = [ "proc-macro2", "quote", @@ -2607,16 +2613,16 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "wasi", "winapi", ] [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" dependencies = [ "tinyvec_macros", ] @@ -2629,13 +2635,13 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" +checksum = "b4efe6fc2395938c8155973d7be49fe8d03a843726e285e100a8a383cc0154ce" dependencies = [ "autocfg", "bytes", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "memchr", "mio", "num_cpus", @@ -2649,9 +2655,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37" +checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" dependencies = [ "proc-macro2", "quote", @@ -2717,9 +2723,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" +checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" dependencies = [ "bytes", "futures-core", @@ -2757,9 +2763,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" dependencies = [ "lazy_static", ] @@ -2778,9 +2784,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "trybuild" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb73edd97c8d9ffa8140971f07307f0994ae95138ee9cc0fba0369c953f0963a" +checksum = "5bdaf2a1d317f3d58b44b31c7f6436b9b9acafe7bddfeace50897c2b804d7792" dependencies = [ "glob", "lazy_static", @@ -2804,7 +2810,7 @@ dependencies = [ "input_buffer", "log", "rand", - "sha-1 0.9.6", + "sha-1 0.9.8", "thiserror", "url", "utf-8", @@ -2812,9 +2818,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "ucd-trie" @@ -2824,12 +2830,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" [[package]] name = "unicode-normalization" @@ -2842,9 +2845,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" @@ -2896,7 +2899,7 @@ dependencies = [ "byteorder", "dof", "dtrace-parser", - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", "quote", "serde", @@ -2936,9 +2939,9 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vec_map" @@ -2955,7 +2958,7 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "viona_api" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/propolis?rev=a0d1abc2#a0d1abc293accedcaae556a68af62e329516a7f0" +source = "git+https://github.com/oxidecomputer/propolis?rev=bc0661e#bc0661eb0d0c9365bbb69450f3033baabc5b3945" [[package]] name = "walkdir" @@ -2986,9 +2989,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0" dependencies = [ "cfg-if", "serde", @@ -2998,9 +3001,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041" dependencies = [ "bumpalo", "lazy_static", @@ -3013,9 +3016,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" +checksum = "95fded345a6559c2cfee778d562300c581f7d4ff3edb9b0d230d69800d213972" dependencies = [ "cfg-if", "js-sys", @@ -3025,9 +3028,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3035,9 +3038,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad" dependencies = [ "proc-macro2", "quote", @@ -3048,15 +3051,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c" dependencies = [ "js-sys", "wasm-bindgen", @@ -3127,7 +3130,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" dependencies = [ - "libc", + "libc 0.2.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3162,9 +3165,9 @@ dependencies = [ [[package]] name = "zone" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f308411d82ac9426366a91b6a6169aa43e3cacdd108a18e4a7522d9ecd4693" +checksum = "3596bbc963cd9dbaa69b02e349af4d061c56c41d211ba64150a2cedb2f722707" dependencies = [ "itertools", "thiserror", diff --git a/omicron-common/Cargo.toml b/omicron-common/Cargo.toml index b342fd6e5da..68aa7574f31 100644 --- a/omicron-common/Cargo.toml +++ b/omicron-common/Cargo.toml @@ -12,7 +12,7 @@ futures = "0.3.15" http = "0.2.0" hyper = "0.14" libc = "0.2.98" -propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "a0d1abc2" } +propolis-server = { git = "https://github.com/oxidecomputer/propolis", rev = "bc0661e" } postgres-protocol = "0.6.1" rayon = "1.5" reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } diff --git a/omicron-sled-agent/Cargo.toml b/omicron-sled-agent/Cargo.toml index 87e2e906cd5..d870170ddf7 100644 --- a/omicron-sled-agent/Cargo.toml +++ b/omicron-sled-agent/Cargo.toml @@ -13,7 +13,7 @@ http = "0.2.0" hyper = "0.14" ipnet = "2.3" omicron-common = { path = "../omicron-common" } -propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "a0d1abc2" } +propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "bc0661e" } schemars = { version = "0.8", features = [ "chrono", "uuid" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0"