diff --git a/roles/preflight/defaults/main.yml b/roles/preflight/defaults/main.yml index db10a6b..a0b9ac4 100644 --- a/roles/preflight/defaults/main.yml +++ b/roles/preflight/defaults/main.yml @@ -1,2 +1,5 @@ --- -# preflight default variables +min_free_disk_percent: 20 +max_load_multiplier: 2 +change_freeze: false +host_reboot_required: false diff --git a/roles/preflight/tasks/main.yml b/roles/preflight/tasks/main.yml index 872eb0d..963278b 100644 --- a/roles/preflight/tasks/main.yml +++ b/roles/preflight/tasks/main.yml @@ -1,6 +1,81 @@ --- -# preflight tasks -# Implementation to follow -- name: Placeholder +- name: Check change freeze + ansible.builtin.assert: + that: + - change_freeze == false + fail_msg: "FROZEN: {{ inventory_hostname }} is under a change freeze. Aborting." + success_msg: "Change freeze check passed" + +- name: Check disk space on critical mountpoints + ansible.builtin.shell: | + df {{ item }} --output=pcent | tail -1 | tr -d ' %' + register: disk_usage + changed_when: false + loop: + - / + - /var + - /boot + ignore_errors: true + +- name: Assert disk space is sufficient + ansible.builtin.assert: + that: + - item.stdout | int < (100 - min_free_disk_percent) + fail_msg: "DISK: {{ item.item }} is {{ item.stdout }}% full — minimum {{ min_free_disk_percent }}% free required" + success_msg: "Disk OK: {{ item.item }} is {{ item.stdout }}% used" + loop: "{{ disk_usage.results }}" + when: item.rc == 0 + +- name: Get load average + ansible.builtin.shell: | + cat /proc/loadavg | awk '{print $3}' + register: load_avg + changed_when: false + +- name: Get CPU count + ansible.builtin.shell: | + nproc + register: cpu_count + changed_when: false + +- name: Assert load average is acceptable + ansible.builtin.assert: + that: + - load_avg.stdout | float < (cpu_count.stdout | int * max_load_multiplier) + fail_msg: "LOAD: 15min load average {{ load_avg.stdout }} exceeds threshold ({{ cpu_count.stdout }} CPUs x {{ max_load_multiplier }})" + success_msg: "Load average OK: {{ load_avg.stdout }} ({{ cpu_count.stdout }} CPUs)" + +- name: Check for pending reboot (Debian/Ubuntu) + ansible.builtin.stat: + path: /var/run/reboot-required + register: reboot_required + when: ansible_os_family == "Debian" + +- name: Warn if reboot is pending ansible.builtin.debug: - msg: "preflight role - tasks to be implemented" + msg: "WARNING: {{ inventory_hostname }} has a pending reboot. Patching will proceed but reboot required afterwards." + when: + - ansible_os_family == "Debian" + - reboot_required.stat.exists + +- name: Set reboot_required fact (Debian) + ansible.builtin.set_fact: + host_reboot_required: "{{ reboot_required.stat.exists | default(false) }}" + when: ansible_os_family == "Debian" + +- name: Check for pending reboot (RHEL/CentOS) + ansible.builtin.shell: | + needs-restarting -r + register: rhel_reboot_check + changed_when: false + failed_when: false + when: ansible_os_family == "RedHat" + +- name: Set reboot_required fact (RHEL) + ansible.builtin.set_fact: + host_reboot_required: "{{ rhel_reboot_check.rc == 1 }}" + when: ansible_os_family == "RedHat" + +- name: Preflight complete + ansible.builtin.debug: + msg: "Preflight passed for {{ inventory_hostname }} — proceeding with maintenance"