Files
Homelab/ansible/proxmox/update_proxmox.yml

212 lines
6.5 KiB
YAML

---
- name: Rolling update Proxmox VE cluster
hosts: nodes
any_errors_fatal: true
become: true
serial: 1
vars:
ntfy_password: "{{ lookup('env', 'NTFY_PASSWORD') }}"
pre_tasks:
##########################################################
# Verify input variables
##########################################################
- name: Assert ntfy variables
ansible.builtin.assert:
that:
- ntfy_topic is defined
- ntfy_user is defined
- ntfy_password != ""
quiet: true
when: ntfy_url is defined
##########################################################
# Verify cluster health
##########################################################
- name: Verify quorum
ansible.builtin.command: pvecm status
register: quorum_status
changed_when: false
delegate_to: "{{ groups['nodes'][0] }}"
run_once: true
- name: Abort if cluster has no quorum
ansible.builtin.fail:
msg: "Cluster quorum not available"
when: quorum_status.stdout is not search('Quorate:\\s*Yes')
- name: Check Ceph health
ansible.builtin.command: ceph health
register: ceph_health
changed_when: false
delegate_to: "{{ groups['nodes'][0] }}"
run_once: true
- name: Abort if Ceph unhealthy
ansible.builtin.fail:
msg: "{{ ceph_health.stdout }}"
when: "'HEALTH_OK' not in ceph_health.stdout"
tasks:
- block:
##########################################################
# Capture current versions
##########################################################
- name: Capture version after upgrade
ansible.builtin.command: pveversion | awk -F'/' '{print $2}'
register: pve_current_version
changed_when: false
##########################################################
# Enable maintenance mode
##########################################################
- name: Enable maintenance mode
ansible.builtin.command: >
ha-manager crm-command node-maintenance enable {{ inventory_hostname }}
##########################################################
# Wait until node empty
##########################################################
- name: Wait for VMs to leave node
ansible.builtin.shell: |
qm list | awk 'NR>1 && $3=="running" {count++} END {print count+0}'
register: vm_count
changed_when: false
until: vm_count.stdout | int == 0
retries: 60
delay: 15
- name: Wait for LXCs to leave node
ansible.builtin.shell: |
pct list | awk 'NR>1 && $2=="running" {count++} END {print count+0}'
register: lxc_count
changed_when: false
until: lxc_count.stdout | int == 0
retries: 60
delay: 15
##########################################################
# Upgrade packages
##########################################################
- name: Refresh repositories
ansible.builtin.apt:
update_cache: true
- name: Dist upgrade
ansible.builtin.apt:
upgrade: dist
autoremove: true
autoclean: true
##########################################################
# Capture new versions
##########################################################
- name: Capture version after upgrade
ansible.builtin.command: pveversion | awk -F'/' '{print $2}'
register: pve_new_version
changed_when: false
##########################################################
# Check reboot with Ceph rebalancing disabled
##########################################################
- name: Check reboot requirement
ansible.builtin.stat:
path: /var/run/reboot-required
register: reboot_required
- when: reboot_required.stat.exists
block:
- name: Disable Ceph rebalancing
ansible.builtin.command: ceph osd set noout
- name: Reboot node
ansible.builtin.reboot:
reboot_timeout: 900
post_reboot_delay: 30
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 600
- name: Enable Ceph rebalancing
ansible.builtin.command: ceph osd unset noout
##########################################################
# Ceph validation
##########################################################
- name: Wait for HEALTH_OK
ansible.builtin.command: ceph health
register: ceph_status
changed_when: false
until: "'HEALTH_OK' in ceph_status.stdout"
retries: 60
delay: 15
delegate_to: "{{ groups['nodes'][0] }}"
##########################################################
# Disable maintenance mode
##########################################################
- name: Disable maintenance mode
ansible.builtin.command: >
ha-manager crm-command node-maintenance disable {{ inventory_hostname }}
rescue:
##########################################################
# Send notification
##########################################################
- name: Send failure notification
ansible.builtin.uri:
url: "{{ ntfy_url }}/{{ ntfy_topic }}"
method: POST
user: "{{ ntfy_user }}"
password: "{{ ntfy_password }}"
force_basic_auth: true
body: Update failed on {{ inventory_hostname }}
headers:
Title: "Proxmox cluster update failed"
Priority: "5"
Tags: "x"
delegate_to: localhost
run_once: true
when: ntfy_url is defined
- ansible.builtin.fail:
msg: "Update aborted"
post_tasks:
- name: Send success notification
ansible.builtin.uri:
url: "{{ ntfy_url }}/{{ ntfy_topic }}"
method: POST
user: "{{ ntfy_user }}"
password: "{{ ntfy_password }}"
force_basic_auth: true
body: |
Proxmox cluster update completed successfully.
Old version: {{ pve_current_version.stdout }}
New version: {{ pve_new_version.stdout }}
headers:
Title: "Proxmox Update"
Priority: "3"
Tags: "white_check_mark"
delegate_to: localhost
run_once: true
when: ntfy_url is defined