Skip to content

Commit 049fc0f

Browse files
committed
change internal column to use silo id, add and populate default column
1 parent bd61072 commit 049fc0f

File tree

16 files changed

+196
-140
lines changed

16 files changed

+196
-140
lines changed

Cargo.lock

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ sha3 = "0.10.8"
305305
shell-words = "1.1.0"
306306
signal-hook = "0.3"
307307
signal-hook-tokio = { version = "0.3", features = [ "futures-v0_3" ] }
308+
similar-asserts = "1.5.0"
308309
sled = "0.34"
309310
sled-agent-client = { path = "sled-agent-client" }
310311
sled-hardware = { path = "sled-hardware" }

nexus/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ serde.workspace = true
6868
serde_json.workspace = true
6969
serde_urlencoded.workspace = true
7070
serde_with.workspace = true
71+
similar-asserts.workspace = true
7172
sled-agent-client.workspace = true
7273
slog.workspace = true
7374
slog-async.workspace = true

nexus/db-model/src/ip_pool.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,39 +32,34 @@ pub struct IpPool {
3232
#[diesel(embed)]
3333
pub identity: IpPoolIdentity,
3434

35-
/// If true, identifies that this IP pool is dedicated to "Control-Plane
36-
/// Services", such as Nexus.
37-
///
38-
/// Otherwise, this IP pool is intended for usage by customer VMs.
39-
pub internal: bool,
40-
4135
/// Child resource generation number, for optimistic concurrency control of
4236
/// the contained ranges.
4337
pub rcgen: i64,
4438

45-
/// Silo, if IP pool is associated with a particular silo. Must be null
46-
/// if internal is true. Must be non-null if project_id is non-null. When
47-
/// project_id is non-null, silo_id will (naturally) be the ID of the
39+
/// Silo, if IP pool is associated with a particular silo. One special use
40+
/// for this is associating a pool with the internal silo oxide-internal,
41+
/// which is used for internal services. If there is no silo ID, the
42+
/// pool is considered a fleet-wide silo and will be used for allocating
43+
/// instance IPs in silos that don't have their own pool. Must be non-
44+
/// null if project_id is non-null (this is enforced as a DB constraint).
45+
/// When project_id is non-null, silo_id will (naturally) be the ID of the
4846
/// project's silo.
4947
pub silo_id: Option<Uuid>,
5048

51-
/// Project, if IP pool is associated with a particular project. Must be
52-
/// null if internal is true.
49+
/// Project, if IP pool is associated with a particular project
5350
pub project_id: Option<Uuid>,
5451
}
5552

