Copy-AzureVMDiskToSA.ps1
<#PSScriptInfo
.VERSION 1.0.1 .GUID 44ce6bf4-ca04-4237-9088-f905aef1150e .AUTHOR dareynol .COMPANYNAME Microsoft Corporation .COPYRIGHT (c) 2019 Microsoft. All rights reserved. .TAGS Azure Image Images Copy VM Storage Account .LICENSEURI https://github.com/dcrreynolds/Azure-CopyingImages/blob/master/LICENSE .PROJECTURI https://github.com/dcrreynolds/Azure-CopyingImages .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .SYNOPSIS Generalize an Azure VM and export its Disk as VHDs to another region or subscription. .Description Generalize an Azure VM and export its Disk as VHDs to another region or subscription. .PARAMETER StorageAccountSubscriptionId Subscription ID of the target storage account .PARAMETER StorageAccountName Name of the target storage account .PARAMETER StorageAccountResourceGroup Resource group iof the target storage account .PARAMETER StorageAccountContainer Container to place VHDs in .PARAMETER VMSubscriptionID Subscription ID of VM .PARAMETER VMName Name of the VM .PARAMETER VMResourceGroup Resource group of the VM .EXAMPLE .\Copy-AzureVMDiskToSA.ps1 ` -StorageAccountSubscriptionId "Sub 1 ID" ` -StorageAccountName "SA-Name" ` -StorageAccountResourceGroup "SA-RG-Name" ` -StorageAccountContainer "SA-RG-Container-Name" ` -VMSubscriptionID "Sub 2 ID" ` -VMName "VM-Name" ` -VMResourceGroup "VM-RG-Name" #> param ( [parameter(mandatory)] $StorageAccountSubscriptionId, [parameter(mandatory)] $StorageAccountName, [parameter(mandatory)] $StorageAccountResourceGroup, [parameter(mandatory)] $StorageAccountContainer, [parameter(mandatory)] $VMSubscriptionID, [parameter(mandatory)] $VMName, [parameter(mandatory)] $VMResourceGroup ) #region functions <# .SYNOPSIS Connects to Azure and sets the provided subscription. .PARAMETER SubscriptionId ID of subscription to use .PARAMETER AutomationConnection Azure automation connection object for using a AA run as account #> function Set-AzureConnection { Param ( [parameter(mandatory = $true)] $SubscriptionId, $AutomationConnection, $AzureEnvironment = "AzureCloud" ) $context = Get-AzureRmContext if($null -eq $context.Account) { $envARM = Get-AzureRmEnvironment -Name $AzureEnvironment if($null -ne $AutomationConnection) { $context = Add-AzureRmAccount ` -ServicePrincipal ` -Tenant $Conn.TenantID ` -ApplicationId $Conn.ApplicationID ` -CertificateThumbprint $Conn.CertificateThumbprint ` -Environment $envARM } else # if no connection info, log in using the web prompts { $context = Add-AzureRmAccount -Environment $envARM -ErrorAction Stop } } $null = Set-AzureRmContext -Subscription $SubscriptionId -ErrorAction Stop } #endregion Set-AzureConnection -SubscriptionId $VMSubscriptionID # Make sure the VM is generalized. Write-Output "Generalizing VM $VMName" $null = Set-AzureRmVm -ResourceGroupName $VMResourceGroup -Name $VMName -Generalized # get info about the VM disk so we can DL them Write-Output "Obtaining VM $VMName disk SAS access" $vm = Get-AzureRMVM -Name $VMName -ResourceGroupName $VMResourceGroup $diskList = @($vm.StorageProfile.OsDisk) $diskList += $vm.StorageProfile.DataDisks $SASList = @() foreach($disk in $diskList) { $SAS = Grant-AzureRmDiskAccess ` -ResourceGroupName $VMResourceGroup ` -DiskName $disk.Name ` -Access 'Read' ` -DurationInSecond (60 * 60) $SASList += @{ AccessSAS = $SAS.AccessSAS DiskName = $disk.Name } } # Set these storage account variables Set-AzureConnection -SubscriptionId $StorageAccountSubscriptionId $storageAccount = Get-AzureRmStorageAccount ` -Name $StorageAccountName ` -ResourceGroupName $StorageAccountResourceGroup Write-Output "Starting the disk copy to $StorageAccountName" $copyJob = @() foreach($diskSAS in $SASList) { $copyJob += Start-AzureStorageBlobCopy ` -AbsoluteUri $diskSAS.AccessSAS ` -DestContainer $StorageAccountContainer ` -DestContext $storageAccount.Context ` -DestBlob "$($diskSAS.DiskName).vhd" } # wait for the copy job to complete foreach($copy in $copyJob) { Write-Output "Waiting for disk $($copy.Name) copy to complete" Get-AzureStorageBlobCopyState ` -Blob $copy.Name ` -Container $StorageAccountContainer ` -Context $storageAccount.Context ` -WaitForComplete } |