Skip to content
Open
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
29 changes: 28 additions & 1 deletion defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ openhpc_default_config:
SlurmctldTimeout: 300
SchedulerType: sched/backfill
SelectType: select/cons_tres
SelectTypeParameters: CR_Core
SelectTypeParameters: CR_Core_Memory
PriorityWeightPartition: 1000
PreemptType: preempt/partition_prio
PreemptMode: SUSPEND,GANG
Expand All @@ -43,6 +43,7 @@ openhpc_default_config:
Epilog: /etc/slurm/slurm.epilog.clean
ReturnToService: 2
GresTypes: "{{ ohpc_gres_types if ohpc_gres_types != '' else 'omit' }}"
DefMemPerCPU: "{{ ohpc_nodegroups_computed.values() | map(attribute='def_mem_per_cpu') | default([100], true) | min }}"
openhpc_cgroup_default_config:
ConstrainCores: "yes"
ConstrainDevices: "yes"
Expand Down Expand Up @@ -91,6 +92,32 @@ openhpc_slurmdbd_mysql_host: "{{ openhpc_slurm_control_host }}"
openhpc_slurmdbd_mysql_database: slurm_acct_db
#openhpc_slurmdbd_mysql_password:
openhpc_slurmdbd_mysql_username: slurm
openhpc_slurmdbd_default_config:
AuthType: auth/munge
DbdHost: "{{ openhpc_slurmdbd_host }}"
DbdAddr: "{{ openhpc_slurmdbd_host }}"
DbdPort: "{{ openhpc_slurmdbd_port }}"
DebugLevel: verbose
# NOTE: By default, slurmdbd will log to syslog
# LogFile: /var/log/slurm/slurmdbd.log
PidFile: /var/run/slurmdbd.pid
PurgeEventAfter: 24month
PurgeJobAfter: 24month
PurgeResvAfter: 24month
PurgeStepAfter: 24month
PurgeSuspendAfter: 24month
PurgeTXNAfter: 24month
PurgeUsageAfter: 24month
SlurmUser: slurm
StorageType: accounting_storage/mysql
StorageHost: "{{ openhpc_slurmdbd_mysql_host }}"
StorageUser: "{{ openhpc_slurmdbd_mysql_username }}"
StoragePass: "{{ openhpc_slurmdbd_mysql_password | mandatory('You must set openhpc_slurmdbd_mysql_password') }}"
StorageLoc: "{{ openhpc_slurmdbd_mysql_database }}"

# override openhpc_slurmdbd_config in the appliance
openhpc_slurmdbd_config: {}


