126 lines
5.9 KiB
YAML
126 lines
5.9 KiB
YAML
---
|
|
- name: Reboot Linux hosts if required (or forced)
|
|
hosts: linux_hosts
|
|
gather_facts: true
|
|
vars:
|
|
force_reboot: false # override with -e force_reboot=true to reboot all hosts
|
|
tasks:
|
|
|
|
- name: Get running kernel version
|
|
ansible.builtin.command: uname -r
|
|
register: running_kernel
|
|
changed_when: false
|
|
|
|
- name: Detect if running inside an LXC container
|
|
# Works on both Debian and Alpine — checks /proc/1/environ for container=lxc
|
|
# This is set by the Proxmox LXC runtime and is reliable across distros
|
|
ansible.builtin.shell: |
|
|
cat /proc/1/environ | tr '\0' '\n' | grep -q '^container=lxc' && echo "lxc" || echo "none"
|
|
register: virt_detect
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Set is_lxc fact
|
|
ansible.builtin.set_fact:
|
|
is_lxc: "{{ virt_detect.stdout | trim == 'lxc' }}"
|
|
|
|
# ── Debian/Ubuntu ──────────────────────────────────────────────────────────
|
|
- name: Get installed kernel version (Debian/Ubuntu)
|
|
ansible.builtin.shell: |
|
|
dpkg -l 'linux-image-*' 2>/dev/null \
|
|
| awk '/^ii/ {print $3}' \
|
|
| sort -V | tail -1
|
|
register: installed_kernel_deb
|
|
changed_when: false
|
|
when: ansible_os_family == "Debian"
|
|
|
|
- name: Normalize installed kernel version (Debian/Ubuntu)
|
|
ansible.builtin.set_fact:
|
|
installed_kernel_version: "{{ installed_kernel_deb.stdout | trim }}"
|
|
installed_kernel_base: "{{ installed_kernel_deb.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
running_kernel_base: "{{ running_kernel.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
when: ansible_os_family == "Debian"
|
|
|
|
# ── Alpine ─────────────────────────────────────────────────────────────────
|
|
- name: Get installed kernel version (Alpine)
|
|
ansible.builtin.shell: |
|
|
apk info --installed 2>/dev/null \
|
|
| grep '^linux-' | sort -V | tail -1 | awk '{print $1}'
|
|
register: installed_kernel_alpine
|
|
changed_when: false
|
|
when: ansible_os_family == "Alpine"
|
|
|
|
- name: Normalize installed kernel version (Alpine)
|
|
ansible.builtin.set_fact:
|
|
installed_kernel_version: "{{ installed_kernel_alpine.stdout | trim }}"
|
|
installed_kernel_base: "{{ installed_kernel_alpine.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
running_kernel_base: "{{ running_kernel.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
when: ansible_os_family == "Alpine"
|
|
|
|
# ── RHEL/CentOS ────────────────────────────────────────────────────────────
|
|
- name: Get installed kernel version (RHEL/CentOS)
|
|
ansible.builtin.shell: |
|
|
rpm -q --last kernel 2>/dev/null \
|
|
| head -1 | awk '{print $1}' | sed 's/kernel-//'
|
|
register: installed_kernel_rhel
|
|
changed_when: false
|
|
when: ansible_os_family == "RedHat"
|
|
|
|
- name: Normalize installed kernel version (RHEL/CentOS)
|
|
ansible.builtin.set_fact:
|
|
installed_kernel_version: "{{ installed_kernel_rhel.stdout | trim }}"
|
|
installed_kernel_base: "{{ installed_kernel_rhel.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
running_kernel_base: "{{ running_kernel.stdout | trim | regex_replace('^(\\d+\\.\\d+\\.\\d+).*', '\\1') }}"
|
|
when: ansible_os_family == "RedHat"
|
|
|
|
# ── Fallback ───────────────────────────────────────────────────────────────
|
|
- name: Set fallback for unknown hosts
|
|
ansible.builtin.set_fact:
|
|
installed_kernel_version: "unknown"
|
|
installed_kernel_base: "unknown"
|
|
running_kernel_base: "unknown"
|
|
when: installed_kernel_version is not defined
|
|
|
|
# ── Determine reboot need ──────────────────────────────────────────────────
|
|
- name: Determine if reboot is needed
|
|
ansible.builtin.set_fact:
|
|
reboot_needed: >-
|
|
{{
|
|
not is_lxc | bool
|
|
and installed_kernel_version != 'unknown'
|
|
and installed_kernel_base != ''
|
|
and installed_kernel_base != running_kernel_base
|
|
}}
|
|
|
|
- name: Report reboot status
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
{{ inventory_hostname }}:
|
|
running={{ running_kernel.stdout | trim }} (base={{ running_kernel_base }}),
|
|
installed={{ installed_kernel_version }} (base={{ installed_kernel_base }}),
|
|
virt={{ virt_detect.stdout | trim }},
|
|
is_lxc={{ is_lxc }},
|
|
reboot_needed={{ reboot_needed }},
|
|
force_reboot={{ force_reboot }}
|
|
— {{ 'WILL reboot' if (reboot_needed | bool or force_reboot | bool) else 'Skipping reboot' }}
|
|
|
|
- name: Reboot host
|
|
ansible.builtin.reboot:
|
|
reboot_timeout: 300
|
|
pre_reboot_delay: 10
|
|
post_reboot_delay: 30
|
|
msg: "Scheduled reboot — initiated by Ansible"
|
|
when: reboot_needed | bool or force_reboot | bool
|
|
|
|
- name: Verify kernel version after reboot
|
|
ansible.builtin.command: uname -r
|
|
register: post_reboot_kernel
|
|
changed_when: false
|
|
when: reboot_needed | bool or force_reboot | bool
|
|
|
|
- name: Report post-reboot kernel
|
|
ansible.builtin.debug:
|
|
msg: "{{ inventory_hostname }} rebooted — now running kernel {{ post_reboot_kernel.stdout | trim }}"
|
|
when: reboot_needed | bool or force_reboot | bool
|
|
|