Skip to content
Open
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
3 changes: 3 additions & 0 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@ pub enum ResourceType {
DeviceAccessToken,
DeviceAuthRequest,
Disk,
ExternalSubnet,
Fleet,
FloatingIp,
IdentityProvider,
Expand Down Expand Up @@ -996,6 +997,8 @@ pub enum ResourceType {
Snapshot,
SshKey,
SupportBundle,
SubnetPool,
SubnetPoolMember,
Switch,
SwitchPort,
SwitchPortSettings,
Expand Down
26 changes: 26 additions & 0 deletions nexus/external-api/output/nexus_tags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ support_bundle_update PUT /experimental/v1/system/suppor
support_bundle_view GET /experimental/v1/system/support-bundles/{bundle_id}
timeseries_query POST /v1/timeseries/query

API operations found with tag "external-subnets"
OPERATION ID METHOD URL PATH
external_subnet_attach POST /v1/external-subnets/{external_subnet}/attach
external_subnet_create POST /v1/external-subnets
external_subnet_delete DELETE /v1/external-subnets/{external_subnet}
external_subnet_detach POST /v1/external-subnets/{external_subnet}/detach
external_subnet_list GET /v1/external-subnets
external_subnet_update PUT /v1/external-subnets/{external_subnet}
external_subnet_view GET /v1/external-subnets/{external_subnet}

API operations found with tag "floating-ips"
OPERATION ID METHOD URL PATH
floating_ip_attach POST /v1/floating-ips/{floating_ip}/attach
Expand Down Expand Up @@ -304,6 +314,22 @@ API operations found with tag "system/status"
OPERATION ID METHOD URL PATH
ping GET /v1/ping

API operations found with tag "system/subnet-pools"
OPERATION ID METHOD URL PATH
subnet_pool_create POST /v1/system/subnet-pools
subnet_pool_delete DELETE /v1/system/subnet-pools/{pool}
subnet_pool_list GET /v1/system/subnet-pools
subnet_pool_member_list GET /v1/system/subnet-pools/{pool}/subnets
subnet_pool_silo_link POST /v1/system/subnet-pools/{pool}/silos
subnet_pool_silo_list GET /v1/system/subnet-pools/{pool}/silos
subnet_pool_silo_unlink DELETE /v1/system/subnet-pools/{pool}/silos/{silo}
subnet_pool_silo_update PUT /v1/system/subnet-pools/{pool}/silos/{silo}
subnet_pool_subnet_add POST /v1/system/subnet-pools/{pool}/subnets/add
subnet_pool_subnet_remove POST /v1/system/subnet-pools/{pool}/subnets/remove
subnet_pool_update PUT /v1/system/subnet-pools/{pool}
subnet_pool_utilization_view GET /v1/system/subnet-pools/{pool}/utilization
subnet_pool_view GET /v1/system/subnet-pools/{pool}

API operations found with tag "system/update"
OPERATION ID METHOD URL PATH
system_update_repository_list GET /v1/system/update/repositories
Expand Down
282 changes: 282 additions & 0 deletions nexus/external-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ api_versions!([
// | date-based version should be at the top of the list.
// v
// (next_yyyymmddnn, IDENT),
(2026011601, EXTERNAL_SUBNET_ATTACHMENT),
(2026011600, RENAME_ADDRESS_SELECTOR_TO_ADDRESS_ALLOCATOR),
(2026011501, AUDIT_LOG_CREDENTIAL_ID),
(2026011500, AUDIT_LOG_AUTH_METHOD_ENUM),
Expand Down Expand Up @@ -187,6 +188,12 @@ const PUT_UPDATE_REPOSITORY_MAX_BYTES: usize = 4 * GIB;
url = "http://docs.oxide.computer/api/floating-ips"
}
},
"external-subnets" = {
description = "External subnets that can be attached to instances.",
external_docs = {
url = "http://docs.oxide.computer/api/external-subnets"
}
},
"images" = {
description = "Images are read-only virtual disks that may be used to boot virtual machines.",
external_docs = {
Expand Down Expand Up @@ -295,6 +302,15 @@ const PUT_UPDATE_REPOSITORY_MAX_BYTES: usize = 4 * GIB;
url = "http://docs.oxide.computer/api/system-ip-pools"
}
},
"system/subnet-pools" = {
description = "Subnet pools are collections of IP subnets \
that can be assigned to silos. When a pool is linked to \
a silo, users in that silo can allocate external subnets \
from the pool.",
external_docs = {
url = "http://docs.oxide.computer/api/system-subnet-pools"
}
},
"system/networking" = {
description = "This provides rack-level network configuration.",
external_docs = {
Expand Down Expand Up @@ -1277,6 +1293,272 @@ pub trait NexusExternalApi {
range_params: TypedBody<shared::IpRange>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

// Subnet Pools

/// List subnet pools
#[endpoint {
method = GET,
path = "/v1/system/subnet-pools",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_list(
rqctx: RequestContext<Self::Context>,
query_params: Query<PaginatedByNameOrId>,
) -> Result<HttpResponseOk<ResultsPage<views::SubnetPool>>, HttpError>;

/// Create a subnet pool
#[endpoint {
method = POST,
path = "/v1/system/subnet-pools",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_create(
rqctx: RequestContext<Self::Context>,
pool_params: TypedBody<params::SubnetPoolCreate>,
) -> Result<HttpResponseCreated<views::SubnetPool>, HttpError>;

/// Fetch a subnet pool
#[endpoint {
method = GET,
path = "/v1/system/subnet-pools/{pool}",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_view(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
) -> Result<HttpResponseOk<views::SubnetPool>, HttpError>;

/// Update a subnet pool
#[endpoint {
method = PUT,
path = "/v1/system/subnet-pools/{pool}",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_update(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
updates: TypedBody<params::SubnetPoolUpdate>,
) -> Result<HttpResponseOk<views::SubnetPool>, HttpError>;

/// Delete a subnet pool
#[endpoint {
method = DELETE,
path = "/v1/system/subnet-pools/{pool}",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_delete(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
) -> Result<HttpResponseDeleted, HttpError>;

/// List subnets in a pool
#[endpoint {
method = GET,
path = "/v1/system/subnet-pools/{pool}/subnets",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_member_list(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
query_params: Query<PaginatedByNameOrId>,
) -> Result<HttpResponseOk<ResultsPage<views::SubnetPoolMember>>, HttpError>;

/// Add a subnet to a pool
#[endpoint {
method = POST,
path = "/v1/system/subnet-pools/{pool}/subnets/add",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_subnet_add(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
subnet_params: TypedBody<params::SubnetPoolMemberAdd>,
) -> Result<HttpResponseCreated<views::SubnetPoolMember>, HttpError>;

/// Remove a subnet from a pool
#[endpoint {
method = POST,
path = "/v1/system/subnet-pools/{pool}/subnets/remove",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_subnet_remove(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
subnet_params: TypedBody<params::SubnetPoolMemberRemove>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// List silos linked to a subnet pool
#[endpoint {
method = GET,
path = "/v1/system/subnet-pools/{pool}/silos",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_silo_list(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
query_params: Query<PaginatedById>,
) -> Result<HttpResponseOk<ResultsPage<views::SubnetPoolSiloLink>>, HttpError>;

/// Link a subnet pool to a silo
#[endpoint {
method = POST,
path = "/v1/system/subnet-pools/{pool}/silos",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_silo_link(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
silo_link: TypedBody<params::SubnetPoolLinkSilo>,
) -> Result<HttpResponseCreated<views::SubnetPoolSiloLink>, HttpError>;

/// Update a subnet pool's link to a silo
#[endpoint {
method = PUT,
path = "/v1/system/subnet-pools/{pool}/silos/{silo}",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_silo_update(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolSiloPath>,
update: TypedBody<params::SubnetPoolSiloUpdate>,
) -> Result<HttpResponseOk<views::SubnetPoolSiloLink>, HttpError>;

/// Unlink a subnet pool from a silo
#[endpoint {
method = DELETE,
path = "/v1/system/subnet-pools/{pool}/silos/{silo}",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_silo_unlink(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolSiloPath>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// Fetch subnet pool utilization
#[endpoint {
method = GET,
path = "/v1/system/subnet-pools/{pool}/utilization",
tags = ["system/subnet-pools"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn subnet_pool_utilization_view(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::SubnetPoolPath>,
) -> Result<HttpResponseOk<views::SubnetPoolUtilization>, HttpError>;

// External Subnets

/// List external subnets in a project
#[endpoint {
method = GET,
path = "/v1/external-subnets",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_list(
rqctx: RequestContext<Self::Context>,
query_params: Query<PaginatedByNameOrId<params::ProjectSelector>>,
) -> Result<HttpResponseOk<ResultsPage<views::ExternalSubnet>>, HttpError>;

/// Create an external subnet
#[endpoint {
method = POST,
path = "/v1/external-subnets",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_create(
rqctx: RequestContext<Self::Context>,
query_params: Query<params::ProjectSelector>,
subnet_params: TypedBody<params::ExternalSubnetCreate>,
) -> Result<HttpResponseCreated<views::ExternalSubnet>, HttpError>;

/// Fetch an external subnet
#[endpoint {
method = GET,
path = "/v1/external-subnets/{external_subnet}",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_view(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::ExternalSubnetPath>,
query_params: Query<params::OptionalProjectSelector>,
) -> Result<HttpResponseOk<views::ExternalSubnet>, HttpError>;

/// Update an external subnet
#[endpoint {
method = PUT,
path = "/v1/external-subnets/{external_subnet}",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_update(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::ExternalSubnetPath>,
query_params: Query<params::OptionalProjectSelector>,
subnet_params: TypedBody<params::ExternalSubnetUpdate>,
) -> Result<HttpResponseOk<views::ExternalSubnet>, HttpError>;

/// Delete an external subnet
#[endpoint {
method = DELETE,
path = "/v1/external-subnets/{external_subnet}",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_delete(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::ExternalSubnetPath>,
query_params: Query<params::OptionalProjectSelector>,
) -> Result<HttpResponseDeleted, HttpError>;

/// Attach an external subnet to an instance
///
/// Begins an asynchronous attach operation. Returns the subnet with
/// `instance_id` set to the target instance. The attach completes
/// asynchronously; poll the subnet to check completion.
#[endpoint {
method = POST,
path = "/v1/external-subnets/{external_subnet}/attach",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_attach(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::ExternalSubnetPath>,
query_params: Query<params::OptionalProjectSelector>,
attach_params: TypedBody<params::ExternalSubnetAttach>,
) -> Result<HttpResponseAccepted<views::ExternalSubnet>, HttpError>;

/// Detach an external subnet from an instance
///
/// Begins an asynchronous detach operation. Returns the subnet with
/// `instance_id` cleared. The detach completes asynchronously.
#[endpoint {
method = POST,
path = "/v1/external-subnets/{external_subnet}/detach",
tags = ["external-subnets"],
versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT..,
}]
async fn external_subnet_detach(
rqctx: RequestContext<Self::Context>,
path_params: Path<params::ExternalSubnetPath>,
query_params: Query<params::OptionalProjectSelector>,
) -> Result<HttpResponseAccepted<views::ExternalSubnet>, HttpError>;

// Floating IP Addresses

/// List floating IPs
Expand Down
Loading
Loading