From 3765da4293979a03ce9f806810bf90789b80283a Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Tue, 9 Jun 2026 15:36:19 +0200 Subject: [PATCH] fix(cli)!: require explicit gpu sandbox flag BREAKING CHANGE: GPU sandbox mode is no longer inferred from sandbox image names. Users must pass --gpu to request GPU resources. Signed-off-by: Evan Lezar --- README.md | 2 +- crates/openshell-cli/src/main.rs | 2 -- crates/openshell-cli/src/run.rs | 47 ++------------------------------ 3 files changed, 3 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 4fe242d93..8dd36b8b5 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ OpenShell can pass host GPUs into sandboxes for local inference, fine-tuning, or openshell sandbox create --gpu --from [gpu-enabled-sandbox] -- claude ``` -Docker-backed GPU sandboxes auto-select CDI when available and otherwise fall back to Docker's NVIDIA GPU request path (`--gpus all`). GPU intent is also inferred automatically for community images with `gpu` in the name. +Docker-backed GPU sandboxes auto-select CDI when available and otherwise fall back to Docker's NVIDIA GPU request path (`--gpus all`). **Requirements:** NVIDIA drivers and the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) must be installed on the host. The sandbox image itself must include the appropriate GPU drivers and libraries for your workload — the default `base` image does not. See the [BYOC example](https://github.com/NVIDIA/OpenShell/tree/main/examples/bring-your-own-container) for building a custom sandbox image with GPU support. diff --git a/crates/openshell-cli/src/main.rs b/crates/openshell-cli/src/main.rs index d1fc30308..19fe2df83 100644 --- a/crates/openshell-cli/src/main.rs +++ b/crates/openshell-cli/src/main.rs @@ -1208,8 +1208,6 @@ enum SandboxCommands { editor: Option, /// Request GPU resources for the sandbox. - /// GPU intent is also inferred automatically for known GPU-designated - /// image names such as `nvidia-gpu`. #[arg(long)] gpu: bool, diff --git a/crates/openshell-cli/src/run.rs b/crates/openshell-cli/src/run.rs index 5801c6629..7290ac05e 100644 --- a/crates/openshell-cli/src/run.rs +++ b/crates/openshell-cli/src/run.rs @@ -1781,7 +1781,7 @@ pub async fn sandbox_create( } None => None, }; - let requested_gpu = gpu || image.as_deref().is_some_and(image_requests_gpu); + let requested_gpu = gpu; let providers_v2_enabled = gateway_providers_v2_enabled(&mut client).await?; let inferred_types: Vec = if providers_v2_enabled { @@ -2388,19 +2388,6 @@ fn value_looks_like_bare_dockerfile_name(value: &str) -> bool { !value.contains('/') && !value.contains(':') && filename_looks_like_dockerfile(Path::new(value)) } -fn image_requests_gpu(image: &str) -> bool { - let image_name = image - .rsplit('/') - .next() - .unwrap_or(image) - .split([':', '@']) - .next() - .unwrap_or(image) - .to_ascii_lowercase(); - - image_name.contains("gpu") -} - fn dockerfile_sources_supported_for_gateway(metadata: Option<&GatewayMetadata>) -> bool { !metadata.is_some_and(|metadata| metadata.is_remote) } @@ -7538,7 +7525,7 @@ mod tests { dockerfile_sources_supported_for_gateway, format_endpoint, format_gateway_select_header, format_gateway_select_items, format_provider_attachment_table, gateway_add, gateway_auth_label, gateway_env_override_warning, gateway_select_with, gateway_type_label, - git_sync_files, http_health_check, image_requests_gpu, import_local_package_mtls_bundle, + git_sync_files, http_health_check, import_local_package_mtls_bundle, inferred_provider_type, mtls_certs_exist_for_gateway, package_managed_tls_dirs, parse_cli_setting_value, parse_credential_expiry_cli_value, parse_credential_expiry_pairs, parse_credential_pairs, parse_driver_config_json, plaintext_gateway_is_remote, @@ -8044,36 +8031,6 @@ mod tests { assert!(sandbox_should_persist(false, Some(&spec))); } - #[test] - fn image_requests_gpu_matches_known_gpu_image_names() { - for image in [ - "ghcr.io/nvidia/openshell-community/sandboxes/nvidia-gpu:latest", - "registry.example.com/team/gpu:dev", - "nvcr.io/example/my-gpu-image@sha256:deadbeef", - ] { - assert!( - image_requests_gpu(image), - "expected GPU detection for {image}" - ); - } - } - - #[test] - fn image_requests_gpu_ignores_non_gpu_image_names() { - for image in [ - "ghcr.io/nvidia/openshell-community/sandboxes/base:latest", - "registry.example.com/gpu/team/base:latest", - "registry.example.com/team/notebook:latest", - "cuda-toolkit:latest", - "registry.example.com/team/graphics:latest", - ] { - assert!( - !image_requests_gpu(image), - "did not expect GPU detection for {image}" - ); - } - } - #[test] fn resolve_from_classifies_existing_dockerfile_path() { let temp = tempfile::tempdir().expect("failed to create tempdir");