• sqlfriends - Wednesday, April 18, 2018 11:56 PM

    Thanks for the article! Great information. Could you share the Powershel script? Thanks

    Here you go.  May need a bit of tweaking.

    # CopyBackupFilesToAzure
    #
    # You need to supply the following mandatory parameters
    #
    # SourceDirectory  - The directory where backups are kept. E.g E:\BACKUP\MyserverName
    # ServerName   - The name of the server / instance
    # BackupType   - Backuptype to copy (Options are FULL, LOG, DIFF, MySQL)
    # StorageAccountName - The name of the azure storage account
    # StorageAccountKey - The key to access the storage account
    #
    # Usage
    #
    # .\CopyBackupFilesToAzure -SourceDirectory "E:\Backup\MyServerName" -ServerName "MyServer" -BackupType "LOG" -StorageAccountName "myazurestorage" -StorageAccountKey "mykey"

    param
    (
    [Parameter(Mandatory=$true)]
    [string]$SourceDirectory,
    [Parameter(Mandatory=$true)]
    [string]$ServerName,
    [Parameter(Mandatory=$true)]
    [string]$BackupType,
    [Parameter(Mandatory=$true)]
    [string]$StorageAccountName,
    [Parameter(Mandatory=$true)]
    [string]$StorageAccountKey
    )

    FUNCTION Generate-StorageContext
    {
      param
      (
      [Parameter(Mandatory=$true)]
      [string]$StorageAccountName,
      [Parameter(Mandatory=$true)]
      [string]$StorageAccountKey

    )

      $TryCounter = 0
      $StorageContext = $null
      WHILE ($TryCounter -lt 3 -and !$StorageContext)
      {
       $StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey -ErrorAction Stop
       $TryCounter = $TryCounter + 1
       if (!$StorageContext)
       {
        Start-Sleep -s 45
       }
      }
      Return $StorageContext

    }

    Function CheckForCreateContainer
    {
      param
      (
      [Parameter(Mandatory=$true)]
      [object]$SContext,
      [Parameter(Mandatory=$true)]
      [string]$SContainer
      )

      $ContainerNotThere = $null
      $null = Get-AzureStorageContainer -Context $SContext -Name $SContainer -ErrorAction SilentlyContinue -ErrorVariable ContainerNotThere

      if ($ContainerNotThere)
      {
       $null = New-AzureStorageContainer -Name $SContainer -Context $SContext -ErrorAction SilentlyContinue
       Start-Sleep -Seconds 10
       $ContainerNotThere = $null
       $null = Get-AzureStorageContainer -Context $SContext -Name $SContainer -ErrorAction SilentlyContinue -ErrorVariable ContainerNotThere
      }
     
      if ($ContainerNotThere)
      {
       $ContainerStatus = "Unable to find / create container"
      }
      else
      {
       $ContainerStatus = "Exists"
      }

      Return $ContainerStatus
    }

    Function CheckForAndTranferFileToBlobStorage
    {
      param
      (
      [Parameter(Mandatory=$true)]
      [object]$SContext,
      [Parameter(Mandatory=$true)]
      [string]$SContainer,
      [Parameter(Mandatory=$true)]
      [string]$SFileName,
      [Parameter(Mandatory=$true)]
      [string]$SBackupURI,
      [Parameter(Mandatory=$false)]
      [boolean]$SOverWrite = $false

      )

      [object] $FileDoesNotExist
      if ($FileDoesNotExist)
      {
       $FileDoesNotExist.clear()
      }

      $null = Get-AzureStorageBlob -Blob $SBackupURI -Container $SContainer -Context $SContext -ErrorAction SilentlyContinue -ErrorVariable FileDoesNotExist
      if ($FileDoesNotExist -or $OverWrite)
      {
       if ($CopyToAzureError)
       {
        $CopyToAzureError.clear()
       }
      
       if($SOverWrite)
       {
        $null = Set-AzureStorageBlobContent -File $SFileName -Container $SContainer -Blob $SBackupURI -Context $SContext -Force -ErrorAction SilentlyContinue -ErrorVariable CopyToAzureError
       }
       else
       {
        $null = Set-AzureStorageBlobContent -File $SFileName -Container $SContainer -Blob $SBackupURI -Context $SContext -ErrorAction SilentlyContinue -ErrorVariable CopyToAzureError
       }

       if($CopyToAzureError)
       {
        Return "Copy Error [$SBackupURI] to container [$SContainer]"
       }
       else
       {
        Return "Success"
       }
      }
      else
      {
       Return "File In Storage"
      }
    }

    #------------------------------------------------------ START ------------------------------------------------------#

    $ProgressPreference = ’SilentlyContinue’

    #Check we have one of the allowed backup types
    if($BackupType -notin "FULL", "DIFF", "LOG", "MySQL")
    {
      Write-Output "ERROR - You can only specify FULL, DIFF or LOG for BackupType"
      Exit 1
    }

    $ContainerName = $ServerName.ToLower() + "-" + $BackupType.ToLower()

    #Generate the storage context
    Write-Output "Generating Storage Context For Storage Account [$StorageAccountName]"
    $StorageContext = Generate-StorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey

    #Check to see if the container exists for the storage account. If not, create it.
    Write-Output "Checking for container [$ContainerName] in Storage Account [$StorageAccountName] (Will attempt create if container not present)"
    $ContainerStatus = CheckForCreateContainer -SContext $StorageContext -SContainer $ContainerName

    if ($ContainerStatus -notin "Exists","Created")
    {
      Write-Output "-----------------------------------------------------------------------------------"
      Write-Output "Container does not exist for the specified storage account and could not be created"
      Write-Output "-----------------------------------------------------------------------------------"
      Exit 1
    }

    #Set the fileextention and directory parts
    switch ($BackupType)
    {
      FULL {$FileExtension = '.bak'}
      DIFF {$FileExtension = '.bak'}
      LOG {$FileExtension = '.trn'}
      MYSQL {$FileExtension = '.SQL'}
    }

    switch ($BackupType)
    {
      FULL {$DirectoryPart = '*\FULL'}
      DIFF {$DirectoryPart = '*\DIFF'}
      LOG {$DirectoryPart = '*\LOG'}
      MYSQL {$DirectoryPart = '*\MySQL*'}
    }

    #Get the list of files based on the type of backup file and backup type
    $FileListing = Get-ChildItem -Path $SourceDirectory -Recurse | where {!$_.psIsContainer -and $_.Extension -eq "$FileExtension" -and $_.DirectoryName -like $DirectoryPart}

    #Get file listing, check if in Azure storage account and tranfer if not there
    foreach ($File in $FileListing)
    {
      $SourceFileName = $File.FullName
      $StorageAccountSubDirectory = (((($File.DirectoryName.Replace("$SourceDirectory","")).SubString(1).ToLower()) -replace "\\","") -replace $BackupType,"")
      $StorageURI = ($StorageAccountSubDirectory + "`\" + ($File.Name)).replace("\\","\$BackupType\").ToLower()
      $FileCopyStatus = CheckForAndTranferFileToBlobStorage -SContext $StorageContext -SContainer $ContainerName -SFileName $SourceFileName -SBackupURI $StorageURI
      Write-Output "Processing File [$SourceFileName] : Status [$FileCopyStatus]"
    }