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"