Is it possible to migrate Azure VM image from one Subscription to another Subscription?

7,931

Solution 1

Try this:

Select-AzureSubscription -SubscriptionName "EXISTING SUBSCRIPTION NAME"
#Get-AzureVM

$vmName = "YOUR_VM_NAME"
$serviceName = "CLOUD_SERVICE_NAME"
$destServiceName = "NEW_CLOUD_SERVICE_NAME"
$workingDir = (Get-Location).Path

$sourceVm = Get-AzureVM -ServiceName $serviceName -Name $vmName
$vmConfigurationPath = $workingDir + "\exportedVM.xml"
$sourceVm | Export-AzureVM -Path $vmConfigurationPath

$sourceOSDisk = $sourceVm.VM.OSVirtualHardDisk
$sourceDataDisks = $sourceVm.VM.DataVirtualHardDisks

$sourceStorageName = $sourceOSDisk.MediaLink.Host -split "\." | select -First 1
$sourceStorageAccount = Get-AzureStorageAccount -StorageAccountName $sourceStorageName
$sourceStorageKey = (Get-AzureStorageKey -StorageAccountName $sourceStorageName).Primary

Stop-AzureVM -ServiceName $serviceName -Name $vmName -Force

Select-AzureSubscription -SubscriptionName "NEW SUBSCRIPTION NAME"

$location = $sourceStorageAccount.Location

$destStorageAccount = Get-AzureStorageAccount | ? {$_.Location -eq $location} | select -first 1
if ($destStorageAccount -eq $null)
{   
    $destStorageName = "NEW_STORAGE_NAME"
New-AzureStorageAccount -StorageAccountName $destStorageName -Location $location
$ destStorageAccount = Get-AzureStorageAccount -StorageAccountName $destStorageName
}
$destStorageName = $destStorageAccount.StorageAccountName
$destStorageKey = (Get-AzureStorageKey -StorageAccountName $destStorageName).Primary

$sourceContext = New-AzureStorageContext  -StorageAccountName $sourceStorageName `
    -StorageAccountKey $sourceStorageKey 
$destContext = New-AzureStorageContext  -StorageAccountName $destStorageName `
    -StorageAccountKey $destStorageKey 

if ((Get-AzureStorageContainer -Context $destContext -Name vhds -ErrorAction SilentlyContinue) -eq $null)
{
    New-AzureStorageContainer -Context $destContext -Name vhds
}

$allDisks = @($sourceOSDisk) + $sourceDataDisks
$destDataDisks = @()
foreach($disk in $allDisks)
{   
    $blobName = $disk.MediaLink.Segments[2]
    $targetBlob = Start-CopyAzureStorageBlob -SrcContainer vhds -SrcBlob $blobName `
                                            -DestContainer vhds -DestBlob $blobName `
                                            -Context $sourceContext -DestContext $destContext -Force
    Write-Host "Copying blob $blobName"
    $copyState = $targetBlob | Get-AzureStorageBlobCopyState
    while ($copyState.Status -ne "Success")
    {           
        $percent = ($copyState.BytesCopied / $copyState.TotalBytes) * 100       
        Write-Host "Completed $('{0:N2}' -f $percent)%"
        sleep -Seconds 5
        $copyState = $targetBlob | Get-AzureStorageBlobCopyState
    }
    If ($disk -eq $sourceOSDisk)
    {
        $destOSDisk = $targetBlob
    }
    Else
    {
        $destDataDisks += $targetBlob
    }
}

Add-AzureDisk -OS $sourceOSDisk.OS -DiskName $sourceOSDisk.DiskName -MediaLocation $destOSDisk.ICloudBlob.Uri
foreach($currenDataDisk in $destDataDisks)
{
    $diskName = ($sourceDataDisks | ? {$_.MediaLink.Segments[2] -eq $currenDataDisk.Name}).DiskName    
    Add-AzureDisk -DiskName $diskName -MediaLocation $currenDataDisk.ICloudBlob.Uri
}

Get-AzureSubscription -Current | Set-AzureSubscription -CurrentStorageAccountName $destStorageName

$vmConfig = Import-AzureVM -Path $vmConfigurationPath
New-AzureVM -ServiceName $destServiceName -Location $location -VMs $vmConfig -WaitForBoot

