top of page
markjramos

VMware Snapshot Cleanup Script

Updated: Apr 24


<#

.SYNOPSIS

This command is meant to add clean up snapshots that are generated on a Daily basis by default.  Parameters can be used to change the scope of the searches.

 

.DESCRIPTION

 

Date        Updated By  Details

1-3-2023        BW      Begin adding ability to use CSV File see notes below for format.

09-13-2022      BW      Fixed issue where cleanupmatch was being ignored when using -daily, -weekly, or -monthly

06-02-2022      BW      Added Key Press (Q) for stopping loops.

02-02-2022      BW      Added Monthly quick parameter.

12-21-2021      BW      Updated to throw and STOP an error.

11-15-2021      BW      Added parameters for Daily and Weekly, so that it will automatically fill in the keepdate and  cleanup match.

5-20-2021       BW      Now stops the script when there's an error, also createst folder for logs called snapLog

05-21-2020      BW      Modified to show whether we are listing or removing snapshots.

11-07-2019      BW      Updated script to track number of snapshots to delete per VM.

10-30-2019      BW      Added Logging mechanism with start/stop-transcript

10-29-2019      BW      Initial release.  Parameters set to clean Any daily snaphots older than 8 days.

 

 

NOTES 1-3-2023

CSV FILE FORMAT

VMName,KeepType,KeepInterval

WWW_2019,WEEKLY,6

MY_TEST_VM,DAILY,7

 

#>

 

 

Param(

    [Parameter(Mandatory = $false) ] [string] $vcServer="",

    [Parameter(Mandatory = $false) ] [string[]] $vmName="",

    [Parameter(Mandatory = $false,ParameterSetName="LoadFile") ] [string] $vmList="",

    [Parameter(Mandatory = $false,ParameterSetName='Custom') ] [string] $cleanupMatch,

    [Parameter(Mandatory = $false) ] [string] $keepDate=(get-Date).adddays(-8),

 

    [Parameter(Mandatory = $false) ] [pscredential] $vcCred,

    [Parameter(Mandatory = $false) ] [switch] $cleanAll,

    [Parameter(Mandatory = $false) ] [bool] $doConfirm=$false, #has to be a [bool] because of -doConfirm in the remove-snapshot bits.

    [Parameter(Mandatory = $false) ] [switch] $liveRun,

    [Parameter(Mandatory = $false,ParameterSetName='Daily') ] [switch] $Daily, #Run with default daily parameters

    [Parameter(Mandatory = $false,ParameterSetName='Daily') ] [int] $keepDays=8, #Run with default daily parameters

 

    [Parameter(Mandatory = $false,parametersetname='Weekly') ] [switch] $Weekly, #Run with default weekly parameters

    [Parameter(Mandatory = $false,parametersetname='Weekly') ] [int] $keepWeeks=6, #Run with default weekly parameters

 

    [Parameter(Mandatory = $false,Parametersetname='Monthly') ] [switch] $Monthly, #Run with default monthlyparameters

    [Parameter(Mandatory = $false,Parametersetname='Monthly') ] [int] $keepMonths=3, #Run with default monthlyparameters

 

    [Parameter(Mandatory = $false) ] [string] $logFile

 

)

 

if ($Daily -eq $true) {

    write-host "Daily uses 1 day at a time, keeping $keepDays day(s)."

    if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Daily" }

    $keepDate=(get-date).adddays(-1 * $keepDays)

    if ([string]::IsNullOrEmpty($vmName)) { $vmName=(get-content "daily-list.txt") }

}

 

if ($Weekly -eq $true) {

    write-host "Weekly cleanup uses 7 Days per week, keeping $keepWeeks week(s)"

    if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Weekly" }

    $keepdate=(get-date).adddays(-1 ($keepWeeks 7))

    if ([string]::IsNullOrEmpty($vmName)) { $vmName=(get-content "weekly-list.txt") }

}

 

if ($Monthly -eq $true) {

    write-host "Monthly cleanup uses 30 days per month, keeping $keepMonths month(s)."

    if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Monthly" }

     $keepdate=(get-date).adddays(-1 ($keepMonths 30 ))

    if ([string]::IsNullOrEmpty($vmName)) { $vmName=(get-content "monthly-list.txt") }

}

 

#the default progress bar is useless for this.  Disable it!

$origProgressBar = $ProgressPreference

$ProgressPreference = "SilentlyContinue"

 

$origErrorAction = $ErrorActionPreference

$ErrorActionPreference = "STOP"

 

if (!(Test-Path snapLog)) { mkdir snapLog }

 

if ($liveRun -eq $false) {$action="Listing"} else {$action = "Cleaning"}

