🖥️ VMware Automation

Automate VMware Snapshot Reports with Jenkins & Email Alerts

📅 June 2026 ✍️ Ravindrakumar Narayanan ⏱ ~12 min read
VMware PowerCLI Jenkins PowerShell vSphere Email Alert CI/CD Scheduled Build
📋 Table of Contents
  1. Overview & Problem Statement
  2. Solution Architecture
  3. PowerCLI Script — Snapshot Detection & Email
  4. Jenkins Setup — Parameterised Build
  5. Scheduling the Build
  6. Email Configuration in Jenkins
  7. What You Get — Sample Output
  8. Summary

01 Overview & Problem Statement

VM snapshots are indispensable for rollback safety — but left unchecked, they grow silently, consume datastore space, and degrade VM performance. In environments with Prod and DR vCenters, manually tracking snapshots across hundreds of VMs is error-prone and time-consuming.

This guide walks you through a fully automated solution using PowerCLI + Jenkins Parameterised Build that:

ℹ️
Prerequisites Jenkins server with PowerShell plugin installed, VMware PowerCLI module on the Jenkins agent, SMTP relay accessible from the agent, and credentials configured in Jenkins Credential Store.

02 Solution Architecture

The diagram below shows how the components interact at scheduled trigger time:

⏰ Jenkins
Cron Schedule
⚙️ Parameterised
Build
🖥️ PowerCLI
Script
☁️ vCenter
(Prod / DR)
📄 CSV Report
Generated
📧 Email Alert
+ Attachment
📥 Inbox /
Distribution List

03 PowerCLI Script — Snapshot Detection & Email

Save this as Get-VMSnapshots.ps1 on your Jenkins agent. All sensitive values are injected as environment variables from Jenkins — no hardcoded credentials.

PowerShell Get-VMSnapshots.ps1
<#
.SYNOPSIS
    VMware Snapshot Report — PowerCLI + Email Alert
.DESCRIPTION
    Connects to a specified vCenter (Prod or DR), identifies all VMs
    with snapshots, exports a timestamped CSV, and emails the report.
.NOTES
    Author  : automatewithravi.com
    Version : 1.0
    All credentials and server names are injected via Jenkins env vars.
#>

# ── Initialise transcript log ──────────────────────────────────────────────
$Timestamp  = Get-Date -Format 'MM-dd-yyyy_HHmmss'
$LogPath    = "C:\Jenkins_Logs\SnapshotReport_$Timestamp.txt"
$CsvPath    = "C:\Jenkins_Reports\VMSnapshots_$Timestamp.csv"
New-Item -ItemType Directory -Force -Path "C:\Jenkins_Logs"    | Out-Null
New-Item -ItemType Directory -Force -Path "C:\Jenkins_Reports" | Out-Null
Start-Transcript -Path $LogPath -NoClobber -IncludeInvocationHeader

# ── Read credentials from Jenkins environment variables ────────────────────
$vCenter  = $Env:VCENTER_SERVER   # e.g. prod-vcenter.corp.local or dr-vcenter.corp.local
$Username = $Env:VCENTER_USER
$Password = $Env:VCENTER_PASS
$SmtpServer   = $Env:SMTP_SERVER      # e.g. smtp.corp.local
$EmailFrom    = $Env:SMTP_FROM        # e.g. alerts@automatewithravi.com
$EmailTo      = $Env:SMTP_TO          # e.g. infra-team@automatewithravi.com
$Environment  = $Env:ENVIRONMENT      # "Prod" or "DR"

# ── Connect to vCenter ─────────────────────────────────────────────────────
Write-Host "[INFO] Connecting to $Environment vCenter: $vCenter"

try {
    $Connection = Connect-VIServer -Server $vCenter -User $Username -Password $Password -ErrorAction Stop
} catch {
    Write-Error "[ERROR] Unable to connect to $Environment vCenter ($vCenter). $_"
    Stop-Transcript
    exit 1
}

if (-not $Connection.IsConnected) {
    Write-Error "[ERROR] vCenter connection check failed."
    Stop-Transcript
    exit 1
}
Write-Host "[INFO] Successfully connected to $Environment vCenter."

# ── Collect snapshot data ──────────────────────────────────────────────────
Write-Host "[INFO] Retrieving VM snapshots..."

