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
18 changes: 12 additions & 6 deletions src/holoscan_cli/container/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,12 @@ def run(
) -> None:
"""Launch the container"""

if not self.dryrun:
default_run_args = shlex.split(HoloscanContainer.DEFAULT_DOCKER_RUN_ARGS or "")
extra_run_args = shlex.split(docker_opts or "")
configured_runtime = get_cli_arg_value(default_run_args + extra_run_args, "--runtime")
runtime = configured_runtime or "nvidia"

if not self.dryrun and runtime == "nvidia":
check_nvidia_ctk()

if local_sdk_root is not None:
Expand All @@ -562,8 +567,6 @@ def run(
# If the caller already supplies --cidfile (via DEFAULT_DOCKER_RUN_ARGS or
# docker_opts), use that path for cleanup and skip injecting our own —
# Docker rejects duplicate --cidfile flags.
default_run_args = shlex.split(HoloscanContainer.DEFAULT_DOCKER_RUN_ARGS or "")
extra_run_args = shlex.split(docker_opts or "")
explicit_cidfile = get_cli_arg_value(default_run_args + extra_run_args, "--cidfile")
internal_cidfile: Optional[Path] = None
if explicit_cidfile:
Expand All @@ -579,7 +582,7 @@ def run(
cmd.extend(["--cidfile", str(internal_cidfile)])
cmd.extend(self.get_security_args(as_root))
cmd.extend(self.get_volume_args(add_volumes, enable_mps))
cmd.extend(self.get_gpu_runtime_args())
cmd.extend(self.get_gpu_runtime_args(None if configured_runtime is not None else runtime))
cmd.extend(self.get_environment_args())

cmd.extend(self.get_conditional_options(use_tini, persistent))
Expand Down Expand Up @@ -733,9 +736,12 @@ def get_device_cgroup_args(self) -> List[str]:
"c 189:* rmw", # /dev/bus/usb/*
]

def get_gpu_runtime_args(self) -> List[str]:
def get_gpu_runtime_args(self, runtime: Optional[str] = "nvidia") -> List[str]:
args = []
args.extend(self.get_nvidia_runtime_args())
if runtime == "nvidia":
args.extend(self.get_nvidia_runtime_args())
elif runtime is not None:
args.extend(["--runtime", runtime])
args.extend(
[
"--cap-add",
Expand Down
12 changes: 7 additions & 5 deletions tests/unit/test_container_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,15 +493,15 @@ def test_build_dryrun_omits_base_sdk_version_when_not_configured(tmp_path, monke
assert not any(arg.startswith("BASE_SDK_VERSION=") for arg in first)


def test_run_dryrun_assembles_docker_command_without_runtime_checks(tmp_path, monkeypatch):
"""Dry-run container launch covers docker-run argument composition while
skipping NVIDIA runtime validation and the real docker command."""
def test_run_assembles_docker_command_without_ctk_for_custom_runtime(tmp_path, monkeypatch):
"""A custom Docker runtime bypasses NVIDIA Container Toolkit validation."""
project_dir = tmp_path / "applications" / "my_app"
project_dir.mkdir(parents=True)
(project_dir / "Dockerfile").write_text("FROM scratch\n", encoding="utf-8")
volume = tmp_path / "input-data"
volume.mkdir()
calls = []
ctk_checks = []
monkeypatch.delenv("DISPLAY", raising=False)
monkeypatch.delenv("WAYLAND_DISPLAY", raising=False)
monkeypatch.delenv("HOLOSCAN_CLI_ENABLE_SCCACHE", raising=False)
Expand All @@ -510,6 +510,7 @@ def test_run_dryrun_assembles_docker_command_without_runtime_checks(tmp_path, mo
monkeypatch.setattr(container_core, "get_image_pythonpath", lambda img, dryrun: "/image/python")
monkeypatch.setattr(container_core, "get_group_id", lambda group: {"video": 44}.get(group))
monkeypatch.setattr(container_core, "run_command", lambda cmd, **kwargs: calls.append(cmd))
monkeypatch.setattr(container_core, "check_nvidia_ctk", lambda: ctk_checks.append(True))

c = _stub_container(
tmp_path,
Expand All @@ -519,15 +520,14 @@ def test_run_dryrun_assembles_docker_command_without_runtime_checks(tmp_path, mo
"metadata": {"language": "python"},
},
)
c.dryrun = True
c.verbose = True

c.run(
img="custom:image",
use_tini=True,
persistent=False,
as_root=False,
docker_opts="--name smoke --cidfile /tmp/custom.cid",
docker_opts="--name smoke --cidfile /tmp/custom.cid --runtime runc",
add_volumes=[str(volume)],
nsys_profile=True,
nsys_location="/opt/nsys",
Expand Down Expand Up @@ -555,6 +555,8 @@ def test_run_dryrun_assembles_docker_command_without_runtime_checks(tmp_path, mo
assert "NGC_CLI_ORG=nvidia" in cmd
assert "--name" in cmd
assert "/tmp/custom.cid" in cmd
assert container_core.get_cli_arg_value(cmd, "--runtime") == "runc"
assert not ctk_checks
assert cmd[-4:] == ["custom:image", "bash", "-lc", "echo ok"]


Expand Down
Loading