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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ tower-test = "0.4"

[profile.release]
debug = "line-tables-only"
debug-assertions = true # Add some extra assurance during development
overflow-checks = true # Add some extra assurance during development
debug-assertions = true # Add some extra assurance during development
overflow-checks = true # Add some extra assurance during development

[workspace.lints.clippy]
cloned_instead_of_copied = "warn"
Expand Down
4 changes: 2 additions & 2 deletions crates/admin-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ toml = { workspace = true }
tonic = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { features = [
"env-filter",
"local-time",
"env-filter",
"local-time",
], workspace = true }
urlencoding = { workspace = true }
uuid = { workspace = true }
Expand Down
12 changes: 10 additions & 2 deletions crates/admin-cli/src/cfg/cli_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ use crate::{
machine_interfaces, machine_validation, managed_host, managed_switch, mlx, network_devices,
network_security_group, network_segment, nvl_logical_partition, nvl_partition,
nvlink_nmxc_endpoints, operating_system, os_image, ping, power_shelf, rack, rack_firmware,
redfish, resource_pool, rms, route_server, scout_stream, set, site_explorer, sku, ssh, switch,
tenant, tenant_keyset, tpm_ca, trim_table, version, vpc, vpc_peering, vpc_prefix,
redfish, resource_pool, rms, route_server, scout_stream, set, site_explorer, sku,
spx_partition, ssh, switch, tenant, tenant_keyset, tpm_ca, trim_table, version, vpc,
vpc_peering, vpc_prefix,
};

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -344,6 +345,13 @@ pub enum CliCommand {
)]
NvlPartition(nvl_partition::Cmd),

#[clap(
about = "SPX Partition related handling",
subcommand,
visible_alias = "spx"
)]
SpxPartition(spx_partition::Cmd),

#[clap(
about = "Logical partition related handling",
subcommand,
Expand Down
3 changes: 3 additions & 0 deletions crates/admin-cli/src/dpa/ensure/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub struct Args {
pub device_type: String,
#[clap(help = "PCI name (e.g. 5e:00.0)")]
pub pci_name: String,
#[clap(help = "Device description (e.g. NVIDIA BlueField-3 B3140L E-Series FHHL SuperNIC)")]
pub device_description: Option<String>,
}

impl From<Args> for ::rpc::forge::DpaInterfaceCreationRequest {
Expand All @@ -37,6 +39,7 @@ impl From<Args> for ::rpc::forge::DpaInterfaceCreationRequest {
mac_addr: args.mac_addr,
device_type: args.device_type,
pci_name: args.pci_name,
device_description: args.device_description,
}
}
}
9 changes: 8 additions & 1 deletion crates/admin-cli/src/instance/allocate/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use carbide_uuid::machine::MachineId;
use carbide_uuid::vpc::VpcPrefixId;
use clap::{ArgGroup, Parser};
use rpc::forge::InstanceOperatingSystemConfig;
use rpc::forge::{InstanceOperatingSystemConfig, InstanceSpxConfig};

#[derive(Parser, Debug)]
#[clap(group(ArgGroup::new("selector").required(true).args(&["subnet", "vpc_prefix_id"])))]
Expand Down Expand Up @@ -58,6 +58,13 @@ pub struct Args {
#[clap(long, help = "OS definition in JSON format", value_name = "OS_JSON")]
pub os: Option<InstanceOperatingSystemConfig>,

#[clap(
long,
help = "SPX configuration in JSON format",
value_name = "SPX_JSON"
)]
pub spxconfig: Option<InstanceSpxConfig>,

#[clap(long, help = "The subnet to assign to a VF")]
pub vf_subnet: Vec<String>,

Expand Down
3 changes: 3 additions & 0 deletions crates/admin-cli/src/instance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod show;
mod update_ib_config;
mod update_nvlink_config;
mod update_os;
mod update_spx_config;

