Part 16 – VMware Automation with AAP: Managing VM Snapshots

Instead of clicking around vCenter, we write a single Ansible playbook that handles any VM. AWX gives it a web form (called a survey) so anyone can run it without touching the command line.

Each playbook does one thing. No hardcoded VM names and everything comes in as a variable at runtime so we will add playbooks in this format.

playbooks/
├── get_all_vms.yml ← inventory
├── get_vm_info.yml ← VM details
├── vm_hardware.yml ← change RAM/CPU
├── vm_snapshot.yml ← snapshot management
├── vm_power.yml ← power on/off/restart
├── vm_deploy.yml ← deploy from template
├── vm_delete.yml ← delete VM
├── vm_network.yml ← change network
└── vm_disk.yml ← add/expand disk

---
- name: VM Snapshot Management
  hosts: localhost
  gather_facts: false
  connection: local
  become: false

  tasks:
    - name: Validate snapshot action
      fail:
        msg: "Invalid action! Must be: create, revert, delete, delete_all, list"
      when: snapshot_action not in ['create', 'revert', 'delete', 'delete_all', 'list']

    - name: Get current VM info
      community.vmware.vmware_guest_info:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
      register: vm_info

    - name: Set VM folder
      set_fact:
        vm_folder: "{{ vm_info.instance.hw_folder }}"

    - name: Get existing snapshots
      community.vmware.vmware_guest_snapshot_info:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
      register: snapshot_info

    - name: Set existing snapshots list
      set_fact:
        existing_snapshots: "{{ snapshot_info.guest_snapshots.snapshots | default([]) }}"

    - name: Show VM info
      debug:
        msg:
          - "VM Name  : {{ vm_info.instance.hw_name }}"
          - "Power    : {{ vm_info.instance.hw_power_status }}"
          - "Action   : {{ snapshot_action }}"

    - name: Set timestamp
      set_fact:
        timestamp: "{{ lookup('pipe', 'date +%Y%m%d-%H%M') }}"
      when: snapshot_action == 'create'

    - name: Set final snapshot name
      set_fact:
        final_snapshot_name: >-
          {% if existing_snapshots | selectattr('name', 'equalto', snapshot_name) | list | length > 0 %}
          {{ snapshot_name }}-{{ timestamp }}
          {% else %}
          {{ snapshot_name }}
          {% endif %}
      when: snapshot_action == 'create'

    - name: Show planned snapshot name
      debug:
        msg:
          - "Requested name : {{ snapshot_name }}"
          - "Final name     : {{ final_snapshot_name | trim }}"
          - "{% if final_snapshot_name | trim != snapshot_name %}Name already existed - timestamp added!{% else %}Name is available{% endif %}"
      when: snapshot_action == 'create'

    - name: Fail if snapshot does not exist on revert or delete
      fail:
        msg: "Snapshot '{{ snapshot_name }}' does not exist on {{ vm_name }}! Existing: {{ existing_snapshots | map(attribute='name') | list }}"
      when:
        - snapshot_action in ['revert', 'delete']
        - existing_snapshots | selectattr('name', 'equalto', snapshot_name) | list | length == 0

    - name: Create snapshot
      vmware.vmware.vm_snapshot:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
        state: present
        snapshot_name: "{{ final_snapshot_name | trim }}"
        description: "{{ snapshot_desc | default('Created by Ansible') }}"
        memory_dump: "{{ memory_snapshot | default(false) }}"
        quiesce: "{{ quiesce | default(false) }}"
      when: snapshot_action == 'create'

    - name: Revert to snapshot
      vmware.vmware.vm_snapshot:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
        state: revert
        snapshot_name: "{{ snapshot_name }}"
      when: snapshot_action == 'revert'

    - name: Delete single snapshot
      vmware.vmware.vm_snapshot:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
        state: absent
        snapshot_name: "{{ snapshot_name }}"
      when: snapshot_action == 'delete'

    - name: Delete ALL snapshots
      community.vmware.vmware_guest_snapshot:
        hostname: "{{ lookup('env', 'VMWARE_HOST') }}"
        username: "{{ lookup('env', 'VMWARE_USER') }}"
        password: "{{ lookup('env', 'VMWARE_PASSWORD') }}"
        validate_certs: false
        datacenter: "Datacenter"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
        state: absent
        remove_children: true
        snapshot_name: "{{ existing_snapshots[0].name }}"
      when:
        - snapshot_action == 'delete_all'
        - existing_snapshots | length > 0

    - name: Nothing to delete
      debug:
        msg: "No snapshots found on {{ vm_name }}"
      when:
        - snapshot_action == 'delete_all'
        - existing_snapshots | length == 0

    - name: List snapshots
      debug:
        msg: "{{ existing_snapshots | map(attribute='name') | list }}"
      when: snapshot_action == 'list'

1. Basic snapshot without quiesce

-e "vm_name=ad01 snapshot_action=create snapshot_name=before-changes"

2 . Snapshot with quiesce is most commonly used.

-e "vm_name=ad01 snapshot_action=create snapshot_name=before-changes quiesce=true"

3. With memory ( not used often )

-e "vm_name=ad01 snapshot_action=create snapshot_name=before-changes memory_snapshot=true"

4. List snapshots

-e "vm_name=ad01 snapshot_action=list"
-e "vm_name=ad01 snapshot_action=list" 2>/dev/null | grep -A10 "msg"

5. Revert

-e "vm_name=ad01 snapshot_action=revert snapshot_name=before-changes"

6. Delete

# Delete specific snapshot
-e "vm_name=ad01 snapshot_action=delete snapshot_name=before-changes"

# Delete ALL snapshots
-e "vm_name=ad01 snapshot_action=delete_all"

Lets run the git and push it all

AWX → Projects → VMware Automation → Sync

(Visited 3 times, 1 visits today)

By Ash Thomas

Ash Thomas is a seasoned IT professional with extensive experience as a technical expert, complemented by a keen interest in blockchain technology.