Snippets

SeanB Restore from S3

Created by SeanB
param (
    [string]$from = "selectcs-backup",
    [string]$to = $(get-location).ToString()
 )


#todo:if no parameters, then show instructions 
#todo:mirror option that deletes items that don't exist 
#todo:aws details need to be in the environment.

#$DebugPreference = "Continue"

import-module "C:\Program Files (x86)\AWS Tools\PowerShell\AWSPowerShell\AWSPowerShell.psd1"
add-type -assemblyName "System.Web"

$maxkeys = 1000
$blocksize = (1024*1024*5)
$startblocks = (1024*1024*16)
$region = "eu-west-1"   # Regions: us-east-1, us-west-2, us-west-1, eu-west-1, ap-southeast-1

$AccessKeyId = (get-item env:aws-access-key-id -erroraction ignore).value 
$AccessKeySecret = (get-item env:aws-access-key-secret -erroraction ignore).value 

if ( !($AccessKeyId) -or !($AccessKeySecret)) {
	$ok = ($AccessKeyId) -or ($AccessKeySecret)
	Write-Host "AWS Access keys have not been created."
	Write-Host "==================================================================="
	Write-Host "To run this script you must create two environment variables called"
	Write-Host "aws-access-key-id and aws-access-key-secret"
	Write-Host "--"
	break
} 

$restoreTo = $to
$restoreFrom = $from 

$restoreTo  = $restoreTo.ToLower()
if ($restoreTo[-1] -ne "\") { $restoreTo += "\" }

$restoreFrom  = $restoreFrom.ToLower()
$bucket = $restoreFrom.Split(":")[0]
$s3folder = $restoreFrom.Split(":")[1]

if (!($s3folder)) {
    $s3folder = $env:COMPUTERNAME + "/"
    $s3folder += $(get-location).ToString() + "/"
    $s3folder = $s3folder.replace("\\","/").replace(":\","/").replace("\","/") 
    $s3folder = $s3folder.ToLower()
}
$s3folder = $s3folder.ToLower().replace("\" , "/")
if ($s3folder[-1] -ne "/") { $s3folder += "/" }

$msg="Restoring files from $restoreFrom to $restoreTo  " 
Write-Host $msg
Write-Host "-"
Write-Host "Bucket: $bucket"
Write-Host "S3 Folder: $s3folder"
Write-Host ("=" * $msg.Length)

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider

function AmazonEtagHashForFile($filename) {
    $lines = 0
    [byte[]] $binHash = @()

    $reader = [System.IO.File]::Open($filename,"OPEN","READ")
	
	if ((Get-Item $filename).length -gt $startblocks) {
		$buf = new-object byte[] $blocksize
		while (($read_len = $reader.Read($buf,0,$buf.length)) -ne 0){
			$lines   += 1
			$binHash += $md5.ComputeHash($buf,0,$read_len)
		}
		$binHash=$md5.ComputeHash( $binHash )
	}
	else {
	    $lines   = 1
		$binHash += $md5.ComputeHash($reader)
	}

    $reader.Close()
    
	$hash = [System.BitConverter]::ToString( $binHash )
    $hash = $hash.Replace("-","").ToLower()

    if ($lines -gt 1) {
        $hash = $hash + "-$lines"
    }

    return $hash
}

function s3RestoreFile($RestoreFile) {

	$LocalFile = $RestoreFile
	$LocalFile = $LocalFile.replace($s3Folder,"")
	$LocalFile = $LocalFile.replace("/" , "\")
	$LocalFile = [System.Web.HttpUtility]::UrlDecode($LocalFile) 
	$LocalFile = $restoreTo + $LocalFile 

	$copyfile = $true 
	if (Test-Path $LocalFile) {
		$hash = AmazonEtagHashForFile($LocalFile)
		$s3file = (Get-S3Object -BucketName $bucket -Key $RestoreFile)
		$etag =$s3file[0].etag.Replace('"',"")
		$copyfile = ($etag -ne $hash)
	}

	if ($copyfile) {
	    Read-S3Object -BucketName $bucket -File $LocalFile -Key $RestoreFile
	}
}


Set-AWSCredentials -AccessKey $AccessKeyId -SecretKey $AccessKeySecret
Set-DefaultAWSRegion $region

# we use -Marker to start searching from a point.
# because AWS only returns up to 1000 items at a time. 
$marker = ""
do {
	$s3files = (Get-S3Object -Marker $marker -MaxKeys $maxkeys -BucketName $bucket -KeyPrefix $s3Folder )
	$s3files | Foreach-Object{
		$marker = $_.key
		s3RestoreFile $_.key
	}
}
while ($s3files.length -eq $maxkeys)

Write-Host("..")

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.