Get-AzureRemoteDesktopFile -ServiceName $destServiceName -Name $vmConfig.RoleName -LocalPath ($workingDir+"\newVM.rdp")`

Solution 2

Azure provides little support for switching any Azure service from one Subscription to another.

If you create a ticket, I have done this by the way, you can have Azure support staff manually switch ALL services from one Subscription (source) to another Subscription (destination) where the destination Subscription has NO services in that Subscription.

You CANNOT select individual services from the source Subscription to transfer, to the destination Subscription (its all or nothing from the source Subscription) and you CANNOT have any existing services in the destination Subscription.

**A service is any Azure feature (VM, Website, Storage Blob etc)

It is likely that the support rep has not done this procedure before and you will have to let them know it is possible, my support rep for the ticket took about a week to figure it all out. Make sure you use the vernacular source Subscription and destination Subscription with GUIDs for both Subscriptions in all conversations with the Azure support rep.

Now for a VM in particular, it looks like you can copy a VM from one storage account to another using a tool called AzCopy, check out this article:

http://thecodejunkie.com/2014/01/20/copying-virtual-machines-between-azure-subscriptions/

Share:
7,931

Related videos on Youtube

billcyz
Author by

billcyz

Updated on September 18, 2022

Comments

  • billcyz
    billcyz over 1 year

    I recently captured one azure vm image in one storage account, and planning to migrate this image to another storage account under a different subscription. I used PowerShell Script to run this task, but I came across with this problem: The storage account was not found. And one more concern is that PowerShell has to be related to the specific Azure Account, otherwise it can not run script. So the story is how to use PowerShell control different subscriptions at the same time, and also perform the migration task?? Thank You.

    BTW, the PowerShell script is shown below:

    Change these to match the source account

    $sourceStorageAccountName = "" $sourceContainerName = "" $sourceStorageKey = "" #Need this if moving data from a different subscription

    Destination Account Information

    $destStorageAccountName = Read-Host "Enter Destination Storage Account Name" $destStorageAccountKey = Get-AzureStorageKey $destStorageAccountName | %{$_.Primary} $destContainerName = Read-Host "Enter Destination Container Name"

    $sourceContext = New-AzureStorageContext -StorageAccountName $sourceStorageAccountName -StorageAccountKey $sourceStorageKey -Protocol Http $destContext = New-AzureStorageContext -StorageAccountName $destStorageAccountName -StorageAccountKey $destStorageAccountKey

    $uri = $sourceContext.BlobEndPoint + $sourceContainerName +"/"

    Copy Operation

    Get-AzureStorageBlob -Context $sourceContext -Container $sourceContainerName | ForEach-Object { Start-AzureStorageBlobCopy -SrcUri "$uri$($_.Name)" -DestContext $destContext -DestContainer $destContainerName -DestBlob "hackathon/$($_.Name)" }

    Checking Status of Blob Copy -- This can be commented out if no confirmation is needed

    Get-AzureStorageBlob -Context $sourceContext -Container $sourceContainerName | ForEach-Object { Get-AzureStorageBlobCopyState -Blob $_.Name -Context $destContext -Container $destContainerName -WaitForComplete }

    The problem is like this: Get-AzureStorageKey : No current subscription has been designated. Use Select-AzureSubscription -Current to set the current subscription.

  • billcyz
    billcyz over 9 years
    Sorry, when I run this script, it shows this problem: + If ($disk –eq $sourceOSDisk) + ~ Unexpected token ')' in expression or statement.
  • Michael Hampton
    Michael Hampton over 9 years
    @billcyz Looks like some of the hyphens were replaced with (not very) "smart" ones. I made a pass through them and took them out.
  • raja
    raja over 9 years
    @MichaelHampton thanks, I suspect the paste process replaced them. I pasted then made it a code block, I should have put in the code block then pasted.
  • andreimarinescu
    andreimarinescu almost 9 years
    I used AzCopy to copy over the entire VHDS blob container over and the recreated the disks for the VMs in the new subscription. Worked like a charm, copied 300GB+ in 1h51min
  • Royden Rego
    Royden Rego about 7 years
    Any way this script can be made to work with multiple VM's under a cloud service?