VMware Cloud Community
pamiller21
Enthusiast
Enthusiast

Snapshot report

I got a snapshot report that is designed to show VM's with snapshots that are 5 days old and then show the description of the snapshot, the size of the snapshot, the date it was created, the age, and the creator of the snapshot and I am not sure it is working.  It is showing some VMs with no snapshots at all and rarely shows some of the details I was trying to pull.  Here is the script:

#############################
# Variables #
#############################
$date = Get-Date -format "yyyy-MMM-dd"
$datetime = Get-Date
$filelocation = "\var\www\Snapshots\snapshot-$date.htm"

#############################
# Content #
#############################

$timeDiff = 2
$report = Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn';'Snapshot'=".+"} |
Select -First 50 name,
@{N='Description';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList |
where{$_.CreateTime -le (Get-Date).AddDays(-5) | % {
Get-Snap -Snap $_ }
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='Size';E={
((Get-VM -Name $_.Name | Get-Snapshot -Name $script:snaps.Name).SizeGB | %{"{0:N1}" -f $_}) -join '|'
}},
@{N='Date Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Age";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$startEvents = $script:snaps.CreateTime
$start = $startEvents | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start.AddSeconds(- $timeDiff) -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot'} |
ForEach-Object -Process {
$event = $_
$startEvents | ForEach-Object -Process {
if([math]::Abs((New-TimeSpan -Start $event.CreatedTime -End $_.ToLocalTime()).TotalSeconds) -lt $timeDiff){
$event
}
}
} | Select-Object -ExpandProperty UserName) -join '|'}}

## Build Count Var
$count = $report | where{$_.Snapshot -ne ''}

#############################
# Add Text to the HTML file #
#############################
$report | where{$_.Snapshot -ne ''} | ConvertTo-Html –Title "VMware Snapshot Check " –Body "<H1>VMware Snapshot Check</H1>" -Head "<link rel='stylesheet' href='style.css' type='text/css' />" | Out-File $filelocation
ConvertTo-Html –title "VMware Snapshot Check " -body "<H4>Date and time</H4>",$datetime -head "<link rel='stylesheet' href='style.css' type='text/css' />" | Out-File -Append $filelocation
ConvertTo-Html –title "VMware Snapshot Check " -body "<H4>VM Count</H4>",$count.Count -head "<link rel='stylesheet' href='style.css' type='text/css' />" | Out-File -Append $filelocation

Reply
0 Kudos
14 Replies
LucD
Leadership
Leadership

You have to be a bit more specific on the "rarely shows some of the details I was trying to pull".
Which properties are not shown?
Note that the script uses events to obtain additional info on the snapshots.
If the event for a snapshot does not exist anymore, that info can not be retrieved.

To check why it shows VMs without Snapshots, you will have to check if the following returns such VMs.

Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn';'Snapshot'=".+"} |
Select Name,@{N='Snapshots';E={$_.Snapshot.Count}}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
pamiller21
Enthusiast
Enthusiast

ok I think the issue is its not applying the filter to show snapshots that are 5 days old.  That command is showing some VMs with snapshots but they are not past that expiration date.

Reply
0 Kudos
LucD
Leadership
Leadership

The Get-View is returning any VMs that are powered on and that do have a snapshot.

Only in the Description calculated property, the script limits the traversal of the root snapshot tree to entries that are 5 or more days old.

This script will not be limited to snapshots that are 5 days or older


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
pamiller21
Enthusiast
Enthusiast

How do I fix it?

Reply
0 Kudos
LucD
Leadership
Leadership

You tell me.
You apparently used my script from Re: PowerCLI SnapShot Creator in Report - VMware Technology Network VMTN and added that Where-clause.
You must have had an idea what that Where-clause was supposed to be doing?

Also, note that the script only looks at the first 50 VM returned by Get-View.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
pamiller21
Enthusiast
Enthusiast

I am trying to only look at snapshot that are older than 5 days, but not sure I did it right or where to filter it at.

Reply
0 Kudos
Steve005
Contributor
Contributor

Here's a script I use with Saved Credentials in a secure cred file and run with Task scheduler to delete snapshots older than 3 days:

 

Import-Module VMware.PowerCLI

#Make sure invalid certificate errors don't halt the script
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -confirm:$false
#Turn off CEIP
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -confirm:$false

#Interactive use
#connect-viserver -Server <vcenter IP or name> -Verbose

#Script use
$creds = Get-VICredentialStoreItem -file "C:\Scripts\vmware\vmservicecred.xml"
Connect-viserver -Server $creds.Host -User $creds.User -Password $creds.Password


:: Delete snapshots older than 3 days ::
Get-VM | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-3)} | Remove-Snapshot -Confirm:$false

You can just delete or comment out "Remove-Snapshot -Confirm:$false" from the last like and run the script interactively. Adjust to the number of days you want.

Reply
0 Kudos
Steve005
Contributor
Contributor

Here' another script that can be run interactively or as a scheduled task to Email a formatted report of all snapshots:

#$vCenterServer = "<IP or Name>"

# Connect to the vcenter server
#connect-viserver -Server $vCenterServer -Verbose

#Script use
$creds = Get-VICredentialStoreItem -file “C:\Scripts\vmservicecred.xml”
Connect-viserver -Server $creds.Host -User $creds.User -Password $creds.Password

