Snapshot all running VMs on Proxmox via Ansible

Hey there

I use Ansible to automate all VM updates in my Proxmox Cluster. The annoying thing currently is, that I have to snapshot every single VM by hand from Proxmox GUI before running my Playbooks.

Yes indeed, I have a Proxmox Backup Server and daily backups and additional ZFS replication of the VM storage itself, but I don’t want to rely on those to restore in case of non recoverable failure because I run the updates randomly when I have some spare time (yes yes, at least weekly). :smiley:

I know Proxmox offers the possibility to take snapshots via CMD

qm snapshot <vmid> <snapshotname>

where <vmid> has following option:

<vmid>: <integer> (1 - N)
            The (unique) ID of the VM.

So I guess i could deploy a command like this?

qm snapshot 100,101,102 before_update

Not really sure if I understand the 1-N corretly.

Either case, I don’t really want to maintain the list everytime a VM is deleted or added.

Is there a command in Proxmox to update every VM currently running with a single snapshot name for all of them or will I have to create a script that will be called from Ansible?

If I have to go with a script, how do I make Ansible wait for the script to finish before continuing with the execution and get the status back in case of failure?

Thanks in advance

The 1-N is describing the expected value of <vmid> (i.e., a non-zero integer – though, the valid range of Proxmox vmids is currently 100 - 999999999, rather than actually 1 - N).

Unfortunately, this means qm snapshot 100,101,102 before_update won’t work, but you can get there with a little work.

You can use qm list and a little AWK to get the IDs of all running VMs:
qm list | awk '$3 == "running" { print $1 }'

You have a couple options for how to use the results of that:

  1. Pipe to xargs to snapshot each VM (this could be run using the Ansible shell module):

    • qm list | awk '$3 == "running" { print $1 }' | xargs -I % qm snapshot % before_update
  2. Register the output as an Ansible variable, then use Ansible to iterate over the running VMs and snapshot them:

---
- hosts: all
  tasks:
    - name: Use qm list and awk to get all running vmids
      ansible.builtin.shell: qm list | awk '$3 == "running" { print $1 }'
      register: running_vmids
      failed_when: running_vmids.stderr # Check for stderr, as pipe to awk may mask a failure (e.g., qm command not found)

    - name: Snapshot each running VM
      ansible.builtin.command: "qm snapshot {{ item }} before_update"
      with_items:
        - "{{ running_vmids.stdout_lines }}"

Best of luck, and let me know if I can clarify anything for you!

2 Likes

Amazing, thanks a lot! I will try your solution very soon and report back if it worked, but am I positive it will.

There are some things still unclear to me in your solution but I will try reading through the documentation first. :smiley:

EDIT:
Worked like a charm, thanks again!

proxmox has its own api also… could use that instead of shell cmds

You mean something like an Ansible module? Or better ask, what would the benefit be of using the API instead of shell commands?

A quick google search didn’t yield any “official” results besides user modules, none of which supported snapshot functionality unfortunately.

Do you have a useful link with further informations?

I haven’t checked ansible Galaxy for anything but someone likely wrote something already to use it.