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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 0 additions & 2 deletions crates/openshell-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1208,8 +1208,6 @@ enum SandboxCommands {
editor: Option<CliEditor>,

/// 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,

Expand Down
47 changes: 2 additions & 45 deletions crates/openshell-cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> = if providers_v2_enabled {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down
Loading