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
Add a new playbook to vm_snapshot.yml
---
- 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


