Skip to content
Draft
18 changes: 10 additions & 8 deletions src/tests/ftest/slurm_setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
"""
(C) Copyright 2018-2024 Intel Corporation.
(C) Copyright 2026 Hewlett Packard Enterprise Development LP

SPDX-License-Identifier: BSD-2-Clause-Patent
"""
Expand Down Expand Up @@ -34,7 +35,7 @@ class SlurmSetup():
'/etc/slurm/slurmdbd.conf.example']
MUNGE_DIR = '/etc/munge'
MUNGE_KEY = '/etc/munge/munge.key'
PACKAGE_LIST = ['slurm', 'slurm-example-configs', 'slurm-slurmctld', 'slurm-slurmd']
PACKAGE_LIST = ['slurm', 'slurm-slurmdbd', 'slurm-slurmctld', 'slurm-slurmd']
SLURM_CONF = '/etc/slurm/slurm.conf'
SLURM_LOG_DIR = '/var/log/slurm'

Expand Down Expand Up @@ -182,18 +183,19 @@ def start_slurm(self, user, debug):

# Restart slurmctld on the control node
self._restart_systemctl(
self.control, 'slurmctld', '/var/log/slurmctld.log', self.SLURM_CONF)
self.control, 'slurmctld', '/var/log/slurm/slurmctld.log', self.SLURM_CONF)

# Restart slurmd on all nodes
self._restart_systemctl(self.all_nodes, 'slurmd', '/var/log/slurmd.log', self.SLURM_CONF)
self._restart_systemctl(
self.all_nodes, 'slurmd', '/var/log/slurm/slurmd.log', self.SLURM_CONF)

# Update nodes to the idle state
command = command_as_user(
f'scontrol update nodename={str(self.nodes)} state=idle', self.root)
result = run_remote(self.log, self.nodes, command)
if not result.passed or debug:
self._display_debug(self.control, '/var/log/slurmctld.log', self.SLURM_CONF)
self._display_debug(self.all_nodes, '/var/log/slurmd.log', self.SLURM_CONF)
self._display_debug(self.control, '/var/log/slurm/slurmctld.log', self.SLURM_CONF)
self._display_debug(self.all_nodes, '/var/log/slurm/slurmd.log', self.SLURM_CONF)
if not result.passed:
raise SlurmSetupException(f'Error setting nodes to idle on {self.nodes}')

Expand Down Expand Up @@ -268,8 +270,8 @@ def _update_slurm_config(self, slurm_user, partition):

# Update the config file with the slurm epilog file
self._modify_slurm_config_file(
'epilog file', self.all_nodes, 's#EpilogSlurmctld=#EpilogSlurmctld={EPILOG_FILE}#g',
self.root)
'epilog file', self.all_nodes,
f's#EpilogSlurmctld=#EpilogSlurmctld={self.EPILOG_FILE}#g', self.root)

