Skip to content

Commit 9c16729

Browse files
committed
refactor(sandbox): add ResourceSpec for sandbox resources
Signed-off-by: Ryan Angilly <rangilly@nvidia.com>
1 parent 3dd8d5a commit 9c16729

12 files changed

Lines changed: 592 additions & 266 deletions

File tree

architecture/compute-runtimes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ Custom sandbox images must include the agent runtime and any system
6363
dependencies, but they should not need to include the gateway. GPU-capable
6464
images must include the user-space libraries required by the workload. The
6565
runtime still owns GPU device injection or resource scheduling. Kubernetes maps
66-
template resource limits such as `nvidia.com/gpu` into the sandbox pod when the
67-
cluster exposes those resources.
66+
portable `SandboxSpec.resources` CPU, memory, and GPU count requirements into
67+
pod resource requests and limits when the cluster exposes those resources.
6868

6969
## Deployment Shape
7070

crates/openshell-cli/src/main.rs

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,7 @@ enum DoctorCommands {
10301030
}
10311031

10321032
#[derive(Subcommand, Debug)]
1033+
#[allow(clippy::large_enum_variant)]
10331034
enum SandboxCommands {
10341035
/// Create a sandbox.
10351036
#[command(help_template = LEAF_HELP_TEMPLATE, next_help_heading = "FLAGS")]
@@ -1088,21 +1089,33 @@ enum SandboxCommands {
10881089
///
10891090
/// This implies --gpu. Kubernetes-backed gateways schedule pods with
10901091
/// the corresponding nvidia.com/gpu resource limit.
1091-
#[arg(long, value_name = "COUNT", value_parser = clap::value_parser!(u32).range(1..))]
1092+
#[arg(long, value_name = "COUNT", value_parser = clap::value_parser!(u32).range(1..), conflicts_with = "gpu_device")]
10921093
gpu_count: Option<u32>,
10931094

1094-
/// Set compute resource requests and limits as JSON.
1095-
///
1096-
/// The JSON must be an object with the same shape as
1097-
/// SandboxTemplate.resources, for example:
1098-
/// {"requests":{"cpu":"2"},"limits":{"cpu":"16"}}
1099-
#[arg(long, value_name = "JSON")]
1100-
resources_json: Option<String>,
1095+
/// Minimum CPU cores requested, e.g. "500m" or "2".
1096+
#[arg(long, value_name = "QUANTITY")]
1097+
cpu_request: Option<String>,
1098+
1099+
/// Maximum CPU cores allowed, e.g. "2" or "4".
1100+
#[arg(long, value_name = "QUANTITY")]
1101+
cpu_limit: Option<String>,
1102+
1103+
/// Minimum memory requested, e.g. "512Mi" or "4Gi".
1104+
#[arg(long, value_name = "QUANTITY")]
1105+
memory_request: Option<String>,
1106+
1107+
/// Maximum memory allowed, e.g. "1Gi" or "8Gi".
1108+
#[arg(long, value_name = "QUANTITY")]
1109+
memory_limit: Option<String>,
1110+
1111+
/// Driver-specific resource configuration as KEY=VALUE.
1112+
#[arg(long = "resource-config", value_name = "KEY=VALUE")]
1113+
resource_config: Vec<String>,
11011114

11021115
/// Target a driver-specific GPU device. Docker and Podman use CDI device IDs
11031116
/// (for example "nvidia.com/gpu=0"); VM uses a PCI BDF or index.
11041117
/// Only valid with --gpu. When omitted with --gpu, the driver uses its default GPU selection.
1105-
#[arg(long, requires = "gpu")]
1118+
#[arg(long, requires = "gpu", conflicts_with = "gpu_count")]
11061119
gpu_device: Option<String>,
11071120

11081121
/// Provider names to attach to this sandbox.
@@ -2380,7 +2393,11 @@ async fn main() -> Result<()> {
23802393
editor,
23812394
gpu,
23822395
gpu_count,
2383-
resources_json,
2396+
cpu_request,
2397+
cpu_limit,
2398+
memory_request,
2399+
memory_limit,
2400+
resource_config,
23842401
gpu_device,
23852402
providers,
23862403
policy,
@@ -2447,8 +2464,14 @@ async fn main() -> Result<()> {
24472464
upload_spec.as_ref(),
24482465
keep,
24492466
gpu,
2450-
gpu_count,
2451-
resources_json.as_deref(),
2467+
run::SandboxResourceArgs {
2468+
cpu_request: cpu_request.as_deref(),
2469+
cpu_limit: cpu_limit.as_deref(),
2470+
memory_request: memory_request.as_deref(),
2471+
memory_limit: memory_limit.as_deref(),
2472+
gpu_count,
2473+
driver_config: &resource_config,
2474+
},
24522475
gpu_device.as_deref(),
24532476
editor,
24542477
&providers,
@@ -3853,27 +3876,66 @@ mod tests {
38533876
}
38543877

38553878
#[test]
3856-
fn sandbox_create_resources_json_parses() {
3879+
fn sandbox_create_resource_spec_flags_parse() {
38573880
let cli = Cli::try_parse_from([
38583881
"openshell",
38593882
"sandbox",
38603883
"create",
3861-
"--resources-json",
3862-
r#"{"requests":{"cpu":"2"},"limits":{"cpu":"16"}}"#,
3884+
"--cpu-request",
3885+
"2",
3886+
"--cpu-limit",
3887+
"4",
3888+
"--memory-request",
3889+
"8Gi",
3890+
"--memory-limit",
3891+
"16Gi",
3892+
"--resource-config",
3893+
"kubernetes.resource-name=nvidia.com/gpu",
38633894
])
3864-
.expect("sandbox create --resources-json should parse");
3895+
.expect("sandbox create resource flags should parse");
38653896

38663897
match cli.command {
38673898
Some(Commands::Sandbox {
3868-
command: Some(SandboxCommands::Create { resources_json, .. }),
3899+
command:
3900+
Some(SandboxCommands::Create {
3901+
cpu_request,
3902+
cpu_limit,
3903+
memory_request,
3904+
memory_limit,
3905+
resource_config,
3906+
..
3907+
}),
38693908
..
38703909
}) => {
3910+
assert_eq!(cpu_request.as_deref(), Some("2"));
3911+
assert_eq!(cpu_limit.as_deref(), Some("4"));
3912+
assert_eq!(memory_request.as_deref(), Some("8Gi"));
3913+
assert_eq!(memory_limit.as_deref(), Some("16Gi"));
38713914
assert_eq!(
3872-
resources_json.as_deref(),
3873-
Some(r#"{"requests":{"cpu":"2"},"limits":{"cpu":"16"}}"#)
3915+
resource_config,
3916+
vec!["kubernetes.resource-name=nvidia.com/gpu".to_string()]
38743917
);
38753918
}
38763919
other => panic!("expected sandbox create command, got: {other:?}"),
38773920
}
38783921
}
3922+
3923+
#[test]
3924+
fn sandbox_create_gpu_count_conflicts_with_gpu_device() {
3925+
let result = Cli::try_parse_from([
3926+
"openshell",
3927+
"sandbox",
3928+
"create",
3929+
"--gpu",
3930+
"--gpu-count",
3931+
"2",
3932+
"--gpu-device",
3933+
"nvidia.com/gpu=0",
3934+
]);
3935+
3936+
assert!(
3937+
result.is_err(),
3938+
"sandbox create should reject combining --gpu-count and --gpu-device"
3939+
);
3940+
}
38793941
}

0 commit comments

Comments
 (0)