Skip to content

Commit

Permalink
WIP: Initial DB Model for NAT RPW
Browse files Browse the repository at this point in the history
WIP: add cleanup method, add query for nat_gen sequence

WIP: internal API endpoints

begin replacing direct nat config calls with rpw
  • Loading branch information
internet-diglett committed Sep 13, 2023
1 parent 9700d44 commit f23e2a2
Show file tree
Hide file tree
Showing 17 changed files with 928 additions and 38 deletions.
2 changes: 1 addition & 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 common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ pub enum ResourceType {
UpdateableComponent,
UserBuiltin,
Zpool,
Ipv4NatEntry,
}

// IDENTITY METADATA
Expand Down
116 changes: 116 additions & 0 deletions nexus/db-model/src/ipv4_nat_entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::net::{Ipv4Addr, Ipv6Addr};

use super::MacAddr;
use crate::{
schema::{ipv4_nat_entry, nat_gen},
SqlU16, SqlU32, Vni,
};
use chrono::{DateTime, Utc};
use omicron_common::api::external;
use schemars::JsonSchema;
use serde::Serialize;
use uuid::Uuid;

// TODO correctness
// If we're not going to store ipv4 and ipv6
// NAT entries in the same table, and we don't
// need any of the special properties of the IpNetwork
// column type, does it make sense to use a different
// column type?
/// Database representation of an Ipv4 NAT Entry.
#[derive(Insertable, Debug, Clone)]
#[diesel(table_name = ipv4_nat_entry)]
pub struct NewIpv4NatEntry {
pub external_address: ipnetwork::IpNetwork,
pub first_port: SqlU16,
pub last_port: SqlU16,
pub sled_address: ipnetwork::IpNetwork,
pub vni: Vni,
pub mac: MacAddr,
}

// TODO correctness
// If we're not going to store ipv4 and ipv6
// NAT entries in the same table, we should probably
// make the types more restrictive to prevent an
// accidental ipv6 entry from being created.
#[derive(Queryable, Debug, Clone, Selectable)]
#[diesel(table_name = ipv4_nat_entry)]
pub struct Ipv4NatEntry {
pub id: Uuid,
pub external_address: ipnetwork::IpNetwork,
pub first_port: SqlU16,
pub last_port: SqlU16,
pub sled_address: ipnetwork::IpNetwork,
pub vni: Vni,
pub mac: MacAddr,
pub gen: SqlU32,
pub time_created: DateTime<Utc>,
pub time_deleted: Option<DateTime<Utc>>,
}

impl Ipv4NatEntry {
pub fn first_port(&self) -> u16 {
self.first_port.into()
}

pub fn last_port(&self) -> u16 {
self.last_port.into()
}

pub fn gen(&self) -> u32 {
self.gen.into()
}
}

#[derive(Queryable, Debug, Clone, Selectable)]
#[diesel(table_name = nat_gen)]
pub struct Ipv4NatGen {
pub last_value: SqlU32,
pub log_cnt: SqlU32,
pub is_called: bool,
}

/// NAT Record
#[derive(Clone, Debug, Serialize, JsonSchema)]
pub struct Ipv4NatEntryView {
pub external_address: Ipv4Addr,
pub first_port: u16,
pub last_port: u16,
pub sled_address: Ipv6Addr,
pub vni: external::Vni,
pub mac: external::MacAddr,
pub gen: u32,
pub deleted: bool,
}

impl From<Ipv4NatEntry> for Ipv4NatEntryView {
fn from(value: Ipv4NatEntry) -> Self {
let external_address = match value.external_address.ip() {
std::net::IpAddr::V4(a) => a,
std::net::IpAddr::V6(_) => unreachable!(),
};

let sled_address = match value.sled_address.ip() {
std::net::IpAddr::V4(_) => unreachable!(),
std::net::IpAddr::V6(a) => a,
};

Self {
external_address,
first_port: value.first_port(),
last_port: value.last_port(),
sled_address,
vni: value.vni.0,
mac: *value.mac,
gen: value.gen(),
deleted: value.time_deleted.is_some(),
}
}
}

/// NAT Generation
#[derive(Clone, Debug, Serialize, JsonSchema)]
pub struct Ipv4NatGenView {
pub gen: u32,
}
2 changes: 2 additions & 0 deletions nexus/db-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod system_update;
// These actually represent subqueries, not real table.
// However, they must be defined in the same crate as our tables
// for join-based marker trait generation.
mod ipv4_nat_entry;
pub mod queries;
mod rack;
mod region;
Expand Down Expand Up @@ -119,6 +120,7 @@ pub use instance::*;
pub use instance_cpu_count::*;
pub use instance_state::*;
pub use ip_pool::*;
pub use ipv4_nat_entry::*;
pub use ipv4net::*;
pub use ipv6::*;
pub use ipv6net::*;
Expand Down
27 changes: 26 additions & 1 deletion nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,31 @@ table! {
}
}

table! {
ipv4_nat_entry (id) {
id -> Uuid,
external_address -> Inet,
first_port -> Int4,
last_port -> Int4,
sled_address -> Inet,
vni -> Int4,
mac -> Int8,
gen -> Int8,
time_created -> Timestamptz,
time_deleted -> Nullable<Timestamptz>,
}
}

// This is the sequence used for the generation number
// in ipv4_nat_entry.
table! {
nat_gen (last_value) {
last_value -> Int8,
log_cnt -> Int8,
is_called -> Bool,
}
}

table! {
external_ip (id) {
id -> Uuid,
Expand Down Expand Up @@ -1130,7 +1155,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(4, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(4, 0, 1);

allow_tables_to_appear_in_same_query!(
system_update,
Expand Down
Loading

0 comments on commit f23e2a2

Please sign in to comment.