GinShell.Azure/Public/Send-GsAzureSnapshotsToStorage.ps1

function Send-GsAzureSnapshotsToStorage {
    param (
        [Parameter(Mandatory = $true)]
        [object[]]$Snapshot,

        [Parameter(Mandatory = $true)]
        [string]$StorageAccountName,

        [Parameter(Mandatory = $true)]
        [string]$StorageAccountKey,

        [Parameter(Mandatory = $true)]
        [string]$ContainerName,

        [int]$TimeOutSec = 86400,

        [switch]$WaitForComplete
    )
    try {
        Write-GsLog -Message "Creating storage context for '$StorageAccountName'" -Type Info
        $context = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
    }
    catch {
        Write-GsLog -Message "Failed to create storage context: $($_.Exception.Message)" -Type Error
        return
    }

    $blobNames = @()

    foreach ($snap in $Snapshot) {
        try {
            # Validate snapshot network configuration
            if (($snap.PublicNetworkAccess -ne 'Enabled') -or ($snap.NetworkAccessPolicy -ne "AllowAll")) {
                Write-GsLog -Message "Public network access is not enabled for snapshot '$($snap.Name)'" -Type Warning
                Enable-GsAzureSnapshotPublicAccess -Snapshot $snap
            }

            Write-GsLog -Message "Generating SAS URL for snapshot '$($snap.Name)' in resource group '$($snap.ResourceGroupName)'" -Type Debug
            $sas = Grant-AzSnapshotAccess -ResourceGroupName $snap.ResourceGroupName -SnapshotName $snap.Name -DurationInSecond $TimeOutSec -Access Read

            Write-GsLog -Message "Starting blob copy for snapshot '$($snap.Name)' to container '$ContainerName'" -Type Action
            $copyResult = Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $ContainerName -DestContext $context -DestBlob $snap.Name

            $blobNames += $snap.Name
        }
        catch {
            Write-GsLog -Message "Failed to start copy for snapshot '$($snap.Name)': $($_.Exception.Message)" -Type Error
            return $null
        }
    }

    if ($WaitForComplete) {
        Write-GsLog -Message "Monitoring snapshot copy progress..." -Type Info
        $inProgress = $true

        while ($inProgress) {
            $inProgress = $false

            foreach ($blobName in $blobNames) {
                $copyState = Get-AzStorageBlobCopyState -Blob $blobName -Container $ContainerName -Context $context

                if ($copyState.Status -ne "Success") {
                    $inProgress = $true
                    $percent = if ($copyState.TotalBytes -gt 0) {
                        [math]::Round(100 * $copyState.BytesCopied / $copyState.TotalBytes, 2)
                    }
                    else { 0 }

                    Write-GsLog -Message "Snapshot '$blobName' copy status: $($copyState.Status) - $percent% completed" -Type Debug
                }
                else {
                    Write-GsLog -Message "Snapshot '$blobName' copy completed successfully" -Type Success
                }
            }

            if ($inProgress) {
                Start-Sleep -Seconds 30
            }
        }
    }

    Write-GsLog -Message "Fetching blob references from container '$ContainerName'" -Type Info
    $blobs = @()
    foreach ($blobName in $blobNames) {
        try {
            $blob = Get-AzStorageBlob -Blob $blobName -Container $ContainerName -Context $context
            if ($blob) {
                $blobs += $blob.ICloudBlob
            }
        }
        catch {
            Write-GsLog -Message "Failed to retrieve blob '$blobName': $($_.Exception.Message)" -Type Warning
        }
    }

    return $blobs
}