5653
impl IpPool {
5754
pub fn new(
5855
pool_identity: &external::IdentityMetadataCreateParams,
59-
internal: bool,
6056
silo_id: Option<Uuid>,
6157
) -> Self {
6258
Self {
6359
identity: IpPoolIdentity::new(
6460
Uuid::new_v4(),
6561
pool_identity.clone(),
6662
),
67-
internal,
6863
rcgen: 0,
6964
silo_id,
7065
project_id: None,

nexus/db-model/src/schema.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,6 @@ table! {
452452
time_created -> Timestamptz,
453453
time_modified -> Timestamptz,
454454
time_deleted -> Nullable<Timestamptz>,
455-
internal -> Bool,
456455
rcgen -> Int8,
457456
silo_id -> Nullable<Uuid>,
458457
project_id -> Nullable<Uuid>,
@@ -1131,7 +1130,7 @@ table! {
11311130
///
11321131
/// This should be updated whenever the schema is changed. For more details,
11331132
/// refer to: schema/crdb/README.adoc
1134-
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(3, 0, 0);
1133+
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(3, 0, 2);
11351134

11361135
allow_tables_to_appear_in_same_query!(
11371136
system_update,

nexus/db-queries/src/db/datastore/ip_pool.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::db::collection_insert::DatastoreCollection;
1414
use crate::db::error::diesel_pool_result_optional;
1515
use crate::db::error::public_error_from_diesel_pool;
1616
use crate::db::error::ErrorHandler;
17+
use crate::db::fixed_data::silo::INTERNAL_SILO_ID;
1718
use crate::db::identity::Resource;
1819
use crate::db::lookup::LookupPath;
1920
use crate::db::model::IpPool;
@@ -27,7 +28,6 @@ use async_bb8_diesel::{AsyncRunQueryDsl, PoolError};
2728
use chrono::Utc;
2829
use diesel::prelude::*;
2930
use ipnetwork::IpNetwork;
30-
use nexus_types::external_api::params;
3131
use nexus_types::external_api::shared::IpRange;
3232
use omicron_common::api::external::http_pagination::PaginatedBy;
3333
use omicron_common::api::external::CreateResult;
@@ -65,7 +65,8 @@ impl DataStore {
6565
&pagparams.map_name(|n| Name::ref_cast(n)),
6666
),
6767
}
68-
.filter(dsl::internal.eq(false))
68+
// != excludes nulls so we explicitly include them
69+
.filter(dsl::silo_id.ne(*INTERNAL_SILO_ID).or(dsl::silo_id.is_null()))
6970
.filter(dsl::time_deleted.is_null())
7071
.select(db::model::IpPool::as_select())
7172
.get_results_async(self.pool_authorized(opctx).await?)
@@ -98,7 +99,8 @@ impl DataStore {
9899
.ip_pool_name(&name)
99100
.fetch_for(action)
100101
.await?;
101-
if pool.internal {
102+
// Can't look up the internal pool
103+
if pool.silo_id == Some(*INTERNAL_SILO_ID) {
102104
return Err(authz_pool.not_found());
103105
}
104106

@@ -120,7 +122,7 @@ impl DataStore {
120122

121123
// Look up this IP pool by rack ID.
122124
let (authz_pool, pool) = dsl::ip_pool
123-
.filter(dsl::internal.eq(true))
125+
.filter(dsl::silo_id.eq(*INTERNAL_SILO_ID))
124126
.filter(dsl::time_deleted.is_null())
125127
.select(IpPool::as_select())
126128
.get_result_async(self.pool_authorized(opctx).await?)
@@ -142,20 +144,15 @@ impl DataStore {
142144
}
143145

144146
/// Creates a new IP pool.
145-
///
146-
/// - If `internal` is set, this IP pool is used for Oxide services.
147147
pub async fn ip_pool_create(
148148
&self,
149149
opctx: &OpContext,
150-
new_pool: &params::IpPoolCreate,
151-
internal: bool,
152-
silo_id: Option<Uuid>,
150+
pool: IpPool,
153151
) -> CreateResult<IpPool> {
154152
use db::schema::ip_pool::dsl;
155153
opctx
156154
.authorize(authz::Action::CreateChild, &authz::IP_POOL_LIST)
157155
.await?;
158-
let pool = IpPool::new(&new_pool.identity, internal, silo_id);
159156
let pool_name = pool.name().as_str().to_string();
160157

161158
diesel::insert_into(dsl::ip_pool)
@@ -205,7 +202,10 @@ impl DataStore {
205202
// in between the above check for children and this query.
206203
let now = Utc::now();
207204
let updated_rows = diesel::update(dsl::ip_pool)
208-
.filter(dsl::internal.eq(false))
205+
// != excludes nulls so we explicitly include them
206+
.filter(
207+
dsl::silo_id.ne(*INTERNAL_SILO_ID).or(dsl::silo_id.is_null()),
208+
)
209209
.filter(dsl::time_deleted.is_null())
210210
.filter(dsl::id.eq(authz_pool.id()))
211211
.filter(dsl::rcgen.eq(db_pool.rcgen))
@@ -237,7 +237,10 @@ impl DataStore {
237237
use db::schema::ip_pool::dsl;
238238
opctx.authorize(authz::Action::Modify, authz_pool).await?;
239239
diesel::update(dsl::ip_pool)
240-
.filter(dsl::internal.eq(false))
240+
// != excludes nulls so we explicitly include them
241+
.filter(
242+
dsl::silo_id.ne(*INTERNAL_SILO_ID).or(dsl::silo_id.is_null()),
243+
)
241244
.filter(dsl::id.eq(authz_pool.id()))
242245
.filter(dsl::time_deleted.is_null())
243246
.set(updates)

nexus/db-queries/src/db/datastore/project.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,8 @@ impl DataStore {
351351
}
352352
// TODO(2148, 2056): filter only pools accessible by the given
353353
// project, once specific projects for pools are implemented
354-
.filter(dsl::internal.eq(false))
354+
// != excludes nulls so we explicitly include them
355+
.filter(dsl::silo_id.ne(*INTERNAL_SILO_ID).or(dsl::silo_id.is_null()))
355356
.filter(dsl::time_deleted.is_null())
356357
.select(db::model::IpPool::as_select())
357358
.get_results_async(self.pool_authorized(opctx).await?)

nexus/db-queries/src/db/datastore/rack.rs

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::db::collection_insert::DatastoreCollection;
1515
use crate::db::error::public_error_from_diesel_pool;
1616
use crate::db::error::ErrorHandler;
1717
use crate::db::error::TransactionError;
18+
use crate::db::fixed_data::silo::INTERNAL_SILO_ID;
1819
use crate::db::fixed_data::vpc_subnet::DNS_VPC_SUBNET;
1920
use crate::db::fixed_data::vpc_subnet::NEXUS_VPC_SUBNET;
2021
use crate::db::fixed_data::vpc_subnet::NTP_VPC_SUBNET;
@@ -556,39 +557,34 @@ impl DataStore {
556557

557558
self.rack_insert(opctx, &db::model::Rack::new(rack_id)).await?;
558559

559-
let params = external_params::IpPoolCreate {
560-
identity: IdentityMetadataCreateParams {
560+
let internal_pool = db::model::IpPool::new(
561+
&IdentityMetadataCreateParams {
561562
name: SERVICE_IP_POOL_NAME.parse::<Name>().unwrap(),
562563
description: String::from("IP Pool for Oxide Services"),
563564
},
564-
silo: None,
565-
};
566-
self.ip_pool_create(
567-
opctx, &params, /*internal=*/ true, /*silo_id*/ None,
568-
)
569-
.await
570-
.map(|_| ())
571-
.or_else(|e| match e {
572-
Error::ObjectAlreadyExists { .. } => Ok(()),
573-
_ => Err(e),
574-
})?;
565+
Some(*INTERNAL_SILO_ID),
566+
);
567+
568+
self.ip_pool_create(opctx, internal_pool).await.map(|_| ()).or_else(
569+
|e| match e {
570+
Error::ObjectAlreadyExists { .. } => Ok(()),
571+
_ => Err(e),
572+
},
573+
)?;
575574

576-
let params = external_params::IpPoolCreate {
577-
identity: IdentityMetadataCreateParams {
575+
let default_pool = db::model::IpPool::new(
576+
&IdentityMetadataCreateParams {
578577
name: "default".parse::<Name>().unwrap(),
579578
description: String::from("default IP pool"),
580579
},
581-
silo: None,
582-
};
583-
self.ip_pool_create(
584-
opctx, &params, /*internal=*/ false, /*silo_id*/ None,
585-
)
586-
.await
587-
.map(|_| ())
588-
.or_else(|e| match e {
589-
Error::ObjectAlreadyExists { .. } => Ok(()),
590-
_ => Err(e),
591-
})?;
580+
None, // no silo ID, fleet scoped
581+
);
582+
self.ip_pool_create(opctx, default_pool).await.map(|_| ()).or_else(
583+
|e| match e {
584+
Error::ObjectAlreadyExists { .. } => Ok(()),
585+
_ => Err(e),
586+
},
587+
)?;
592588

593589
Ok(())
594590
}
@@ -1104,7 +1100,7 @@ mod test {
11041100
// been allocated as a part of the service IP pool.
11051101
let (.., svc_pool) =
11061102
datastore.ip_pools_service_lookup(&opctx).await.unwrap();
1107-
assert!(svc_pool.internal);
1103+
assert_eq!(svc_pool.silo_id, Some(*INTERNAL_SILO_ID));
11081104

11091105
let observed_ip_pool_ranges = get_all_ip_pool_ranges(&datastore).await;
11101106
assert_eq!(observed_ip_pool_ranges.len(), 1);
@@ -1306,7 +1302,7 @@ mod test {
13061302
// allocated as a part of the service IP pool.
13071303
let (.., svc_pool) =
13081304
datastore.ip_pools_service_lookup(&opctx).await.unwrap();
1309-
assert!(svc_pool.internal);
1305+
assert_eq!(svc_pool.silo_id, Some(*INTERNAL_SILO_ID));
13101306

13111307
let observed_ip_pool_ranges = get_all_ip_pool_ranges(&datastore).await;
13121308
assert_eq!(observed_ip_pool_ranges.len(), 1);

nexus/db-queries/src/db/queries/external_ip.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ mod tests {
816816
use crate::context::OpContext;
817817
use crate::db::datastore::DataStore;
818818
use crate::db::datastore::SERVICE_IP_POOL_NAME;
819+
use crate::db::fixed_data::silo::INTERNAL_SILO_ID;
819820
use crate::db::identity::Resource;
820821
use crate::db::model::IpKind;
821822
use crate::db::model::IpPool;
@@ -862,14 +863,12 @@ mod tests {
862863
}
863864

864865
async fn create_ip_pool(&self, name: &str, range: IpRange) {
865-
let internal = false;
866866
let pool = IpPool::new(
867867
&IdentityMetadataCreateParams {
868868
name: String::from(name).parse().unwrap(),
869869
description: format!("ip pool {}", name),
870870
},
871-
internal,
872-
None, // silo id
871+
Some(*INTERNAL_SILO_ID),
873872
);
874873

875874
use crate::db::schema::ip_pool::dsl as ip_pool_dsl;

0 commit comments

Comments
 (0)