Skip to content

Instantly share code, notes, and snippets.

@mmckechney
Last active June 20, 2019 13:02
Show Gist options
  • Save mmckechney/f32f958826eb9f26f88398a9ac9c6e0c to your computer and use it in GitHub Desktop.
Save mmckechney/f32f958826eb9f26f88398a9ac9c6e0c to your computer and use it in GitHub Desktop.
Copy a managed disk to another region
<#
.SYNOPSIS
Managed disks in Azure have no direct facilitites to access the underlying URL/path the disk resides in since
they are placed into storage accounts under the hood by Azure. Often times there's a desire to take a disk from a single
VM and move to another region where you can create a new VM and attach to the disk that's copied. This script
provides a means to do that and has been tested as working using the new AZ PowerShell cmdlets.
If this is run in a PowerShell context without the new AZ cmdlets installed; simply do a search and replace of Az to AzureRM.
Note: The SOURCE VM needs to be powered off to create the SAS URL and to ensure no writes are occuring to the disk during the copy.
.DESCRIPTION
This script will require you to populate the source resource group and source managed disk name as well as the destination resource group,
destination managed disk name and destination Azure region. It will create a temporary resource group and storage account for the
copy process, then clean up both the resource group and storage account.
This script takes advantage of the Grant-AzDiskAccess provding a temporary SAS token to a managed disk.
#>
#login-azaccount -- ensure you are logged in and that the context is set to the proper subscription
$subscriptionId = ""
#Location and name for the source Managed Disk
$sourceResourceGroupName = ""
$sourceDiskName = ""
$osType = "" # Windows or Linux
#Destination resource group and name for the managed disk
$destinationResourceGroup = ""
$destinationDiskName = ""
$destinationRegion = ""
#Set the subscription context
Set-AzContext -SubscriptionId $subscriptionId
#Create the temporary storage account to stage the VHD copy and get context object
$tempStorageAccountName = "managedcopy" + -join ((97..122) | Get-Random -Count 10 | % {[char]$_})
$tempStorageAccountResourceGroup = $tempStorageAccountName + "-rg"
$tempVhdBlob = $tempStorageAccountName + ".vhd"
New-AzResourceGroup -Name $tempStorageAccountResourceGroup -Location $destinationRegion
New-AzStorageAccount -Name $tempStorageAccountName -ResourceGroupName $tempStorageAccountResourceGroup -SkuName Premium_LRS -Location $destinationRegion
$tempStorageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $tempStorageAccountResourceGroup -Name $tempStorageAccountName ).Value[0]
$stagingContext = New-AzStorageContext -StorageAccountName $tempStorageAccountName -StorageAccountKey $tempStorageAccountKey
New-AzStorageContainer -Context $stagingContext -name 'vhds' -ErrorAction SilentlyContinue
#Get a reference to the source managed disk and access the underlying VHD
$managedDisk= Get-AzDisk -ResourceGroupName $sourceResourceGroupName -DiskName $sourceDiskName
$sas = Grant-AzDiskAccess -ResourceGroupName $sourceResourceGroupName -DiskName $managedDisk.Name -DurationInSecond 14400 -Access Read
#Start copying the VHD for the source managed disk
$copyfile = Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer 'vhds' -DestContext $stagingContext -DestBlob $tempVhdBlob -ConcurrentTaskCount 500
$blobVhdUri = $stagingContext.Context.BlobEndPoint + "vhds/" + $tempVhdBlob
#Get status of the copy
Get-AzStorageBlob -Context $stagingContext -Container 'vhds' | ForEach-Object { Get-AzStorageBlobCopyState -Blob $_.Name -Context $stagingContext -Container 'vhds' -WaitForComplete }
$status = $copyfile | Get-AzStorageFileCopyState
while ($status.Status -eq "Pending")
{
$status = $copyfile | Get-AzStorageFileCopyState
Start-Sleep -Milliseconds 500
}
#Create the new Managed Disk from the URL
$storageAccountId = '/subscriptions/' +$subscriptionId + '/resourceGroups/' + $destinationResourceGroup + '/providers/Microsoft.Storage/storageAccounts/' + $tempStorageAccountName
$diskConfig = New-AzDiskConfig -AccountType Premium_LRS -Location $destinationRegion -CreateOption Import -StorageAccountId $storageAccountId -SourceUri $blobVhdUri -OsType $osType
New-AzDisk -Disk $diskConfig -ResourceGroupName $destinationResourceGroup -DiskName $destinationDiskName
#Cleanup ----
#remove the VHD access token frou the source managed disk
Revoke-AzDiskAccess -ResourceGroupName $sourceResourceGroupName -DiskName $sourceDiskName
#Delete the temporary storage account
Remove-AzStorageAccount -ResourceGroupName $tempStorageAccountResourceGroup -Name $tempStorageAccountName -Force
#Delete the temp resource group
Remove-AzResourceGroup -Name $tempStorageAccountResourceGroup -Force
@mmckechney
Copy link
Author

Modified version of script originally written by Ryan Berry that fully manages the storage account used to stage the VHD copy.
(https://github.com/microsoft/csa-misc-utils/blob/master/psh-ManagedDiskUtils/ManagedDiskCopy.ps1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment