Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions nexus/db-model/src/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ pub struct IncompleteNetworkInterface {
pub kind: NetworkInterfaceKind,
pub parent_id: Uuid,
pub subnet: VpcSubnet,
pub transit_ips: Vec<IpNetwork>,
pub ip: Option<std::net::IpAddr>,
pub mac: Option<external::MacAddr>,
pub slot: Option<u8>,
Expand All @@ -334,6 +335,7 @@ impl IncompleteNetworkInterface {
parent_id: Uuid,
subnet: VpcSubnet,
identity: external::IdentityMetadataCreateParams,
transit_ips: Vec<oxnet::IpNet>,
ip: Option<std::net::IpAddr>,
mac: Option<external::MacAddr>,
slot: Option<u8>,
Expand Down Expand Up @@ -380,6 +382,7 @@ impl IncompleteNetworkInterface {
kind,
parent_id,
subnet,
transit_ips: transit_ips.into_iter().map(Into::into).collect(),
ip,
mac,
slot,
Expand All @@ -391,6 +394,7 @@ impl IncompleteNetworkInterface {
instance_id: InstanceUuid,
subnet: VpcSubnet,
identity: external::IdentityMetadataCreateParams,
transit_ips: Vec<oxnet::IpNet>,
ip: Option<std::net::IpAddr>,
) -> Result<Self, external::Error> {
Self::new(
Expand All @@ -399,6 +403,7 @@ impl IncompleteNetworkInterface {
instance_id.into_untyped_uuid(),
subnet,
identity,
transit_ips,
ip,
None,
None,
Expand All @@ -420,6 +425,7 @@ impl IncompleteNetworkInterface {
service_id,
subnet,
identity,
vec![],
Some(ip),
Some(mac),
Some(slot),
Expand All @@ -440,6 +446,7 @@ impl IncompleteNetworkInterface {
probe_id,
subnet,
identity,
vec![],
ip,
mac,
None,
Expand Down
1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/vpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3918,6 +3918,7 @@ mod tests {
name: "nic".parse().unwrap(),
description: "A NIC...".into(),
},
vec![],
None,
)
.unwrap(),
Expand Down
27 changes: 27 additions & 0 deletions nexus/db-queries/src/db/queries/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,13 @@ impl QueryFragment<Pg> for InsertQuery {
out.push_identifier(dsl::parent_id::NAME)?;
out.push_sql(", ");

out.push_bind_param::<sql_types::Array<sql_types::Inet>, Vec<IpNetwork>>(
&self.interface.transit_ips,
)?;
out.push_sql(" AS ");
out.push_identifier(dsl::transit_ips::NAME)?;
out.push_sql(", ");

// Helper function to push a subquery selecting something from the CTE.
fn select_from_cte(
mut out: AstPass<Pg>,
Expand Down Expand Up @@ -1239,6 +1246,8 @@ impl QueryFragment<Pg> for InsertQueryValues {
out.push_sql(", ");
out.push_identifier(dsl::parent_id::NAME)?;
out.push_sql(", ");
out.push_identifier(dsl::transit_ips::NAME)?;
out.push_sql(", ");
out.push_identifier(dsl::vpc_id::NAME)?;
out.push_sql(", ");
out.push_identifier(dsl::subnet_id::NAME)?;
Expand Down Expand Up @@ -2145,6 +2154,7 @@ mod tests {
name: "interface-a".parse().unwrap(),
description: String::from("description"),
},
vec![],
Some(requested_ip),
)
.unwrap();
Expand Down Expand Up @@ -2174,6 +2184,7 @@ mod tests {
name: "interface-a".parse().unwrap(),
description: String::from("description"),
},
vec![],
Some(requested_ip),
)
.unwrap();
Expand Down Expand Up @@ -2206,6 +2217,7 @@ mod tests {
name: "interface-b".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2244,6 +2256,7 @@ mod tests {
name: format!("interface-{}", i).parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2288,6 +2301,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand All @@ -2307,6 +2321,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
Some(inserted_interface.ip.ip()),
)
.unwrap();
Expand Down Expand Up @@ -2555,6 +2570,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand All @@ -2574,6 +2590,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2605,6 +2622,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand All @@ -2621,6 +2639,7 @@ mod tests {
name: "interface-d".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2649,6 +2668,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2691,6 +2711,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand All @@ -2709,6 +2730,7 @@ mod tests {
name: "interface-a".parse().unwrap(),
description: String::from("description"),
},
vec![],
addr,
)
.unwrap();
Expand Down Expand Up @@ -2748,6 +2770,7 @@ mod tests {
name: "interface-c".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2777,6 +2800,7 @@ mod tests {
name: "interface-d".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2810,6 +2834,7 @@ mod tests {
name: format!("if{}", i).parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2878,6 +2903,7 @@ mod tests {
name: format!("interface-{}", slot).parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down Expand Up @@ -2913,6 +2939,7 @@ mod tests {
name: "interface-8".parse().unwrap(),
description: String::from("description"),
},
vec![],
None,
)
.unwrap();
Expand Down
1 change: 1 addition & 0 deletions nexus/src/app/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl super::Nexus {
InstanceUuid::from_untyped_uuid(authz_instance.id()),
db_subnet,
params.identity.clone(),
params.transit_ips.clone(),
params.ip,
)?;
self.db_datastore
Expand Down
3 changes: 3 additions & 0 deletions nexus/src/app/sagas/instance_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ async fn create_custom_network_interface(
instance_id,
db_subnet.clone(),
interface_params.identity.clone(),
interface_params.transit_ips.clone(),
interface_params.ip,
)
.map_err(ActionError::action_failed)?;
Expand Down Expand Up @@ -598,6 +599,7 @@ async fn create_default_primary_network_interface(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: None, // Request an IP address allocation
transit_ips: vec![],
};

// Lookup authz objects, used in the call to actually create the NIC.
Expand All @@ -619,6 +621,7 @@ async fn create_default_primary_network_interface(
instance_id,
db_subnet.clone(),
interface_params.identity.clone(),
interface_params.transit_ips.clone(),
interface_params.ip,
)
.map_err(ActionError::action_failed)?;
Expand Down
1 change: 1 addition & 0 deletions nexus/tests/integration_tests/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ pub static DEMO_INSTANCE_NIC_CREATE: LazyLock<
vpc_name: DEMO_VPC_NAME.clone(),
subnet_name: DEMO_VPC_SUBNET_NAME.clone(),
ip: None,
transit_ips: vec![],
});
pub static DEMO_INSTANCE_NIC_PUT: LazyLock<
params::InstanceNetworkInterfaceUpdate,
Expand Down
21 changes: 21 additions & 0 deletions nexus/tests/integration_tests/instances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,7 @@ async fn test_instance_create_saga_removes_instance_database_record(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: Some(requested_address),
transit_ips: vec![],
};
let interface_params =
params::InstanceNetworkInterfaceAttachment::Create(vec![
Expand Down Expand Up @@ -2192,6 +2193,7 @@ async fn test_instance_create_saga_removes_instance_database_record(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: Some(requested_address),
transit_ips: vec![],
};
let interface_params =
params::InstanceNetworkInterfaceAttachment::Create(vec![
Expand Down Expand Up @@ -2234,6 +2236,7 @@ async fn test_instance_with_single_explicit_ip_address(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: Some(requested_address),
transit_ips: vec![],
};
let interface_params =
params::InstanceNetworkInterfaceAttachment::Create(vec![
Expand Down Expand Up @@ -2342,6 +2345,7 @@ async fn test_instance_with_new_custom_network_interfaces(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: None,
transit_ips: vec![],
};
let if1_params = params::InstanceNetworkInterfaceCreate {
identity: IdentityMetadataCreateParams {
Expand All @@ -2351,6 +2355,7 @@ async fn test_instance_with_new_custom_network_interfaces(
vpc_name: default_name.clone(),
subnet_name: non_default_subnet_name.clone(),
ip: None,
transit_ips: vec![],
};
let interface_params =
params::InstanceNetworkInterfaceAttachment::Create(vec![
Expand Down Expand Up @@ -2529,6 +2534,7 @@ async fn test_instance_create_delete_network_interface(
vpc_name: "default".parse().unwrap(),
subnet_name: "default".parse().unwrap(),
ip: Some("172.30.0.10".parse().unwrap()),
transit_ips: vec![],
},
params::InstanceNetworkInterfaceCreate {
identity: IdentityMetadataCreateParams {
Expand All @@ -2538,6 +2544,7 @@ async fn test_instance_create_delete_network_interface(
vpc_name: "default".parse().unwrap(),
subnet_name: secondary_subnet.identity.name.clone(),
ip: Some("172.31.0.11".parse().unwrap()),
transit_ips: vec!["10.0.0.0/24".parse().unwrap()],
},
];

Expand Down Expand Up @@ -2591,6 +2598,15 @@ async fn test_instance_create_delete_network_interface(
i == 0,
"Only the first interface should be primary"
);
if i == 1 {
assert!(
iface.transit_ips.len() == 1
&& iface.transit_ips[0].to_string() == "10.0.0.0/24",
"Only the second interface has a transit IP"
);
} else {
assert!(iface.transit_ips.is_empty())
}
interfaces.push(iface);
}

Expand All @@ -2611,6 +2627,7 @@ async fn test_instance_create_delete_network_interface(
assert_eq!(iface0.subnet_id, iface1.subnet_id);
assert_eq!(iface0.ip, iface1.ip);
assert_eq!(iface0.primary, iface1.primary);
assert_eq!(iface0.transit_ips, iface1.transit_ips);
}

// Verify we cannot delete either interface while the instance is running
Expand Down Expand Up @@ -2764,6 +2781,7 @@ async fn test_instance_update_network_interfaces(
vpc_name: "default".parse().unwrap(),
subnet_name: "default".parse().unwrap(),
ip: Some("172.30.0.10".parse().unwrap()),
transit_ips: vec![],
},
params::InstanceNetworkInterfaceCreate {
identity: IdentityMetadataCreateParams {
Expand All @@ -2773,6 +2791,7 @@ async fn test_instance_update_network_interfaces(
vpc_name: "default".parse().unwrap(),
subnet_name: secondary_subnet.identity.name.clone(),
ip: Some("172.31.0.11".parse().unwrap()),
transit_ips: vec![],
},
];

Expand Down Expand Up @@ -3335,6 +3354,7 @@ async fn test_instance_with_multiple_nics_unwinds_completely(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: Some("172.30.0.6".parse().unwrap()),
transit_ips: vec![],
};
let if1_params = params::InstanceNetworkInterfaceCreate {
identity: IdentityMetadataCreateParams {
Expand All @@ -3344,6 +3364,7 @@ async fn test_instance_with_multiple_nics_unwinds_completely(
vpc_name: default_name.clone(),
subnet_name: default_name.clone(),
ip: Some("172.30.0.7".parse().unwrap()),
transit_ips: vec![],
};
let interface_params =
params::InstanceNetworkInterfaceAttachment::Create(vec![
Expand Down
1 change: 1 addition & 0 deletions nexus/tests/integration_tests/internet_gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ async fn test_setup(c: &ClientTestContext) {
ip: None,
subnet_name: "default".parse().unwrap(),
vpc_name: VPC_NAME.parse().unwrap(),
transit_ips: vec![],
},
]);
let _inst = create_instance_with(
Expand Down
Loading
Loading