VMware Snapshot reminder script

Here is a modified script for sending notifications to owners of Snapshots.    I found a couple of examples I hacked together.  I added a function to help Sanitize based on three different attributes. I consolidated them into a single function that determines to send a notification or not.  We have some static machines used for packaging software that maintain a single snapshot.  I included the two links of the original articles that have notification routines.

I wish the user who created the snapshot would be recorded on each snapshot as the owner.  A person has to retrieve the owner from the tasks / events, which is a bit of extra work.  I’ve been running this script for a couple months and been helpful. 

Enjoy

Steve Schofield
Microsoft MVP – IIS

 

# – SnapReminder V1.0 By Virtu-Al – http://virtu-al.net
#
# Please use the below variables to define your settings before use
# function GetSnapList uses http://virtualcurtis.wordpress.com/2011/10/02/find-virtual-machine-snapshots-with-powercli/
param
(
    [string]$vCenterServer = $(throw “Please specify the vCenter server you want to query for snapshots.”),
    [string]$smtpServer = “mail.example.com”,
    [string]$MailFrom = “steve@example.com”,
    [string]$CredentialID = “domain\user”,
    [int]$AgeOfSnap = 14,
    [string]$Output = “Output”,
    [string]$OutputErrors = “OutputErrors”,
    [string]$OutputEmailAudit = “OutputEmailAudit”   
)

function Log([string]$path, [string]$value)
{
    Add-Content -Path “$($Path)$($LogDate).txt” -Value $value
}

# Loading Snapins
function LoadSnapin{
  param($PSSnapinName)
  if (!(Get-PSSnapin | where {$_.Name   -eq $PSSnapinName})){
    Add-pssnapin -name $PSSnapinName
  }
}
LoadSnapin -PSSnapinName   “VMware.VimAutomation.Core”

function Find-User ($username){
    if ($username -ne $null)
    {
        $usr = (($username.split(“\”))[1])
        $root = [ADSI]””
        $filter = (“(&(objectCategory=user)(samAccountName=$Usr))”)
        $ds = new-object system.DirectoryServices.DirectorySearcher($root,$filter)
        $ds.PageSize = 1000
        $ds.FindOne()
    }
}

function GetSnapList
{

$myVMs = Get-VM
$VMsWithSnaps = @()

foreach ($vm in $myVMs)
{
    $vmView = $vm | Get-View
    if ($vmView.snapshot -ne $null)
    {
         $SnapshotEvents = Get-VIEvent -Entity $vm -type info -MaxSamples 1000 | Where { $_.FullFormattedMessage.contains(“Create virtual machine snapshot”)}
        try
        {
            $user = $SnapshotEvents[0].UserName
            $time = $SnapshotEvents[0].CreatedTime
        }
        catch [System.Exception]
        {
                $user = $SnapshotEvents.UserName
                $time = $SnapshotEvents.CreatedTime
        }
       $VMInfo = “” | Select “VM”,”CreationDate”,”User”
       $VMInfo.”VM” = $vm.Name
       $VMInfo.”CreationDate” = $time
       $VMInfo.”User” = $user
       $VMsWithSnaps += $VMInfo
    }
}

#Causes the array to be doubled
#$VMsWithSnaps | Sort CreationDate

return $VMsWithSnaps
}

function SnapMail ($Mailto, $snapshot)
{
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $msg.From = $MailFrom
    $msg.To.Add($Mailto)
    $msg.Subject = “Snapshot Reminder”
    $MailText = “This is a reminder that you have a snapshot active on $($snapshot.VM) which was taken on $($snapshot.Created)”       
    $msg.Body = $MailText
    $smtp.Send($msg)
    $VMDiskSize = [Math]::Round(($snapshot.SizeGB),2)
    Log -Path $OutputEmailAudit -Value “$($Mailto),$($snapshot.VM),$($snapshot.Created),$($VMDiskSize) GB”   
}

#Sanitize if a notification is sent to owner of Snap
function Sanitize ($SnapInfo,[string]$VMName)
{
    [string]$SnapDescription=$SnapInfo.Description
    [string]$SnapName=$SnapInfo.Name
   
    switch -wildcard ($VMName)
    {
        “*abc*” {return $false}
        “*xyz*” {return $false}
        “*123*” {return $false}
        “*xp*” {return $false}
        #”*templates*” {return $false}
    }   
   
    switch -wildcard ($SnapDescription)
    {
        “*abc*” {return $false}
        “*xyz*” {return $false}
        “*123*” {return $false}
        “*xp*” {return $false}
        #”*templates*” {return $false}
    }   
   
    switch -wildcard ($SnapName)
    {
        “*abc*” {return $false}
        “*xyz*” {return $false}
        “*123*” {return $false}
        “*xp*” {return $false}
        #”*templates*” {return $false}
        default {return $true}
    }
}

[double]$SnapSpaceUsed=0
[int]$SnapCount=0
$StartDate = Get-Date
$LogDate = “$($StartDate.Month)-$($StartDate.Day)-$($StartDate.Year)-$($StartDate.Hour)-$($StartDate.Minute)-$($vCenterServer)”
$cred = Get-Credential $CredentialID
Connect-VIServer -server $vCenterServer -credential $cred
Log -Path $Output -Value “Starting process as $($Cred.Username) connecting to $($vCenterServer) at $($StartDate)”

$vmlist = GetSnapList

