@@ -74,6 +74,7 @@ api_versions!([
7474 // | date-based version should be at the top of the list.
7575 // v
7676 // (next_yyyymmddnn, IDENT),
77+ ( 2026011601 , EXTERNAL_SUBNET_ATTACHMENT ) ,
7778 ( 2026011600 , RENAME_ADDRESS_SELECTOR_TO_ADDRESS_ALLOCATOR ) ,
7879 ( 2026011501 , AUDIT_LOG_CREDENTIAL_ID ) ,
7980 ( 2026011500 , AUDIT_LOG_AUTH_METHOD_ENUM ) ,
@@ -187,6 +188,12 @@ const PUT_UPDATE_REPOSITORY_MAX_BYTES: usize = 4 * GIB;
187188 url = "http://docs.oxide.computer/api/floating-ips"
188189 }
189190 } ,
191+ "external-subnets" = {
192+ description = "External subnets that can be attached to instances." ,
193+ external_docs = {
194+ url = "http://docs.oxide.computer/api/external-subnets"
195+ }
196+ } ,
190197 "images" = {
191198 description = "Images are read-only virtual disks that may be used to boot virtual machines." ,
192199 external_docs = {
@@ -295,6 +302,15 @@ const PUT_UPDATE_REPOSITORY_MAX_BYTES: usize = 4 * GIB;
295302 url = "http://docs.oxide.computer/api/system-ip-pools"
296303 }
297304 } ,
305+ "system/subnet-pools" = {
306+ description = "Subnet pools are collections of IP subnets \
307+ that can be assigned to silos. When a pool is linked to \
308+ a silo, users in that silo can allocate external subnets \
309+ from the pool.",
310+ external_docs = {
311+ url = "http://docs.oxide.computer/api/system-subnet-pools"
312+ }
313+ } ,
298314 "system/networking" = {
299315 description = "This provides rack-level network configuration." ,
300316 external_docs = {
@@ -1277,6 +1293,272 @@ pub trait NexusExternalApi {
12771293 range_params : TypedBody < shared:: IpRange > ,
12781294 ) -> Result < HttpResponseUpdatedNoContent , HttpError > ;
12791295
1296+ // Subnet Pools
1297+
1298+ /// List subnet pools
1299+ #[ endpoint {
1300+ method = GET ,
1301+ path = "/v1/system/subnet-pools" ,
1302+ tags = [ "system/subnet-pools" ] ,
1303+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1304+ } ]
1305+ async fn subnet_pool_list (
1306+ rqctx : RequestContext < Self :: Context > ,
1307+ query_params : Query < PaginatedByNameOrId > ,
1308+ ) -> Result < HttpResponseOk < ResultsPage < views:: SubnetPool > > , HttpError > ;
1309+
1310+ /// Create a subnet pool
1311+ #[ endpoint {
1312+ method = POST ,
1313+ path = "/v1/system/subnet-pools" ,
1314+ tags = [ "system/subnet-pools" ] ,
1315+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1316+ } ]
1317+ async fn subnet_pool_create (
1318+ rqctx : RequestContext < Self :: Context > ,
1319+ pool_params : TypedBody < params:: SubnetPoolCreate > ,
1320+ ) -> Result < HttpResponseCreated < views:: SubnetPool > , HttpError > ;
1321+
1322+ /// Fetch a subnet pool
1323+ #[ endpoint {
1324+ method = GET ,
1325+ path = "/v1/system/subnet-pools/{pool}" ,
1326+ tags = [ "system/subnet-pools" ] ,
1327+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1328+ } ]
1329+ async fn subnet_pool_view (
1330+ rqctx : RequestContext < Self :: Context > ,
1331+ path_params : Path < params:: SubnetPoolPath > ,
1332+ ) -> Result < HttpResponseOk < views:: SubnetPool > , HttpError > ;
1333+
1334+ /// Update a subnet pool
1335+ #[ endpoint {
1336+ method = PUT ,
1337+ path = "/v1/system/subnet-pools/{pool}" ,
1338+ tags = [ "system/subnet-pools" ] ,
1339+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1340+ } ]
1341+ async fn subnet_pool_update (
1342+ rqctx : RequestContext < Self :: Context > ,
1343+ path_params : Path < params:: SubnetPoolPath > ,
1344+ updates : TypedBody < params:: SubnetPoolUpdate > ,
1345+ ) -> Result < HttpResponseOk < views:: SubnetPool > , HttpError > ;
1346+
1347+ /// Delete a subnet pool
1348+ #[ endpoint {
1349+ method = DELETE ,
1350+ path = "/v1/system/subnet-pools/{pool}" ,
1351+ tags = [ "system/subnet-pools" ] ,
1352+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1353+ } ]
1354+ async fn subnet_pool_delete (
1355+ rqctx : RequestContext < Self :: Context > ,
1356+ path_params : Path < params:: SubnetPoolPath > ,
1357+ ) -> Result < HttpResponseDeleted , HttpError > ;
1358+
1359+ /// List members in a subnet pool
1360+ #[ endpoint {
1361+ method = GET ,
1362+ path = "/v1/system/subnet-pools/{pool}/members" ,
1363+ tags = [ "system/subnet-pools" ] ,
1364+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1365+ } ]
1366+ async fn subnet_pool_member_list (
1367+ rqctx : RequestContext < Self :: Context > ,
1368+ path_params : Path < params:: SubnetPoolPath > ,
1369+ query_params : Query < PaginatedByNameOrId > ,
1370+ ) -> Result < HttpResponseOk < ResultsPage < views:: SubnetPoolMember > > , HttpError > ;
1371+
1372+ /// Add a member to a subnet pool
1373+ #[ endpoint {
1374+ method = POST ,
1375+ path = "/v1/system/subnet-pools/{pool}/members/add" ,
1376+ tags = [ "system/subnet-pools" ] ,
1377+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1378+ } ]
1379+ async fn subnet_pool_member_add (
1380+ rqctx : RequestContext < Self :: Context > ,
1381+ path_params : Path < params:: SubnetPoolPath > ,
1382+ subnet_params : TypedBody < params:: SubnetPoolMemberAdd > ,
1383+ ) -> Result < HttpResponseCreated < views:: SubnetPoolMember > , HttpError > ;
1384+
1385+ /// Remove a member from a subnet pool
1386+ #[ endpoint {
1387+ method = POST ,
1388+ path = "/v1/system/subnet-pools/{pool}/members/remove" ,
1389+ tags = [ "system/subnet-pools" ] ,
1390+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1391+ } ]
1392+ async fn subnet_pool_member_remove (
1393+ rqctx : RequestContext < Self :: Context > ,
1394+ path_params : Path < params:: SubnetPoolPath > ,
1395+ subnet_params : TypedBody < params:: SubnetPoolMemberRemove > ,
1396+ ) -> Result < HttpResponseUpdatedNoContent , HttpError > ;
1397+
1398+ /// List silos linked to a subnet pool
1399+ #[ endpoint {
1400+ method = GET ,
1401+ path = "/v1/system/subnet-pools/{pool}/silos" ,
1402+ tags = [ "system/subnet-pools" ] ,
1403+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1404+ } ]
1405+ async fn subnet_pool_silo_list (
1406+ rqctx : RequestContext < Self :: Context > ,
1407+ path_params : Path < params:: SubnetPoolPath > ,
1408+ query_params : Query < PaginatedById > ,
1409+ ) -> Result < HttpResponseOk < ResultsPage < views:: SubnetPoolSiloLink > > , HttpError > ;
1410+
1411+ /// Link a subnet pool to a silo
1412+ #[ endpoint {
1413+ method = POST ,
1414+ path = "/v1/system/subnet-pools/{pool}/silos" ,
1415+ tags = [ "system/subnet-pools" ] ,
1416+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1417+ } ]
1418+ async fn subnet_pool_silo_link (
1419+ rqctx : RequestContext < Self :: Context > ,
1420+ path_params : Path < params:: SubnetPoolPath > ,
1421+ silo_link : TypedBody < params:: SubnetPoolLinkSilo > ,
1422+ ) -> Result < HttpResponseCreated < views:: SubnetPoolSiloLink > , HttpError > ;
1423+
1424+ /// Update a subnet pool's link to a silo
1425+ #[ endpoint {
1426+ method = PUT ,
1427+ path = "/v1/system/subnet-pools/{pool}/silos/{silo}" ,
1428+ tags = [ "system/subnet-pools" ] ,
1429+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1430+ } ]
1431+ async fn subnet_pool_silo_update (
1432+ rqctx : RequestContext < Self :: Context > ,
1433+ path_params : Path < params:: SubnetPoolSiloPath > ,
1434+ update : TypedBody < params:: SubnetPoolSiloUpdate > ,
1435+ ) -> Result < HttpResponseOk < views:: SubnetPoolSiloLink > , HttpError > ;
1436+
1437+ /// Unlink a subnet pool from a silo
1438+ #[ endpoint {
1439+ method = DELETE ,
1440+ path = "/v1/system/subnet-pools/{pool}/silos/{silo}" ,
1441+ tags = [ "system/subnet-pools" ] ,
1442+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1443+ } ]
1444+ async fn subnet_pool_silo_unlink (
1445+ rqctx : RequestContext < Self :: Context > ,
1446+ path_params : Path < params:: SubnetPoolSiloPath > ,
1447+ ) -> Result < HttpResponseUpdatedNoContent , HttpError > ;
1448+
1449+ /// Fetch subnet pool utilization
1450+ #[ endpoint {
1451+ method = GET ,
1452+ path = "/v1/system/subnet-pools/{pool}/utilization" ,
1453+ tags = [ "system/subnet-pools" ] ,
1454+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1455+ } ]
1456+ async fn subnet_pool_utilization_view (
1457+ rqctx : RequestContext < Self :: Context > ,
1458+ path_params : Path < params:: SubnetPoolPath > ,
1459+ ) -> Result < HttpResponseOk < views:: SubnetPoolUtilization > , HttpError > ;
1460+
1461+ // External Subnets
1462+
1463+ /// List external subnets in a project
1464+ #[ endpoint {
1465+ method = GET ,
1466+ path = "/v1/external-subnets" ,
1467+ tags = [ "external-subnets" ] ,
1468+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1469+ } ]
1470+ async fn external_subnet_list (
1471+ rqctx : RequestContext < Self :: Context > ,
1472+ query_params : Query < PaginatedByNameOrId < params:: ProjectSelector > > ,
1473+ ) -> Result < HttpResponseOk < ResultsPage < views:: ExternalSubnet > > , HttpError > ;
1474+
1475+ /// Create an external subnet
1476+ #[ endpoint {
1477+ method = POST ,
1478+ path = "/v1/external-subnets" ,
1479+ tags = [ "external-subnets" ] ,
1480+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1481+ } ]
1482+ async fn external_subnet_create (
1483+ rqctx : RequestContext < Self :: Context > ,
1484+ query_params : Query < params:: ProjectSelector > ,
1485+ subnet_params : TypedBody < params:: ExternalSubnetCreate > ,
1486+ ) -> Result < HttpResponseCreated < views:: ExternalSubnet > , HttpError > ;
1487+
1488+ /// Fetch an external subnet
1489+ #[ endpoint {
1490+ method = GET ,
1491+ path = "/v1/external-subnets/{external_subnet}" ,
1492+ tags = [ "external-subnets" ] ,
1493+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1494+ } ]
1495+ async fn external_subnet_view (
1496+ rqctx : RequestContext < Self :: Context > ,
1497+ path_params : Path < params:: ExternalSubnetPath > ,
1498+ query_params : Query < params:: OptionalProjectSelector > ,
1499+ ) -> Result < HttpResponseOk < views:: ExternalSubnet > , HttpError > ;
1500+
1501+ /// Update an external subnet
1502+ #[ endpoint {
1503+ method = PUT ,
1504+ path = "/v1/external-subnets/{external_subnet}" ,
1505+ tags = [ "external-subnets" ] ,
1506+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1507+ } ]
1508+ async fn external_subnet_update (
1509+ rqctx : RequestContext < Self :: Context > ,
1510+ path_params : Path < params:: ExternalSubnetPath > ,
1511+ query_params : Query < params:: OptionalProjectSelector > ,
1512+ subnet_params : TypedBody < params:: ExternalSubnetUpdate > ,
1513+ ) -> Result < HttpResponseOk < views:: ExternalSubnet > , HttpError > ;
1514+
1515+ /// Delete an external subnet
1516+ #[ endpoint {
1517+ method = DELETE ,
1518+ path = "/v1/external-subnets/{external_subnet}" ,
1519+ tags = [ "external-subnets" ] ,
1520+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1521+ } ]
1522+ async fn external_subnet_delete (
1523+ rqctx : RequestContext < Self :: Context > ,
1524+ path_params : Path < params:: ExternalSubnetPath > ,
1525+ query_params : Query < params:: OptionalProjectSelector > ,
1526+ ) -> Result < HttpResponseDeleted , HttpError > ;
1527+
1528+ /// Attach an external subnet to an instance
1529+ ///
1530+ /// Begins an asynchronous attach operation. Returns the subnet with
1531+ /// `instance_id` set to the target instance. The attach completes
1532+ /// asynchronously; poll the subnet to check completion.
1533+ #[ endpoint {
1534+ method = POST ,
1535+ path = "/v1/external-subnets/{external_subnet}/attach" ,
1536+ tags = [ "external-subnets" ] ,
1537+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1538+ } ]
1539+ async fn external_subnet_attach (
1540+ rqctx : RequestContext < Self :: Context > ,
1541+ path_params : Path < params:: ExternalSubnetPath > ,
1542+ query_params : Query < params:: OptionalProjectSelector > ,
1543+ attach_params : TypedBody < params:: ExternalSubnetAttach > ,
1544+ ) -> Result < HttpResponseAccepted < views:: ExternalSubnet > , HttpError > ;
1545+
1546+ /// Detach an external subnet from an instance
1547+ ///
1548+ /// Begins an asynchronous detach operation. Returns the subnet with
1549+ /// `instance_id` cleared. The detach completes asynchronously.
1550+ #[ endpoint {
1551+ method = POST ,
1552+ path = "/v1/external-subnets/{external_subnet}/detach" ,
1553+ tags = [ "external-subnets" ] ,
1554+ versions = VERSION_EXTERNAL_SUBNET_ATTACHMENT ..,
1555+ } ]
1556+ async fn external_subnet_detach (
1557+ rqctx : RequestContext < Self :: Context > ,
1558+ path_params : Path < params:: ExternalSubnetPath > ,
1559+ query_params : Query < params:: OptionalProjectSelector > ,
1560+ ) -> Result < HttpResponseAccepted < views:: ExternalSubnet > , HttpError > ;
1561+
12801562 // Floating IP Addresses
12811563
12821564 /// List floating IPs
0 commit comments