Skip to content

Commit c324922

Browse files
Merge pull request #9 from larsbuntemeyer/tests
added tests with docker
2 parents c70e705 + 8886785 commit c324922

File tree

7 files changed

+256
-1
lines changed

7 files changed

+256
-1
lines changed

.github/workflows/slurm.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: test with slurm
2+
on: [push, pull_request]
3+
jobs:
4+
Build:
5+
runs-on: ubuntu-20.04
6+
strategy:
7+
matrix:
8+
python-version:
9+
- "3.8"
10+
- "3.9"
11+
- "3.10"
12+
- "3.11"
13+
fail-fast: false
14+
steps:
15+
- name: Checkout repository code
16+
uses: actions/checkout@v3
17+
- name: Set up Python ${{ matrix.python-version }}
18+
uses: actions/setup-python@v2
19+
with:
20+
python-version: ${{ matrix.python-version }}
21+
- name: Install Dependencies
22+
run: |
23+
which python
24+
which python${{ matrix.python-version }}
25+
pip install pytest pytest-cov pytest-env pandas
26+
- name: Start Slurm Container
27+
uses: sudo-bot/action-docker-compose@latest
28+
with:
29+
cli-args: "-f docker-compose.yml up -d"
30+
env:
31+
PYTHON: ${{ matrix.python-version }}
32+
- name: Debug
33+
run: |
34+
docker ps -a
35+
docker version
36+
pwd
37+
ls -al
38+
docker inspect slurmctl
39+
env | sort
40+
- name: Configure slurm
41+
run: |
42+
docker exec slurmctl ./scripts/configure.sh
43+
env:
44+
PYTHON: ${{ matrix.python-version }}
45+
- name: Install enjoy-slurm
46+
run: |
47+
docker exec slurmctl python -m pip install pytest pytest-env pytest-cov
48+
docker exec slurmctl python -m pip install -e .
49+
- name: Run tests
50+
timeout-minutes: 5
51+
run: docker exec slurmctl python -u -m pytest
52+
--cov=enjoy_slurm
53+
--cov-report=xml
54+
--junitxml=test-results/${{ runner.os }}-${{ matrix.python-version }}.xml
55+
- name: Upload code coverage to Codecov
56+
uses: codecov/codecov-action@v3
57+
with:
58+
file: ./coverage.xml
59+
flags: unittests
60+
env_vars: RUNNER_OS,PYTHON_VERSION
61+
name: codecov-umbrella
62+
fail_ci_if_error: false

docker-compose.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: "3.8"
2+
3+
services:
4+
slurm:
5+
image: giovtorres/docker-centos7-slurm:21.08.6
6+
hostname: slurmctl
7+
container_name: slurmctl
8+
stdin_open: true
9+
tty: true
10+
working_dir: /enjoy-slurm
11+
environment:
12+
PYTHON: "3.9"
13+
volumes:
14+
- ${RUNNER_WORKSPACE}/enjoy-slurm:/enjoy-slurm

docs/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ Top-level functions
1414

1515
sbatch
1616
sacct
17-
scontrol
17+
scontrol.show
1818
jobinfo

docs/conf.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@
7878
#
7979
# html_theme = "pangeo"
8080
html_theme = "sphinx_book_theme"
81+
html_title = "enjoy slurm!"
82+
83+
html_theme_options = dict(
84+
repository_url="https://github.com/larsbuntemeyer/enjoy-slurm",
85+
repository_branch="main",
86+
path_to_docs="docs",
87+
use_edit_page_button=True,
88+
use_repository_button=True,
89+
use_issues_button=True,
90+
home_page_in_toc=False,
91+
extra_navbar="",
92+
navbar_footer_text="",
93+
)
8194

8295
# Add any paths that contain custom static files (such as style sheets) here,
8396
# relative to this directory. They are copied after the builtin static files,

