| ############################################################################ | |
| # Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| ############################################################################ | |
| """ | |
| Test that a batch job whose prolog is interrupted by a scontrol reconfigure | |
| still completes normally. | |
| With PrologFlags=Alloc,Contain,DeferBatch the batch launch is held in the | |
| agent defer_list until the prolog finishes. A reconfigure discards the | |
| in-memory defer_list; on recovery the slurmctld must re-queue the launch | |
| from the persisted step state (launch_sent=False). | |
| Ticket: 24361 | |
| """ | |
| import re | |
| import pytest | |
| import atf | |
| pytestmark = pytest.mark.slow | |
| @pytest.fixture(scope="module", autouse=True) | |
| def setup(): | |
| atf.require_version( | |
| (26, 11), | |
| component="sbin/slurmctld", | |
| reason="Ticket 24361: deferred batch re-launch fixed in 26.11", | |
| ) | |
| atf.require_auto_config("needs to set Prolog, PrologFlags, and BatchStartTimeout") | |
| atf.require_config_parameter_includes("PrologFlags", "Alloc") | |
| atf.require_config_parameter_includes("PrologFlags", "Contain") | |
| atf.require_config_parameter_includes("PrologFlags", "DeferBatch") | |
| atf.require_nodes(1) | |
| atf.set_config_parameter("BatchStartTimeout", "30") | |
| atf.require_slurm_running() | |
| def test_batch_survives_reconfigure_during_prolog(tmp_path): | |
| """Batch job completes after a reconfigure that interrupts the prolog.""" | |
| slurm_user = atf.properties["slurm-user"] | |
| # A flag file the prolog touches when it starts running so we know when to | |
| # reconfigure, and a sentinel that tells the prolog it may exit. | |
| prolog_started = str(tmp_path / "prolog_started") | |
| prolog_proceed = str(tmp_path / "prolog_proceed") | |
| prolog_script = str(tmp_path / "prolog.sh") | |
| output_file = str(tmp_path / "job.out") | |
| # Prolog: signal that it is running, then busy-wait until released. | |
| atf.make_bash_script( | |
| prolog_script, | |
| f"""touch {prolog_started} | |
| while [ ! -f {prolog_proceed} ]; do sleep 0.5; done | |
| """, | |
| ) | |
| atf.set_config_parameter("Prolog", prolog_script) | |
| job_id = atf.submit_job_sbatch(f"-o {output_file} --wrap 'echo OK'", fatal=True) | |
| # Wait until the prolog is running before we reconfigure. | |
| assert atf.wait_for_file( | |
| prolog_started, timeout=30 | |
| ), "Prolog did not start within 30 s" | |
| # Reconfigure while the prolog (and deferred batch launch) are in flight. | |
| atf.run_command("scontrol reconfigure", user=slurm_user, fatal=True, quiet=True) | |
| # Release the prolog so it can complete. | |
| atf.run_command(f"touch {prolog_proceed}", fatal=True) | |
| # The job must complete successfully — not stay stuck or get requeued. | |
| assert atf.wait_for_job_state( | |
| job_id, "COMPLETED", timeout=60 | |
| ), f"Job {job_id} did not complete after reconfigure during prolog" | |
| # The batch launch must have been re-issued, not requeued. | |
| job_info = atf.run_command_output(f"scontrol show job {job_id}", fatal=True) | |
| assert re.search( | |
| r"Restarts=0\b", job_info | |
| ), f"Job {job_id} was requeued instead of relaunched: {job_info}" | |
| # The batch script must have actually run and produced output. | |
| assert atf.wait_for_file( | |
| output_file, timeout=15 | |
| ), f"Job output file {output_file} was not created" | |
| output = atf.run_command_output(f"cat {output_file}", fatal=True) | |
| assert "OK" in output, f"Job output did not contain 'OK': {output!r}" |