--- - 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 }}" cgroups_cmdline_path: "{{ (cmdline_stats.results | selectattr('stat.exists') | map(attribute='stat.path') | list | first) | default('') }}" - name: Select kernel cmdline update targets ansible.builtin.set_fact: cgroups_cmdline_paths: "{{ (cgroups_cmdline_path | length > 0) | ternary([cgroups_cmdline_path], []) }}" - 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_path | 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 - 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) | list }}" cgroups_conflicting_in_proc: "{{ cgroups_remove_params | select('in', proc_cmdline_current.stdout) | 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 - name: Read cgroup v2 controllers ansible.builtin.command: "cat /sys/fs/cgroup/cgroup.controllers" register: cgroup_controllers changed_when: false - 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) | list }}. Reboot required." when: (cgroups_required_params | reject('in', proc_cmdline.stdout) | list) | length > 0 and 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) | list }}. Reboot required." when: (cgroups_remove_params | select('in', proc_cmdline.stdout) | list) | length > 0 and not cgroups_memory_controller_present