Skip to content

Report run status from Slurm exit code in SlurmContainer - #964

Open
malagows-nvd wants to merge 2 commits into
NVIDIA:mainfrom
malagows-nvd:mm/slurmcontainer-add-wasrunsuccessful
Open

Report run status from Slurm exit code in SlurmContainer#964
malagows-nvd wants to merge 2 commits into
NVIDIA:mainfrom
malagows-nvd:mm/slurmcontainer-add-wasrunsuccessful

Conversation

@malagows-nvd

@malagows-nvd malagows-nvd commented Jul 8, 2026

Copy link
Copy Markdown

Grade the run via was_run_successful() - now based on the per-test exit_code.txt file (non-zero = FAILED).

Summary

Every run of SlurmContainer workload was reported PASSED in the scenario summary regardless of what the
container actually did. Grade the run from the container real exit code, which CloudAI already records in slurm-job.toml

Implement was_run_successful() to grade each run from the container command's actual exit code. The generated command writes the exit code to a per-test exit_code.txt file, allowing accurate reporting in both regular and single-sbatch modes without changes to user scripts or container images.

Test Plan

Scenario TOML
name = "Verify.SlurmContainer.StatusCheck"
job_status_check = false

[[Tests]]
id = "Verify.SlurmContainer.Pass"
name = "slurmcontainer-pass"
description = "Should be reported PASSED (exit 0)"
test_template_name = "SlurmContainer"
num_nodes = 1
time_limit = "00:05:00"
extra_srun_args = "--ntasks-per-node=1"

  [Tests.cmd_args]
  docker_image_url = "nvcr.io#nvidia/cuda:12.9.1-devel-ubuntu24.04"
  cmd = "bash -c 'echo PASS-CASE; exit 0'"

[[Tests]]
id = "Verify.SlurmContainer.Fail"
name = "slurmcontainer-fail"
description = "Should be reported FAILED (exit 42)"
test_template_name = "SlurmContainer"
num_nodes = 1
time_limit = "00:05:00"
extra_srun_args = "--ntasks-per-node=1"

  [Tests.cmd_args]
  docker_image_url = "nvcr.io#nvidia/cuda:12.9.1-devel-ubuntu24.04"
  cmd = "bash -c 'echo FAIL-CASE; exit 42'"
CloudAI run

[INFO] System Name: ...
[INFO] Scheduler: slurm
[INFO] Test Scenario Name: Verify.SlurmContainer.StatusCheck
[INFO] Checking if workloads components are installed.
[INFO] Test Scenario: Verify.SlurmContainer.StatusCheck

Section Name: Verify.SlurmContainer.Pass
  Test Name: slurmcontainer-pass
  Description: Should be reported PASSED (exit 0)
  No dependencies
Section Name: Verify.SlurmContainer.Fail
  Test Name: slurmcontainer-fail
  Description: Should be reported FAILED (exit 42)
  No dependencies
[INFO] Initializing Runner [RUN] mode
[INFO] Creating SlurmRunner
[INFO] Scenario results will be stored at: results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03
[INFO] Starting test: Verify.SlurmContainer.Pass (results at: results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03/Verify.SlurmContainer.Pass/0)
[INFO] Running test: Verify.SlurmContainer.Pass
[INFO] Submitted slurm job: 74658
[INFO] Starting test: Verify.SlurmContainer.Fail (results at: results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03/Verify.SlurmContainer.Fail/0)
[INFO] Running test: Verify.SlurmContainer.Fail
[INFO] Submitted slurm job: 74659
[INFO] Job completed: Verify.SlurmContainer.Pass (iteration 1 of 1)
[ERROR] Job 74659 for test Verify.SlurmContainer.Fail failed: Container command exited with code 42.
[INFO] Job completed: Verify.SlurmContainer.Fail (iteration 1 of 1)
[INFO] Generated scenario report at results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03/Verify.SlurmContainer.StatusCheck.html
[INFO] Scenario results                                                                                                                    
╔════════════════════════════╤════════╤════════════════════════════════════════════════════════════════════════════════════════════╗
║ Case                       │ Status │ Details                                                                                    ║
╟────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────────────────╢
║ Verify.SlurmContainer.Pass │ PASSED │ results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03/Verify.SlurmContainer.Pass/0 ║
╟────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────────────────╢
║ Verify.SlurmContainer.Fail │ FAILED │ results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03/Verify.SlurmContainer.Fail/0 ║
║                            │        │ Container command exited with code 42.                                                     ║
╚════════════════════════════╧════════╧════════════════════════════════════════════════════════════════════════════════════════════╝

