Skip to content

Commit

Permalink
Merge branch 'main' into Transport-Engine__factor-out-cwd
Browse files Browse the repository at this point in the history
  • Loading branch information
khsrali committed Nov 5, 2024
2 parents 21c2be3 + 8350df0 commit 3536b02
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/aiida/orm/nodes/data/code/installed.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ def validate_filepath_executable(self):
with override_log_level(): # Temporarily suppress noisy logging
with self.computer.get_transport() as transport:
file_exists = transport.isfile(str(self.filepath_executable))
if file_exists:
mode = transport.get_mode(str(self.filepath_executable))
# `format(mode, 'b')` with default permissions
# gives 110110100, representing rw-rw-r--
# Check on index 2 if user has execute
user_has_execute = format(mode, 'b')[2] == '1'

except Exception as exception:
raise exceptions.ValidationError(
'Could not connect to the configured computer to determine whether the specified executable exists.'
Expand All @@ -147,6 +154,13 @@ def validate_filepath_executable(self):
f'The provided remote absolute path `{self.filepath_executable}` does not exist on the computer.'
)

if not user_has_execute:
execute_msg = (
f'The file at the remote absolute path `{self.filepath_executable}` exists, '
'but might not actually be executable. Check the permissions.'
)
raise exceptions.ValidationError(execute_msg)

def can_run_on_computer(self, computer: Computer) -> bool:
"""Return whether the code can run on a given computer.
Expand Down
6 changes: 3 additions & 3 deletions src/aiida/schedulers/plugins/slurm.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,14 @@ def _get_submit_script_header(self, job_tmpl):
lines.append(f'#SBATCH --time={days:d}-{hours:02d}:{minutes:02d}:{seconds:02d}')

# It is the memory per node, not per cpu!
if job_tmpl.max_memory_kb:
if job_tmpl.max_memory_kb is not None:
try:
physical_memory_kb = int(job_tmpl.max_memory_kb)
if physical_memory_kb <= 0:
if physical_memory_kb < 0: # 0 is allowed and means no limit (https://slurm.schedmd.com/sbatch.html)
raise ValueError
except ValueError:
raise ValueError(
f'max_memory_kb must be a positive integer (in kB)! It is instead `{job_tmpl.max_memory_kb}`'
f'max_memory_kb must be a non-negative integer (in kB)! It is instead `{job_tmpl.max_memory_kb}`'
)
# --mem: Specify the real memory required per node in MegaBytes.
# --mem and --mem-per-cpu are mutually exclusive.
Expand Down
14 changes: 13 additions & 1 deletion tests/orm/data/code/test_installed.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,15 @@ def computer(request, aiida_computer_local, aiida_computer_ssh):

@pytest.mark.usefixtures('aiida_profile_clean')
@pytest.mark.parametrize('computer', ('core.local', 'core.ssh'), indirect=True)
def test_validate_filepath_executable(ssh_key, computer, bash_path):
def test_validate_filepath_executable(ssh_key, computer, bash_path, tmp_path):
"""Test the :meth:`aiida.orm.nodes.data.code.installed.InstalledCode.validate_filepath_executable` method."""

filepath_executable = '/usr/bin/not-existing'
dummy_executable = tmp_path / 'dummy.sh'
# Default Linux permissions are 664, so file is not executable
dummy_executable.touch()
code = InstalledCode(computer=computer, filepath_executable=filepath_executable)
dummy_code = InstalledCode(computer=computer, filepath_executable=str(dummy_executable))

with pytest.raises(ValidationError, match=r'Could not connect to the configured computer.*'):
code.validate_filepath_executable()
Expand All @@ -117,6 +122,13 @@ def test_validate_filepath_executable(ssh_key, computer, bash_path):
with pytest.raises(ValidationError, match=r'The provided remote absolute path .* does not exist on the computer\.'):
code.validate_filepath_executable()

with pytest.raises(
ValidationError,
match=r'The file at the remote absolute path .* exists, but might not actually be executable\.',
):
# Didn't put this in the if, using transport.put, as we anyway only connect to localhost via SSH in this test
dummy_code.validate_filepath_executable()

code.filepath_executable = str(bash_path.absolute())
code.validate_filepath_executable()

Expand Down
52 changes: 52 additions & 0 deletions tests/schedulers/test_slurm.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,58 @@ def test_submit_script_with_num_cores_per_machine_and_mpiproc2(self):
num_machines=1, num_mpiprocs_per_machine=1, num_cores_per_machine=24, num_cores_per_mpiproc=23
)

def test_submit_script_with_mem(self):
"""Test to verify if script can be created with memory specification.
It should pass this check:
if physical_memory_kb < 0: # 0 is allowed and means no limit (https://slurm.schedmd.com/sbatch.html)
raise ValueError
and correctly set the memory value in the script with the --mem option.
"""
from aiida.common.datastructures import CodeRunMode
from aiida.schedulers.datastructures import JobTemplate, JobTemplateCodeInfo

scheduler = SlurmScheduler()
job_tmpl = JobTemplate()

job_tmpl.uuid = str(uuid.uuid4())
job_tmpl.max_wallclock_seconds = 24 * 3600
tmpl_code_info = JobTemplateCodeInfo()
tmpl_code_info.cmdline_params = ['mpirun', '-np', '23', 'pw.x', '-npool', '1']
tmpl_code_info.stdin_name = 'aiida.in'
job_tmpl.codes_info = [tmpl_code_info]
job_tmpl.codes_run_mode = CodeRunMode.SERIAL
job_tmpl.job_resource = scheduler.create_job_resource(num_machines=1, num_mpiprocs_per_machine=1)
# Check for a regular (positive) value
job_tmpl.max_memory_kb = 316 * 1024
submit_script_text = scheduler.get_submit_script(job_tmpl)
assert '#SBATCH --mem=316' in submit_script_text
# Check for the special zero value
job_tmpl.max_memory_kb = 0
submit_script_text = scheduler.get_submit_script(job_tmpl)
assert '#SBATCH --mem=0' in submit_script_text

def test_submit_script_with_negative_mem_value(self):
"""Test to verify if script can be created with an invalid memory value.
It should fail in check:
if physical_memory_kb < 0: # 0 is allowed and means no limit (https://slurm.schedmd.com/sbatch.html)
raise ValueError
"""
import re

from aiida.schedulers.datastructures import JobTemplate

scheduler = SlurmScheduler()
job_tmpl = JobTemplate()

with pytest.raises(
ValueError, match=re.escape('max_memory_kb must be a non-negative integer (in kB)! It is instead `-9`')
):
job_tmpl.job_resource = scheduler.create_job_resource(num_machines=1, num_mpiprocs_per_machine=1)
job_tmpl.max_memory_kb = -9
scheduler.get_submit_script(job_tmpl)

def test_submit_script_rerunnable(self):
"""Test the creation of a submission script with the `rerunnable` option."""
from aiida.common.datastructures import CodeRunMode
Expand Down

0 comments on commit 3536b02

Please sign in to comment.