blob: a1d50c396f9746bf7a9b754a066bcb3a0c70d475 [file]
############################################################################
# Copyright (C) SchedMD LLC.
############################################################################
import re
import pytest
import atf
# Global variables
cluster1 = "cluster1"
cluster2 = "cluster2"
cluster3 = "cluster3"
acct1 = "acct1"
acct2 = "acct2"
acct3 = "acct3"
acct4 = "acct4"
acct5 = "acct4_sub"
acct6 = "acct4_sub_sub"
acct7 = "acct5"
acct8 = "acct6"
acct9 = "acct7"
user1 = "user1"
user2 = "user2"
user3 = "user3"
part1 = "part1"
part2 = "part2"
part3 = "part3"
part4 = "part4"
defacct = acct1
@pytest.fixture(scope="module", autouse=True)
def setup():
"""Test setup with required configurations."""
atf.require_accounting(modify=True)
atf.require_config_parameter_includes("AccountingStorageEnforce", "associations")
atf.require_config_parameter("AllowNoDefAcct", "No", source="slurmdbd")
# these can be helpful when debugging/tracing
# atf.require_config_parameter("DebugLevel", "debug4", source="slurmdbd")
# atf.require_config_parameter("DebugFlags", f"{atf.get_config(live=False, source="slurmdbd", quiet=True)["DebugFlags"]},DB_ASSOC", source="slurmdbd")
atf.require_slurm_running()
@pytest.fixture(scope="function", autouse=True)
def setup_db():
# Create test clusters and accounts
atf.run_command(
f"sacctmgr -i add cluster {cluster1},{cluster2},{cluster3}",
user=atf.properties["slurm-user"],
fatal=True,
)
atf.run_command(
f"sacctmgr -i add account {acct1},{acct2},{acct3},{acct4} cluster={cluster1},{cluster2},{cluster3}",
user=atf.properties["slurm-user"],
fatal=True,
)
atf.run_command(
f"sacctmgr -i add user {user1} DefaultAccount={defacct} account={acct1},{acct2},{acct3},{acct4} cluster={cluster1},{cluster2},{cluster3}",
user=atf.properties["slurm-user"],
fatal=True,
)
yield
atf.run_command(
f"sacctmgr -i remove user {user1} acct={acct1},{acct2},{acct3},{acct4}",
user=atf.properties["slurm-user"],
quiet=True,
)
atf.run_command(
f"sacctmgr -i remove account {acct1},{acct2},{acct3},{acct4}",
user=atf.properties["slurm-user"],
quiet=True,
)
atf.run_command(
f"sacctmgr -i remove cluster {cluster1},{cluster2},{cluster3}",
user=atf.properties["slurm-user"],
quiet=True,
)
def test_account_removal():
"""Test removing an account:
- Verify that removing default account for a user fails.
"""
# Try to remove a user's default account
result = atf.run_command(
f"sacctmgr -i remove account {defacct} cluster={cluster1},{cluster2},{cluster3}",
user=atf.properties["slurm-user"],
xfail=True,
)
assert result["exit_code"] != 0, "Removing default account should fail"
assert (
"can not remove the default account of a user" in result["stderr"]
), 'sacctmgr should explain that we "can not remove the default account of a user"'
# Try to remove subset (including default) of accounts of user on cluster1
result = atf.run_command(
f"sacctmgr -i remove account {defacct},{acct2} cluster={cluster1}",
user=atf.properties["slurm-user"],
xfail=True,
)
assert (
result["exit_code"] != 0
), "Removing default account, either with other accounts, should fail"
assert (
"can not remove the default account of a user" in result["stderr"]
), 'sacctmgr should explain that we "can not remove the default account of a user"'
# Make user have only one account, the default on cluster1
atf.run_command(
f"sacctmgr -i remove account {acct2},{acct3},{acct4} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Try to remove default account on all clusters
result = atf.run_command(
f"sacctmgr -i remove account {defacct}",
user=atf.properties["slurm-user"],
xfail=True,
)
assert (
result["exit_code"] != 0
), "Removing default account when it's the only one account should fail"
assert (
"can not remove the default account of a user" in result["stderr"]
), 'sacctmgr should explain that we "can not remove the default account of a user"'
# Make acct2 have acct1 as parent
atf.run_command(
f"sacctmgr -i modify account {acct2} cluster={cluster1},{cluster2},{cluster3} set parent={acct1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Again, try to remove default account on all clusters
result = atf.run_command(
f"sacctmgr -i remove account {defacct}",
user=atf.properties["slurm-user"],
xfail=True,
)
assert (
result["exit_code"] != 0
), "Removing default account, either when it's a parent, should fail"
assert (
"can not remove the default account of a user" in result["stderr"]
), 'sacctmgr should explain that we "can not remove the default account of a user"'
# Remove all accounts of user on cluster2
atf.run_command(
f"sacctmgr -i remove user {user1} acct={acct2},{acct3},{acct4} cluster={cluster2}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Remove accounts acct2,acct3,acct4 from user on remaining clusters
atf.run_command(
f"sacctmgr -i remove user {user1} acct={acct2},{acct3},{acct4}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Again, try to remove default account on all clusters since it is now user's only account
result = atf.run_command(
f"sacctmgr -i remove account {defacct}",
user=atf.properties["slurm-user"],
)
assert (
result["exit_code"] == 0
), "Removing default account when it's not a default account should succeed"
assert defacct in result["stdout"], "sacctmgr should report the deleted account"
@pytest.mark.xfail(
atf.get_version("sbin/slurmdbd") < (24, 11, 4)
or (
(25, 5) <= atf.get_version("sbin/slurmdbd")
and atf.get_version("sbin/slurmdbd") < (25, 11)
),
reason="Ticket 24228: In 24.11.4 we fixed an issue when removing an account specifying the parent",
)
def test_account_removal_with_parent():
"""Test removing an account using parent="""
# Add a sub acct
atf.run_command(
f"sacctmgr -i add account {acct5} parent={acct4} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add another sub acct
atf.run_command(
f"sacctmgr -i add account {acct6} parent={acct5} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Now add user to it
atf.run_command(
f"sacctmgr -i add user {user1} acct={acct5} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Remove non-default account with parent specified
result = atf.run_command(
f"sacctmgr -i remove account {acct5} parent={acct4} cluster={cluster1}",
user=atf.properties["slurm-user"],
)
assert (
result["exit_code"] == 0
), "Removing non-default account with a parent should succeed"
assert (
f"A = {acct5}" in result["stdout"]
), "sacctmgr should report the deleted account"
# Confirm previous operation succeeded
output = atf.run_command_output(
f"sacctmgr -n show assoc format=acct,user,lineage acct={acct5},{acct6} cluster={cluster1}",
fatal=True,
)
assert (
output == ""
), f"User {user1} with acct {acct5} shouldn't have an assoc anymore"
def test_account_removal_with_partition():
"""Test removing an account using partition="""
# Add user to non-def account with partition
atf.run_command(
f"sacctmgr -i add user {user1} acct={acct4} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Remove account with partition specified
result = atf.run_command(
f"sacctmgr -i remove acct {acct4} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
)
assert result["exit_code"] == 0, "Removing account with a partition should succeed"
# Confirm previous operation succeeded
output = atf.run_command_output(
f"sacctmgr -n show assoc format=acct,user,lineage acct={acct4} partition={part1} cluster={cluster1}",
fatal=True,
)
assert (
output == ""
), f"Account {acct4} with partition {part1} shouldn't have an assoc anymore"
@pytest.mark.xfail(
atf.get_version("sbin/slurmdbd") < (25, 11, 6),
reason="Ticket 24442: In 24.11.6+ we allow a user default account to be removed if more than one set",
)
def test_add_del_user_def_acct():
"""Test adding multiple default accounts"""
# Add account
atf.run_command(
f"sacctmgr -i add acct {acct7} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with default account (no partition)
atf.run_command(
f"sacctmgr -i add user {user2} defaultaccount={acct7} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with default account and partition
atf.run_command(
f"sacctmgr -i add user {user2} defaultaccount={acct7} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Confirm there are two defaults
output = atf.run_command_output(
f"sacctmgr -n -P show assoc where user={user2} format=acct onlydef",
fatal=True,
)
assert (
len(re.findall(rf"{acct7}", output, re.IGNORECASE)) == 2
), f"User {user2} should have more than one default assoc"
# Confirm the last default added should be able to be removed
result = atf.run_command(
f"sacctmgr -i del user {user2} acct={acct7} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
assert (
result["exit_code"] == 0
), f"Should be able to remove acct {acct7} for user {user2} with partition {part1}"
# Add back in the default account (with partition)
atf.run_command(
f"sacctmgr -i add user {user2} defaultaccount={acct7} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Confirm removing user assoc with default account AND no partition succeeds
result = atf.run_command(
f'sacctmgr -i del user {user2} acct={acct7} partition=\\"\\" cluster={cluster1}',
user=atf.properties["slurm-user"],
fatal=True,
)
assert (
result["exit_code"] == 0
), f"Should be able to remove acct {acct7} for user {user2} with empty partition"
def test_change_user_def_acct():
"""Test changing default account for user"""
# Add two accts
atf.run_command(
f"sacctmgr -i add acct {acct8} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
atf.run_command(
f"sacctmgr -i add acct {acct9} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with default account and partition
atf.run_command(
f"sacctmgr -i add user {user3} defaultaccount={acct8} partition={part1} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with another default account and partition
atf.run_command(
f"sacctmgr -i add user {user3} defaultaccount={acct8} partition={part2} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with default account and no partition
atf.run_command(
f"sacctmgr -i add user {user3} defaultaccount={acct8} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with a non-def account and partition
atf.run_command(
f"sacctmgr -i add user {user3} account={acct9} partition={part3} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Add user with a non-def account and another partition
atf.run_command(
f"sacctmgr -i add user {user3} account={acct9} partition={part4} cluster={cluster1}",
user=atf.properties["slurm-user"],
fatal=True,
)
# Now change def account
result = atf.run_command(
f"sacctmgr -i mod user {user3} cluster={cluster1} set defaultaccount={acct9}",
user=atf.properties["slurm-user"],
fatal=True,
)
assert (
result["exit_code"] == 0
), f"Should be able to set new default account {acct9} for user {user3}"
# Confirm total assocs for user
output = atf.run_command_output(
f"sacctmgr -n -P show assoc where user={user3} format=acct,partition",
fatal=True,
)
assert (
len(re.findall(rf"{acct8}", output, re.IGNORECASE)) == 3
), f"User {user3} should have 3 assocs for acct {acct8}"
assert (
len(re.findall(rf"{acct9}", output, re.IGNORECASE)) == 2
), f"User {user3} should have 5 assocs for acct {acct9}"
# Confirm there are two defaults with partitions
output = atf.run_command_output(
f"sacctmgr -n -P show assoc where user={user3} format=acct,partition onlydef",
fatal=True,
)
assert (
len(re.findall(rf"{acct9}\|part[0-9]", output, re.IGNORECASE)) == 2
), f"User {user3} should have 2 default assocs with partitions"