Skip to content

Commit

Permalink
We now have valid, sane, default system routes
Browse files Browse the repository at this point in the history
These update in response to VPC subnet changes. Now to plumb them into
OPTE.
  • Loading branch information
FelixMcFelix committed May 15, 2024
1 parent 389c185 commit b48da00
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 69 deletions.
2 changes: 1 addition & 1 deletion nexus/db-model/src/vpc_route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl RouterRoute {
system_router_id: Uuid,
subnet: Name,
) -> Result<Self, ()> {
let name = format!("subnet_{}", subnet).parse().map_err(|_| ())?;
let name = format!("sn-{}", subnet).parse().map_err(|_| ())?;
Ok(Self::new(
route_id,
system_router_id,
Expand Down
31 changes: 26 additions & 5 deletions nexus/db-queries/src/db/datastore/vpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,26 @@ impl DataStore {

// Unwrap safety: these are known valid CIDR blocks.
let default_ips = [
("0.0.0.0/0".parse().unwrap(), *SERVICES_VPC_DEFAULT_V4_ROUTE_ID),
("::/0".parse().unwrap(), *SERVICES_VPC_DEFAULT_V6_ROUTE_ID),
(
"default-v4",
"0.0.0.0/0".parse().unwrap(),
*SERVICES_VPC_DEFAULT_V4_ROUTE_ID,
),
(
"default-v6",
"::/0".parse().unwrap(),
*SERVICES_VPC_DEFAULT_V6_ROUTE_ID,
),
];

for (default, uuid) in default_ips {
for (name, default, uuid) in default_ips {
let route = RouterRoute::new(
uuid,
SERVICES_VPC.system_router_id,
ExternalRouteKind::Default,
nexus_types::external_api::params::RouterRouteCreate {
identity: IdentityMetadataCreateParams {
name: "default".parse().unwrap(),
name: name.parse().unwrap(),
description:
"Default internet gateway route for Oxide Services"
.to_string(),
Expand Down Expand Up @@ -1036,6 +1044,18 @@ impl DataStore {
ErrorHandler::NotFoundByResource(authz_router),
)
})?;

// All child routes are deleted.
use db::schema::router_route::dsl as rr;
let now = Utc::now();
diesel::update(rr::router_route)
.filter(rr::time_deleted.is_null())
.filter(rr::vpc_router_id.eq(authz_router.id()))
.set(rr::time_deleted.eq(now))
.execute_async(&*self.pool_connection_authorized(opctx).await?)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;

Ok(())
}

Expand Down Expand Up @@ -1291,6 +1311,7 @@ impl DataStore {
.transaction(&conn, |conn| {
let log = log.clone();
async move {

use db::schema::router_route::dsl;
use db::schema::vpc_subnet::dsl as subnet;
use db::schema::vpc::dsl as vpc;
Expand All @@ -1304,7 +1325,7 @@ impl DataStore {
.await?;

let valid_subnets: Vec<VpcSubnet> = subnet::vpc_subnet
.filter(subnet::id.eq(vpc_id))
.filter(subnet::vpc_id.eq(vpc_id))
.filter(subnet::time_deleted.is_null())
.select(VpcSubnet::as_select())
.load_async(&conn)
Expand Down
64 changes: 2 additions & 62 deletions nexus/src/app/sagas/vpc_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ declare_saga_actions! {
+ svc_create_subnet
- svc_create_subnet_undo
}
VPC_CREATE_SUBNET_ROUTE -> "route" {
+ svc_create_subnet_route
- svc_create_subnet_route_undo
}
VPC_UPDATE_FIREWALL -> "firewall" {
+ svc_update_firewall
- svc_update_firewall_undo
Expand Down Expand Up @@ -97,11 +93,6 @@ pub fn create_dag(
"GenerateDefaultV6RouteId",
ACTION_GENERATE_ID.as_ref(),
));
builder.append(Node::action(
"default_subnet_route_id",
"GenerateDefaultV6RouteId",
ACTION_GENERATE_ID.as_ref(),
));
builder.append(Node::action(
"default_subnet_id",
"GenerateDefaultSubnetId",
Expand All @@ -112,7 +103,6 @@ pub fn create_dag(
builder.append(vpc_create_v4_route_action());
builder.append(vpc_create_v6_route_action());
builder.append(vpc_create_subnet_action());
builder.append(vpc_create_subnet_route_action());
builder.append(vpc_update_firewall_action());
builder.append(vpc_notify_sleds_action());

Expand Down Expand Up @@ -246,7 +236,7 @@ async fn svc_create_v4_route(
let default_route_id = sagactx.lookup::<Uuid>("default_v4_route_id")?;
let default_route =
"0.0.0.0/0".parse().expect("known-valid specifier for a default route");
svc_create_route(sagactx, default_route_id, default_route, "default_v4")
svc_create_route(sagactx, default_route_id, default_route, "default-v4")
.await
}

Expand All @@ -263,7 +253,7 @@ async fn svc_create_v6_route(
let default_route_id = sagactx.lookup::<Uuid>("default_v6_route_id")?;
let default_route =
"::/0".parse().expect("known-valid specifier for a default route");
svc_create_route(sagactx, default_route_id, default_route, "default_v6")
svc_create_route(sagactx, default_route_id, default_route, "default-v6")
.await
}

Expand Down Expand Up @@ -427,56 +417,6 @@ async fn svc_create_subnet_undo(
Ok(())
}

async fn svc_create_subnet_route(
sagactx: NexusActionContext,
) -> Result<(), ActionError> {
let osagactx = sagactx.user_data();
let params = sagactx.saga_params::<Params>()?;
let opctx = crate::context::op_context_for_saga_action(
&sagactx,
&params.serialized_authn,
);
let system_router_id = sagactx.lookup::<Uuid>("system_router_id")?;
let authz_router = sagactx.lookup::<authz::VpcRouter>("router")?;
let route_id = sagactx.lookup::<Uuid>("default_subnet_route_id")?;
let (_, db_subnet) =
sagactx.lookup::<(authz::VpcSubnet, db::model::VpcSubnet)>("subnet")?;

let route = db::model::RouterRoute::for_subnet(
route_id,
system_router_id,
db_subnet.identity.name,
)
.expect("default subnet name is short enough for route naming");

osagactx
.datastore()
.router_create_route(&opctx, &authz_router, route)
.await
.map_err(ActionError::action_failed)?;
Ok(())
}

async fn svc_create_subnet_route_undo(
sagactx: NexusActionContext,
) -> Result<(), anyhow::Error> {
let osagactx = sagactx.user_data();
let params = sagactx.saga_params::<Params>()?;
let opctx = crate::context::op_context_for_saga_action(
&sagactx,
&params.serialized_authn,
);
let authz_router = sagactx.lookup::<authz::VpcRouter>("router")?;
let route_id = sagactx.lookup::<Uuid>("default_subnet_route_id")?;
let authz_route = authz::RouterRoute::new(
authz_router,
route_id,
LookupType::ById(route_id),
);
osagactx.datastore().router_delete_route(&opctx, &authz_route).await?;
Ok(())
}

async fn svc_update_firewall(
sagactx: NexusActionContext,
) -> Result<Vec<db::model::VpcFirewallRule>, ActionError> {
Expand Down
1 change: 0 additions & 1 deletion nexus/src/app/vpc_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ impl super::Nexus {
.await
}

// TODO: When a router is deleted all its routes should be deleted
// TODO: When a router is deleted it should be unassociated w/ any subnets it may be associated with
// or trigger an error
pub(crate) async fn vpc_delete_router(
Expand Down

0 comments on commit b48da00

Please sign in to comment.