Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nexus] Silo IP pools #3985

Merged
merged 17 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ sha3 = "0.10.8"
shell-words = "1.1.0"
signal-hook = "0.3"
signal-hook-tokio = { version = "0.3", features = [ "futures-v0_3" ] }
similar-asserts = "1.5.0"
sled = "0.34"
sled-agent-client = { path = "sled-agent-client" }
sled-hardware = { path = "sled-hardware" }
Expand Down
1 change: 1 addition & 0 deletions nexus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ petgraph.workspace = true
pretty_assertions.workspace = true
rcgen.workspace = true
regex.workspace = true
similar-asserts.workspace = true
rustls = { workspace = true }
subprocess.workspace = true
term.workspace = true
Expand Down
29 changes: 11 additions & 18 deletions nexus/db-model/src/ip_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,48 +32,41 @@ pub struct IpPool {
#[diesel(embed)]
pub identity: IpPoolIdentity,

/// If true, identifies that this IP pool is dedicated to "Control-Plane
/// Services", such as Nexus.
///
/// Otherwise, this IP pool is intended for usage by customer VMs.
pub internal: bool,

/// Child resource generation number, for optimistic concurrency control of
/// the contained ranges.
pub rcgen: i64,

/// Silo, if IP pool is associated with a particular silo. Must be null
/// if internal is true. Must be non-null if project_id is non-null. When
/// project_id is non-null, silo_id will (naturally) be the ID of the
/// project's silo.
/// Silo, if IP pool is associated with a particular silo. One special use
/// for this is associating a pool with the internal silo oxide-internal,
/// which is used for internal services. If there is no silo ID, the
/// pool is considered a fleet-wide pool and will be used for allocating
/// instance IPs in silos that don't have their own pool.
pub silo_id: Option<Uuid>,

/// Project, if IP pool is associated with a particular project. Must be
/// null if internal is true.
pub project_id: Option<Uuid>,
pub is_default: bool,
}

impl IpPool {
pub fn new(
pool_identity: &external::IdentityMetadataCreateParams,
internal: bool,
silo_id: Option<Uuid>,
is_default: bool,
) -> Self {
Self {
identity: IpPoolIdentity::new(
Uuid::new_v4(),
pool_identity.clone(),
),
internal,
rcgen: 0,
silo_id: None,
project_id: None,
silo_id,
is_default,
}
}
}

impl From<IpPool> for views::IpPool {
fn from(pool: IpPool) -> Self {
Self { identity: pool.identity() }
Self { identity: pool.identity(), silo_id: pool.silo_id }
}
}

Expand Down
5 changes: 2 additions & 3 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,9 @@ table! {
time_created -> Timestamptz,
time_modified -> Timestamptz,
time_deleted -> Nullable<Timestamptz>,
internal -> Bool,
rcgen -> Int8,
silo_id -> Nullable<Uuid>,
project_id -> Nullable<Uuid>,
is_default -> Bool,
}
}

Expand Down Expand Up @@ -1131,7 +1130,7 @@ table! {
///
/// This should be updated whenever the schema is changed. For more details,
/// refer to: schema/crdb/README.adoc
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(3, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(3, 0, 3);

allow_tables_to_appear_in_same_query!(
system_update,
Expand Down
19 changes: 9 additions & 10 deletions nexus/db-queries/src/db/datastore/external_ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//! [`DataStore`] methods on [`ExternalIp`]s.

use super::DataStore;
use crate::authz;
use crate::context::OpContext;
use crate::db;
use crate::db::error::public_error_from_diesel_pool;
Expand All @@ -25,9 +24,7 @@ use nexus_types::identity::Resource;
use omicron_common::api::external::CreateResult;
use omicron_common::api::external::Error;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::Name as ExternalName;
use std::net::IpAddr;
use std::str::FromStr;
use uuid::Uuid;

impl DataStore {
Expand Down Expand Up @@ -55,14 +52,16 @@ impl DataStore {
instance_id: Uuid,
pool_name: Option<Name>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be NameOrId? No need to do it now, just asking...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm pretty sure it could be. I think the main reason it was name only was that the name "default" was significant, and now it isn't.

) -> CreateResult<ExternalIp> {
let name = pool_name.unwrap_or_else(|| {
Name(ExternalName::from_str("default").unwrap())
});
let (.., pool) = self
.ip_pools_fetch_for(opctx, authz::Action::CreateChild, &name)
.await?;
let pool_id = pool.identity.id;
// If we have a pool name, look up the pool by name and return it
// as long as its scopes don't conflict with the current scope.
// Otherwise, not found.
let pool = match pool_name {
Some(name) => self.ip_pools_fetch(&opctx, &name).await?,
// If no name given, use the default logic
None => self.ip_pools_fetch_default(&opctx).await?,
};

let pool_id = pool.identity.id;
let data =
IncompleteExternalIp::for_ephemeral(ip_id, instance_id, pool_id);
self.allocate_external_ip(opctx, data).await
Expand Down
Loading