Skip to content

Output slurm config as facts #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,17 @@ jobs:
- test4
- test5
- test6
- test7
- test8
- test9
- test10
- test11
- test12
- test13
- test14
exclude: []
exclude:
# mariadb package provides /usr/bin/mysql on RL8 which doesn't work with geerlingguy/mysql role
- scenario: test4
image: 'rockylinux:8.9'

steps:
- name: Check out the codebase.
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ You will need to configure these variables if you have set `openhpc_enable.datab

`openhpc_slurmdbd_mysql_username`: Username for authenticating with the database, defaults to `slurm`.

## Facts

This role creates local facts from the live Slurm configuration, which can be
accessed (with facts gathering enabled) using `ansible_local.slurm`. As per the
`scontrol show config` man page, uppercase keys are derived parameters and keys
in mixed case are from from config files. Note the facts are only refreshed
when this role is run.

## Example Inventory

And an Ansible inventory as this:
Expand Down
35 changes: 35 additions & 0 deletions filter_plugins/slurm_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,46 @@ def dict2parameters(d):
parts = ['%s=%s' % (k, v) for k, v in d.items()]
return ' '.join(parts)

def config2dict(lines):
""" Convert a sequence of output lines from `scontrol show config` to a dict.

As per man page uppercase keys are derived parameters, mixed case are from
from config files.

The following case-insensitive conversions of values are carried out:
- '(null)' and 'n/a' are converted to None.
- yes and no are converted to True and False respectively

Except for these, values are always strings.
"""
cfg = {}
for line in lines:
if '=' not in line: # ditch blank/info lines
continue
else:
parts = [x.strip() for x in line.split('=', maxsplit=1)] # maxplit handles '=' in values
if len(parts) != 2:
raise errors.AnsibleFilterError(f'line {line} cannot be split into key=value')
k, v = parts
small_v = v.lower()
if small_v == '(null)':
v = None
elif small_v == 'n/a':
v = None
elif small_v == 'no':
v = False
elif small_v == 'yes':
v = True
cfg[k] = v
return cfg


class FilterModule(object):

def filters(self):
return {
'hostlist_expression': hostlist_expression,
'error': error,
'dict2parameters': dict2parameters,
'config2dict': config2dict,
}
4 changes: 4 additions & 0 deletions handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,7 @@
- openhpc_slurm_service_started | bool
- openhpc_enable.batch | default(false) | bool
# 2nd condition required as notification happens on controller, which isn't necessarily a compute note

- name: Reload facts
ansible.builtin.setup:
filter: ansible_local
2 changes: 1 addition & 1 deletion molecule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test3 | 1 | Y | -
test4 | 1 | N | 2x compute node, accounting enabled
test5 | 1 | N | As for #1 but configless
test6 | 1 | N | 0x compute nodes, configless
test7 | 1 | N | 1x compute node, no login node so specified munge key, configless (checks image build should work)
test7 | 1 | N | [removed, image build should just run install.yml task, this is not expected to work]
test8 | 1 | N | 2x compute node, 2x login-only nodes, configless
test9 | 1 | N | As test8 but uses `--limit=testohpc-control,testohpc-compute-0` and checks login nodes still end up in slurm.conf
test10 | 1 | N | As for #5 but then tries to add an additional node
Expand Down
30 changes: 0 additions & 30 deletions molecule/test7/converge.yml

This file was deleted.

20 changes: 0 additions & 20 deletions molecule/test7/molecule.yml

This file was deleted.

Binary file not shown.
32 changes: 0 additions & 32 deletions molecule/test7/verify.yml

This file was deleted.

24 changes: 24 additions & 0 deletions tasks/facts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
- name: Capture configuration from scontrol
# this includes any dynamically-generated config, not just what is set in
# slurm.conf
ansible.builtin.command: scontrol show config
changed_when: false
register: _scontrol_config

- name: Create facts directory
ansible.builtin.file:
path: /etc/ansible/facts.d/
state: directory
owner: root
group: root
mode: ugo=rwX

- name: Template slurm configuration facts
copy:
dest: /etc/ansible/facts.d/slurm.fact
content: "{{ _scontrol_config.stdout_lines | config2dict | to_nice_json }}"
owner: slurm
group: slurm
mode: ug=rw,o=r # any user can run scontrol show config anyway
register: _template_facts
notify: Reload facts
2 changes: 2 additions & 0 deletions tasks/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,5 @@
enabled: "{{ openhpc_slurm_service_enabled | bool }}"
state: "{{ 'started' if openhpc_slurm_service_started | bool else 'stopped' }}"
when: openhpc_enable.batch | default(false) | bool

- import_tasks: facts.yml