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
14 changes: 14 additions & 0 deletions crates/api-core/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,20 @@ impl Forge for Api {
crate::handlers::vpc::find_by_ids(self, request).await
}

async fn find_site_prefix_ids(
&self,
request: Request<rpc::SitePrefixSearchFilter>,
) -> Result<Response<rpc::SitePrefixIdList>, Status> {
crate::handlers::site_prefix::find_ids(self, request).await
}

async fn find_site_prefixes_by_ids(
&self,
request: Request<rpc::SitePrefixesByIdsRequest>,
) -> Result<Response<rpc::SitePrefixList>, Status> {
crate::handlers::site_prefix::find_by_ids(self, request).await
}

async fn create_vpc_prefix(
&self,
request: Request<rpc::VpcPrefixCreationRequest>,
Expand Down
2 changes: 2 additions & 0 deletions crates/api-core/src/auth/internal_rbac_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ impl InternalRBACRules {
x.perm("DeleteVpc", vec![Machineatron, SiteAgent]);
x.perm("FindVpcIds", vec![SiteAgent, ForgeAdminCLI, Machineatron]);
x.perm("FindVpcsByIds", vec![ForgeAdminCLI, SiteAgent]);
x.perm("FindSitePrefixIds", vec![ForgeAdminCLI, SiteAgent]);
x.perm("FindSitePrefixesByIds", vec![ForgeAdminCLI, SiteAgent]);
x.perm("CreateVpcPrefix", vec![ForgeAdminCLI, SiteAgent]);
x.perm("SearchVpcPrefixes", vec![ForgeAdminCLI, SiteAgent]);
x.perm("GetVpcPrefixes", vec![ForgeAdminCLI, SiteAgent]);
Expand Down
1 change: 1 addition & 0 deletions crates/api-core/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub mod route_server;
pub mod scout_stream;
pub mod secrets;
pub mod site_explorer;
pub mod site_prefix;
pub mod sku;
pub mod spx_partition;
pub mod svpc;
Expand Down
65 changes: 65 additions & 0 deletions crates/api-core/src/handlers/site_prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use ::rpc::forge as rpc;
use tonic::{Request, Response, Status};

use crate::CarbideError;
use crate::api::{Api, log_request_data};

pub(crate) async fn find_ids(
api: &Api,
request: Request<rpc::SitePrefixSearchFilter>,
) -> Result<Response<rpc::SitePrefixIdList>, Status> {
log_request_data(&request);

let filter: model::site_prefix::SitePrefixSearchFilter = request.into_inner().try_into()?;
let site_prefix_ids = db::site_prefix::find_ids(&api.database_connection, filter).await?;

Ok(Response::new(rpc::SitePrefixIdList { site_prefix_ids }))
}

pub(crate) async fn find_by_ids(
api: &Api,
request: Request<rpc::SitePrefixesByIdsRequest>,
) -> Result<Response<rpc::SitePrefixList>, Status> {
log_request_data(&request);

let site_prefix_ids = request.into_inner().site_prefix_ids;
if site_prefix_ids.is_empty() {
return Err(
CarbideError::InvalidArgument("at least one ID must be provided".to_string()).into(),
);
}

let max_find_by_ids = api.runtime_config.max_find_by_ids as usize;
if site_prefix_ids.len() > max_find_by_ids {
return Err(CarbideError::InvalidArgument(format!(
"no more than {max_find_by_ids} IDs can be accepted"
))
.into());
}

let site_prefixes =
db::site_prefix::find_by_ids(&api.database_connection, site_prefix_ids.as_slice())
.await?
.into_iter()
.map(Into::into)
.collect();

Ok(Response::new(rpc::SitePrefixList { site_prefixes }))
}
13 changes: 9 additions & 4 deletions crates/api-core/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,12 @@ pub async fn start_api(
};

// Note: Normally we want initialize_and_start_controllers to be responsible for populating
// information into the database, but resource pools and route servers need to be defined first,
// since the controllers rely on a fully-hydrated Api object, which relies on route_servers and
// common_pools being populated. So if we're configured for listen_only, strictly read them from
// the database (assuming another instance has populated them), otherwise, populate them now.
// information into the database, but resource pools, route servers, and configured site
// prefixes need to be defined first. The controllers rely on a fully-hydrated Api object, which
// relies on route_servers and common_pools being populated, while site-prefix inventory must
// reflect the complete configured set before the API starts serving it. So if we're configured
// for listen_only, strictly read them from the database (assuming another instance has populated
// them), otherwise, populate them now.
//
// Pool reconciliation specifically must happen before `create_common_pools` runs below, because
// that call queries `resource_pool` and bails if any mandatory pool is missing or empty.
Expand All @@ -290,6 +292,9 @@ pub async fn start_api(
)
.await?;

db::site_prefix::reconcile_configured(&mut txn, &carbide_config.site_fabric_prefixes)
.await?;

txn.commit().await?;

// Idempotently seed the dedicated site-wide lockdown IKM (v0) from the
Expand Down
1 change: 1 addition & 0 deletions crates/api-core/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ mod service_health_metrics;
mod set_primary_dpu;
mod set_primary_interface;
mod site_explorer;
mod site_prefix;
mod sku;
mod spdm;
mod switch;
Expand Down
Loading
Loading