[INFO] Created tarball at results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-50-03.tgz
[INFO] All jobs are complete.

CloudAI run --single-sbatch
[INFO] System Name: ...
[INFO] Scheduler: slurm
[INFO] Test Scenario Name: Verify.SlurmContainer.StatusCheck
[INFO] Checking if workloads components are installed.
[INFO] Test Scenario: Verify.SlurmContainer.StatusCheck

Section Name: Verify.SlurmContainer.Pass
  Test Name: slurmcontainer-pass
  Description: Should be reported PASSED (exit 0)
  No dependencies
Section Name: Verify.SlurmContainer.Fail
  Test Name: slurmcontainer-fail
  Description: Should be reported FAILED (exit 42)
  No dependencies
[INFO] Initializing Runner [RUN] mode
[INFO] Creating SingleSbatchRunner
[INFO] Scenario results will be stored at: results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-45-31
[INFO] Submitted slurm job: 74656
[INFO] Generated scenario report at results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-45-31/Verify.SlurmContainer.StatusCheck.html
[INFO] Scenario results                                                                                                                    
╔════════════════════════════╤════════╤════════════════════════════════════════════════════════════════════════════════════════════╗
║ Case                       │ Status │ Details                                                                                    ║
╟────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────────────────╢
║ Verify.SlurmContainer.Pass │ PASSED │ results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-45-31/Verify.SlurmContainer.Pass/0 ║
╟────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────────────────╢
║ Verify.SlurmContainer.Fail │ FAILED │ results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-45-31/Verify.SlurmContainer.Fail/0 ║
║                            │        │ Container command exited with code 42.                                                     ║
╚════════════════════════════╧════════╧════════════════════════════════════════════════════════════════════════════════════════════╝

[INFO] Created tarball at results/Verify.SlurmContainer.StatusCheck_2026-08-04_12-45-31.tgz
[INFO] All jobs are complete.
PyTest (SlurmContainer)
uv run --extra dev pytest tests/workloads/slurm_container/ -v
==================================================================================================================== test session starts ====================================================================================================================
platform linux -- Python 3.14.6, pytest-9.0.3, pluggy-1.6.0 -- /auto/mtrswgwork/mmalagowski/workspace/cloudai-fix-slurmcontainer/.venv/bin/python3
cachedir: .pytest_cache
rootdir: /auto/mtrswgwork/mmalagowski/workspace/cloudai-fix-slurmcontainer
configfile: pyproject.toml
plugins: cov-7.0.0, anyio-4.12.1, deadfixtures-3.1.0
collected 13 items                                                                                                                                                                                                                                          