# Update the config file with the slurm control node
not_updated = self.all_nodes.copy()
Expand All @@ -280,7 +282,7 @@ def _update_slurm_config(self, slurm_user, partition):
not_updated.remove(
self._modify_slurm_config_file(
'slurm control node', results.passed_hosts,
f's/{control_keyword}=linux0/{control_keyword}={str(self.control)}/g',
f's/{control_keyword}=localhost/{control_keyword}={str(self.control)}/g',
self.root))
if not_updated:
raise SlurmSetupException(f'Slurm control node not updated on {not_updated}')
Expand Down
2 changes: 1 addition & 1 deletion src/tests/ftest/soak/smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ smoke:
- fio_smoke
#- daos_racer
- mdtest_smoke
- vpic_smoke
#- vpic_smoke
- lammps_smoke
- macsio_smoke
- datamover_smoke
Expand Down
6 changes: 3 additions & 3 deletions src/tests/ftest/util/slurm_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
(C) Copyright 2019-2024 Intel Corporation.
(C) Copyright 2025 Hewlett Packard Enterprise Development LP
(C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP

SPDX-License-Identifier: BSD-2-Clause-Patent
"""
Expand Down Expand Up @@ -52,7 +52,7 @@ def create_partition(log, control, name, hosts, default='yes', max_time='UNLIMIT
Returns:
CommandResult: results from the scontrol command
"""
command = ['scontrol', 'create']
command = ['sudo', 'scontrol', 'create']
command.append('='.join(['PartitionName', str(name)]))
command.append('='.join(['Nodes', str(hosts)]))
command.append('='.join(['Default', str(default)]))
Expand All @@ -73,7 +73,7 @@ def delete_partition(log, control, name):
int: return status from scontrol command

"""
command = ['scontrol', 'delete']
command = ['sudo', 'scontrol', 'delete']
command.append('='.join(['PartitionName', str(name)]))
return run_remote(log, control, ' '.join(command))

Expand Down
27 changes: 25 additions & 2 deletions src/tests/ftest/util/soak_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
SPDX-License-Identifier: BSD-2-Clause-Patent
"""
# pylint: disable=too-many-lines
# pylint: disable=too-many-locals

import getpass
import os
Expand Down Expand Up @@ -1482,8 +1483,30 @@ def create_app_cmdline(self, job_spec, pool, ppn, nodesperjob):
# ${DAOS_TEST_APP_SRC}/suse => apps built with suse and gnu-mpich
# pylint: disable-next=wrong-spelling-in-comment,fixme
# ${DAOS_TEST_APP_SRC}/suse/intelmpi => apps built with suse and intelmpi
if "suse" in detect().name.lower() and os.environ.get("DAOS_TEST_MODE") is None:
os.environ["DAOS_TEST_APP_DIR"] += os.path.join(os.sep, "suse")
os_info = detect()
os_name = (os_info.name or "").lower()
os_version = str(os_info.version or "").strip()

# Fallback for cases where avocado detect() returns unknown/0.

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.

Where are we running into cases where avocado detect() returns unknown/0? We use detect() in every CI test in https://github.com/daos-stack/daos/blob/master/src/tests/ftest/util/apricot/apricot/test.py#L156 and it works with all of the distros we run on.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note: Discard results for Build#9 as wrong slurm_setup.py was accidentally pushed.

Regarding detect(), as noticed for the results of build#8, it was not able to detect the correct os version for el9 hence was not able to copy the correct lammps build hence lammps jobs failed. So I am just trying to bullet proof that in scenarios where it is failing to detect is especially in case of el9. Not sure what exactly is detect() used for in other tests, but here I need the version number as well.

if (not os_name or os_name == "unknown" or not os_version or os_version == "0") \
and os.path.exists("/etc/os-release"):
os_release = {}
with open("/etc/os-release", "r", encoding="utf-8") as fd:
for line in fd:
if "=" not in line:
continue
key, value = line.rstrip().split("=", 1)
os_release[key] = value.strip().strip('"')
os_name = (os_release.get("NAME") or os_release.get("ID") or os_name).lower()
os_version = (os_release.get("VERSION_ID") or os_version).strip()

if os.environ.get("DAOS_TEST_MODE") is None:

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.

This may be a bit out of scope for this PR, but it seems all DAOS_TEST_MODE does is prevent the code from updating DAOS_TEST_APP_DIR and I_MPI_OFI_LIBRARY_INTERNAL in certain situations. It seems like the updating of those variables should be dependent upon whether or not they are already set - and then we don't need DAOS_TEST_MODE.

if "suse" in os_name:
os.environ["DAOS_TEST_APP_DIR"] += os.path.join(os.sep, "suse")
elif os_version == "9":
os.environ["DAOS_TEST_APP_DIR"] += os.path.join(os.sep, "el9")
elif os_version == "8":
os.environ["DAOS_TEST_APP_DIR"] += os.path.join(os.sep, "el8")
if "mpi/latest" in mpi_module and os.environ.get("DAOS_TEST_MODE") is None:
os.environ["DAOS_TEST_APP_DIR"] += os.path.join(os.sep, "intelmpi")
os.environ["I_MPI_OFI_LIBRARY_INTERNAL"] = "0"
Expand Down
Loading