prole/infrastructure/roles/cgroups/tasks/main.yml

197 lines
7.2 KiB
YAML

---
- name: Find kernel cmdline file
ansible.builtin.stat:
path: "{{ item }}"
loop: "{{ cgroups_cmdline_candidates }}"
register: cmdline_stats
- name: Select kernel cmdline path
ansible.builtin.set_fact:
cgroups_cmdline_all_paths: "{{ cmdline_stats.results | selectattr('stat.exists') | map(attribute='stat.path') | list }}"
- name: Select kernel cmdline update targets
ansible.builtin.set_fact:
cgroups_cmdline_paths: "{{ cgroups_cmdline_all_paths }}"
- name: Fail when kernel cmdline file is missing
ansible.builtin.fail:
msg: "No kernel cmdline file found. Checked: {{ cgroups_cmdline_candidates | join(', ') }}"
when: cgroups_cmdline_paths | length == 0
- name: Remove literal backslash escapes from kernel cmdline files
ansible.builtin.replace:
path: "{{ item }}"
regexp: "\\\\[nrt]"
replace: " "
loop: "{{ cgroups_cmdline_paths }}"
register: cmdline_escape_cleanup
- name: Remove stray backslashes from kernel cmdline files
ansible.builtin.replace:
path: "{{ item }}"
regexp: "\\\\"
replace: " "
loop: "{{ cgroups_cmdline_paths }}"
register: cmdline_backslash_cleanup
- name: Read kernel cmdline files
ansible.builtin.slurp:
path: "{{ item }}"
loop: "{{ cgroups_cmdline_paths }}"
register: cmdline_files
- name: Read current /proc/cmdline
ansible.builtin.command: "cat /proc/cmdline"
register: proc_cmdline_current
changed_when: false
check_mode: no
- name: Check current cgroup params in /proc/cmdline
ansible.builtin.set_fact:
cgroups_missing_in_proc: "{{ cgroups_required_params | reject('in', proc_cmdline_current.stdout | default('')) | list }}"
cgroups_conflicting_in_proc: "{{ cgroups_remove_params | select('in', proc_cmdline_current.stdout | default('')) | list }}"
- name: Normalize kernel cmdline content
ansible.builtin.set_fact:
cgroups_cmdline_files: >-
{{ (cgroups_cmdline_files | default([])) + [{
'path': item.item,
'raw_line': ((item.content | b64decode).splitlines() | join(' ') | trim),
'sanitized': (((item.content | b64decode).splitlines() | join(' ') | trim)
| regex_replace('\\\\[nrt]', ' ')
| regex_replace('\\\\', ' ')
| regex_replace('\\s+', ' ')
| trim)
}] }}
loop: "{{ cmdline_files.results }}"
- name: Select kernel cmdline line
ansible.builtin.set_fact:
cgroups_cmdline_current: "{{ (cgroups_cmdline_files | map(attribute='sanitized') | list | first) | default('') }}"
- name: Select cmdline source
ansible.builtin.set_fact:
cgroups_cmdline_source: "{{ (cgroups_cmdline_current | length > 0) | ternary(cgroups_cmdline_current, proc_cmdline_current.stdout | default('')) }}"
- name: Sanitize kernel cmdline
ansible.builtin.set_fact:
cgroups_cmdline_sanitized: >-
{{ cgroups_cmdline_source
| regex_replace('\\\\[nrt]', ' ')
| regex_replace('\\\\', ' ')
| regex_replace('\\s+', ' ')
| trim }}
- name: Tokenize kernel cmdline
ansible.builtin.set_fact:
cgroups_cmdline_tokens: "{{ cgroups_cmdline_sanitized.split() }}"
- name: Remove conflicting cgroup params
ansible.builtin.set_fact:
cgroups_cmdline_filtered: "{{ cgroups_cmdline_tokens | reject('in', cgroups_remove_params) | list }}"
- name: Calculate missing cgroup params
ansible.builtin.set_fact:
cgroups_missing_params: "{{ cgroups_required_params | reject('in', cgroups_cmdline_filtered) | list }}"
- name: Build updated kernel cmdline tokens
ansible.builtin.set_fact:
cgroups_cmdline_new_tokens: "{{ (cgroups_cmdline_filtered + cgroups_missing_params) | unique | list }}"
- name: Build updated kernel cmdline line
ansible.builtin.set_fact:
cgroups_cmdline_new: "{{ cgroups_cmdline_new_tokens | join(' ') }}"
- name: Sanitize updated kernel cmdline line
ansible.builtin.set_fact:
cgroups_cmdline_new: >-
{{ cgroups_cmdline_new
| regex_replace('\\\\[nrt]', ' ')
| regex_replace('\\\\', ' ')
| regex_replace('\\s+', ' ')
| trim }}
- name: Determine if kernel cmdline needs update
ansible.builtin.set_fact:
cgroups_cmdline_needs_update: >-
{{ cgroups_cmdline_new != cgroups_cmdline_sanitized or
(cgroups_cmdline_paths | length) > 1 }}
- name: Update kernel cmdline when params are missing
ansible.builtin.copy:
dest: "{{ item.path }}"
content: >-
{{ cgroups_cmdline_new ~ '\n' }}
mode: "0644"
register: cmdline_update
when: item.raw_line != cgroups_cmdline_new
loop: "{{ cgroups_cmdline_files }}"
- name: Remove literal backslash escapes from updated cmdline files
ansible.builtin.replace:
path: "{{ item }}"
regexp: "\\\\[nrt]"
replace: " "
loop: "{{ cgroups_cmdline_paths }}"
when: (cmdline_update.results | default([]) | selectattr('changed') | list | length) > 0
- name: Normalize updated cmdline whitespace
ansible.builtin.replace:
path: "{{ item }}"
regexp: "\\s+"
replace: " "
loop: "{{ cgroups_cmdline_paths }}"
when: (cmdline_update.results | default([]) | selectattr('changed') | list | length) > 0
- name: Determine if kernel cmdline was updated
ansible.builtin.set_fact:
cgroups_cmdline_changed: >-
{{ (cmdline_escape_cleanup.results | default([]) | selectattr('changed') | list | length) > 0 or
(cmdline_backslash_cleanup.results | default([]) | selectattr('changed') | list | length) > 0 or
(cmdline_update.results | default([]) | selectattr('changed') | list | length) > 0 }}
- name: Determine if reboot is required
ansible.builtin.set_fact:
cgroups_reboot_needed: >-
{{ cgroups_cmdline_changed | bool or
(cgroups_missing_in_proc | default([]) | length) > 0 }}
- name: Reboot to apply cgroup settings
ansible.builtin.reboot:
msg: "Rebooting to apply cgroup kernel parameters"
pre_reboot_delay: 3
reboot_timeout: 600
when: cgroups_reboot_needed | bool and cgroups_reboot | bool
- name: Verify cgroup kernel parameters after reboot
ansible.builtin.command: "cat /proc/cmdline"
register: proc_cmdline
changed_when: false
check_mode: no
- name: Read cgroup v2 controllers
ansible.builtin.command: "cat /sys/fs/cgroup/cgroup.controllers"
register: cgroup_controllers
changed_when: false
check_mode: no
- name: Record cgroup memory controller presence
ansible.builtin.set_fact:
cgroups_memory_controller_present: "{{ 'memory' in (cgroup_controllers.stdout | default('')) }}"
- name: Fail when cgroup params are missing (reboot required)
ansible.builtin.fail:
msg: "Missing cgroup params in /proc/cmdline: {{ cgroups_required_params | reject('in', proc_cmdline.stdout | default('')) | list }}. Reboot required."
when:
- not ansible_check_mode
- (cgroups_required_params | reject('in', proc_cmdline.stdout | default('')) | list) | length > 0
- not cgroups_memory_controller_present
- name: Fail when conflicting cgroup params are present
ansible.builtin.fail:
msg: "Conflicting cgroup params in /proc/cmdline: {{ cgroups_remove_params | select('in', proc_cmdline.stdout | default('')) | list }}. Reboot required."
when:
- not ansible_check_mode
- (cgroups_remove_params | select('in', proc_cmdline.stdout | default('')) | list) | length > 0
- not cgroups_memory_controller_present