Azure ASM

As you know, Microsoft is recommending the newer Azure Resource Manager (ARM) as the default environment for Azure. Many of us have deployed Virtual Machines (VMs) in the older Azure Service Manager (ASM) model. And now we are looking at how to get your Azure ASM VMs into the new ARM world for access to newer features.

There are many solutions out there to help with this migration, however, most are fairly new and untested by the community and do not address specific needs or architecture. For today, I’m going to describe how to make this migration using an approach with PowerShell that I have used for the last six months – it worked for Azure ASM  migration in the public cloud to ARM public or government cloud. The approach is fairly simple but it allows you more controls over the process.

Step 1: Prepare your ARM Environment

Basically, you need to create the required resources in ARM (or leverage existing ARM environment). These are items you need to have provisioned:

  • VNET – new ARM VNET
  • VNET Subnet – subnet where you are going to migrate the VM or VMs to
  • Availability Set (AVS) – optional if you want to setup AVS for High Availability for each workload as needed (remember at this time you cannot add an already provisioned VM into an AVS – it must be done at time of VM provisioning).
  • ARM Storage Account (SA) or two – I like to keep my VM OS disk on one Storage Account and Data disk on another account. Or for Disaster Recovery consideration, you can use SA per workload for easy backup and restore/recovery (but keep in mind of the 250 SA limit per subscription). I used “vhds” as the container name for the OS disks and “data” for data disks.

Once you have these items provisioned or have an existing environment, you are ready.

Step 2: Setup your PowerShell (PoS) for ARM

You need to make sure you PoS has the latest version if possible 2.1+. For installation instructions, see How to install and configure Azure PowerShell.

You must import the RM module:

$Install-Module AzureRM

And then log into your Azure account and select the subscription you want to work with.


$Get-AzureRmSubscription -SubscriptionName “(your subname here)” | Select-AzureRmSubscription

Or $Select-AzureRMSubscription –Subscriptionid “(your sub id here looks like a GUID)”

(Notice that all the RM stuff has the “RM” in the command).


Step 3: Copy your VHDs from Azure ASM storage to ARM storage

Yes, you must now manually copy all your VHDs file over to your ARM storage.    This also moves your VHD files from ASM to ARM storage. To do that I defined a set of parameters to use with my copy command.

Define your destination:

$destStorageAccount = “(your ARM storage account for OS disks)”

$destStorageKey = “(your storage key for your storage account from the Azure portal)”

$destContainerName = “vhds” (this is typical or change it to match your container name used).

Define your source location.

$srcStorageAccount= “(your ASM storage account for OS disks)”

$srcStorageKey = “(your storage key for your storage account from the Azure portal)”

$scrContainerName = “vhds” (this is standard or change it to match your container name used).

Now for each VMs targeted for migration I define the following parameters:

$vhdName= “(name of your OS vhd)”

$vmName = “(name of the VM)”

$vmSize = “(VM size in the ARM environment – like Stardard_A6)”

$srcUri= “https://” + $srcStorageAccount + “” + $ scrContainerName +”/” + $vhdName

(for government cloud use “” instead of “

$srcContext = New-AzureStorageContext -StorageAccountName $srcStorageAccount -StorageAccountKey $srcStorageKey

$destContext = New-AzureStorageContext -StorageAccountName $destStorageAccount -StorageAccountKey $destStorageKey

Now you are ready to copy the OS VHD to ARM. I use the AzureStorageBlobCopy command since it is an asynchronous call to Azure to copy data directly between Azure resources thus no data download to your desktop is needed. Before running this, you will need to TURN OFF the VM in the Azure Portal so you will be down until the whole process is completed. This process typically take 2 to 3 hours for the copy of OS VHD from Azure ASM to ARM – longer if you move across regions. For data files it can take longer if it is over 200 GB+.

$blobOS = Start-AzureStorageBlobCopy -srcUri $srcUri -SrcContext $srcContext -DestContainer $destContainerName -DestBlob $vhdName -DestContext $destContext

For a data file (if you have one):

$destDataStorageAccount = “(your ARM storage account for data disks)”

$destDataStorageKey = “(your storage key for your storage account from the Azure portal)”

$destDataContainerName = “data” (this is standard or change it to match your container name used).

$srcDataStorageAccount= “(your ASM storage account for OS disks)”

$srcDataStorageKey = “(your storage key for your storage account from the Azure portal)”

$scrDataContainerName = “data” (this is standard or change it to match your container name used).

$vhdDataName= “(name of your data vhd)”

$srcDataUri= “https://” + $srcDataStorageAccount + “” + $ scrDataContainerName +”/” + $vhdDataName

$srcDataContext = New-AzureStorageContext -StorageAccountName $srcDataStorageAccount -StorageAccountKey $srcDataStorageKey

$destDataContext = New-AzureStorageContext -StorageAccountName $destDataStorageAccount -StorageAccountKey $destDataStorageKey

Copy the data VHD:

$blobData = Start-AzureStorageBlobCopy -srcUri $srcDataUri -SrcContext $srcDataContext -DestContainer $destDataContainerName -DestBlob $vhdDataName -DestContext $destDataContext


For a quick check on the process use this command:

$blobOS | Get-AzureStorageBlobCopyState

$blobData | Get-AzureStorageBlobCopyState

or a loop command

$while(($blobOS | Get-AzureStorageBlobCopyState).Status -eq “Pending”)


   $blobOS | Get-AzureStorageBlobCopyState

   $blobData | Get-AzureStorageBlobCopyState

   Start-Sleep -s 600



You will need to wait until the status = “Success” before moving the next step.

As you can see you can make multiple copy requests in parallel. The only limit would be the bandwidth limitation on each Storage Account.


Step 4: Provision your ARM VM based on copied VHDs

Now that copies are completed, we can add some parameters to use for provisioning.

$resourceGroupName = “(your RG name)”

$virtualNetworkName = “(your VNET name)”

$locationName= “(your Azure region name)”

$avSetName = “(your AVS name)”

$vhdLocation= “https://” +$destStorageAccount + “” + $ destContainerName + “/” + $vhdName

$ipName = $vmName + “-ip” (I used the VM name as part of the IP name)

$nicName = $vmName + “-nic01” (I used the VM name as part of the NIC name)

$virtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $resourceGroupName -Name $virtualNetworkName

# Decide if Public IP should be static or Dynamic

$publicIp = New-AzureRmPublicIpAddress -Name $ipName -ResourceGroupName $ResourceGroupName -Location $locationName -AllocationMethod Dynamic

#(for static) $publicIp = New-AzureRmPublicIpAddress -Name $ipName -ResourceGroupName $ResourceGroupName -Location $locationName -AllocationMethod Static

Depending on which subnet you want to place the VM – change $virtualNetwork.Subnets[0].Id -> [0] is first subnet.

$networkInterface = New-AzureRmNetworkInterface -ResourceGroupName $resourceGroupName -Name $nicName -Location $locationName -SubnetId $virtualNetwork.Subnets[0].Id -PublicIpAddressId $publicIp.Id

$avSet = Get-AzureRmAvailabilitySet -Name $avSetName -ResourceGroupName $resourceGroupName

$vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $avSet.Id

$vmConfig = Set-AzureRmVMOSDisk -VM $vmConfig -Name $vmName -VhdUri $vhdLocation -CreateOption Attach -Windows

$vmConfig = Add-AzureRmVMNetworkInterface -VM $vmConfig -Id $networkInterface.Id

Now you are ready to provision the VM:

$vm = New-AzureRmVM -VM $vmConfig -Location $locationName -ResourceGroupName $resourceGroupName

Wait at least 10 minutes for provisioning to complete.

Step 5: Add data VHDs and validate

The last step is to add in the data disk(s) and validate the ARM VM. I do this by going to Azure portal and add the existing data VHD disk to the VM as well as verify it is provisioned successfully.  To add existing data disk,, select the storage account and container then the data VHD file to attach as disk for the VM from that option.

Note that if you have multiple data disks, you will need to add them in the same order as shown in the old Azure ASM VM disk information.

Next step is to verify VM is running – select Overview tab on the VM in the Azure Portal. Last step is to reboot/restart the VM to re-load the attached disk(s).   You are done now J.