ce7e2bc205
Claude-Session: https://claude.ai/code/session_01JEczyvRjfakkiDNkbZA7PR
147 lines
5.0 KiB
YAML
147 lines
5.0 KiB
YAML
---
|
|
# Reports which Ubuntu/Rocky guests need a reboot and, only when asked,
|
|
# reboots them. LXC containers restart via Proxmox when they reboot themselves.
|
|
#
|
|
# Extra vars (optional):
|
|
# do_reboot - default false (report only)
|
|
# reboot_exclude - hosts never rebooted by this playbook (default: [docker],
|
|
# which most likely runs Semaphore itself)
|
|
|
|
- name: Check Host Availability
|
|
hosts: ubuntu:rocky
|
|
gather_facts: false
|
|
ignore_unreachable: true
|
|
|
|
tasks:
|
|
- name: Ping hosts to check availability
|
|
ansible.builtin.ping:
|
|
register: ping_result
|
|
ignore_errors: true
|
|
ignore_unreachable: true
|
|
|
|
- name: Add reachable hosts to group
|
|
ansible.builtin.group_by:
|
|
key: reachable_hosts
|
|
when: ping_result is succeeded
|
|
|
|
- name: Report offline hosts
|
|
ansible.builtin.debug:
|
|
msg: "{{ inventory_hostname }} - OFFLINE"
|
|
when: ping_result is not succeeded
|
|
delegate_to: localhost
|
|
|
|
- name: Reboot Check - Ubuntu
|
|
hosts: ubuntu:&reachable_hosts
|
|
become: true
|
|
gather_facts: true
|
|
|
|
tasks:
|
|
- name: Check for the reboot-required flag
|
|
ansible.builtin.stat:
|
|
path: /var/run/reboot-required
|
|
register: reboot_flag
|
|
|
|
- name: Read the packages that requested a reboot
|
|
ansible.builtin.slurp:
|
|
src: /var/run/reboot-required.pkgs
|
|
register: reboot_pkgs
|
|
when: reboot_flag.stat.exists
|
|
failed_when: false
|
|
|
|
- name: Record reboot status
|
|
ansible.builtin.set_fact:
|
|
reboot_needed: "{{ reboot_flag.stat.exists }}"
|
|
reboot_reason: "{{ (reboot_pkgs.content | default('') | b64decode | trim | replace('\n', ', ')) if reboot_flag.stat.exists else '' }}"
|
|
|
|
- name: Reboot Check - Rocky Linux
|
|
hosts: rocky:&reachable_hosts
|
|
become: true
|
|
gather_facts: true
|
|
|
|
tasks:
|
|
- name: Ensure needs-restarting is available
|
|
ansible.builtin.dnf:
|
|
name: yum-utils
|
|
state: present
|
|
|
|
# needs-restarting -r compares package install times against the kernel boot
|
|
# time, which inside an LXC container is the host's boot time, so the flag
|
|
# would never clear. Containers use the process-based check instead.
|
|
- name: Check whether a reboot is required (VM)
|
|
ansible.builtin.command: needs-restarting -r
|
|
register: needs_reboot
|
|
failed_when: needs_reboot.rc not in [0, 1]
|
|
changed_when: false
|
|
when: ansible_virtualization_type != "lxc"
|
|
|
|
- name: Check for processes using updated libraries (LXC)
|
|
ansible.builtin.command: needs-restarting
|
|
register: stale_procs
|
|
failed_when: stale_procs.rc not in [0, 1]
|
|
changed_when: false
|
|
when: ansible_virtualization_type == "lxc"
|
|
|
|
- name: Record reboot status
|
|
ansible.builtin.set_fact:
|
|
reboot_needed: >-
|
|
{{ (needs_reboot.rc == 1) if ansible_virtualization_type != 'lxc'
|
|
else ((stale_procs.stdout | trim | length) > 0) }}
|
|
reboot_reason: >-
|
|
{{ (needs_reboot.stdout | default('') | trim | replace('\n', '; ')) if ansible_virtualization_type != 'lxc'
|
|
else ((stale_procs.stdout_lines | default([]) | length | string) ~ ' process(es) using updated libraries') }}
|
|
|
|
- name: Reboot Check - Report
|
|
hosts: reachable_hosts
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Print reboot status
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
{{ inventory_hostname }} ({{ ansible_virtualization_type | default('unknown') }}) -
|
|
REBOOT NEEDED: {{ 'YES' if reboot_needed | default(false) | bool else 'no' }}
|
|
{{ ('- ' ~ reboot_reason) if (reboot_needed | default(false) | bool and reboot_reason | default('') | length > 0) else '' }}
|
|
|
|
- name: Reboot Check - Reboot hosts that need it
|
|
hosts: reachable_hosts
|
|
become: true
|
|
gather_facts: false
|
|
|
|
vars:
|
|
do_reboot: false
|
|
reboot_exclude:
|
|
- docker
|
|
|
|
tasks:
|
|
- name: Report hosts skipped because they are excluded
|
|
ansible.builtin.debug:
|
|
msg: "SKIPPED: {{ inventory_hostname }} needs a reboot but is listed in reboot_exclude"
|
|
when:
|
|
- do_reboot | bool
|
|
- reboot_needed | default(false) | bool
|
|
- inventory_hostname in reboot_exclude
|
|
|
|
# Inside a container the default boot_id belongs to the host and never
|
|
# changes, so the reboot module would wait forever. PID 1's start time does
|
|
# change when the container restarts.
|
|
- name: Reboot LXC container
|
|
ansible.builtin.reboot:
|
|
boot_time_command: "awk '{print $22}' /proc/1/stat"
|
|
reboot_timeout: 300
|
|
msg: "Reboot initiated by Ansible (reboot_check.yml)"
|
|
when:
|
|
- do_reboot | bool
|
|
- reboot_needed | default(false) | bool
|
|
- inventory_hostname not in reboot_exclude
|
|
- ansible_virtualization_type == "lxc"
|
|
|
|
- name: Reboot VM
|
|
ansible.builtin.reboot:
|
|
reboot_timeout: 300
|
|
msg: "Reboot initiated by Ansible (reboot_check.yml)"
|
|
when:
|
|
- do_reboot | bool
|
|
- reboot_needed | default(false) | bool
|
|
- inventory_hostname not in reboot_exclude
|
|
- ansible_virtualization_type != "lxc"
|