tests/workloads/slurm_container/test_command_gen_strategy_slurm.py::test_default PASSED                                                                                                                                                               [  7%]
tests/workloads/slurm_container/test_command_gen_strategy_slurm.py::test_with_nsys PASSED                                                                                                                                                             [ 15%]
tests/workloads/slurm_container/test_command_gen_strategy_slurm.py::test_with_extra_srun_args PASSED                                                                                                                                                  [ 23%]
tests/workloads/slurm_container/test_command_gen_strategy_slurm.py::test_single_sbatch_writes_exit_code_to_per_test_output PASSED                                                                                                                     [ 30%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_missing_exit_code_fails PASSED                                                                                                                          [ 38%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_exit_code_is_honored[0-True] PASSED                                                                                                                     [ 46%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_exit_code_is_honored[0\n-True] PASSED                                                                                                                   [ 53%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_exit_code_is_honored[1-False] PASSED                                                                                                                    [ 61%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_exit_code_is_honored[42-False] PASSED                                                                                                                   [ 69%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_exit_code_is_honored[137-False] PASSED                                                                                                                  [ 76%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_malformed_exit_code_is_reported PASSED                                                                                                                  [ 84%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_unreadable_exit_code_is_reported PASSED                                                                                                                 [ 92%]
tests/workloads/slurm_container/test_slurm_container.py::TestSlurmContainerSuccessCheck::test_undecodable_exit_code_is_reported PASSED                                                                                                                [100%]

==================================================================================================================== 13 passed in 0.30s ====================================================================================================================
PyTest (all)
...
tests/workloads/ucc_test/test_report_gen_strategy.py ..                                                                                                                                                                                               [ 96%]
tests/workloads/vllm/test_command_gen_strategy_slurm.py ........................                                                                                                                                                                      [ 97%]
tests/workloads/vllm/test_job_status_retrieval_strategy.py .......                                                                                                                                                                                    [ 97%]
tests/workloads/vllm/test_report_gen_strategy.py .....................                                                                                                                                                                                [ 99%]
tests/workloads/vllm/test_workload.py ................                                                                                                                                                                                                [100%]

===================================================================================================== 1819 passed, 5 skipped, 510 deselected in 28.25s ======================================================================================================

Additional Notes

None

@malagows-nvd
malagows-nvd marked this pull request as draft July 8, 2026 12:24
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 4bd8a393-3ffe-44d1-a2bc-1194d817cffb

📥 Commits

Reviewing files that changed from the base of the PR and between d6d97b2 and 3cd366f.

📒 Files selected for processing (3)
  • src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py
  • tests/ref_data/slurm_container.sbatch
  • tests/workloads/slurm_container/test_command_gen_strategy_slurm.py

📝 Walkthrough

Walkthrough

Adds exit-code recording to generated Slurm container commands and adds was_run_successful grading from exit_code.txt. Tests cover command wrapping, output mounting, missing or invalid files, read errors, and zero or nonzero exit codes. Documentation updates configuration examples and status rules.

Changes

Slurm container exit status handling

Layer / File(s) Summary
Exit status grading contract
src/cloudai/workloads/slurm_container/slurm_container.py, tests/workloads/slurm_container/test_slurm_container.py
Defines EXIT_CODE_FILE_NAME and grades runs from exit_code.txt. Missing, unreadable, undecodable, and invalid files return unsuccessful results. Zero indicates success, and nonzero values indicate failure.
Command exit status recording
src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py, tests/workloads/slurm_container/test_command_gen_strategy_slurm.py, tests/ref_data/slurm_container.sbatch
Wraps generated commands, writes their exit status to the per-test results directory, and exits with the same status. Tests cover standard, Nsight Systems, extra-argument, single-batch, and multi-task behavior.
Configuration and status documentation
doc/workloads/slurm_container.rst
Replaces image_path with docker_image_url and documents exit-code-based status results.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: jj10306

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: reporting SlurmContainer run status from the Slurm exit code.
Description check ✅ Passed The description directly explains the exit-code-based grading implementation, test coverage, and observed results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cloudai/workloads/slurm_container/slurm_container.py`:
- Around line 71-72: The `was_run_successful` path in `SlurmContainer` currently
lets `toml.load()` and `SlurmJobMetadata.model_validate()` throw on bad or
partial `slurm-job.toml`, which can abort `Reporter.is_successful()` and
`BaseRunner.get_job_status()`. Wrap the metadata parsing in this method with
error handling, catch parse/validation failures, and return a failed
`JobStatusResult` that includes an error message instead of propagating the
exception. Keep the fix localized to the `was_run_successful` logic and preserve
the existing success path when metadata loads correctly.

In `@tests/workloads/slurm_container/test_slurm_container.py`:
- Around line 62-73: The pytest parametrization in the test module uses a tuple
of tuples for `pytest.mark.parametrize`, which triggers PT007. Update the
`parametrize` values in `test_slurm_container.py` to use a list of tuples
instead of a tuple, keeping the existing `exit_code` and `is_successful` cases
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: ff3fb4b3-e0f1-470e-8df6-c60fa43d873b

📥 Commits

Reviewing files that changed from the base of the PR and between 2dd195d and a286eb8.

📒 Files selected for processing (2)
  • src/cloudai/workloads/slurm_container/slurm_container.py
  • tests/workloads/slurm_container/test_slurm_container.py

Comment thread src/cloudai/workloads/slurm_container/slurm_container.py Outdated
Comment thread tests/workloads/slurm_container/test_slurm_container.py
@malagows-nvd
malagows-nvd force-pushed the mm/slurmcontainer-add-wasrunsuccessful branch from a286eb8 to 3081afb Compare July 8, 2026 13:57
@malagows-nvd
malagows-nvd force-pushed the mm/slurmcontainer-add-wasrunsuccessful branch 2 times, most recently from 1551373 to fda7f77 Compare August 4, 2026 12:52
@malagows-nvd
malagows-nvd marked this pull request as ready for review August 4, 2026 13:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@doc/workloads/slurm_container.rst`:
- Around line 56-58: Update the success-criteria documentation to describe
CloudAI reading per-test exit_code.txt from the test output directory: only
integer 0 succeeds, while non-zero, missing, malformed, unreadable, or
undecodable files fail the run; explicitly remove the claim that 0:0 is
accepted.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 5d2f4b8f-7cbc-44f2-8335-f5ddd5934faf

📥 Commits

Reviewing files that changed from the base of the PR and between a286eb8 and fda7f77.

📒 Files selected for processing (6)
  • doc/workloads/slurm_container.rst
  • src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py
  • src/cloudai/workloads/slurm_container/slurm_container.py
  • tests/ref_data/slurm_container.sbatch
  • tests/workloads/slurm_container/test_command_gen_strategy_slurm.py
  • tests/workloads/slurm_container/test_slurm_container.py

Comment thread doc/workloads/slurm_container.rst Outdated
Grade the run via was_run_successful() - now based on the
per-test exit_code.txt file (non-zero = FAILED).

Document the exit-code file and its parsing and failure rules.

Signed-off-by: Marcin Malagowski <mmalagowski@nvidia.com>
@malagows-nvd
malagows-nvd force-pushed the mm/slurmcontainer-add-wasrunsuccessful branch from fda7f77 to d6d97b2 Compare August 4, 2026 13:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py`:
- Around line 49-55: Change the wrapper generated by the Slurm command strategy
so one aggregate srun status is recorded outside per-task container execution,
or collect per-task statuses and fail if any task fails; do not let concurrent
tasks overwrite a shared result with the last writer’s status. Update
tests/workloads/slurm_container/test_command_gen_strategy_slurm.py lines 32-38
for the new wrapper, add coverage at lines 114-128 for differing multi-task exit
codes, and regenerate tests/ref_data/slurm_container.sbatch line 17.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 090b383f-afa9-4d4f-b63d-176bc858e827

📥 Commits

Reviewing files that changed from the base of the PR and between fda7f77 and d6d97b2.

📒 Files selected for processing (6)
  • doc/workloads/slurm_container.rst
  • src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py
  • src/cloudai/workloads/slurm_container/slurm_container.py
  • tests/ref_data/slurm_container.sbatch
  • tests/workloads/slurm_container/test_command_gen_strategy_slurm.py
  • tests/workloads/slurm_container/test_slurm_container.py

Comment thread src/cloudai/workloads/slurm_container/slurm_command_gen_strategy.py Outdated
Move exit-code recording outside per-task container execution so one
host-side writer records the aggregate srun result. Add multi-task
coverage and update the sbatch reference.

Signed-off-by: Marcin Malagowski <mmalagowski@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant