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

I was curious to see what ChatGPT code interpreter would do with this code and this is it’s output.

<#
.SYNOPSIS
NetApp-Gather Snapshot Information

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

.NOTES
Written by Thomas Lasswell, TechColumnist
Version 1.1
#>

Param (
    [Parameter(Mandatory=$True)]
    [Array]$nodes,
    [Parameter(Mandatory=$True)]
    [String]$username,
    [Parameter(Mandatory=$True,ParameterSetName = 'Secret')]
    [Security.SecureString]$password,
    [switch]$IsVerbose
)

$exedir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$currentDate = (Get-Date -format "yyyyMMdd.Hms")
$outsummary = -join ($exedir, "\GatherSnapshotInformation_", $currentDate, "_Summary.csv")
$outdetails = -join ($exedir, "\GatherSnapshotInformation_", $currentDate, "_Detail.csv")

Import-Module DataONTAP -ErrorAction SilentlyContinue

try {
    $requiredVersion = New-Object System.Version(1.2)
    if ((Get-NaToolkitVersion).CompareTo($requiredVersion) -LT 0) { throw "This script requires Data ONTAP PowerShell Toolkit 1.2 or higher." }
} catch {
    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 Get-DateDiff {
    param (
        [parameter(Mandatory=$true)]
        [datetime]$date1,
        [parameter(Mandatory=$true)]
        [datetime]$date2
    )
    return [Math]::Abs(($date2 - $date1).Days)
}

$objDetail = @()
$objSummary = @()

foreach ($node in $nodes) {
    Write-Host "Connecting to node $node..."
    $conn = Connect-NaController -name $node -HTTPS -Credential $cred

    if ($conn) {
        Write-host "Node connected, continuing on to snapshot calculations..."
        $vols = Get-NaVol | Where-Object {$_.state -eq "online" -and $_.raidstatus -notmatch "read-only"}

        foreach ($vol in $vols) {
            $snaps = Get-NaSnapshot -targetname $vol
            $snapsdatecount = $snaps | Group-Object { ($_.Created).Days } -NoElement | Sort-Object Name -Descending
            $totalavgdays = $snapsdatecount | Measure-Object Count -Average | Select-Object Count,Average
            $totalsize = $snaps | Measure-Object Total -Sum | Select-Object Count,Sum
            $foldestsnap = $snaps | Sort-Object Created -Descending | Select-Object -Last 1

            if ($totalavgdays.Average) {
                $summaryprop = @{
                    'Node' = $node;
                    'Volume' = $vol;
                    'TotalSnaps' = $snaps.length;
                    'TotalDays' = $totalavgdays.Count;
                    'AvgPerDay' = $totalavgdays.Average;
                    'TotalSize' = [System.Math]::Round($totalsize.Sum, 2);
                    'Oldest' = $foldestsnap.created
                }
                $objSummary += New-Object -TypeName PSObject -Property $summaryprop

                foreach ($snap in $snaps) {
                    $daysold = Get-DateDiff (Get-Date) $snap.created
                    $detailprop = @{
                        'Node' = $node;
                        'Volume' = $vol;
                        'Name' = $snap.name;
                        'Created' = $snap.created;
                        'DaysOld' = $daysold;
                        'TotalSize' = [System.Math]::Round($snap.total, 2);
                        'CumulativeTotal' = [System.Math]::Round($snap.CumulativeTotal, 2)
                    }
                    $objDetail += New-Object -TypeName PSObject -Property $detailprop
                }
            } else {
                Write-Host "`tNo Snapshots Exist on $vol..."
            }
        }
    }
}

$objSummary | Export-CSV -Path $outsummary -NoTypeInformation
$objDetail | Export-CSV -Path $outdetails -NoTypeInformation