Why is this useful?
Let’s say you have a VM that you use for unsavory things like malware analysis and you would like to automatically revert it on a scheduled basis. There are many ways to go about this manually, but for my particular use-case, I wanted it done automatically everyday at 3AM.
While this can be accomplished a few different ways such as non-persistent disks, I found the snapshot revert method ideal for me because the machine stays up and on at all times except the brief moment the snapshot is being restored.
Great, just tell me how to do it!
In my example, I am using standalone ESXi 6.7 (no vCenter). There is a VM running that has a single snapshot called “Clean”. Of course, one could use the ESXi WebUI to revert the snapshot at will, but in order to get it to revert automatically on a schedule, I scripted up the following tasks in ESXi CLI and created a cronjob.
Snapshot your VM in the WebUI
SSH to the ESXi server and run the following commands:
Get your target VM ID with this command:
vim-cmd vmsvc/getallvms
Learn the snapshot ID of your VM with this command:
vim-cmd vmsvc/get.snapshotinfo [VM_id]
Create a cronjob that reverts this VM everyday at 3AM (customize as neccesary)
Backup existing crontab
cp /var/spool/cron/crontabs/root /var/spool/cron/crontabs/root.old
Edit running crontab
vi /var/spool/cron/crontabs/root
Add the new job on the last line, this job runs everyday at 3AM. The 0 at the end is to ensure the VM stays powered on after the snapshot is restored.
* 3 * * * /bin/vim-cmd vmsvc/snapshot.revert [VM_id] [snapshot_id] 0
Restart cron service (yes, this is a odd way of doing it, but ESXi is weird like that)
PID=$(cat /var/run/crond.pid)
echo "Old cron PID was $PID"
kill $PID
/usr/lib/vmware/busybox/bin/busybox crond
PID=$(cat /var/run/crond.pid)echo "NEW cron PID is $PID"
And you’re set! Your VM will now revert to the snapshot everyday at 3AM.
Ok so now your VM will revert to this snapshot everyday at 3AM, but what happens if you create a new snapshot and want the cron to use the new snapshot ID? Luckily, I crafted a little script that will ensure that your latest snapshot ID is always used by the cron.
NOTE: This script only works if there is ONE snapshot for the VM. Multiple snapshots will break it.
The script:
#/bin/bash
# NOTE: This script only works if there is ONE snapshot for the VM.
# Multiple snapshots will break it.
# BE SURE TO CHANGE VM_id TO YOUR VM's ID!
VM_id=33
# get snapshot ID for VM
SNAPSHOTID=$(vim-cmd vmsvc/get.snapshotinfo $VM_id | grep id | egrep -o '[0-9]+')
# edit cron to reflect new snapshot id
sed -ri "s/$VM_id [0-9]+ 0/$VM_id $SNAPSHOTID 0/" /var/spool/cron/crontabs/root
# restart crond
PID=$(cat /var/run/crond.pid)
echo "Old cron PID was $PID"
kill $PID
/usr/lib/vmware/busybox/bin/busybox crond
PID=$(cat /var/run/crond.pid)
echo "NEW cron PID is $PID"
echo "New crontab contents:"
cat /var/spool/cron/crontabs/root
Now that we have a script that can automatically update the crontab when a new snapshot ID exists, we can use another cronjob to make sure this happens before the snapshot revert happens.
Edit running crontab
vi /var/spool/cron/crontabs/root
Add the new job on the last line, you want this job to run before the revert job runs. This job runs everyday at 2AM.
* 2 * * * /path_to_above_script.sh
Restart cron service
PID=$(cat /var/run/crond.pid)
echo "Old cron PID was $PID"
kill $PID
/usr/lib/vmware/busybox/bin/busybox crond
PID=$(cat /var/run/crond.pid)echo "NEW cron PID is $PID"
And you’re set! Your VM will now revert to the snapshot everyday at 3AM, even if you delete and recreate a new snapshot!