Creating snaps with ansible

Wadera

Renowned Member
Jan 31, 2013
11
2
68
I'm trying to improve my patching automation of my VM infrastructure and as a first step which would be my rescue if anything goes wrong

I've managed to grow it up to that mostrosity already trying to catch snap status and wait for be completed:

YAML:
---
# roles/proxmox_snapshot/tasks/take_snap.yml

- name: Get VM info
  community.general.proxmox_vm_info:
    api_host: "{{ proxmox_api_host }}:8006"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: {{ vm_id }}
  become: no
  delegate_to: localhost
  register: vm_info

- name: Set node fact
  set_fact:
    vm_node: "{{ vm_info.proxmox_vms[0].node }}"

- name: Display VM node
  debug:
    msg: "VM {{ vm_id }} is on node: {{ vm_node }}"

- name: Generate snapshot name
  set_fact:
    snapshot_name: "ans-{{ lookup('pipe', 'date +\"%Y%m%d%H%M%S\"') }}"

- name: Ensure VM is present
  community.general.proxmox_kvm:
    api_host: "{{ proxmox_api_host }}:8006"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: {{ vm_id }}
    node: "{{ vm_node }}"
    state: present
  become: no
  delegate_to: localhost

- name: Get timestamp before snapshot
  set_fact:
    snapshot_start_time: "{{ lookup('pipe', 'date +%s') | float }}"
  delegate_to: localhost

- name: Create snapshot with memory dump
  community.general.proxmox_snap:
    api_host: "{{ proxmox_api_host }}:8006"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: {{ vm_id }}
    state: present
    vmstate: true
    snapname: "{{ snapshot_name }}"
    description: "Automated snapshot before DirectAdmin upgrade"
  become: no
  delegate_to: localhost
  register: snapshot_result

- name: Get timestamp when snapshot started
  set_fact:
    snapshot_start_timestamp: "{{ '%Y%m%d%H%M%S' | strftime(ansible_date_time.epoch | int) }}"


# Debug task output to see the UPID
- name: Debug snapshot task output
  debug:
    var: snapshot_result
    verbosity: 2

- name: Get running snapshot tasks
  community.general.proxmox_tasks_info:
    api_host: "{{ proxmox_api_host }}:8006"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    node: "{{ vm_node }}"
  become: no
  delegate_to: localhost
  register: task_list
  until: >
    task_list.proxmox_tasks |
    selectattr('type', 'eq', 'qmsnapshot') |
    selectattr('status', 'eq', 'running') | list | length > 0 or
    task_list.proxmox_tasks | selectattr('type', 'eq', 'qmsnapshot') |
    selectattr('status', 'eq', 'OK') | list | length > 0
    task_list.proxmox_tasks |
    selectattr('type', 'eq', 'qmsnapshot') |
    selectattr('starttime', 'ge', snapshot_start_timestamp | int) |
    list | length > 0
  retries: 10
  delay: 3

- name: Set snapshot task ID
  set_fact:
    snapshot_upid: "{{ (task_list.proxmox_tasks | selectattr('type', 'eq', 'qmsnapshot') | list | first).upid }}"
  when: task_list.proxmox_tasks | selectattr('type', 'eq', 'qmsnapshot') | list | length > 0

- name: Wait for snapshot task to complete
  community.general.proxmox_tasks_info:
    api_host: "{{ proxmox_api_host }}:8006"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    node: "{{ vm_node }}"
  register: task_status
  until: >
    task_status.proxmox_tasks | selectattr('upid', 'eq', snapshot_upid) |
    selectattr('status', 'eq', 'OK') | list | length > 0
  retries: 60  # Adjust based on your needs
  delay: 10
  become: no
  delegate_to: localhost
  when: snapshot_upid is defined

- name: Verify task completion
  debug:
    msg: "Snapshot task {{ snapshot_upid }} completed successfully"
  when: snapshot_upid is defined

- name: Display snapshot creation success
  debug:
    msg:
      - "Snapshot creation completed successfully"
      - "Snapshot name: {{ snapshot_name }}"
      - "Node: {{ vm_node }}"

