Public/Backup/Invoke-VergeSiteSync.ps1
|
function Invoke-VergeSiteSync { <# .SYNOPSIS Manually queues a cloud snapshot for sync to a remote site. .DESCRIPTION Invoke-VergeSiteSync adds a cloud snapshot to the transfer queue for an outgoing site sync. This allows manual syncing of specific snapshots outside of the automatic schedule. .PARAMETER SyncKey The key (ID) of the outgoing sync to use. .PARAMETER SyncName The name of the outgoing sync to use. .PARAMETER SiteSync A site sync object from Get-VergeSiteSync. .PARAMETER SnapshotKey The key (ID) of the cloud snapshot to sync. .PARAMETER SnapshotName The name of the cloud snapshot to sync. .PARAMETER CloudSnapshot A cloud snapshot object from Get-VergeCloudSnapshot. .PARAMETER Retention How long to keep the snapshot on the remote site. Accepts TimeSpan or seconds as integer. Default is 3 days (259200 seconds). .PARAMETER Priority The priority for syncing (lower numbers sync first). Default is 0. .PARAMETER DoNotExpire If set, the snapshot will stay in the queue without expiring until sent. .PARAMETER DestinationPrefix Prefix to add to the snapshot name on the destination. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE Invoke-VergeSiteSync -SyncName "DR-Sync" -SnapshotName "Manual-2024-01-15" Queues the specified snapshot for sync with default retention. .EXAMPLE Get-VergeCloudSnapshot -Name "Pre-Update*" | Invoke-VergeSiteSync -SyncName "DR-Sync" -Retention (New-TimeSpan -Days 30) Queues all matching snapshots for sync with 30 day retention. .EXAMPLE Invoke-VergeSiteSync -SyncKey 1 -SnapshotKey 5 -Priority 1 -DoNotExpire Queues a snapshot with high priority that won't expire until synced. .OUTPUTS PSCustomObject with queue item details .NOTES The snapshot is added to the sync queue and will be transferred when the sync is enabled and the transfer begins. Use Get-VergeSiteSyncQueue to see queued snapshots. Use Start-VergeSiteSync to enable a disabled sync. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByName')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, ParameterSetName = 'ByKey')] [Parameter(Mandatory, ParameterSetName = 'ByKeySnapshot')] [Parameter(Mandatory, ParameterSetName = 'ByKeySnapshotObj')] [int]$SyncKey, [Parameter(Mandatory, Position = 0, ParameterSetName = 'ByName')] [Parameter(Mandatory, ParameterSetName = 'ByNameSnapshot')] [Parameter(Mandatory, ParameterSetName = 'ByNameSnapshotObj')] [string]$SyncName, [Parameter(Mandatory, ParameterSetName = 'ByObject')] [Parameter(Mandatory, ParameterSetName = 'ByObjectSnapshot')] [Parameter(Mandatory, ParameterSetName = 'ByObjectSnapshotObj')] [PSTypeName('Verge.SiteSync')] [PSCustomObject]$SiteSync, [Parameter(Mandatory, ParameterSetName = 'ByKey')] [Parameter(Mandatory, ParameterSetName = 'ByName')] [Parameter(Mandatory, ParameterSetName = 'ByObject')] [int]$SnapshotKey, [Parameter(Mandatory, ParameterSetName = 'ByKeySnapshot')] [Parameter(Mandatory, ParameterSetName = 'ByNameSnapshot')] [Parameter(Mandatory, ParameterSetName = 'ByObjectSnapshot')] [string]$SnapshotName, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByKeySnapshotObj')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByNameSnapshotObj')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByObjectSnapshotObj')] [PSTypeName('Verge.CloudSnapshot')] [PSCustomObject]$CloudSnapshot, [Parameter()] [object]$Retention = 259200, [Parameter()] [int]$Priority = 0, [Parameter()] [switch]$DoNotExpire, [Parameter()] [ValidatePattern('^[a-zA-Z0-9 :_.,+-]*$')] [string]$DestinationPrefix, [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.' ) } # Convert retention to seconds $retentionSeconds = if ($Retention -is [TimeSpan]) { [int]$Retention.TotalSeconds } elseif ($Retention -is [int] -or $Retention -is [long]) { [int]$Retention } else { throw [System.ArgumentException]::new( 'Retention must be a TimeSpan or an integer representing seconds.' ) } # Resolve sync key (in begin block since it's the same for all pipeline items) $targetSyncKey = $null $targetSyncName = $null if ($SiteSync) { $targetSyncKey = $SiteSync.Key $targetSyncName = $SiteSync.Name } elseif ($SyncKey) { $targetSyncKey = $SyncKey $sync = Get-VergeSiteSync -Key $SyncKey -Server $Server if ($sync) { $targetSyncName = $sync.Name } } elseif ($SyncName) { $sync = Get-VergeSiteSync -Name $SyncName -Server $Server if (-not $sync) { throw [System.InvalidOperationException]::new( "Site sync not found: $SyncName" ) } $targetSyncKey = $sync.Key $targetSyncName = $sync.Name } } process { # Resolve snapshot key $targetSnapshotKey = $null $targetSnapshotName = $null if ($CloudSnapshot) { $targetSnapshotKey = $CloudSnapshot.Key $targetSnapshotName = $CloudSnapshot.Name } elseif ($SnapshotKey) { $targetSnapshotKey = $SnapshotKey try { $snap = Get-VergeCloudSnapshot -Key $SnapshotKey -Server $Server if ($snap) { $targetSnapshotName = $snap.Name } } catch { Write-Verbose "Could not retrieve snapshot name" } } elseif ($SnapshotName) { $snap = Get-VergeCloudSnapshot -Name $SnapshotName -Server $Server if (-not $snap) { Write-Error -Message "Cloud snapshot not found: $SnapshotName" -ErrorId 'CloudSnapshotNotFound' return } # Handle multiple matches if ($snap -is [array]) { Write-Error -Message "Multiple snapshots found matching '$SnapshotName'. Please use -SnapshotKey for a specific snapshot." -ErrorId 'MultipleSnapshotsFound' return } $targetSnapshotKey = $snap.Key $targetSnapshotName = $snap.Name } if (-not $targetSnapshotKey) { Write-Error -Message "Could not resolve cloud snapshot" -ErrorId 'SnapshotNotResolved' return } $description = "Snapshot '$targetSnapshotName' to Sync '$targetSyncName'" if ($PSCmdlet.ShouldProcess($description, 'Queue for sync')) { # Build params for add_to_queue action $params = @{ cloud_snapshot = $targetSnapshotKey retention = $retentionSeconds priority = $Priority do_not_expire = [bool]$DoNotExpire } if ($DestinationPrefix) { $params['destination_prefix'] = $DestinationPrefix } $body = @{ site_syncs_outgoing = $targetSyncKey action = 'add_to_queue' params = $params } try { Write-Verbose "Queueing snapshot $targetSnapshotKey for sync $targetSyncKey" $response = Invoke-VergeAPI -Method POST -Endpoint 'site_syncs_outgoing_actions' -Body $body -Connection $Server Write-Verbose "Snapshot queued successfully" # Return queue information [PSCustomObject]@{ PSTypeName = 'Verge.SiteSyncQueueItem' SyncKey = $targetSyncKey SyncName = $targetSyncName SnapshotKey = $targetSnapshotKey SnapshotName = $targetSnapshotName Retention = [TimeSpan]::FromSeconds($retentionSeconds) Priority = $Priority DoNotExpire = [bool]$DoNotExpire Status = 'Queued' } } catch { Write-Error -Message "Failed to queue snapshot for sync: $($_.Exception.Message)" -ErrorId 'QueueSnapshotFailed' } } } } |