Skip to content

Commit 0fe3e4d

Browse files
authored
Database support for delegating IP Pools for Oxide internal use (#9103)
- Add database queries for marking any number of IP Pools as delegated for Oxide internal use, rather than assuming there's just one. - Rework queries for linking / unlinking IP Pool and Silo, making them concurrency-safe and preventing deletion when there are IPs or we're trying to delete the last internal IP Pool. - The public API does not change here. We're still assuming exactly one IP Pool per IP version for internal usage, and not allowing the link or pool to appear in the API. That'll be a follow-up commit. - Fixes #8948
1 parent 77bb62f commit 0fe3e4d

File tree

21 files changed

+1766
-349
lines changed

21 files changed

+1766
-349
lines changed

nexus/db-model/src/ip_pool.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,37 @@ use omicron_common::api::external;
2424
use std::net::IpAddr;
2525
use uuid::Uuid;
2626

27+
impl_enum_type!(
28+
IpPoolReservationTypeEnum:
29+
30+
#[derive(
31+
AsExpression,
32+
Clone,
33+
Copy,
34+
Debug,
35+
Eq,
36+
FromSqlRow,
37+
PartialEq,
38+
schemars::JsonSchema,
39+
serde::Deserialize,
40+
serde::Serialize,
41+
)]
42+
pub enum IpPoolReservationType;
43+
44+
ExternalSilos => b"external_silos"
45+
OxideInternal => b"oxide_internal"
46+
);
47+
48+
impl ::std::fmt::Display for IpPoolReservationType {
49+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50+
let s = match self {
51+
IpPoolReservationType::ExternalSilos => "external_silos",
52+
IpPoolReservationType::OxideInternal => "oxide_internal",
53+
};
54+
f.write_str(s)
55+
}
56+
}
57+
2758
impl_enum_type!(
2859
IpVersionEnum:
2960

@@ -77,7 +108,9 @@ impl From<IpVersion> for shared::IpVersion {
77108
/// IP pools can be external or internal. External IP pools can be associated
78109
/// with a silo or project so that instance IP allocation draws from that pool
79110
/// instead of a system pool.
80-
#[derive(Queryable, Insertable, Selectable, Clone, Debug, Resource)]
111+
#[derive(
112+
Queryable, Insertable, Selectable, Clone, Debug, Resource, PartialEq,
113+
)]
81114
#[diesel(table_name = ip_pool)]
82115
pub struct IpPool {
83116
#[diesel(embed)]
@@ -89,12 +122,19 @@ pub struct IpPool {
89122
/// Child resource generation number, for optimistic concurrency control of
90123
/// the contained ranges.
91124
pub rcgen: i64,
125+
126+
/// Indicates what the pool is reserved for.
127+
pub reservation_type: IpPoolReservationType,
92128
}
93129

94130
impl IpPool {
131+
/// Create a new IP Pool.
132+
///
133+
/// The pool is reserved for external customer Silos.
95134
pub fn new(
96135
pool_identity: &external::IdentityMetadataCreateParams,
97136
ip_version: IpVersion,
137+
reservation_type: IpPoolReservationType,
98138
) -> Self {
99139
Self {
100140
identity: IpPoolIdentity::new(
@@ -103,19 +143,24 @@ impl IpPool {
103143
),
104144
ip_version,
105145
rcgen: 0,
146+
reservation_type,
106147
}
107148
}
108149

150+
/// Create a new IPv4 IP Pool.
109151
pub fn new_v4(
110152
pool_identity: &external::IdentityMetadataCreateParams,
153+
reservation_type: IpPoolReservationType,
111154
) -> Self {
112-
Self::new(pool_identity, IpVersion::V4)
155+
Self::new(pool_identity, IpVersion::V4, reservation_type)
113156
}
114157

158+
/// Create a new IPv6 IP Pool.
115159
pub fn new_v6(
116160
pool_identity: &external::IdentityMetadataCreateParams,
161+
reservation_type: IpPoolReservationType,
117162
) -> Self {
118-
Self::new(pool_identity, IpVersion::V6)
163+
Self::new(pool_identity, IpVersion::V6, reservation_type)
119164
}
120165
}
121166

nexus/db-model/src/schema_versions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
1616
///
1717
/// This must be updated when you change the database schema. Refer to
1818
/// schema/crdb/README.adoc in the root of this repository for details.
19-
pub const SCHEMA_VERSION: Version = Version::new(197, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(198, 0, 0);
2020

2121
/// List of all past database schema versions, in *reverse* order
2222
///
@@ -28,6 +28,7 @@ static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
2828
// | leaving the first copy as an example for the next person.
2929
// v
3030
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
31+
KnownVersion::new(198, "add-ip-pool-reservation-type-column"),
3132
KnownVersion::new(197, "scim-users-and-groups"),
3233
KnownVersion::new(196, "user-provision-type-for-silo-user-and-group"),
3334
KnownVersion::new(195, "tuf-pruned-index"),

0 commit comments

Comments
 (0)