// Cross-module re-exports for jump module
// Cross-module re-export for rpc module
Expand Down Expand Up @@ -53,4 +54,6 @@ pub enum Cmd {
UpdateIbConfig(update_ib_config::Args),
#[clap(about = "Update instance NVLink configuration")]
UpdateNvLinkConfig(update_nvlink_config::Args),
#[clap(about = "Update instance SPX configuration")]
UpdateSpxConfig(update_spx_config::Args),
}
33 changes: 33 additions & 0 deletions crates/admin-cli/src/instance/update_spx_config/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 carbide_uuid::instance::InstanceId;
use clap::Parser;
use rpc::forge::InstanceSpxConfig;

#[derive(Parser, Debug)]
pub struct Args {
#[clap(short, long, required(true))]
pub instance: InstanceId,
#[clap(
long,
required(true),
help = "SPX configuration in JSON format",
value_name = "SPX_JSON"
)]
pub config: InstanceSpxConfig,
}
57 changes: 57 additions & 0 deletions crates/admin-cli/src/instance/update_spx_config/cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 super::args::Args;
use crate::errors::{CarbideCliError, CarbideCliResult};
use crate::instance::common::GlobalOptions;
use crate::rpc::ApiClient;

pub async fn update_spx_config(
api_client: &ApiClient,
update_request: Args,
opts: GlobalOptions<'_>,
) -> CarbideCliResult<()> {
if opts.cloud_unsafe_op.is_none() {
return Err(CarbideCliError::GenericError(
"Operation not allowed due to potential inconsistencies with cloud database."
.to_owned(),
));
}

match api_client
.update_instance_config_with(
update_request.instance,
|config| {
config.spxconfig = Some(update_request.config);
},
|_metadata| {},
opts.cloud_unsafe_op,
)
.await
{
Ok(i) => {
tracing::info!(
"update-spx-config was successful. Updated instance: {:?}",
i
);
}
Err(e) => {
tracing::info!("update-spx-config failed with {} ", e);
}
};
Ok(())
}
43 changes: 43 additions & 0 deletions crates/admin-cli/src/instance/update_spx_config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.
*/

pub mod args;
pub mod cmd;

pub use args::Args;

use super::common::GlobalOptions;
use crate::cfg::run::Run;
use crate::cfg::runtime::RuntimeContext;
use crate::errors::CarbideCliResult;

