Source code for ramble.test.systems_and_platforms.system_platform_general
# Copyright 2022-2026 The Ramble Authors
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
import os
import re
import pytest
import ramble.software_info
import ramble.workspace
from ramble.main import RambleCommand
from ramble.util.command_runner import RunnerError
import spack.util.spack_yaml as syaml
workspace = RambleCommand("workspace")
pytestmark = pytest.mark.usefixtures(
"mutable_config",
"mutable_mock_workspace_path",
)
[docs]
def test_system_platform_works(workspace_name, mock_platforms, mock_systems):
ws = ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"-v",
"n_ranks={processes_per_node}*{n_nodes}",
"-v",
"n_nodes=1",
"-v",
"processes_per_node={max_cores_per_node}",
"-V",
"system=spack-slurm-sys",
"-V",
"system-variant1=bar",
global_args=global_args,
)
try:
workspace("concretize", "--dry-run", global_args=global_args)
# Verify there is spack info in the workspace
with open(ws.config_file_path) as f:
data = f.read()
assert "gromacs@{application::gromacs::version}" in data
assert "intel-mpi" in data
assert "intel-oneapi-mpi" in data
env_file = os.path.join(ws.software_dir, "spack", "gromacs", "spack.yaml")
workspace("setup", "--dry-run", global_args=["-D", ws.root])
# Verify the packages.yaml files were merged
with open(env_file) as f:
spack_config = syaml.load(stream=f)
assert "spack" in spack_config
assert "packages" in spack_config["spack"]
assert "openmpi" in spack_config["spack"]["packages"]
assert "buildable" in spack_config["spack"]["packages"]["openmpi"]
assert "externals" in spack_config["spack"]["packages"]["openmpi"]
# Verify slurm portions of execute script (to show workflow was applied)
exec_file = os.path.join(
ws.experiment_dir, "gromacs", "lignocellulose", "generated", "slurm_experiment_sbatch"
)
assert os.path.isfile(exec_file)
with open(exec_file) as f:
data = f.read()
assert "SBATCH" in data
# Ensure cores_per_node=4 propagated, and srun is used from slurm
assert "srun -n 4" in data
# Verify command variables were "defined"
log_file = os.path.join(ws.log_dir, "setup.latest", "gromacs.lignocellulose.generated.out")
expected = (
"max_nodes = 4 (dry-run) from 'sinfo -p " "mock-partition -O 'Nodes' | tail -n 1'"
)
with open(log_file) as f:
data = f.read()
assert expected in data
except RunnerError as e:
pytest.skip(str(e))
[docs]
def test_platform_validator_threads_per_core(workspace_name, mock_platforms, mock_systems):
ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"-v",
"n_ranks={processes_per_node}*{n_nodes}",
"-v",
"n_nodes=1",
"-v",
"n_threads=2",
"-v",
"processes_per_node=3",
"-V",
"system=spack-slurm-sys",
global_args=global_args,
)
err_regex = re.escape(
"Validator 'threads_per_node_platform_validation' (defined in 'mock-platform1') "
"fails with message: 'Number of threads per node (2 * 3) exceeds max cores per node (4)'"
)
with pytest.raises(ramble.error.ObjectValidationError, match=err_regex):
workspace("info", "--dry-run", global_args=global_args)
[docs]
def test_skipping_platform_validator_threads_per_core(
workspace_name, mock_platforms, mock_systems
):
ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"-v",
"n_ranks={processes_per_node}*{n_nodes}",
"-v",
"n_nodes=1",
"-v",
"n_threads=2",
"-v",
"processes_per_node=3",
"-V",
"system=spack-slurm-sys",
"-V",
"validate_platform=false",
global_args=global_args,
)
workspace("concretize", "--dry-run", global_args=global_args)
workspace("info", "--dry-run", global_args=global_args)
[docs]
def test_platform_validator_accelerators_per_node(workspace_name, mock_platforms, mock_systems):
ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"--default-variable-value",
"1",
"-v",
"n_ranks=1",
"-v",
"processes_per_node=1",
"-v",
"accelerators_per_node=2",
"-V",
"system=spack-slurm-sys",
"-V",
"accelerator=true",
global_args=global_args,
)
err_regex = re.escape(
"Validator 'accelerators_per_node_platform_validation' (defined in 'mock-platform1') "
"fails with message: 'Number of accelerators per node (2) exceeds max accelerators "
"on node (0)'"
)
workspace("concretize", "--dry-run", global_args=global_args)
with pytest.raises(ramble.error.ObjectValidationError, match=err_regex):
workspace("info", "--dry-run", global_args=global_args)
[docs]
def test_system_validator_n_nodes(workspace_name, mock_platforms, mock_systems):
ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"--default-variable-value",
"1",
"-v",
"n_nodes=10",
"-v",
"processes_per_node=1",
"-V",
"system=spack-slurm-sys",
global_args=global_args,
)
err_regex = re.escape(
"Validator 'n_nodes_system_validation' (defined in 'spack-slurm-sys') fails with message: "
"'Number of nodes requested (10) exceeds max nodes (4)'"
)
with pytest.raises(ramble.error.ObjectValidationError, match=err_regex):
workspace("info", "--dry-run", global_args=global_args)
[docs]
def test_system_validator_n_ranks(workspace_name, mock_platforms, mock_systems):
ramble.workspace.create(workspace_name)
global_args = ["-w", workspace_name]
workspace(
"manage",
"experiments",
"gromacs",
"--wf",
"lignocellulose",
"--default-variable-value",
"1",
"-v",
"n_ranks=10",
"-v",
"n_nodes=2",
"-V",
"system=spack-slurm-sys",
global_args=global_args,
)
err_regex = re.escape(
"Validator 'n_ranks_system_validation' (defined in 'spack-slurm-sys') fails with "
"message: 'Total number of ranks (10) exceeds max cores (4 * 2)'"
)
with pytest.raises(ramble.error.ObjectValidationError, match=err_regex):
workspace("info", "--dry-run", global_args=global_args)