$Snapshots = Get-VM | Get-Snapshot | Select-Object `
    VM,
    Name,
    Description,
    @{Label = "SizeGB";  Expression = { "{0:N2} GB" -f $_.SizeGB }},
    Created,
    @{Label = "AgeDays"; Expression = { (New-TimeSpan -Start $_.Created -End (Get-Date)).Days }},
    @{Label = "Environment"; Expression = { $Environment }}

Write-Host "[INFO] Total snapshots found: $($Snapshots.Count)"

# ── Export CSV ─────────────────────────────────────────────────────────────
$Snapshots | Export-Csv -Path $CsvPath -NoTypeInformation -UseCulture
Write-Host "[INFO] CSV exported to: $CsvPath"

# ── Send email alert ───────────────────────────────────────────────────────
if ($Snapshots.Count -gt 0) {
    $Subject = "[$Environment] VMware Snapshot Report — $($Snapshots.Count) snapshot(s) found — $(Get-Date -Format 'dd MMM yyyy')"
    $Body = @"
Hi Team,

The automated snapshot audit has completed for the <b>$Environment</b> vCenter environment.

Summary:
  - vCenter   : $vCenter
  - Environment : $Environment
  - Total Snapshots : $($Snapshots.Count)
  - Report Date  : $(Get-Date -Format 'dd MMMM yyyy HH:mm')

Please review the attached CSV report and action any snapshots older than your retention policy.

-- Automated Report via Jenkins | automatewithravi.com
"@

    Send-MailMessage `
        -From       $EmailFrom `
        -To         ($EmailTo -split ",") `
        -Subject    $Subject `
        -Body       $Body `
        -BodyAsHtml `
        -Attachments $CsvPath `
        -SmtpServer $SmtpServer

    Write-Host "[INFO] Email alert sent to: $EmailTo"
} else {
    Write-Host "[INFO] No snapshots found. No email sent."
}

# ── Disconnect and cleanup ─────────────────────────────────────────────────
Disconnect-VIServer -Server $vCenter -Confirm:$false
Write-Host "[INFO] Disconnected from vCenter. Job complete."
Stop-Transcript
💡
Age tracking included The AgeDays calculated column lets your team instantly identify stale snapshots without opening vCenter. Filter the CSV for AgeDays > 7 to flag policy violations.

04 Jenkins Setup — Parameterised Build

The build accepts parameters so one job covers both vCenters — just change the dropdown at trigger time (or let the cron set it via separate schedules).

4.1 Jenkins Job Parameters

Parameter Name Type Values / Default Description
ENVIRONMENT Choice Prod, DR Selects which vCenter to target
VCENTER_SERVER String prod-vcenter.corp.local vCenter FQDN or IP (can be pre-filled per environment)
VCENTER_USER Credential (injected) vcenter-readonly@vsphere.local vCenter service account username
VCENTER_PASS Credential (injected) (secret) vCenter password — stored in Jenkins Credential Store
SMTP_SERVER String smtp.corp.local Internal SMTP relay
SMTP_FROM String alerts@automatewithravi.com Sender address displayed in the alert email
SMTP_TO String infra-team@automatewithravi.com Recipient(s) — comma-separated for multiple

05 Scheduling the Build

In your Jenkins job configuration, scroll to Build Triggers and enable Build periodically. Use standard cron syntax:

Cron Jenkins Build Trigger — Cron Examples
# Every day at 07:00 AM (Mon–Fri)
0 7 * * 1-5

# Every day at 07:00 AM (7 days a week)
0 7 * * *

# Every Monday at 08:00 AM
0 8 * * 1

# Every 6 hours
H/6 * * * *
1

Navigate to Job Configuration

Open the Jenkins job → Configure → scroll to Build Triggers section.

2

Enable "Build periodically"

Tick the checkbox and paste your chosen cron expression into the Schedule field.

3

Set Default Parameter Values

For scheduled (unattended) runs, ensure the default parameter values match the intended environment so the job doesn't prompt interactively.

4

Create Separate Jobs for Prod & DR (recommended)

Copy the job and set ENVIRONMENT=DR and VCENTER_SERVER=dr-vcenter.corp.local as defaults. Schedule at offset times (e.g. Prod at 07:00, DR at 07:30) to avoid resource contention.

06 Email Configuration in Jenkins

The script uses PowerShell's native Send-MailMessage cmdlet — no Jenkins email plugin needed on the script side. However, configure the SMTP relay details as follows:

⚠️
Security note Always store SMTP credentials (if your relay requires auth) in the Jenkins Credential Store and inject them as environment variables. Never hardcode passwords in your Jenkinsfile or PowerShell script.

Jenkins → Manage Jenkins → System → E-mail Notification

FieldValue
SMTP serversmtp.corp.local (or your relay)
Default user e-mail suffix@automatewithravi.com
Use SSLTick if your relay requires TLS
SMTP Port25 (unauthenticated) or 587 (TLS)

The PowerShell script handles all email logic directly — no additional Jenkins email plugin configuration is required for the snapshot report itself.

07 What You Get — Sample Output

After a successful run you'll have:

CSV VMSnapshots_06-08-2026_070012.csv (sample)
"VM","Name","Description","SizeGB","Created","AgeDays","Environment"
"WEB-SVR-01","Pre-Patch-May26","Before May patch","12.44 GB","05/01/2026 09:12:00","38","Prod"
"DB-SVR-04","Upgrade-Snapshot","Before DB upgrade","31.07 GB","04/15/2026 14:55:00","54","Prod"
"APP-SVR-02","Test-Rollback","UAT rollback point","8.92 GB","05/28/2026 17:30:00","11","Prod"
💡
Next step: age-based alerting Extend the script to filter $Snapshots | Where-Object { $_.AgeDays -gt 14 } and send a high-priority alert for stale snapshots exceeding your retention policy.

08 Summary

You now have a production-ready, fully automated VMware snapshot reporting pipeline that runs hands-free on a schedule:

The complete script is available on GitHub. If you have questions or want to extend this to include snapshot age-based deletion, drop a comment or reach out via the contact page.

View on GitHub ← Back to all blogs