# Set Email Variables
$fromemail = "vcenter@domain.tld"
$users = "vcadmin@doman.tld"
$server = "smtp.domain.tld"
$subject = "VMware Snapshot Report for " + (get-date -Format d/M/yyyy)
#---uncomment to use email authentication---#
#$username = ""
#$smtppassword = ""
#$secpasswd = ConvertTo-SecureString $smtppassword -AsPlainText -Force
#$smtpCredential = New-Object System.Management.Automation.PSCredential ($smtpusername, $secpasswd) 

#Get all snapshots
$Snapshots = Get-VM | Get-Snapshot | select Description,Created,VM,SizeMB,SizeGB

# Format snapshot Size
function Get-SnapshotSize ($Snapshot)
{
    if ($snapshot.SizeGB -ge "1")
    {
        $Snapshotsize = [string]([math]::Round($snapshot.SizeGB,3)) + " GB"
        }
        else {
        $Snapshotsize = [string]([math]::Round($snapshot.SizeMB,3)) + " MB"
        }
   Return $Snapshotsize
}

# Style the dates - colourise 
function set-SnapshotDate ($snapshot)
{
    $greenValue = (get-date).AddDays(-1)
    $RedValue = (get-date).AddDays(-3)
    
    if ($snapshot.created -gt $greenValue)
        {
            $backgroundcolor = "green"
        }
    elseif ($snapshot.Created -lt $greenValue -and $snapshot.Created -gt $RedValue)
        {
            $backgroundcolor = "yellow"
        }
    else 
        {
        $backgroundcolor = "red"
        }
    return $backgroundcolor
}

#Format the HTML
function Format-HTMLBody ($body)
{
    $newbody = @()
    foreach ($line in $body)
    {
        ## Remove the Format Header
        if ($line -like "*<th>Format</th>*")
            {
                $line = $line -replace '<th>Format</th>',''
            }
        ## Format all the Red rows
        if ($line -like "*<td>red</td>*")
            {
                $line = $line -replace '<td>red</td>','' 
                $line = $line -replace '<tr>','<tr style="background-color:Tomato;">'
            }
        ## Formating all the Yellow Rows
        elseif ($line -like "*<td>yellow</td>*")
            {
                $line = $line -replace '<td>yellow</td>','' 
                $line = $line -replace '<tr>','<tr style="background-color:Orange;">'
            }
        ## Formating all the Green Rows
        elseif ($line -like "*<td>green</td>*")
            {
                $line = $line -replace '<td>green</td>','' 
                $line = $line -replace '<tr>','<tr style="background-color:MediumSeaGreen;">'
            }
        ## Building the new HTML file
            $newbody += $line
    }
    return $newbody
}

# --------------------------------Create the report-------------------------------- #
# ----------Header and Style-------------- #
$date = (get-date -Format d/M/yyyy)
$header =@"
 <Title>Snapshot Report - $date</Title>
<style>
body {   font-family: 'Helvetica Neue', Helvetica, Arial;
         font-size: 14px;
         line-height: 20px;
         font-weight: 400;
         color: black;
    }
table{
  margin: 0 0 40px 0;
  width: 100%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
  display: table;
  border-collapse: collapse;
  border: 1px solid black;
}
th {
    font-weight: 900;
    color: #ffffff;
    background: black;
   }
td {
    border: 0px;
    border-bottom: 1px solid black
    }
</style>
"@
# ----------Header and Style-------------- #

# Create title for the Table
$PreContent = "<H1> Snapshot Report for " + $date + "</H1>"

# Convert to HTML
$HTMLmessage = $Snapshots | select VM,Created,@{Label="Size";Expression={Get-SnapshotSize($_)}},Description,@{Label="Format";Expression={Get-SnapshotDateStyle($_)}}| sort Created -Descending | ConvertTo-Html -Head $header -PreContent $PreContent

# -------Formay the HTML Report ------------- #
$Report = Format-HTMLBody ($HTMLmessage)

# --------------------------------Create the report-------------------------------- #

# Email report
send-mailmessage -from $fromemail -to $users -subject $subject -BodyAsHTML -body ([string]$Report) -priority Normal -smtpServer $server #-Credential $smtpCredential

# Logoff the server
Disconnect-VIServer -Confirm:$false
Steve005
Contributor
Contributor

The procedure to create a saved credential file is as follows:

The credential file creation must be done in the context of the user that will be reading the saved and encrypted credentials.

This user needs VM power user permission in vCenter and runasbatch in windows. 

  1. Open CMD prompt / powershell window
  2. Execute: "runas /noprofile /user:"{username}" powershell.exe
    1. Enter the password
    2. This will open powershell console as the user specified.
  3. Execute the powerCLI command, "New-VICredentialStoreItem" command, specify the Username and password.

#> New-VICredentialStorItem -host <IP or name of vCenter> -User "DOMAIN\VCAdmin" -password "<accountpassword>" -file c:\script\vmservicecred.xml

Reply
0 Kudos
LucD
Leadership
Leadership

You are aware that the VICredentialStore does not work on PSv7?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Steve005
Contributor
Contributor

Hi @LucD,

No I was not aware of that.

What command should you use as a replacement?

All these scripts run with  6.7.

Reply
0 Kudos
LucD
Leadership
Leadership

There is no PowerCLI native solution, but there are others like the SecretManagement and SecretStore modules.
They require a bit more work but the SecretStore module allows one to plug in some of the more common secret storage solutions.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
ferds101
Contributor
Contributor

Can anyone help to modify this script to add more 3 rows for the datastore name, datastore size, datastore free size

Reply
0 Kudos
ferdz101
Contributor
Contributor

Can help to modify this script to add more column for datastore size, datastore free space & VM size 

Reply
0 Kudos