Skip to content
Merged
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
11 changes: 7 additions & 4 deletions crates/admin-cli/src/instance/allocate/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
*/

use carbide_uuid::machine::MachineId;
use carbide_uuid::vpc::VpcPrefixId;
use carbide_uuid::vpc::{VpcId, VpcPrefixId};
use clap::{ArgGroup, Parser};
use rpc::forge::{InstanceOperatingSystemConfig, InstanceSpxConfig};

#[derive(Parser, Debug)]
#[clap(group(ArgGroup::new("selector").required(true).args(&["subnet", "vpc_prefix_id"])))]
#[clap(group(ArgGroup::new("selector").required(true).multiple(true).args(&["subnet", "vpc_prefix_id", "flat_vpc_id"])))]
#[command(after_long_help = "\
EXAMPLES:

Expand Down Expand Up @@ -101,8 +101,11 @@ pub struct Args {
#[clap(short, long, help = "The VPC prefix to assign to a PF")]
pub vpc_prefix_id: Vec<VpcPrefixId>,

#[clap(long, help = "Allocate a zero-dpu host")]
pub zero_dpu: bool,
#[clap(
long,
help = "Create an instance in the given \"flat\" VPC, for machines without DPUs"
)]
pub flat_vpc_id: Option<VpcId>,