#vmware initialization

 

$hasVI=get-command connect-viserver* -ErrorAction SilentlyContinue

 

if ([string]::IsNullOrEmpty($hasVI) -eq $true) {

    try {

        import-module VMware.PowerCLI

    }

    catch {

        write-host -foregroundcolor "Yellow" "You MUST have the VMware PowerShell Modules installed for this to work."

        write-host -foregroundcolor "yellow" "Open PowerShell as an administrator and then "

        write-host " "

        write-host -foregroundcolor "white" "install-module vmware.powercli"

        write-host " "

        write-host -foregroundcolor "Yellow" "And then try this script again."

 

        exit -2048;

    }

}

 

 

if ($global:DefaultVIServers.count -lt 1) {

 

    if ([string]::IsNullOrEmpty($vcServer) -eq $true ) {

        write-host -foreground Yellow "vCenter Server Connection"

        $vcServer = read-host "vCenter Server: "

   

    }

 

    if ($vcCred -eq $null ) {

   

        write-host -foreground Yellow "Please enter your VCenter Admin Credentials..."

        $username = read-host "Username: "

        $password = read-host "Password: " -AsSecureString

        $VCCred = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password

 

    }

 

    try {

         connect-viserver -server $vcServer -Credential $vcCred

    } catch {

        write-host "There was an error connecting to $vcServer!"

        error[0]

        exit -3072

    }

 

}

 

if ($cleanAll -eq $true) {

    write-host "Loading All Powered On VMs..."

    $vmName=(get-vm | where {$_.PowerState -eq 'PoweredOn'} | Select Name).Name

   

    write-host "Found $($vmName.count) machines to clean..."

}

 

$logFile="snapLog\snapshotCleanup_$(get-date -format "MMddyyyy_HHmmss").log"

 

if ($liveRun -eq $true) {start-transcript -Path $logFIle -Append }

 

if ($PSCmdlet.ParameterSetName -eq "LoadFile") {

    $isFile=test-path $vmList

    if ($isFile -eq $false) {

        write-host -foregroundcolor "Red" "Unable to open file $vmList."

        exit -2048

    }

 

    $csvFile=import-csv -Path $vmList

    $RunTimer=new-object System.Diagnostics.Stopwatch

    $runtimer.start()

 

 

    foreach ($item in $csvFile) {

        $vmName=""

        $firstChar=""

        $keepType=""

        $keepInterval=""

        $cleanupmatch=""

 

        $vmName=$item.VMName

        $firstChar=$vmname.tochararray()[0]

        $keepType=[string] $item.KeepType

        $keepInterval=$item.KeepInterval

        #write-host -foregroundcolor white "Checking $vmName,$keepType,$keepInterval"

        #write-host "Keep Date: $keepDate"

 

        if ($keepType -ne "DAILY" -and $keepType -ne "WEEKLY" -and $KeepType -ne "MONTHLY") {

            write-host -foregroundcolor "Invalid Content in $vmList!"

            exit -2048

        }

 

        if ($keepType -eq "DAILY") {

            if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Daily" }

            $keepdate=(get-date).adddays(-1 * $keepInterval)

        }

 

        if ($keepType -eq "WEEKLY") {

            #write-host "Setting Weekly... $keepInterval * 7"

            if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Weekly" }

            $keepdate=(get-date).adddays(-1 $keepInterval 7)

        }

 

        if ($keepType -eq "MONTHLY") {

            if ([string]::isnullorempty($cleanupmatch)) { $cleanupmatch="Monthly" }

            $keepdate=(get-date).adddays(-1 $keepInterval 30)

        }

 

        if ($firstChar -eq "#") {write-host -foregroundcolor Magenta "Skipping $vmName" }

        write-host -foregroundcolor white "$vmName, Keep Type: $keepType, Keep Date: $keepDate"

 

        if ($liveRun -eq $false) {$action="Listing"} else {$action = "Cleaning"}

        if ([console]::KeyAvailable) {

            $x=[System.Console]::ReadKey()

            if ($x.key -eq "q" -or $x.key -eq "Q") {

                write-host "Pressed Q, Stopping Script."

                exit -1024

            }

        }

 

        if ($firstChar -eq "#") {

            $action="SKIP"

        }

 

        $vm=$vmName

        #write-host "First Char is $firstChar"

 

        write-host "$action snapshots for $vm"

 

        if ($liveRun -eq $true -and $action -ne "SKIP") {

            try {

                $objVM=get-vm $vm

            } catch {

                write-host -ForegroundColor Red "There was a problem with $vm"

                write-host $_.Exception.Message

                exit -2048

            }

            write-host "Active Cleanup Match says: $cleanupmatch"

            $objSnapshots=$objVM | get-snapshot|where {$_.Name -like "*$cleanupMatch*" -and $_.created -lt $keepDate}

            $pass=0

            #| remove-snapshot -confirm:$doConfirm

            $snapCount=$objSnapshots.count

            if ($snapCount -eq 0) {write-host "No snapshots to clean for $vm." }

            if ($snapCount -gt 0) {

                $hasError=$false

                $timer=new-object System.Diagnostics.Stopwatch

                $timer.start()               

                foreach ($snap in $objSnapshots) {

                    if ([console]::KeyAvailable) {

                        $x=[System.Console]::ReadKey()

                        if ($x.key -eq "q" -or $x.key -eq "Q") {

                            write-host "Pressed Q, Stopping Script."

                            exit -1024

                        }

                    }

                    if ($hasError -eq $true) {

                        exit -4096

                    }

                    $pass++

                    write-host "`rCleaning snapshot $pass of $snapCount"

                    try {

                        $snap|remove-snapshot -confirm:$doConfirm

                    } catch {

                        write-host -ForegroundColor Red "There was a problem removing the snapshot!"

                        $ErrorActionPreference = "STOP"

                        $hasError=$true

                        throw "There was a problem removing the snapshot!"

                        exit -4096

                    }

                } #end foreach

                $timer.stop()

                $took="{0:hh}:{0:mm}:{0:ss}" -f $timer.elapsed

                write-host "Took $vmname took $took to clean."

            }

        } elseif ($action -ne "SKIP") {

            write-host "Listing Cleanup Match says: $cleanupmatch"

            if ($firstChar -ne "#") { get-vm $vm | get-snapshot | where { $_.Name -like "*$cleanupMatch*" -and $_.created -lt $keepDate } | Select Created,Name|ft }

 

        }

 

        write-host " "

    }

}

 

 

