Levvel Blog - Synchronizing Your On-Premise Virtual Machines with VMs in Azure

Synchronizing Your On-Premise Virtual Machines with VMs in Azure

Synchronizing Your On-Premise Virtual Machines with VMs in Azure

Use Case

I was recently engaged with a client to help them synchronize an on-premise workload with one in Azure. Let’s say you have virtual machines which you manage on-premise that need to be moved to Azure. You then want to create additional virtual machines based on these virtual machines. You want to also apply any changes that may occur to the on-premise virtual machine to the virtual machines that you have moved to Azure.

The solution we looked at involved Azure Site Recovery. What is Azure Site Recovery (ASR)? According to Microsoft, it is:

“Site Recovery contributes to your business continuity and disaster recovery (BCDR) strategy, by orchestrating and automating replication of Azure VMs between regions, on-premises virtual machines and physical servers to Azure, and on-premises machines to a secondary datacenter.”

So, why ASR? We used parts of ASR to help automate the moving of multiple virtual machines to Azure and also to keep the images in sync with images on-premise.

Let’s get into the workflow.

1. Install Azure Site Recovery

I found that the instructions to Install and Configure the tool were pretty straightforward. The install I attempted was for the Hyper-v with VMM. Some useful links to guide you through the installs are provided at the bottom of this post.

A few things I noted:

  1. A full list of internet sites is required for access, and this list must include .windows.net: https://docs.microsoft.com/en-us/azure/site-recovery/hyper-v-prepare-on-premises-tutorial
Azure AD -  login.microsoftonline.com
Windows - *.windows.net
Backup - *.backup.windowsazure.com
Replication - *.hypervrecoverymanager.windowsazure.com
Storage - *.blob.core.windows.net
Telemetry (optional) - dc.services.visualstudio.com
Time Sync - time.windows.com
  1. After you install the Provider on the Virtual Machine Manager (VMM), the VMM Cloud does not happen instantaneously. Be prepared to wait for a few hours (possibly overnight)for it to appear.
  2. After you install the Recovery Services Agent, there is no need to configure it.

2. Update Virtual Machine Properties


Ensure that these are set up from the previous step:

  • Virtual Machines synchronized across Azure and appear in the list of protected items.
  • Failover Network setup and mapped to the on-premise network.

We can update the properties of the synchronized virtual machines in Azure either via the portal through the Compute and Network or we can automate this using Powershell.

I had a long list of virtual machines which needed their ‘static address’, ‘machine type’, and ‘disk type used’ modified. I opted to use PowerShell.

I did all of my development on Windows, and I used the following versions of Powershell and AzureRM:

Warning: Powershell on macOS or Linux use a different set of libraries.

Powershell Version:


Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      17134  228   

AzureRM Modules:

Get-Module -ListAvailable | Where-Object {$_.Name -like 'AzureRM*'}

   Directory: C:\Program Files\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands                                    