So far I keep manage to catch previous snap task status instead of current one.

Could anyone give me a friendly hand and maybe share any working approach? :)
 
OK, I've changed approach instead of dig into difficult to process tasks status - I'm simply checking if lock on VM appear due to snapshot and then if it's release.

When that happen - I'm finally checking if snapshot exist. That's the code if anyone would need it:


XML:
---
# roles/proxmox_snapshot/tasks/take_snap.yml

- name: Get VM info
  community.general.proxmox_vm_info:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
  become: no
  delegate_to: localhost
  register: vm_info

- name: Set node fact
  set_fact:
    vm_node: "{{ vm_info.proxmox_vms[0].node }}"

- name: Display VM node
  debug:
    msg: "VM 4111 is on node: {{ vm_node }}"

- name: Generate snapshot name
  set_fact:
    snapshot_name: "ans-{{ lookup('pipe', 'date +\"%Y%m%d%H%M%S\"') }}"

- name: Ensure VM is present
  community.general.proxmox_kvm:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
    node: "{{ vm_node }}"
    state: present
  become: no
  delegate_to: localhost

- name: Create snapshot with memory dump
  community.general.proxmox_snap:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
    state: present
    vmstate: true
    snapname: "{{ snapshot_name }}"
    description: "Automated snapshot before DirectAdmin upgrade"
  become: no
  delegate_to: localhost
  register: snapshot_result
  failed_when: >
    snapshot_result is failed and
    'New-style module did not handle its own exit' not in snapshot_result.msg
  ignore_errors: true # Capture any error rather than failing immediately

# First, wait for snapshot lock to appear
- name: Wait for snapshot lock to appear
  community.general.proxmox_vm_info:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
    node: "{{ vm_node }}"
  delegate_to: localhost
  become: no
  register: vm_info
  until: >
    vm_info.proxmox_vms | first is defined and
    vm_info.proxmox_vms | first | dict2items | selectattr('key', 'eq', 'lock') |
    selectattr('value', 'eq', 'snapshot') | list | length > 0
  retries: 6
  delay: 10

# Then, wait for snapshot lock to be released
- name: Wait for snapshot lock to be released
  community.general.proxmox_vm_info:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
    node: "{{ vm_node }}"
  delegate_to: localhost
  become: no
  register: vm_info
  until: >
    vm_info.proxmox_vms | first is defined and
    (
      'lock' not in vm_info.proxmox_vms[0] or
      vm_info.proxmox_vms[0].lock != 'snapshot'
    )
  retries: 90
  delay: 10

# Debug output to help troubleshoot
- name: Debug VM info
  debug:
    msg:
      - "VM Info:"
      - "Lock status: {{ vm_info.proxmox_vms[0].lock | default('no lock') }}"
      - "Full VM info: {{ vm_info.proxmox_vms[0] | to_json }}"

# Finally, verify the snapshot exists using proxmox_snap
- name: Verify snapshot exists
  community.general.proxmox_snap:
    api_host: "{{ proxmox_api_host }}"
    api_user: "{{ proxmox_api_user }}"
    api_token_id: "{{ proxmox_api_token_id }}"
    api_token_secret: "{{ proxmox_api_token_secret }}"
    validate_certs: false
    vmid: "{{ proxmox_vm_id }}"
    node: "{{ vm_node }}"
    state: current  # This will list current snapshots without making changes
    snapname: "{{ snapshot_name }}"
  delegate_to: localhost
  become: no
  register: snapshot_status
  until: snapshot_status is not failed
  retries: 6
  delay: 10
  failed_when: false  # We don't want this to fail the play

- name: Display completion message
  debug:
    msg: "Snapshot {{ snapshot_name }} has been created successfully"
  when: snapshot_status is not failed

- name: Fail if snapshot was not created
  fail:
    msg: "Failed to verify snapshot {{ snapshot_name }} creation"
  when: snapshot_status is failed
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!