impl Run for Args {
async fn run(self, ctx: &mut RuntimeContext) -> CarbideCliResult<()> {
let opts = GlobalOptions {
format: ctx.config.format,
page_size: ctx.config.page_size,
sort_by: &ctx.config.sort_by,
cloud_unsafe_op: if ctx.config.cloud_unsafe_op_enabled {
Some("enabled".to_string())
} else {
None
},
};
cmd::update_spx_config(&ctx.api_client, self, opts).await?;
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/admin-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ mod scout_stream;
mod set;
mod site_explorer;
mod sku;
mod spx_partition;
mod ssh;
mod switch;
mod tenant;
Expand Down Expand Up @@ -249,6 +250,7 @@ async fn main() -> color_eyre::Result<()> {
CliCommand::NetworkSegment(cmd) => cmd.dispatch(ctx).await?,
CliCommand::NvlinkNmxcEndpoints(cmd) => cmd.dispatch(ctx).await?,
CliCommand::NvlPartition(cmd) => cmd.dispatch(ctx).await?,
CliCommand::SpxPartition(cmd) => cmd.dispatch(ctx).await?,
CliCommand::IpxeTemplate(cmd) => cmd.dispatch(ctx).await?,
CliCommand::OsImage(cmd) => cmd.dispatch(ctx).await?,
CliCommand::OperatingSystem(cmd) => cmd.dispatch(ctx).await?,
Expand Down
59 changes: 56 additions & 3 deletions crates/admin-cli/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ use ::rpc::forge::{
IdentifySerialRequest, MachineHardwareInfo, MachineHardwareInfoUpdateType,
ModifyDpfStateRequest, NetworkPrefix, NetworkSecurityGroupAttributes,
NetworkSegmentCreationRequest, NetworkSegmentType, Remediation, RemediationIdList,
RemediationList, UpdateMachineHardwareInfoRequest, UpdateNetworkSecurityGroupRequest,
VpcCreationRequest, VpcSearchFilter, VpcVirtualizationType, VpcsByIdsRequest,
RemediationList, SpxPartitionSearchFilter, UpdateMachineHardwareInfoRequest,
UpdateNetworkSecurityGroupRequest, VpcCreationRequest, VpcSearchFilter, VpcVirtualizationType,
VpcsByIdsRequest,
};
use ::rpc::forge_api_client::ForgeApiClient;
use ::rpc::{Machine, NetworkSegment};
Expand All @@ -40,6 +41,7 @@ use carbide_uuid::network::NetworkSegmentId;
use carbide_uuid::nvlink::{NvLinkLogicalPartitionId, NvLinkPartitionId};
use carbide_uuid::power_shelf::PowerShelfId;
use carbide_uuid::rack::RackId;
use carbide_uuid::spx::SpxPartitionId;
use carbide_uuid::switch::SwitchId;
use carbide_uuid::vpc::VpcId;
use mac_address::MacAddress;
Expand Down Expand Up @@ -1035,6 +1037,33 @@ impl ApiClient {
Ok(all_list)
}

pub async fn get_all_spx_partitions(
&self,
tenant_org_id: Option<String>,
name: Option<String>,
page_size: usize,
) -> CarbideCliResult<rpc::SpxPartitionList> {
let all_ids = self.get_spx_partition_ids(tenant_org_id, name).await?;
let mut all_list = rpc::SpxPartitionList {
spx_partitions: Vec::with_capacity(all_ids.spx_partition_ids.len()),
};

for ids in all_ids.spx_partition_ids.chunks(page_size) {
let list = self.get_spx_partitions_by_ids(ids).await?;
all_list.spx_partitions.extend(list.spx_partitions);
}

Ok(all_list)
}

pub async fn get_one_spx_partition(
&self,
spx_partition_id: SpxPartitionId,
) -> CarbideCliResult<rpc::SpxPartitionList> {
let partitions = self.get_spx_partitions_by_ids(&[spx_partition_id]).await?;
Ok(partitions)
}

pub async fn get_one_ib_partition(
&self,
ib_partition_id: IBPartitionId,
Expand All @@ -1056,6 +1085,19 @@ impl ApiClient {
Ok(self.0.find_ib_partition_ids(request).await?)
}

async fn get_spx_partition_ids(
&self,
tenant_org_id: Option<String>,
name: Option<String>,
) -> CarbideCliResult<rpc::SpxPartitionIdList> {
let request = SpxPartitionSearchFilter {
tenant_org_id,
name,
label: None,
};
Ok(self.0.find_spx_partition_ids(request).await?)
}

async fn get_ib_partitions_by_ids(
&self,
ids: &[IBPartitionId],
Expand All @@ -1067,6 +1109,16 @@ impl ApiClient {
Ok(self.0.find_ib_partitions_by_ids(request).await?)
}

async fn get_spx_partitions_by_ids(
&self,
ids: &[SpxPartitionId],
) -> CarbideCliResult<rpc::SpxPartitionList> {
let request = rpc::SpxPartitionsByIdsRequest {
spx_partition_ids: Vec::from(ids),
};
Ok(self.0.find_spx_partitions_by_ids(request).await?)
}

pub async fn get_all_keysets(
&self,
tenant_org_id: Option<String>,
Expand Down Expand Up @@ -1267,7 +1319,7 @@ impl ApiClient {
allocate_instance
.tenant_org
.as_deref()
.unwrap_or("Forge-simulation-tenant"),
.unwrap_or("devenv_test_org"),
)
} else if !allocate_instance.vpc_prefix_id.is_empty() {
let Some(discovery_info) = &machine.discovery_info else {
Expand Down Expand Up @@ -1413,6 +1465,7 @@ impl ApiClient {
infiniband: None,
dpu_extension_services: None,
nvlink: None,
spxconfig: allocate_instance.spxconfig.clone(),
};

let mut labels = vec![
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@
* limitations under the License.
*/

//! State Controller implementation for Dpa Interface
mod show;

pub mod context;
pub mod handler;
pub mod io;
pub mod metrics;
#[cfg(test)]
mod tests;

use clap::Parser;

use crate::cfg::dispatch::Dispatch;

#[derive(Parser, Debug, Dispatch)]
pub enum Cmd {
#[clap(about = "Display SpectrumX Partition information")]
Show(show::Args),
}
Loading
Loading