---------- -------    ----                                ----------------                                    
Script     6.9.0      AzureRM                                                                                 
Script     4.1.8      AzureRM.RecoveryServices            {Get-AzureRmRecoveryServicesBackupProperty, Get-Az...
Script     0.2.10     AzureRM.RecoveryServices.SiteRec... {Edit-AzureRmRecoveryServicesAsrRecoveryPlan, Get-...
Script     0.3.12     AzureRM.ServiceFabric               {Add-AzureRmServiceFabricApplicationCertificate, A...

A. Login

The first step is to log in to your subscription. Either use your own account and log in interactively or a service principal to do this.


#with a service principal
$applId = "http://my-app"

$pscredential = Get-Credential -UserName $applId -Message "Enter Password"
Connect-AzureRmAccount -ServicePrincipal -ApplicationId $applId -Credential $pscredential -TenantId $tenantId

B. Set to Vault Context

Set to the Recovery Vault Context.

$rsVaultName = "resourceVaultName"

$rsVault = Get-AzureRmRecoveryServicesVault -Name $rsVaultName
Set-AzureRmRecoveryServicesAsrVaultSettings -Vault $rsVault

Now we are ready to query and work with the items held in the vault.

C. Update Protected Item Properties

Update a VM with a single network interface to:

  • Use a static IP address
  • Use ManagedDisk and
  • Use a specific VM type

An example to update a VM called myVm:

  1. Static IP =
  2. Use managed disk
  3. Use VM type - Standard_D2s_v3
  4. Subnet NIC in failover resource group - recovery-subnet-in-recoveryRg
  5. Recovery group name - recovery-resource-group-name

Retrieve the protected item:

$protectedVm = Get-Asrfabric | Get-ASRProtectionContainer -FriendlyName "vmm_cloud_name" | Get-ASRReplicationProtectedItem -FriendlyName "myVm"

Retrieve the recovery group:

$recoveryRg = Get-AzureRmVM -ResourceGroupName "recovery-resource-group-name"

Update the required properties:

$setVm = Set-AzureRmRecoveryServicesAsrReplicationProtectedItem -InputObject $protectedVm -RecoveryResourceGroupId $recoveryRg.ResourceId -PrimaryNic $protectedVm.NicDetailsList[0].NicId -RecoveryNicStaticIPAddress "" -RecoveryNetworkId $protectedVm.NicDetailsList[0].RecoveryVMNetworkId -RecoveryNicSubnetName "recovery-subnet-in-recoveryRg" -Size "Standard_D2s_v3" -UseManagedDisk True -NicSelectionType SelectedByUser

To wait for the update to complete:

$status = Get-ASRJob -Name $setVm.Name
while ( $status.State -ne "Succeeded" )
       sleep 2;
       $status = Get-ASRJob -Name $setVm.Name

If you have more then one NIC (network interface card), repeat the step above to update the required properties for the second NIC after the first update. For example:

  • For a second NIC with a static IP of and a subnet of recovery-subnet2-in-recoveryRg:
$setVm = Set-AzureRmRecoveryServicesAsrReplicationProtectedItem -InputObject $protectedVm -RecoveryResourceGroupId $recoveryRg.ResourceId -PrimaryNic $protectedVm.NicDetailsList[1].NicId -RecoveryNicStaticIPAddress "" -RecoveryNetworkId $protectedVm.NicDetailsList[1].RecoveryVMNetworkId -RecoveryNicSubnetName "recovery-subnet2-in-recoveryRg" -Size "Standard_D2s_v3"

Code samples illustrate the commands required to perform the functions. One of my frustrations when trying to do this was to find the correct commands that work. I managed to find many that were deprecated or not really working. I hope this helps someone out there.

3. Run a Test-Failover

Now that the virtual machines have their properties set up for Azure, we’ll perform a Test Failover. A Test Failover creates an instance of what a real failover will look like. You can then test and evaluate whether your workload will work when failed over in Azure.

The cmdlet that allows you to run a TestFailover is from the AzureRM.RecoveryServices.SiteRecovery module:

The cmdlet uses the latest Recovery Point to perform a test failover of the VM. Test failover is the process by which it creates a test VM in the failover region.

Retrieve the recovery virtual network:

$recoveryVnet = Get-AzureRmVirtualNetwork -Name "virtual-recovery-network-name" -ResourceGroupName "recovery-resource-group"

Retrieve the protected virtual machine:

$protectedVm = (Get-Asrfabric | Get-ASRProtectionContainer -FriendlyName "vmm_cloud_name" | Get-ASRReplicationProtectedItem -FriendlyName "myVm") | Where-Object {$_.ProtectionState -eq "Protected"}

Start the TestFailover:

$job =  Start-AzureRmRecoveryServicesAsrTestFailoverJob -ReplicationProtectedItem $protectedVm -Direction PrimaryToRecovery -AzureVMNetworkId $recoveryVnet.Id

If you need to wait for the job to be completed, use the Get-ASRJob cmdlet:

$status = Get-ASRJob -Name $job.Name

Once the job is completed, you can log into the virtual machine and perform any testing activities. The main issues I encountered were either virtual machines not being able to start up, or, it starts but you are not able to log in to the virtual machine.

4. Create the Disk Snapshots

Create a new resource group for the snapshots to reside:

$rgSnapshot = New-AzureRmResourceGroup -Name "snapshotRg" -Location "Australia Southeast"

Retrieve OS disk and create a snapshot for the VM:

$vm = Get-AzureRmVm -Name "myVm" -ResourceGroupName "recovery-resource-group"       
$snapshotConfig =  New-AzureRmSnapshotConfig -SourceUri $vm.StorageProfile.OsDisk.ManagedDisk.Id -Location "Australia Southeast" -CreateOption copy -AccountType $storageType -OsType $vm.StorageProfile.OsDisk.OsType

New-AzureRmSnapshot -Snapshot $snapshotConfig -SnapshotName "myvm_osdisk" -ResourceGroupName "recovery-resource-group"

Retrieve all data disks and create the snapshots:

ForEach ( $datadisk in $vm.StorageProfile.dataDisks )

   $snapshotConfig =  New-AzureRmSnapshotConfig -SourceUri $datadisk.ManagedDisk.Id -Location "Australia East" -CreateOption copy -AccountType $storageType -OsType $vm.StorageProfile.OsDisk.OsType

   New-AzureRmSnapshot -Snapshot $snapshotConfig -SnapshotName $datadisk.Name -ResourceGroupName "recovery-resource-group"


If you have a lot of virtual machines, you can run this in parallel by using the option -AsJob. For example:

$job = New-AzureRmSnapshot -Snapshot $snapshotConfig -SnapshotName $datadisk.Name -ResourceGroupName "recovery-resource-group" -AsJob

To wait for job completion:

$jobs| Get-Job | Wait-Job |  Receive-Job |  Format-Table -AutoSize

These snapshots can then be used to create new virtual machines in Azure.

5. Clean up

After you’ve completed your testing activities and no longer require the VM, clean up by using the following cmdlet:

Retrieve the recovery virtual network:

$recoveryVnet = Get-AzureRmVirtualNetwork -Name "virtual-recovery-network-name" -ResourceGroupName "recovery-resource-group"

Retrieve the protected virtual machine:

$protectedVm = (Get-Asrfabric | Get-ASRProtectionContainer -FriendlyName "vmm_cloud_name" | Get-ASRReplicationProtectedItem -FriendlyName "myVm" ) | Where-Object {$_.ProtectionState -eq "Protected"}

Start the Clean up—i.e delete all resources that were created as part of the testfailover:

$job =  Start-AzureRmRecoveryServicesAsrTestFailoverCleanupJob -ReplicationProtectedItem $protectedVm

Similar to running the Test Failover, use Get-ASRJob cmdlet to get status of the job if you need it.


Azure Site Recovery works well for the use case of moving on-premise virtual machines to Azure. Thank you for reading and hopefully the workflow and sample PowerShell commands work for what you need to automate Azure Site Recovery. Questions or comments? Say hey at hello@levvel.io.

Celena Tan

Senior Consultant

Celena Tan is a Senior Consultant at Levvel.

Related Posts