Skip to content

Instantly share code, notes, and snippets.

@Sam-Martin
Created April 19, 2015 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sam-Martin/5e1f9bf73643662c0bf5 to your computer and use it in GitHub Desktop.
Save Sam-Martin/5e1f9bf73643662c0bf5 to your computer and use it in GitHub Desktop.
Snapshot EBS Volume and copy snapshot to another region
<#
.Synopsis
Creates a snapshot of an EBS volume, copies it to the destination region, then deletes the snapshot (not the volume) in the source region
.DESCRIPTION
You will need to run either Set-AWSCredentials or Initialize-AWSDefaults passing your accesskey and privatekey prior to execution of this cmdlet in order to establish connectivity to AWS.
.NOTES
To set the default AWS credentials for your current Windows user, use:
Initialize-AWSDefaults -AccessKey ***** -SecretKey ***** -Region us-west-2
Naturally you will need to replace the asterisks and region with the values appropriate to your configuration
.EXAMPLE
New-EC2VolumeSnapshotOffsite -volumeName "TKYMGMT01 Full Backup Z:" -sourceRegion ap-northeast-1 -destinationRegion ap-southeast-2 -Confirm:$false -verbose
.EXAMPLE
New-EC2VolumeSnapshotOffsite -volumeName "TKYSQL01 Z: Backup" -sourceRegion "ap-northeast-1" -destinationRegion "ap-southeast-2" -Description "Backup and offsite of TKYSQL01 Z: Backup on $((get-date).ToString('yyyy-MM-dd HH:mm:ss'))" -snapshotName "Automatic Offsiting" -Verbose -confirm:$false
.OUTPUTS
Amazon.EC2.Model.Snapshot (destination)
#>
function New-EC2VolumeSnapshotOffsite
{
[CmdletBinding(
SupportsShouldProcess=$true,
PositionalBinding=$false,
ConfirmImpact='High')]
#[OutputType([Amazon.EC2.Model.Snapshot])]
Param
(
# Volume Name
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='Volume by name')]
[ValidateNotNullOrEmpty()]
[string]$volumeName,
# Source Region
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=1)]
[ValidateNotNullOrEmpty()]
[string]$sourceRegion,
# Destination Region
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=2)]
[ValidateNotNullOrEmpty()]
[string]$destinationRegion,
# Snapshot Description
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=3)]
[string]$description= "Backup and offsite of $volumeName on $((get-date).ToString('yyyy-MM-dd HH:mm:ss'))",
# Snapshot Name
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=4)]
[string]$snapshotName
)
Begin
{
# Check the AWS module is loaded
if(!(Get-Module | ?{$_.Name -eq "AWSPowerShell"})){
# Check the AWS module is installed
if(Get-Module -ListAvailable | ?{$_.name -eq "AWSPowerShell"}){
# Import AWS module
Import-Module AWSPowerShell
}else{
Throw "Please install the AWS module.";
}
}
# Check we've got AWS creds loaded
if(!(Get-AWSCredentials -ListStoredCredentials)){
Throw "No AWS credentials loaded. Use Set-AWSCredentials or Initialize-AWSDefaults to set credentials.";
}
}
Process
{
if ($pscmdlet.ShouldProcess("$volumeName", "Taking snapshot"))
{
# Take Snapshot
Write-Verbose "Taking snapshot of $volumeName";
try{
$snapshot = New-EC2Snapshot -Description $description -VolumeId $(Get-EC2Volume -Region $sourceRegion | ?{$_.tag | %{$_.value -eq $volumeName }} ).VolumeId -ErrorAction Stop
}catch{
Throw $_.exception.message;
}
# Wait for the snapshot to finish being created
while(($snapshotStatus = (Get-EC2Snapshot -SnapshotId $snapshot.SnapshotId -Region $sourceRegion)).Status -eq "pending"){
Write-Verbose "Sleeping for 20 seconds as snapshot still pending $($snapshotStatus.progress)";
sleep -s 20
}
# Check the snapshot was created successfully
if($snapshotStatus.Status -eq "completed"){
Write-Verbose "Snapshot complete";
}else{
Throw $snapshotStatus
}
}
if ($pscmdlet.ShouldProcess("$destinationRegion", "Copying snapshot"))
{
# Copy snapshot to destination region
Write-Verbose "Copying snapshot from $sourceRegion to $destinationRegion";
try{
$snapshotCopy = Copy-EC2Snapshot -Description $description -SourceRegion $sourceRegion -Region $destinationRegion -SourceSnapshotId $snapshot.SnapshotId -ErrorAction stop
}catch{
Throw $_.exception.message;
}
# Wait for the snapshot to copy
while(($snapshotCopyStatus = Get-EC2Snapshot -SnapshotId $snapshotCopy -region $destinationRegion).status -eq "pending"){
Write-Verbose "Sleeping for 20 seconds as snapshot still copying $($snapshotCopyStatus.progress)";
sleep -s 20
}
# Check the snapshot copied successfully
if($snapshotCopyStatus.Status -eq "completed"){
Write-Verbose "Snapshot complete";
}else{
Throw $snapshotCopyStatus
}
# Set the name of the snapshot
$tag = New-Object Amazon.EC2.Model.Tag
$tag.Key = "Name"
$tag.Value = $snapshotName
New-EC2Tag -ResourceId $snapshotCopy -Tag $tag -Region $destinationRegion
}
if ($pscmdlet.ShouldProcess("$volumeName", "Deleting original snapshot"))
{
# Delete original snapshot
Write-Verbose "Deleting original snapshot of $volumeName in $sourceRegion";
try{
$snapshotDelete = Remove-EC2Snapshot -SnapshotId $snapshot.SnapshotId -Region $sourceRegion -Force -ErrorAction stop
}catch{
Write-Error $_.exception.message;
}
# Wait for deletion to complete
while(($snapshotDeleteStatus = Get-EC2Snapshot -SnapshotId $snapshotDelete -region ap-southeast-2).status -eq "pending"){
Write-Verbose "Sleeping for 20 seconds as snapshot still deleting $($snapshotDeleteStatus.progress)";
sleep -s 20
}
# Check deletion was successful
if($snapshotDeleteStatus.Status -eq "completed"){
Write-Verbose "Snapshot deletion complete";
}else{
Throw $snapshotDeleteStatus
}
}
if ($pscmdlet.ShouldProcess("$destinationRegion", "Returning snapshot in destination") -and $snapshotCopy)
{
return $snapshotCopyStatus
}
}
End
{
}
}
<#
.Synopsis
Get AWS EC2 Snapshots by Name
.EXAMPLE
Example of how to use this cmdlet
.EXAMPLE
Another example of how to use this cmdlet
#>
function get-EC2VolumeSnapshotByName
{
[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact='Low')]
[OutputType([String])]
Param
(
# EC2 Region to search for snapshot
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0)]
[ValidateNotNullOrEmpty()]
[Alias("EC2Region", "SnapshotRegion")]
[string]$region,
# Snapshot Name to search for
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=1)]
[ValidateNotNullOrEmpty()]
[Alias( "Snapshot Name", "name")]
[string]$snapshotName,
# Exclude snapshots taken earlier than this date
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=2)]
[DateTime]$startDate,
# Exclude snapshots taken later than this date
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=3)]
[DateTime]$endDate
)
Begin
{
# Check the AWS module is loaded
if(!(Get-Module | ?{$_.Name -eq "AWSPowerShell"})){
# Check the AWS module is installed
if(Get-Module -ListAvailable | ?{$_.name -eq "AWSPowerShell"}){
# Import AWS module
Import-Module AWSPowerShell
}else{
Throw "Please install the AWS module.";
}
}
# Check we've got AWS creds loaded
if(!(Get-AWSCredentials -ListStoredCredentials)){
Throw "No AWS credentials loaded. Use Set-AWSCredentials or Initialize-AWSDefaults to set credentials.";
}
}
Process
{
# Create name filter
$nameFilter = New-Object Amazon.EC2.Model.Filter
$nameFilter.Name = "tag:Name"
$nameFilter.Value.Add($snapshotName)
# Get Snapshots
$snapshots = get-EC2Snapshot -Filter $nameFilter -Region $region
# Filter by StartDate
if($startDate){
Write-Verbose "Excluding snapshots taken earlier than $startDate";
$snapshots = $snapshots | ?{[DateTime]::Compare($_.StartTime, $startDate) -gt 0}
}
# Filter by EndDate
if($endDate){
Write-Verbose "Excluding snapshots taken later than $endDate";
$snapshots = $snapshots | ?{[DateTime]::Compare($_.StartTime, $endDate) -lt 0}
}
Write-Output $snapshots
}
End
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment