Problem:

Gathering snapshot statistics is a tedious task when looking at autosupports and cli output. I needed to gather information about oldest snapshot, average number of snaps per day, total snapshots, and other various information.

Solution:

A powershell script using the Data ONTAP PS Library. Read more for the script.

.SYNOPSIS
NetApp-Gather Snapshot Information

.DESCRIPTION
This script will collect snapshot information, summary and detail
Including Created Time, Total Snaps, Total Days, Avg Per Day, Oldest, etc

.EXAMPLE
PS S:\102 – Scripts> & ‘.\NetApp-Gather Snapshot Information v1.1.ps1’ -nodes filer1.company.biz,filer2.company.biz -username “domain\username” -IsVerbose

.EXAMPLE
PS S:\102 – Scripts> & ‘.\NetApp-Gather Snapshot Information v1.1.ps1’

cmdlet NetApp-Gather Snapshot Information v1.1.ps1 at command pipeline position 1
Supply values for the following parameters:
nodes[0]: filer1.company.biz
nodes[1]: filer2.company.biz
nodes[2]:
username: domain\username
password: *************

.PARAMETER (IsVerbose)
Use this parameter to display snap detail ( & ‘.\NetApp-Gather Snapshot Information v1.1.ps1’ -IsVerbose )

.NOTES
Written by Thomas Lasswell, TechColumnist
Version 1.1

# #############################################################################
# iVision - SCRIPT - POWERSHELL - NETAPP 7-MODE COMMANDS
# NAME: NetApp-Gather Snapshot Information
#
# AUTHOR:  Thomas Lasswell, TechColumnist
# DATE:  2014/01/21
# EMAIL: lasswellt at TechColumnist.com
#
# COMMENT:  This script will collect snapshot information, summary and detail
#			Including Created Time, Total Snaps, Total Days, Avg Per Day, Oldest, etc
#
# VERSION HISTORY
# 1.0 2014.01.17 Initial Version.
# 1.1 2014.01.21 Added CSV export, days old column fixed
#
# TO ADD
#
# #############################################################################

<#
.SYNOPSIS
	NetApp-Gather Snapshot Information

.DESCRIPTION
	This script will collect snapshot information, summary and detail
	Including Created Time, Total Snaps, Total Days, Avg Per Day, Oldest, etc

.EXAMPLE
PS S:\102 - Scripts> & '.\NetApp-Gather Snapshot Information v1.1.ps1' -nodes filer1.company.biz,filer2.company.biz -username "domain\username" -IsVerbose

.EXAMPLE
PS S:\102 - Scripts> & '.\NetApp-Gather Snapshot Information v1.1.ps1'

cmdlet NetApp-Gather Snapshot Information v1.1.ps1 at command pipeline position 1
Supply values for the following parameters:
nodes[0]: filer1.company.biz
nodes[1]: filer2.company.biz
nodes[2]:
username: domain\username
password: *************

.PARAMETER (IsVerbose)
	Use this parameter to display snap detail ( & '.\NetApp-Gather Snapshot Information v1.1.ps1' -IsVerbose )

.NOTES
Written by Thomas Lasswell, iVision
Version 1.1

.LINK

