Ansible: snapshoting VM on VMWare and cleanup old snapshots.

Solution1. Script to make a snapshoots of listed servers. powershell. store password in separate file (/root/vmware.cred in this case).

script itself

#!/usr/bin/pwsh

# Define log file path
$logFile = "/var/log/vm_snapshot.log"

# Start transcript (captures everything displayed on screen)
Start-Transcript -Path $logFile -Append

# Function to write logs
function Write-Log {
    param (
        [string]$message
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] $message"

    # Write to log file and console
    Add-Content -Path $logFile -Value $logEntry
    Write-Host $logEntry
}

# Read the password from the file
$pass = Get-Content -Path "/root/vmware.cred" -ErrorAction Stop

# Start logging
Write-Log "Starting VM snapshot script execution."

# Connect to vCenter server
try {
    $connectionOutput = Connect-VIServer -Server "your_server_here" -User "user_with_snapsoting_rights" -Pass $pass -Force 2>&1
    Write-Log "Successfully connected to vCenter."
    Write-Log $connectionOutput
} catch {
    Write-Log "Failed to connect to vCenter: $_"
    Stop-Transcript
    exit 1
}

# Read the list of VM names from the servers.inv file
$vmNames = Get-Content -Path "/opt/snaps/servers.inv"  # Adjust path

# Get the current date and time in the desired format
$currentDateTime = (Get-Date).ToString("yyyy-MM-dd_HH-mm-ss")

# Loop through each VM and create a snapshot
foreach ($vmName in $vmNames) {
    # Check if VM exists
    $vm = Get-VM -Name $vmName -ErrorAction SilentlyContinue
    if ($vm) {
        $snapshotName = "autopatch_$currentDateTime" + "_$vmName"
        try {
            $snapshotOutput = New-Snapshot -VM $vm -Name $snapshotName -Quiesce 2>&1
            Write-Log "Snapshot created for VM: $vmName with name: $snapshotName"
            Write-Log $snapshotOutput
        } catch {
            Write-Log "Failed to create snapshot for VM: $vmName. Error: $_"
        }
    } else {
        Write-Log "VM not found: $vmName"
    }
}

Write-Log "VM snapshot script execution completed."

# Stop transcript
Stop-Transcript

servers.inv content – just list of servers (how they present at VMWare). like this:

server1
server2
server3
server4

Solution2. Cleanup old snapshoots. Just schedule it to run periodically and it will delete all associated to servers snapshoots. Yep, best time to run is after-hrs, as deleting snapshoot is impacting procedure at VMWare.

script:

#!/usr/bin/pwsh

# Define Variables
$serverList = @("/opt/snaps/servers.inv", "/opt/snaps/servers2.inv", "/opt/snaps/servers3.inv", "/opt/snaps/servers4.inv")
# Change snapshotLimit to above zero value if you want to keep some snapshoots (not recommended, as VMWare well-known for having bad snapshooting process).
$snapshotLimit = 0
$logFile = "/var/log/vm_snapshot_cleaning.log"
$vcServer = "your_server"
$vcUser = "user_with_right_to_delete_snapsoots"
$vcPassword = Get-Content -Path "/root/vmware2.cred" -ErrorAction Stop

# Function to Log Messages
function Write-Log {
    param (
        [string]$message
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $message" | Out-File -Append -FilePath $logFile
}

# Connect to vCenter
try {
    $connection = Connect-VIServer -Server $vcServer -User $vcUser -Password $vcPassword -Force -ErrorAction Stop
    Write-Log "Connected to vCenter: $vcServer"
} catch {
    Write-Log "Failed to connect to vCenter: $_"
    exit 1
}

# Process Each VM
foreach ($file in $serverList) {
    if (Test-Path $file) {
        Get-Content $file | ForEach-Object {
            $vmName = $_.Trim()
            if ($vmName -eq "") { return }

            # Check if VM exists
            $vm = Get-VM -Name $vmName -ErrorAction SilentlyContinue
            if (-not $vm) {
                Write-Log "VM not found: $vmName. Skipping."
                return
            }

            # Get Snapshots
            $snapshots = Get-Snapshot -VM $vm -ErrorAction SilentlyContinue | Sort-Object Created
            $snapshotCount = $snapshots.Count
            Write-Log "VM: $vmName has $snapshotCount snapshots."

            # Check Snapshot Limit
            if ($snapshotCount -gt $snapshotLimit) {
                $oldestSnapshot = $snapshots | Select-Object -First 1
                try {
                    $deleteOutput = Remove-Snapshot -Snapshot $oldestSnapshot -Confirm:$false -RunAsync 2>&1
                    Write-Log "Deleted oldest snapshot '$($oldestSnapshot.Name)' for VM: $vmName"
                    Write-Log $deleteOutput
                } catch {
                    Write-Log "Failed to delete snapshot for VM: $vmName. Error: $_"
                }
            }
        }
    } else {
        Write-Log "File not found: $file. Skipping."
    }
}

# Disconnect from vCenter
Disconnect-VIServer -Confirm:$false
Write-Log "Disconnected from vCenter."