214 lines
6.6 KiB
YAML
214 lines
6.6 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.shell: 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_short }}
|
|
|
|
##########################################################
|
|
# 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.shell: 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_short }}
|
|
|
|
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_short }}
|
|
headers:
|
|
Title: "Proxmox cluster update failed"
|
|
Priority: "5"
|
|
Tags: "x"
|
|
delegate_to: localhost
|
|
become: false
|
|
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
|
|
become: false
|
|
run_once: true
|
|
when: ntfy_url is defined
|
|
|