Subscribe

Adding expiry time to snapshot not directly possible with PowerShell Cmdlets

I have a customer who needs to set the expiry-time for legal reasons for many snapshots via WFA. Unfortunately the PowerShell Cmdlets currently do not support setting the expiry-time for a snapshot. I would have expected Set-NcSnapshot to have a parameter for expiry time, but it is missing. I have now implemented the missing functionality using Invoke-NcSystemApi, but would be glad if it could be included in the official PowerShell Cmdlets.

 

Here's an example to get the current expiry time

 

$Template = Get-NcSnapshot -Template
$Template.ExpiryTime = ""
$Snapshot = Get-NcSnapshot -Vserver $VserverName -Volume $VolumeName -Snapshot $SnapshotName
Write-Host "Expiry time of snapshot $SnapshotName is $($Snapshot.ExpiryTimeDT)"

 

Here's the Cmdlet to set the expiry time directly using the ZAPI

 

# helper function to convert datetime to unix timestamp
function ConvertTo-UnixTimestamp {
    [CmdletBinding()]
 
    PARAM (
        [parameter(Mandatory=$True,
                    Position=0,
                    ValueFromPipeline=$True,
                    ValueFromPipelineByPropertyName=$True,
                    HelpMessage="Date to be converted.")][DateTime[]]$Date
    )
 
    BEGIN {
        $epoch = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0
    }
 
    PROCESS {
        $Date = @($Date)
 
        foreach ($Date in $Date) {
                $Seconds = [math]::Ceiling($Date.ToUniversalTime().Subtract($epoch).TotalSeconds)
                Write-Output $Seconds
        }
    }
}
 
<#
.SYNOPSIS
Modifies expiry-time of a snapshot
.DESCRIPTION
This operation modifies the expiry time of a snapshot
.EXAMPLE
$ExpiryTime = (Get-Date).AddYear(1)
Set-NcSnapshotExpiryTime -Controller $Controller -Vserver $VserverName -Volume $VolumeName -Snapshot $SnapshotName -ExpiryTime $ExpiryTime
.PARAMETER Controller
A clustered Data ONTAP controller to receive this cmdlet, as embodied by an NcController object.  This parameter is returned by the Connect-NcController cmdlet.  If not specified, the value in the global variable CurrentNcController is used.  In the latter case, if CurrentNcController contains a collection of NcController objects, this cmdlet is invoked on each controller in succession.
.PARAMETER Vserver
Name of the vserver to which this volume belongs.
.PARAMETER Volume
Volume name.
.PARAMETER Snapshot
Snapshot name.
.PARAMETER ExpiryTime
Expiry time as DateTime object.
.LINK
Get-NcSnapshot
#>
function global:Set-NcSnapshotExpiryTime {
    [CmdletBinding(DefaultParameterSetName="none")]
    PARAM (
        [parameter(Mandatory=$False,
                    Position=0,
                    HelpMessage="A clustered Data ONTAP controller to receive this cmdlet, as embodied by an NcController object. This parameter is returned by the Connect-NcController cmdlet.  If not specified, the value in the global variable CurrentNcController is used.  In the latter case, if CurrentNcController contains a collection of NcController objects, this cmdlet is invoked on each controller in succession.")][NetApp.Ontapi.Filer.C.NcController]$Controller,
        [parameter(Mandatory=$True,
                    Position=1,
                    ValueFromPipeline=$True,
                    ValueFromPipelineByPropertyName=$True,
                    HelpMessage="Vserver to which to direct this command. If the currently connected controller (as embodied by an NcController object) represents a cluster, there are multiple means to address commands to one of its vservers.  Either set the Vserver field on the NcController object to direct all subsequent commands to that vserver, or supply the VserverContext parameter to an individual cmdlet.  Only cmdlets which may be invoked on vservers offer the VserverContext parameter.")][String]$Vserver,
        [parameter(Mandatory=$True,
                    Position=2,
                    HelpMessage="Names of the volumes across which the snapshot is to be created.",
                    ValueFromPipeline=$True,
                    ValueFromPipelineByPropertyName=$True)][String]$Volume,
        [parameter(Mandatory=$True,
                    Position=3,
                    HelpMessage="Name of the snapshot to be modified.",
                    ValueFromPipeline=$True,
                    ValueFromPipelineByPropertyName=$True)][Alias("Name")][String]$Snapshot,
        [parameter(Mandatory=$True,
                    Position=4,
                    HelpMessage="Expiry time as DateTime object..")][DateTime]$ExpiryTime
    )
 
    PROCESS {
        Write-Verbose "Setting expiry time $ExpiryTime for snapshot $Snapshot of Volume $Volume in SVM $Vserver"
 
        $xmlDoc = New-Object system.Xml.XmlDocument
        $xmlDoc.loadXml(@"
<snapshot-modify-iter>
    <attributes>
        <snapshot-info>
            <expiry-time></expiry-time>
        </snapshot-info>
    </attributes>
    <query>
        <snapshot-info>
            <name></name>
            <volume></volume>
            <vserver></vserver>
        </snapshot-info>
    </query>
</snapshot-modify-iter>
"@)
 
        $xmlDoc."snapshot-modify-iter".query.'snapshot-info'.vserver = $Vserver
        $xmlDoc."snapshot-modify-iter".query.'snapshot-info'.volume = $Volume
        $xmlDoc."snapshot-modify-iter".query.'snapshot-info'.name = $Snapshot
        $xmlDoc."snapshot-modify-iter".attributes.'snapshot-info'.'expiry-time' = ($ExpiryTime | ConvertTo-UnixTimestamp).ToString()
 
        $result = Invoke-NcSystemApi -RequestXML $xmlDoc -VserverContext $Vserver -ErrorAction Stop
 
        if ($result.results.'num-failed' -ge 1) {
            throw "Setting Expiry Time failed with error " + $result.results.'failure-list'.'snapshot-modify-iter-info'.'error-message'
        }
    }
}