#Get a list of machines that have snapshots
#Loop through it
foreach ($snapdata in $vmlist)
{
    Write-Host “Starting VM – $($snapdata.vm)”
    #Start process that shows creation date is l
     if($snapdata.CreationDate -lt ((Get-Date).AddDays(-$AgeOfSnap)))
    {
      #Get a list of snaphosts per vm
      #Loop through the list of VM’s
      $snapPerVM = Get-VM -Name $snapdata.vm | Get-SnapShot
      foreach($snap in $snapPerVM)
      {           
           [Boolean]$ProcessNotification = Sanitize -SnapInfo $snap -VMName $snapdata.vm
               Log -Path $Output -Value “*************************************************”
            Log -Path $Output -Value “Starting VM – $snapdata.vm”
            Log -Path $Output -Value “Process : $($ProcessNotification) : Snap : $($snap)”
          
           if($ProcessNotification -eq $true -and $snapdata.User -ne $null)
           {
                $mailto = ((Find-User $snapdata.User).Properties)
                $mailattr = $mailto.mail
               
                if($mailattr -ne $null)
                {
                    SnapMail $mailto.mail $snap
                    Write-Host “$($mailto.mail) – $($snapdata.VM) and $($snap)”
                    Log -Path $Output -Value “MailTo Value : $($mailto.mail) : VMName : $($snapdata.VM) : SnapData : $($snap)”                   
                }
                else
                {
                    $FirstName = $mailTo.givenname
                    $LastName = $mailTo.sn
                    $FirstName = $FirstName -replace ” “, “”
                    $LastName = $LastName -replace ” “, “.”
                   
                    if($FirstName -eq $null)
                    {
                        $emailAddress = “steve@example.com”
                    }
                    else
                    {
                        $emailAddress = “$($FirstName).$($LastName)@example.com”
                    }
                   
                    SnapMail $emailAddress $snap
                    Write-Host “$($emailAddress) – $($snapdata.VM) and $($snap)”
                    Log -Path $Output -Value “EmailAddress : $($emailAddress) : VMName : $($snapdata.VM) : SnapData : $($snap)”
                    $emailAddress=””
                }
               
            $SnapCount++
            $SnapSpaceUsed += $snap.SizeGB
           
            Log -Path $Output -Value “Ending VM – $snapdata.vm”
            Log -Path $Output -Value “*************************************************”
           
            }
            else
            {
                Write-Host “Not sending email for $($snapdata) for $($snapdata.VM)”
                Log -Path $OutputErrors -Value ”    Not sending email for VMName : $($snapdata.VM) : SnapData : $($snap)”
            }
        }
    }
   
}

$SnapSpaceUsed = [Math]::Round($SnapSpaceUsed,2)
Log -path $Output -Value “Number of snaps notified via email : $($SnapCount)  `r`nAmount of spaced the snapshots consumed – $($SnapSpaceUsed) GB”

Disconnect-VIServer -Server $vCenterServer -Force -Confirm:$false
$EndDate = Get-Date
Log -Path $Output -Value “Ending process as $($Cred.Username) connecting to $($vCenterServer) at $($EndDate)”

Using CimCmdlets to connect to CIM provider with Powershell and VMware

I needed to retrieve hardware status on memory DIMM’s and used PowerCLI, Powershell to retrieve the data.  Note the script assumes you have a text file list of servers.

#Reference articles
#https://communities.vmware.com/thread/446593
#http://www.virtu-al.net/2012/10/29/using-powershell-v3-0-cim-cmdlets-with-vmware-esxi-hosts/
#http://technet.microsoft.com/en-us/library/jj553783.aspx
#http://www.powertheshell.com/additional-cim-cmdlets-for-download/
#http://blogs.msdn.com/b/powershell/archive/2012/08/24/introduction-to-cim-cmdlets.aspx
#Import-Module : The specified module ‘CimCmdlets’ was not loaded because no valid module file was found in any module directory.

#$Server = “esxiServer1”
#$HostUsername = “root”
#$HostUsername2=Get-Credential
#$CIOpt = New-CimSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -Encoding Utf8 -UseSsl
#$Session = New-CimSession -Authentication Basic -Credential $HostUsername2 -ComputerName $Ipaddress -port 443 -SessionOption $CIOpt
#$Result = Get-CimInstance -CimSession $Session -ClassName CIM_Chip | where {$_.CreationClassName -eq “OMC_PhysicalMemory” } | Select Caption,DataWidth,FormFactor,MaxMemorySpeed,@{N=”CapacityGB”;E={[math]::Round($_.Capacity/1GB,0)}}

Import-module CimCmdlets

#$HostUsername = “root”
$HostUsername=Get-Credential

$serverlist=get-content -path ServerList.txt
foreach($server in $serverlist)
{
    $CIOpt = New-CimSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -Encoding Utf8 -UseSsl
    $Session = New-CimSession -Authentication Basic -Credential $HostUsername -ComputerName $server -port 443 -SessionOption $CIOpt
    $Result = Get-CimInstance -CimSession $Session -ClassName CIM_Chip | where {$_.CreationClassName -eq “OMC_PhysicalMemory” } | Select Caption,DataWidth,FormFactor,MaxMemorySpeed,@{N=”CapacityGB”;E={[math]::Round($_.Capacity/1GB,0)}}

    foreach(  in $Result)
    {
        Write-Host $DIMM
    }
}