Friday, September 4, 2015

Azure Resource Manager (ARM) : Move VM storage

Hi All,

I`ve been working on a new hosting platform in Azure Resource Manager(ARM) for a new customer of ours.
After some weeks of deploying VM`s we came to the conclusion that using only one storage account for the VM`s wan`t the way to go. So we decided that we had to split up the storage.
This is when we found out that there isn`t an easy way to move the VM storage. 
To move/copy the VM storage you need to perform the following steps:

- Stop the VM
- Save the VM config
- Copy the blob`s from one storage account to the other
- Edit the VM config
- Remove the current VM
- And recreate the VM using the saved config

But we`ve had already deployed 21 VM`s so i decided to create a powershell function and script to do this.
And here it is for the people who face similar problem or just don`t want to go through the hassle of finding out how to move the storage  :-) :



function Copy-AzureVMStorage($vmName, $resourceGroup, $oldStorageContext, $newStorageContext, $srcContainer, $dstContainer, $location)
{
 #Retrieve VM Config
 try
 {
  $vm = Get-AzureVM -ResourceGroupName $resourceGroup -Name $vmName
  
   if($vm -eq $null)
   {
    return
   }
 }
 catch
 {
  return
 }

 #Check if container exists in destination storage account
 $container = Get-AzureStorageContainer -Name $dstContainer -Context $newStorageContext -ErrorAction Ignore
 if($container -eq $null)
 {
  New-AzureStorageContainer -Name $dstContainer -Context $newStorageContext
 }
 
 #Stop the VM
 Stop-AzureVM -ResourceGroupName $resourceGroup -Name $vmName -Force
 
 #Copy the vhd`s to their new location
 try
 {
  $osDiskVHD = $vm.StorageProfile.OSDisk.Name + ".vhd"
  $copy = Start-AzureStorageBlobCopy -SrcBlob $osDiskVHD -SrcContainer $srcContainer -DestContainer $dstContainer -DestBlob $osDiskVHD -Context $oldStorageContext -DestContext $newStorageContext -Force
  Get-AzureStorageBlobCopyState -Container $dstContainer -Blob $copy.Name -Context $copy.Context -WaitForComplete
  $newOSDiskEndPoint = $newStorageContext.BlobEndPoint + $dstContainer + "/" + $osDiskVHD
  if($vm.StorageProfile.OSDisk.OperatingSystemType -eq "Linux")
  {
   Set-AzureVMOSDisk -VM $vm -Name $vm.StorageProfile.OSDisk.Name -VhdUri $newOSDiskEndPoint.Replace("https://", "http://") -CreateOption attach -Linux
  }
  else
  {
   Set-AzureVMOSDisk -VM $vm -Name $vm.StorageProfile.OSDisk.Name -VhdUri $newOSDiskEndPoint.Replace("https://", "http://") -CreateOption attach -Windows
  }
  
  foreach($dataDisk in $vm.StorageProfile.DataDisks)
  {
   $dataDiskVHD = $dataDisk.Name + ".vhd"
   $copy = Start-AzureStorageBlobCopy -SrcBlob $dataDiskVHD -SrcContainer $srcContainer -DestContainer $dstContainer -DestBlob $dataDiskVHD -Context $oldStorageContext -DestContext $newStorageContext -Force
   Get-AzureStorageBlobCopyState -Container $dstContainer -Blob $copy.Name -Context $copy.Context -WaitForComplete
   $newDataDiskEndPoint = $newStorageContext.BlobEndPoint + $dstContainer + "/" + $dataDiskVHD
   Remove-AzureVMDataDisk -VM $vm -DataDiskNames $dataDisk.Name
   Add-AzureVMDataDisk -VM $vm -Name $dataDisk.Name -VhdUri $newDataDiskEndPoint.Replace("https://", "http://") -Lun $dataDisk.Lun -CreateOption attach -DiskSizeInGB $dataDisk.DiskSizeGB
  }
 }
 catch
 {
  return
 }
 
 #Clean up the VM config before recreating
 $vm.StorageProfile.ImageReference = $null
 $vm.OSProfile = $null
 
 #Recreate VM
 Remove-AzureVM -ResourceGroupName $resourceGroup -Name $vmName -Force
 New-AzureVM -ResourceGroupName $resourceGroup -Location $location -VM $vm
}

#Setup connection to ARM
Add-AzureAccount
Switch-AzureMode -Name AzureResourceManager
Select-AzureSubscription -SubscriptionName "Contoso Subscription"

#Define storage accounts
$oldstoragecontext = New-AzureStorageContext -StorageAccountName "ContosoOld" -StorageAccountKey "<KEY>"
$newstoragecontext = New-AzureStorageContext -StorageAccountName "ContosoNew" -StorageAccountKey "<KEY>"

#Copy the VM storage and edit its config
Copy-AzureVMStorage "ContosoVM" "ContosoGroup" $oldstoragecontext $newstoragecontext "vhds" "vhds" "westeurope"