openhpc_enable:
control: false
Expand Down
18 changes: 8 additions & 10 deletions templates/slurm.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,16 @@ NodeName={{ node }}
# COMPUTE NODES
{% for nodegroup in openhpc_nodegroups %}
# nodegroup: {{ nodegroup.name }}
{% set inventory_group_name = openhpc_cluster_name ~ '_' ~ nodegroup.name %}
{% set inventory_group_hosts = groups.get(inventory_group_name, []) %}
{% if inventory_group_hosts | length > 0 %}
{% set play_group_hosts = inventory_group_hosts | intersect (play_hosts) %}
{% set first_host = play_group_hosts | first | mandatory('Inventory group "' ~ inventory_group_name ~ '" contains no hosts in this play - was --limit used?') %}
{% set first_host_hv = hostvars[first_host] %}
{% set ram_mb = (first_host_hv['ansible_memory_mb']['real']['total'] * (nodegroup.ram_multiplier | default(openhpc_ram_multiplier))) | int %}
{% set hostlists = (inventory_group_hosts | hostlist_expression) %}{# hosts in inventory group aren't necessarily a single hostlist expression #}
{% set nodegroup_computed = ohpc_nodegroups_computed.get(nodegroup.name) %}
{# see vars/main.yml: if nodegroup_computed, nodegroup has at least 1 host in the inventory #}
{% if nodegroup_computed %}
{% set inventory_group_hosts = groups[nodegroup_computed.inventory_group_name] %}
{% set first_host_hv = hostvars[nodegroup_computed.first_host] %}
{% set hostlists = (inventory_group_hosts | hostlist_expression) %}{# hosts in inventory group aren't necessarily a single hostlist expression #}
NodeName={{ hostlists | join(',') }} {{ '' -}}
Features={{ (['nodegroup_' ~ nodegroup.name] + nodegroup.features | default([]) ) | join(',') }} {{ '' -}}
State=UNKNOWN {{ '' -}}
RealMemory={{ nodegroup.ram_mb | default(ram_mb) }} {{ '' -}}
RealMemory={{ nodegroup.ram_mb | default(nodegroup_computed.ram_mb) }} {{ '' -}}
Sockets={{ first_host_hv['ansible_processor_count'] }} {{ '' -}}
CoresPerSocket={{ first_host_hv['ansible_processor_cores'] }} {{ '' -}}
ThreadsPerCore={{ first_host_hv['ansible_processor_threads_per_core'] }} {{ '' -}}
Expand All @@ -44,7 +42,7 @@ NodeName={{ hostlists | join(',') }} {{ '' -}}
Gres={{ first_host_hv['ohpc_node_gpu_gres'] -}}
{% endif %}

{% endif %}{# 1 or more hosts in inventory #}
{% endif %}{# 1 or more hosts in inventory #}
NodeSet=nodegroup_{{ nodegroup.name }} Feature=nodegroup_{{ nodegroup.name }}

{% endfor %}
Expand Down
44 changes: 7 additions & 37 deletions templates/slurmdbd.conf.j2
Original file line number Diff line number Diff line change
@@ -1,39 +1,9 @@
{{ ansible_managed | comment }}
#
# Example slurmdbd.conf file.
#
# Set openhpc_default_slurmdbd_config and openhpc_slurmdb_config to modify it.
# See the slurmdbd.conf man page for more information.
#
# Archive info
#ArchiveJobs=yes
#ArchiveDir="/tmp"
#ArchiveSteps=yes
#ArchiveScript=
#JobPurge=12
#StepPurge=1
#
# Authentication info
AuthType=auth/munge
#AuthInfo=/var/run/munge/munge.socket.2
#
# slurmDBD info
DbdHost={{ openhpc_slurmdbd_host }}
DbdAddr={{ openhpc_slurmdbd_host }}
DbdPort={{ openhpc_slurmdbd_port }}
SlurmUser=slurm
#MessageTimeout=300
DebugLevel=4
#DefaultQOS=normal,standby
# NOTE: By default, slurmdbd will log to syslog
#LogFile=/var/log/slurm/slurmdbd.log
PidFile=/var/run/slurmdbd.pid
#PluginDir=/usr/lib/slurm
#PrivateData=accounts,users,usage,jobs
#TrackWCKey=yes
#
# Database info
StorageType=accounting_storage/mysql
StorageHost={{ openhpc_slurmdbd_mysql_host }}
StorageUser={{ openhpc_slurmdbd_mysql_username }}
StoragePass={{ openhpc_slurmdbd_mysql_password | mandatory('You must set openhpc_slurmdbd_mysql_password') }}
StorageLoc={{ openhpc_slurmdbd_mysql_database }}

{% for key, val in openhpc_slurmdbd_merged_config.items() | sort %}
{% if val is not none and val != 'omit' %}
{{ key }}={{ 'yes' if val is sameas true else ('no' if val is sameas false else val|string) }}
Comment on lines +5 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-medium medium

The loop used to generate slurmdbd.conf is vulnerable to configuration injection. If any of the keys or values in openhpc_slurmdbd_merged_config contain newline characters, an attacker who can control these variables can inject arbitrary configuration directives into the slurmdbd.conf file. This could lead to unauthorized configuration changes, such as modifying authentication settings or log file locations. Additionally, values containing special characters like # or spaces are not properly quoted, which can lead to parsing errors or truncated values (e.g., in passwords).

{% endif %}
{% endfor %}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

It's a good practice for text-based configuration files to end with a newline character. This file is missing one, which can cause issues with some tools or scripts. Please add a newline at the end of the file.

{% endfor %}

23 changes: 23 additions & 0 deletions vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,27 @@ ohpc_slurm_packages:
- "slurm-slurmdbd-ohpc"

openhpc_merged_config: "{{ openhpc_default_config | combine(openhpc_config) }}"

ohpc_nodegroups_computed: >
{
{% for nodegroup in openhpc_nodegroups %}
{% set inventory_group_name = openhpc_cluster_name ~ '_' ~ nodegroup.name %}
{% set inventory_group_hosts = groups.get(inventory_group_name, []) %}
{% if inventory_group_hosts | length > 0 %}
{% set play_group_hosts = inventory_group_hosts | intersect (play_hosts) %}
{% set first_host = play_group_hosts | first | mandatory('Inventory group "' ~ inventory_group_name ~ '" contains no hosts in this play - was --limit used?') %}
{% set first_host_hv = hostvars[first_host] %}
{% set ram_mb = (first_host_hv['ansible_memory_mb']['real']['total'] * (nodegroup.ram_multiplier | default(openhpc_ram_multiplier))) | int %}
{{ nodegroup.name | to_json }}: {
"inventory_group_name": {{ inventory_group_name | to_json }},
"first_host": {{ first_host | to_json }},
"ram_mb": {{ ram_mb }},
"def_mem_per_cpu": {{ (ram_mb / first_host_hv['ansible_processor_vcpus']) | int }},
},
{% endif %}
{% endfor %}
}
Comment on lines +23 to +41
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The current implementation for constructing ohpc_nodegroups_computed builds a string that is supposed to be a YAML/JSON dictionary. This is fragile and can fail due to a trailing comma if the last item in the loop meets the condition, which would result in invalid YAML. A more robust approach is to build a list of dictionary-item strings and then join them. This avoids manual string formatting and ensures valid output without a trailing comma.

ohpc_nodegroups_computed: >
  {
  {% set items = [] %}
  {% for nodegroup in openhpc_nodegroups %}
  {%  set inventory_group_name = openhpc_cluster_name ~ '_' ~ nodegroup.name %}
  {%  set inventory_group_hosts = groups.get(inventory_group_name, []) %}
  {%      if inventory_group_hosts | length > 0 %}
  {%          set play_group_hosts = inventory_group_hosts | intersect (play_hosts) %}
  {%          set first_host = play_group_hosts | first | mandatory('Inventory group "' ~ inventory_group_name ~ '" contains no hosts in this play - was --limit used?') %}
  {%          set first_host_hv = hostvars[first_host] %}
  {%          set ram_mb = (first_host_hv['ansible_memory_mb']['real']['total'] * (nodegroup.ram_multiplier | default(openhpc_ram_multiplier))) | int %}
  {%          capture item_str %}
      {{ nodegroup.name | to_json }}: {
          "inventory_group_name": {{ inventory_group_name | to_json }},
          "first_host": {{ first_host | to_json }},
          "ram_mb": {{ ram_mb }},
          "def_mem_per_cpu": {{ (ram_mb / first_host_hv['ansible_processor_vcpus']) | int }}
      }
  {%          endcapture %}
  {%          set _ = items.append(item_str) %}
  {%      endif %}
  {% endfor %}
  {{ items | join(',\n') }}
  }


openhpc_slurmdbd_merged_config: "{{ openhpc_slurmdbd_default_config | combine(openhpc_slurmdbd_config) }}"

...