#>
#Get Parameters -- nodes is each node, when finished, hit enter and it will continue
Param (
    [Parameter(Mandatory=$True)]
    [Array]$nodes,
    [Parameter(Mandatory=$True)]
    [String]$username,
    [Parameter(Mandatory=$True,ParameterSetName = 'Secret')]
    [Security.SecureString]$password,
	[switch]$IsVerbose
)
#create outfile information
$exedir= Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$currentDate= (get-date -format yyyymmdd.Hm.s)
$outsummary= ($exedir + "\" + "GatherSnapshotInformation_" + $currentDate + "_Summary.csv")
$outdetails= ($exedir + "\" + "GatherSnapshotInformation_" + $currentDate + "_Detail.csv")

#Load ONTAP PowerShell Toolkit
$module = Get-Module DataONTAP
if ($module -EQ $NULL)
{
	Import-Module DataONTAP
}

try
{
    $requiredVersion = New-Object System.Version(1.2)
    if ((Get-NaToolkitVersion).CompareTo($requiredVersion) -LT 0) { throw }
}
catch [Exception]
{
    Write-Host "`nThis script requires Data ONTAP PowerShell Toolkit 1.2 or higher`n" -ForegroundColor Red
    return
}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password

#function to calculate difference in dates
function Get-DateDiff {
	param (
		[CmdletBinding()]
		[parameter(Mandatory=$true)]
		[datetime]$date1,
		[parameter(Mandatory=$true)]
		[datetime]$date2
	)
		if ($date2 -gt $date1){$diff = $date2 - $date1}
		else {$diff = $date1 - $date2}
		$diff
}
#declare object arrays
$objDetail = @()
$objSummary = @()

#connect to each node individually
foreach ($node in $nodes){
	Write-Host "connecting to node $node..."
	$conn = Connect-NaController -name $node -HTTPS -Credential $cred
	$snapinfoS = @()
	$snapinfoD = @()

	if ( $conn -ne $null ) {
		Write-host "node connected, continuing on to snapshot calculations..."
		Write-host "gathering node volumes..."
		$vols =  Get-NaVol | ? {$_.state -eq "online" -and $_.raidstatus -notmatch "read-only"}
		if ( $vols -ne $null ) {
			foreach ($vol in $vols) {
				Write-host "gathering snapshots for volume $vol..."
				#get snapshots
				$snaps= Get-NaSnapshot -targetname $vol

				#group to count snapshots per day
				$snapsdatecount= $snaps | Group { ((Get-date) - $_.Created).Days } -NoElement | Sort Name -Descending
				#measure to get count and average, average is average snapshots per day
				$totalavgdays= $snapsdatecount | Measure-Object Count -ave | Select Count,Average
				$avgdays= $totalavgdays.Average
				$totaldays= $totalavgdays.Count

				#calculate sum of snapshots for total snapshot consumption
				$totalsize= $snaps | Measure-Object Total -Sum | Select Count,Sum
				$ftotalsize= ConvertTo-FormattedNumber $totalsize.sum DataSize "0.0"

				#get oldest snapshot
				$foldestsnap= $snaps | Sort Created -Descending | Select-Object -Last 1

				#build array for summary
				if ($avgdays -ne $null){
					$summaryprop = @{'Node'=$node;
									'Volume'=$vol;
									'TotalSnaps'=$snaps.length;
									'TotalDays'=$totaldays;
									'AvgPerDay'=$avgdays;
									'TotalSize'=$ftotalsize;
									'Oldest'=$foldestsnap.created}
					$objectS = New-Object -TypeName PSObject -Prop $summaryprop
					$objSummary += $objectS
					$objectS

					foreach ($snap in $snaps){
						$daysold= Get-DateDiff (get-date) $snap.created;
						$ftotal= ConvertTo-FormattedNumber $snap.total DataSize "0.0";
						$fcumulative= ConvertTo-FormattedNumber $snap.CumulativeTotal DataSize "0.0";

						#build array for details
						$detailprop = @{'Node'=$node;
										'Volume'=$vol;
										'Name'=$snap.name;
										'Created'=$snap.created;
										'DaysOld'=$daysold.days;
										'TotalSize'=$ftotal;
										'CumulativeTotal'=$fcumulative}
						$objectD = New-Object -TypeName PSObject -Prop $detailprop
						$objDetail += $objectD
					}
					if ($IsVerbose){
						$snaps | ft `
							@{Expression={$node};Label="Node name";Width=20},`
							@{Expression={$vol};Label="Volume";Width=40},`
							@{Expression={$_.Name};Label="Name";Width=150},`
							@{Expression={$_.Created.ToShortDateString()};Label="Created";Width=12},`
							@{E = {'{0} Days' -f (Get-DateDiff (get-date) $_.created).days};L="Days Old";W=20},`
							@{Expression={ConvertTo-FormattedNumber $_.Total DataSize "0.0"};Label="Total";Width=15},`
							@{Expression={ConvertTo-FormattedNumber $_.CumulativeTotal DataSize "0.0"};Label="Cumulative";Width=10} -autosize `
							|  Out-String -Width 1000 | Write-Host
					}
				}
				if ($avgdays -eq $null){ Write-Host "`tNo Snapshots Exist on $vol..."}
			}
		}
	}
}

#save files
$objSummary | Select Node, Volume, TotalSnaps, TotalDays, AvgPerDay, TotalSize, Oldest | Export-CSV -Path $outsummary -NoTypeInformation
$objDetail | Select Node, Volume, Name, Created, DaysOld, TotalSize, CumulativeTotal | Export-CSV -Path $outdetails -NoTypeInformation