- name: Configure Proxmox backup jobs hosts: mini-pc gather_facts: false vars: pve_backup_jobs: - id: homelab-pbs-daily-cloud comment: Daily PBS backup for cloud-pc service containers node: cloud-pc vmid: 141,145,146,147,149 storage: pbs schedule: "02:10" mode: snapshot exclude_path: /var/lib/docker/fuse-overlayfs/*/merged - id: homelab-pbs-daily-mini comment: Daily PBS backup for mini-pc service containers node: mini-pc vmid: 132,140,142,143,144,150 storage: pbs schedule: "02:40" mode: snapshot exclude_path: /var/lib/docker/fuse-overlayfs/*/merged - id: homelab-local-weekly-pbs comment: Weekly local backup for PBS container rootfs/config node: cloud-pc vmid: 120 storage: backup schedule: "Sun 03:30" mode: snapshot prune_backups: keep-last=2 tasks: - name: Get existing Proxmox backup jobs ansible.builtin.command: pvesh get /cluster/backup --output-format json register: pve_backup_jobs_existing_raw changed_when: false - name: Parse existing Proxmox backup jobs ansible.builtin.set_fact: pve_backup_jobs_existing: "{{ pve_backup_jobs_existing_raw.stdout | from_json }}" - name: Create missing Proxmox backup jobs ansible.builtin.command: >- pvesh create /cluster/backup --id {{ item.id }} --enabled 1 --node {{ item.node }} --vmid {{ item.vmid }} --storage {{ item.storage }} --schedule {{ item.schedule | quote }} --mode {{ item.mode }} {% if item.prune_backups is defined %} --prune-backups {{ item.prune_backups }} --remove 1 {% else %} --remove 0 {% endif %} {% if item.exclude_path is defined %} --exclude-path {{ item.exclude_path | quote }} {% endif %} --notes-template {{ '{{' }}guestname{{ '}}' }} --comment {{ item.comment | quote }} loop: "{{ pve_backup_jobs }}" when: item.id not in (pve_backup_jobs_existing | map(attribute='id') | list) - name: Update existing Proxmox backup jobs ansible.builtin.command: >- pvesh set /cluster/backup/{{ item.id }} --enabled 1 --node {{ item.node }} --vmid {{ item.vmid }} --storage {{ item.storage }} --schedule {{ item.schedule | quote }} --mode {{ item.mode }} {% if item.prune_backups is defined %} --prune-backups {{ item.prune_backups }} --remove 1 {% else %} --delete prune-backups --remove 0 {% endif %} {% if item.exclude_path is defined %} --exclude-path {{ item.exclude_path | quote }} {% else %} --delete exclude-path {% endif %} --notes-template {{ '{{' }}guestname{{ '}}' }} --comment {{ item.comment | quote }} loop: "{{ pve_backup_jobs }}" vars: current_job: >- {{ pve_backup_jobs_existing | selectattr('id', 'equalto', item.id) | first }} when: - item.id in (pve_backup_jobs_existing | map(attribute='id') | list) - >- current_job.enabled | int != 1 or current_job.node != item.node or current_job.vmid | string != item.vmid | string or current_job.storage != item.storage or current_job.schedule != item.schedule or current_job.mode != item.mode or current_job.comment != item.comment or current_job.remove | int != (1 if item.prune_backups is defined else 0) or current_job['exclude-path'] | default([]) != ([item.exclude_path] if item.exclude_path is defined else []) or (item.prune_backups is not defined and current_job['prune-backups'] is defined) or (item.prune_backups is defined and (current_job['prune-backups'] | default({})).get('keep-last', 0) | int != item.prune_backups | regex_replace('^keep-last=', '') | int) changed_when: true - name: Show configured Proxmox backup jobs ansible.builtin.command: pvesh get /cluster/backup --output-format yaml register: pve_backup_jobs_configured changed_when: false - name: Print configured Proxmox backup jobs ansible.builtin.debug: var: pve_backup_jobs_configured.stdout_lines