if ($PSCmdlet.ParameterSetName -ne "LoadFile") {

    write-host "Loading from List..."

    foreach ($vm in $vmName) {

        if ($liveRun -eq $false) {$action="Listing"} else {$action = "Cleaning"}

        if ([console]::KeyAvailable) {

            $x=[System.Console]::ReadKey()

            if ($x.key -eq "q" -or $x.key -eq "Q") {

                write-host "Pressed Q, Stopping Script."

                exit -1024

            }

        }

 

        if ($vm[0] -eq "#") {

            $action="SKIP"

        }

 

        write-host "$action snapshots for $vm"

       

        if ($liveRun -eq $true -and $action -ne "SKIP") {

            try {

                $objVM=get-vm $vm

            } catch {

                write-host -ForegroundColor Red "There was a problem with $vm"

                write-host $_.Exception.Message

                exit -2048

            }

            $objSnapshots=$objVM | get-snapshot|where {$_.Name -like "*$cleanupMatch*" -and $_.created -lt $keepDate}

            $pass=0

            #| remove-snapshot -confirm:$doConfirm

            $snapCount=$objSnapshots.count

            if ($snapCount -eq 0) {write-host "No snapshots to clean for $vm." }

            if ($snapCount -gt 0) {

                $hasError=$false

                foreach ($snap in $objSnapshots) {

                    if ([console]::KeyAvailable) {

                        $x=[System.Console]::ReadKey()

                        if ($x.key -eq "q" -or $x.key -eq "Q") {

                            write-host "Pressed Q, Stopping Script."

                            exit -1024

                        }

                    }

                    if ($hasError -eq $true) {

                        exit -4096

                    }

                    $pass++

                    write-host "`rCleaning snapshot $pass of $snapCount"

                    try {

                        $snap|remove-snapshot -confirm:$doConfirm

                    } catch {

                        write-host -ForegroundColor Red "There was a problem removing the snapshot!"

                        $ErrorActionPreference = "STOP"

                        $hasError=$true

                        throw "There was a problem removing the snapshot!"

                        exit -4096

                    }

                } #end foreach

            }

        } else {

            if ($vm[0] -ne "#") { get-vm $vm | get-snapshot | where { $_.Name -like "*$cleanupMatch*" -and $_.created -lt $keepDate } | Select Created,Name|ft }

 

        }

 

        write-host " "

    }

}

if ($liveRun -eq $true) {

    $runtimer.stop()

    $fulltook="{0:hh}:{0:mm}:{0:ss}" -f $runtimer.elapsed

 

    write-host "Full SCript took $fulltook"

    Stop-Transcript

}

 

$ProgressPreference=$origProgressBar

$ErrorActionPreference=$origErrorAction

 

10 views0 comments

Recent Posts

See All

留言


bottom of page