Public/Storage/New-VergeNASVolumeSnapshot.ps1
|
function New-VergeNASVolumeSnapshot { <# .SYNOPSIS Creates a snapshot of a NAS volume in VergeOS. .DESCRIPTION New-VergeNASVolumeSnapshot creates a point-in-time snapshot of a NAS volume. Snapshots can be used for backup purposes or to restore the volume to a previous state. .PARAMETER Volume The name or object of the volume to snapshot. .PARAMETER Name The name for the new snapshot. .PARAMETER Description Optional description for the snapshot. .PARAMETER ExpiresInDays Number of days until the snapshot expires. Defaults to 3 days. Use -NeverExpires to create a permanent snapshot. .PARAMETER NeverExpires If specified, the snapshot will never automatically expire. .PARAMETER Quiesce If specified, temporarily freezes I/O to the volume while the snapshot is taken for consistency. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE New-VergeNASVolumeSnapshot -Volume "FileShare" -Name "Pre-Update" Creates a snapshot named "Pre-Update" for the FileShare volume. .EXAMPLE New-VergeNASVolumeSnapshot -Volume "FileShare" -Name "Daily-$(Get-Date -Format 'yyyyMMdd')" Creates a daily snapshot with today's date in the name. .EXAMPLE New-VergeNASVolumeSnapshot -Volume "Database" -Name "Before-Migration" -Quiesce -NeverExpires Creates a quiesced, permanent snapshot. .EXAMPLE Get-VergeNASVolume -Name "Prod-*" | ForEach-Object { New-VergeNASVolumeSnapshot -Volume $_ -Name "Backup-$(Get-Date -Format 'yyyyMMdd')" } Creates snapshots for all production volumes. .OUTPUTS Verge.VolumeSnapshot object representing the created snapshot. .NOTES Snapshots are stored on the same tier as the parent volume. Consider storage capacity when creating many snapshots. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [Alias('VolumeName')] [object]$Volume, [Parameter(Mandatory, Position = 1)] [ValidateLength(1, 128)] [string]$Name, [Parameter()] [ValidateLength(0, 2048)] [string]$Description, [Parameter()] [ValidateRange(1, 3650)] [int]$ExpiresInDays = 3, [Parameter()] [switch]$NeverExpires, [Parameter()] [switch]$Quiesce, [Parameter()] [object]$Server ) begin { # Resolve connection if (-not $Server) { $Server = $script:DefaultConnection } if (-not $Server) { throw [System.InvalidOperationException]::new( 'Not connected to VergeOS. Use Connect-VergeOS to establish a connection.' ) } } process { try { # Resolve volume to key $volumeKey = $null $volumeName = $null if ($Volume -is [string]) { $volumeName = $Volume $volumeData = Get-VergeNASVolume -Name $Volume -Server $Server if (-not $volumeData) { throw "Volume '$Volume' not found" } $volumeKey = $volumeData.Key $volumeName = $volumeData.Name } elseif ($Volume.Key) { $volumeKey = $Volume.Key $volumeName = $Volume.Name } elseif ($Volume -is [int]) { $volumeKey = $Volume } if (-not $volumeKey) { throw "Could not resolve volume key" } # Build request body $body = @{ volume = $volumeKey name = $Name } if ($Description) { $body['description'] = $Description } if ($NeverExpires) { $body['expires_type'] = 'never' $body['expires'] = 0 } else { $body['expires_type'] = 'date' # Calculate expiration as Unix timestamp $expiresAt = [DateTimeOffset]::Now.AddDays($ExpiresInDays) $body['expires'] = $expiresAt.ToUnixTimeSeconds() } if ($Quiesce) { $body['quiesce'] = $true } $body['created_manually'] = $true $displayName = $volumeName ?? $volumeKey if ($PSCmdlet.ShouldProcess("Volume '$displayName'", "Create snapshot '$Name'")) { Write-Verbose "Creating snapshot '$Name' for volume '$displayName'" $response = Invoke-VergeAPI -Method POST -Endpoint 'volume_snapshots' -Body $body -Connection $Server # Return the created snapshot if ($response.'$key') { Get-VergeNASVolumeSnapshot -Key $response.'$key' -Server $Server } else { # Try to find by name Get-VergeNASVolumeSnapshot -Volume $volumeKey -Name $Name -Server $Server } } } catch { $displayName = $volumeName ?? $volumeKey ?? 'unknown' Write-Error -Message "Failed to create snapshot for volume '$displayName': $($_.Exception.Message)" -ErrorId 'NewVolumeSnapshotFailed' } } } |