#[clap(long, help = "The VPC prefix to assign to a VF")]
pub vf_vpc_prefix_id: Vec<VpcPrefixId>,
Expand Down
4 changes: 2 additions & 2 deletions crates/admin-cli/src/instance/allocate/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub async fn allocate(
api_client,
&mut machine_ids,
min_interface_count,
allocate_request.zero_dpu,
allocate_request.flat_vpc_id,
)
.await
else {
Expand Down Expand Up @@ -109,7 +109,7 @@ pub async fn allocate(
api_client,
&mut machine_ids,
min_interface_count,
allocate_request.zero_dpu,
allocate_request.flat_vpc_id,
)
.await
else {
Expand Down
204 changes: 123 additions & 81 deletions crates/admin-cli/src/instance/show/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,99 +178,130 @@ async fn convert_instance_to_nice_format(

let width = 25;
writeln!(&mut lines, "INTERFACES:")?;
let if_configs = instance
let network_config = instance
.config
.as_ref()
.and_then(|config| config.network.as_ref())
.and_then(|config| config.network.as_ref());
let if_configs = network_config
.map(|config| config.interfaces.as_slice())
.unwrap_or_default();
let auto_network = network_config.is_some_and(|config| config.auto_config.is_some());
let if_status = instance
.status
.as_ref()
.and_then(|status| status.network.as_ref())
.map(|status| status.interfaces.as_slice())
.unwrap_or_default();

if if_configs.is_empty() || if_status.is_empty() {
if if_status.is_empty() {
writeln!(&mut lines, "\tEMPTY")?;
} else if if_configs.len() != if_status.len() {
} else if !auto_network && if_configs.len() != if_status.len() {
writeln!(&mut lines, "\tLENGTH MISMATCH")?;
} else {
for (i, interface) in if_configs.iter().enumerate() {
let status = &if_status[i];

let vpc = if let Some(network_segment_id) = interface.network_segment_id {
get_vpc_for_interface_network_segment(api_client, network_segment_id).await?
} else {
None
};

let data: &[(&str, Cow<str>)] = &[
(
"FUNCTION_TYPE",
forgerpc::InterfaceFunctionType::try_from(interface.function_type)
.ok()
.map(|ty| format!("{ty:?}").into())
.unwrap_or_else(|| "INVALID".into()),
),
(
"VF ID",
status
.virtual_function_id
.map(|id| id.to_string().into())
.unwrap_or_default(),
),
(
"SEGMENT ID",
interface
.network_segment_id
.unwrap_or_default()
.to_string()
let vpcs: Vec<Option<Vpc>> = if auto_network {
futures::future::join_all(
if_status
.iter()
.filter_map(|s| s.vpc_id)
.map(|vpc_id| get_vpc_by_id(api_client, vpc_id)),
)
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?
.into_iter()
} else {
futures::future::join_all(if_configs.iter().filter_map(|c| c.network_segment_id).map(
|segment_id| async move {
get_vpc_for_interface_network_segment(api_client, segment_id).await
},
))
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?
.into_iter()
}
.collect();
if !auto_network && if_configs.len() != if_status.len() {
writeln!(&mut lines, "\tLENGTH MISMATCH")?;
} else {
for (idx, status) in if_status.iter().enumerate() {
let vpc = vpcs.get(idx);
let if_config = if_configs.get(idx);
let data: &[(&str, Cow<str>)] = &[
(
"FUNCTION_TYPE",
format!(
"{:?}",
match status.virtual_function_id {
Some(_) => forgerpc::InterfaceFunctionType::Virtual,
None => forgerpc::InterfaceFunctionType::Physical,
}
)
.into(),
),
(
"VPC PREFIX ID",
match &interface.network_details {
Some(forgerpc::instance_interface_config::NetworkDetails::SegmentId(_)) => {
"Segment Based Allocation".into()
}
Some(forgerpc::instance_interface_config::NetworkDetails::VpcPrefixId(
x,
)) => x.to_string().into(),
None => "NA".into(),
},
),
(
"MAC ADDR",
status
.mac_address
.as_ref()
.map(|s| s.as_str().into())
.unwrap_or_default(),
),
("ADDRESSES", status.addresses.as_slice().join(", ").into()),
(
"VPC ID",
vpc.as_ref()
.map(|v| v.id.unwrap_or_default().to_string().into())
.unwrap_or("<not found>".into()),
),
(
"VPC NAME",
vpc.as_ref()
.and_then(|v| v.metadata.as_ref())
.map(|v| Cow::Borrowed(v.name.as_str()))
),
(
"VF ID",
status
.virtual_function_id
.map(|id| id.to_string().into())
.unwrap_or_default(),
),
(
"SEGMENT ID",
if_config
.and_then(|c| c.network_segment_id)
.unwrap_or_default()
.to_string()
.into(),
),
(
"VPC PREFIX ID",
match if_config.and_then(|c| c.network_details.as_ref()) {
Some(
forgerpc::instance_interface_config::NetworkDetails::SegmentId(_),
) => "Segment Based Allocation".into(),
Some(
forgerpc::instance_interface_config::NetworkDetails::VpcPrefixId(x),
) => x.to_string().into(),
None => "NA".into(),
},
),
(
"MAC ADDR",
status
.mac_address
.as_ref()
.map(|s| s.as_str().into())
.unwrap_or_default(),
),
("ADDRESSES", status.addresses.as_slice().join(", ").into()),
(
"VPC ID",
vpc.map(|v| {
v.as_ref()
.and_then(|v| v.id)
.unwrap_or_default()
.to_string()
.into()
})
.unwrap_or("<not found>".into()),
),
];

for (key, value) in data {
writeln!(&mut lines, "\t{key:<width$}: {value}")?;
),
(
"VPC NAME",
vpc.and_then(|v| v.as_ref().and_then(|v| v.metadata.as_ref()))
.map(|v| Cow::Borrowed(v.name.as_str()))
.unwrap_or("<not found>".into()),
),
];

for (key, value) in data {
writeln!(&mut lines, "\t{key:<width$}: {value}")?;
}
writeln!(
&mut lines,
"\t--------------------------------------------------"
)?;
}
writeln!(
&mut lines,
"\t--------------------------------------------------"
)?;
}
}

Expand Down Expand Up @@ -555,7 +586,6 @@ pub async fn handle_show(args: Args, ctx: &mut RuntimeContext) -> CarbideCliResu
Ok(())
}

#[allow(deprecated)]
async fn get_vpc_for_interface_network_segment(
api_client: &ApiClient,
network_segment_id: NetworkSegmentId,
Expand All @@ -565,10 +595,10 @@ async fn get_vpc_for_interface_network_segment(
.await?;

if !network_segments.network_segments.is_empty()
&& let Some(vpc_id) = network_segments
.network_segments
.first()
.and_then(|s| s.config.as_ref().and_then(|c| c.vpc_id).or(s.vpc_id))
&& let Some(vpc_id) = network_segments.network_segments.first().and_then(|s| {
#[allow(deprecated)]
s.config.as_ref().and_then(|c| c.vpc_id).or(s.vpc_id)
})
{
let vpc_ids: Vec<VpcId> = vec![vpc_id];
Ok(api_client
Expand All @@ -582,3 +612,15 @@ async fn get_vpc_for_interface_network_segment(
Ok(None)
}
}

async fn get_vpc_by_id(api_client: &ApiClient, vpc_id: VpcId) -> CarbideCliResult<Option<Vpc>> {
Ok(api_client
.0
.find_vpcs_by_ids(VpcsByIdsRequest {
vpc_ids: vec![vpc_id],
})
.await?
.vpcs
.into_iter()
.next())
}
19 changes: 16 additions & 3 deletions crates/admin-cli/src/machine/show/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::fmt::Write;
use ::rpc::admin_cli::OutputFormat;
use ::rpc::forge as forgerpc;
use carbide_uuid::machine::MachineId;
use carbide_uuid::vpc::VpcId;
use prettytable::{Table, row};
use rpc::Machine;

Expand Down Expand Up @@ -428,7 +429,7 @@ pub async fn get_next_free_machine(
api_client: &ApiClient,
machine_ids: &mut VecDeque<MachineId>,
min_interface_count: usize,
zero_dpu: bool,
flat_vpc_id: Option<VpcId>,
) -> Option<Machine> {
while let Some(id) = machine_ids.pop_front() {
tracing::debug!("Checking {}", id);
Expand All @@ -437,8 +438,20 @@ pub async fn get_next_free_machine(
tracing::debug!("Machine is not ready");
continue;
}
if zero_dpu {
return Some(machine);
if flat_vpc_id.is_some() {
if machine
.instance_network_restrictions
.as_ref()
.is_some_and(|r| {
r.network_segment_membership_type()
== forgerpc::InstanceNetworkSegmentMembershipType::Static
})
{
return Some(machine);
} else {
tracing::debug!(machine_id = %id, "machine does not support flat VPC auto allocation");
continue;
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if let Some(discovery_info) = &machine.discovery_info {
let dpu_interfaces = discovery_info
Expand Down
Loading
Loading