scripts/configure.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# CMD - Command to run for up to 30 seconds
5+
# MSG - Message to print while waiting for command to run
6+
RESULT=""
7+
wait_for_cmd() {
8+
CMD="$1"
9+
MSG="$2"
10+
MAX_WAIT=30
11+
until eval ${CMD} || [ $MAX_WAIT -lt 1 ]
12+
do
13+
echo "---> ${MSG} (retries left $MAX_WAIT)"
14+
sleep 1
15+
MAX_WAIT=$((MAX_WAIT - 1))
16+
done
17+
18+
if [ $MAX_WAIT -eq 0 ]
19+
then
20+
RESULT=false
21+
fi
22+
}
23+
24+
#############################
25+
# Configure Slurm for testing
26+
#############################
27+
28+
# Add fake licenses for testing
29+
echo "---> Adding licenses"
30+
echo "Licenses=fluent:30,ansys:100,matlab:50" >> /etc/slurm/slurm.conf
31+
32+
# Add fake topology for testing
33+
echo "---> Adding topology"
34+
cat > /etc/slurm/topology.conf << EOF
35+
SwitchName=s0 Nodes=c[1-5]
36+
SwitchName=s1 Nodes=c[6-10]
37+
SwitchName=s2 Switches=s[0-1]
38+
EOF
39+
40+
# Configure topology plugin
41+
echo "---> Configuring topology plugin"
42+
echo 'TopologyPlugin=topology/tree' >> /etc/slurm/slurm.conf
43+
44+
# Wait for database process to start
45+
wait_for_cmd "2>/dev/null > /dev/tcp/0.0.0.0/6819" "Waiting for Slurmdbd"
46+
47+
if [ "$RESULT" = false ]
48+
then
49+
supervisorctl restart mysqld
50+
supervisorctl restart slurmdbd
51+
supervisorctl status
52+
fi
53+
54+
# Add the cluster to the slurm database
55+
#sacctmgr --immediate add cluster name=linux
56+
57+
# Restart Slurm components to apply configuration changes
58+
supervisorctl restart slurmctld
59+
supervisorctl restart slurmd
60+
61+
62+
####################################################
63+
# Get some output for debugging and troubleshooting
64+
####################################################
65+
66+
# Wait for nodes to become IDLE
67+
wait_for_cmd "sinfo | grep -q normal.*idle" "Waiting for nodes to transition to IDLE"
68+
69+
# TODO: convert to setup method/fixture
70+
# Submit test job with jobstep via srun for testing
71+
echo "---> Submitting sleep job"
72+
sbatch --wrap="srun sleep 1000"
73+
74+
# Wait for the job to transition from PENDING to RUNNING
75+
wait_for_cmd "scontrol show job | grep -q JobState=RUNNING" "Waiting for job to transition to RUNNING"
76+
77+
# Show jobs
78+
squeue
79+
80+
# Show cluster
81+
sacctmgr list cluster
82+
83+
# Debug for CentOS 6 only
84+
# CentOS 6 tends move a little slower
85+
wait_for_cmd "scontrol show license | grep -q LicenseName=matlab" "Waiting for licenses"
86+
wait_for_cmd "scontrol show topology | grep -q Switches" "Waiting for topology"
87+
88+
# Get output from various scontrol show commands
89+
echo "---> scontrol -d show job"
90+
scontrol -d show job
91+
echo "---> scontrol -d show node c1"
92+
scontrol -d show node c1
93+
echo "---> scontrol -d show partition"
94+
scontrol -d show partition
95+
echo "---> scontrol -d show license"
96+
scontrol -d show license
97+
echo "---> scontrol -d show steps"
98+
scontrol -d show steps
99+
echo "---> scontrol -d show topology"
100+
scontrol -d show topology

tests/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Unit test package for enjoy-slurm."""
2+
3+
import pytest
4+
5+
import subprocess
6+
import socket
7+
8+
9+
def _cmlorskip(command):
10+
try:
11+
commands = [command, "-V"]
12+
output = subprocess.run(
13+
commands, stdout=subprocess.PIPE, stderr=subprocess.PIPE
14+
)
15+
has = True
16+
except FileNotFoundError:
17+
has = False
18+
func = pytest.mark.skipif(not has, reason=f"requires slurm")
19+
return has, func
20+
21+
22+
def _machine(machine):
23+
try:
24+
host = socket.gethostname().split(".", 1)[1]
25+
on = host == machine
26+
except Exception:
27+
on = False
28+
func = pytest.mark.skipif(not on, reason=f"no on {machine}")
29+
return on, func
30+
31+
32+
has_slurm, requires_slurm = _cmlorskip("sinfo")
33+
on_levante, requires_levante = _machine("lvt.dkrz.de")
34+
hostname = socket.gethostname()

tests/test_with_slurm.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import pytest
2+
import enjoy_slurm as slurm
3+
from . import hostname, requires_slurm, on_levante, requires_levante
4+
5+
6+
test_kwargs = {
7+
"levante": {"partitions": ["compute", "shared"]},
8+
"docker": {"partitions": ["debug", "normal"]},
9+
}
10+
11+
print(hostname)
12+
13+
14+
@requires_slurm
15+
def test_sbatch():
16+
if on_levante:
17+
kwargs = {"partition": "shared", "account": "ch0636"}
18+
else:
19+
kwargs = {}
20+
jobid = slurm.sbatch(wrap="echo Hello World", **kwargs)
21+
print(jobid)
22+
23+
24+
@requires_slurm
25+
def test_partitions():
26+
if on_levante:
27+
partitions = test_kwargs["levante"]["partitions"]
28+
else:
29+
partitions = test_kwargs["docker"]["partitions"]
30+
for p in partitions:
31+
pdict = slurm.scontrol.show(partition=p)
32+
assert p in pdict

0 commit comments

Comments
 (0)