blob: 485ef7b95476e153b681ecc85692f0a809bc51db [file] [edit]
############################################################################
# Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
############################################################################
"""Test WCKey handling on job submission (sbatch --wckey)."""
import os
import pytest
import atf
test_user = atf.get_user_name()
test_name = os.path.splitext(os.path.basename(__file__))[0]
test_acct = f"{test_name}_acct"
@pytest.fixture(scope="module", autouse=True)
def setup():
atf.require_accounting(True)
atf.require_config_parameter("TrackWcKey", "yes")
atf.require_config_parameter("TrackWcKey", "yes", source="slurmdbd")
atf.require_slurm_running()
def _get_wckeys(user, keylen):
return map(
lambda s: s.strip(" "),
atf.run_command_output(
f"sacctmgr -n show wckey where user={user} format=wckey%{keylen}",
user=atf.properties["slurm-user"],
fatal=True,
).split(),
)
@pytest.fixture(scope="module", autouse=True)
def setup_acct():
atf.run_command(
f"sacctmgr -i add account {test_acct}",
user=atf.properties["slurm-user"],
fatal=True,
)
yield
atf.run_command(
f"sacctmgr -i del account {test_acct}",
user=atf.properties["slurm-user"],
fatal=True,
)
@pytest.fixture(scope="module", autouse=True)
def setup_user():
atf.run_command(
f"sacctmgr -i add user {test_user} account={test_acct}",
user=atf.properties["slurm-user"],
fatal=True,
)
yield
atf.run_command(
f"sacctmgr -i del user {test_user}",
user=atf.properties["slurm-user"],
fatal=True,
)
@pytest.fixture(scope="function")
def setup_enforce():
atf.require_config_parameter_includes("AccountingStorageEnforce", "wckeys")
@pytest.fixture(scope="function")
def setup_nonenforce():
atf.require_config_parameter_excludes("AccountingStorageEnforce", "wckeys")
def test_create_wckey_job_submit(setup_nonenforce):
test_wckey = f"{test_name}_wckey_create"
assert test_wckey not in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should not exist before the job is submitted"
job_id = atf.submit_job_sbatch(f"--wckey={test_wckey} --wrap 'sleep 0'", fatal=True)
atf.wait_for_job_state(job_id, "COMPLETED", fatal=True)
atf.wait_for_job_accounted(job_id, "State", "COMPLETED", fatal=True)
assert test_wckey in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should be created when a job using it starts"
atf.run_command(
f"sacctmgr -i del user wckey={test_wckey}",
fatal=True,
user=atf.properties["slurm-user"],
)
def test_nocreate_wckey_job_submit(setup_enforce):
test_wckey = f"{test_name}_wckey_nocreate"
assert test_wckey not in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should not exist before the job is submitted"
res = atf.run_command(
f"sbatch --wckey={test_wckey} --wrap 'sleep 0'", xfail=True, fatal=True
)
assert (
"Invalid wckey specification" in res["stderr"]
), "sbatch should reject a WCKey the user does not have when enforcing"
assert test_wckey not in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should not be created when enforcing wckeys"
@pytest.mark.xfail(
atf.get_version("sbin/slurmctld") < (25, 5),
reason="Ticket 20771: slurmctld accepted '*' prefixed WCKeys on submission, fixed in 25.05",
)
def test_reject_asterisk_prefix_key(setup_nonenforce):
test_wckey = f"*{test_name}_wckey_asterisk"
assert test_wckey not in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should not exist before the job is submitted"
res = atf.run_command(
f"sbatch --wckey='{test_wckey}' --wrap 'sleep 0'", xfail=True, fatal=True
)
assert (
"Invalid wckey specification" in res["stderr"]
), "sbatch should reject a WCKey starting with the reserved '*' prefix"
assert test_wckey not in _get_wckeys(
test_user, len(test_wckey)
), f"WCKey {test_wckey} should not be created"