Last week we announced PowerShell support for recovery between two Hyper-V sites managed by Azure Site Recovery. The ASR cmdlets can be used to enable protection for virtual machines and performing recovery operations on virtual machines or recovery plan containing virtual machines. PowerShell support will allow administrator to do scripting against ASR service and also enable hosting service providers to extend their Self-Service portal to offer disaster recovery.
PowerShell support for ASR is shipped as part of Azure PowerShell and available with the Azure PowerShell October 2014 release. If you are already using Azure PowerShell you will need to upgrade to version 0.8.10 or later. Once you have setup and configured Azure PowerShell you will be able to view list all the available Azure Site Recovery cmdlets.
Setup the ASR Vault context
To get started with the Azure Site Recovery cmdlets you will need to setup the PowerShell runspace context with your ASR vault info. To setup you will need to download the Registration key file from Azure portal which is also used during setup and registration of SCVMM to your vault. Once context is setup rest of the cmdlets get executed within the context that has been setup.
List registered SCVMM servers
Once a SCVMM server is setup and registered with Azure Site Recovery, they can be viewed using Get-AzureSiteRecoveryServer cmdlet. The cmdlet outputs communication heartbeat and provider version along with server information enabling the server health monitoring in view of ASR.
List SCVMM clouds
Azure Site Recovery uses SCVMM clouds to do the scale management of the virtual machines. After the configuration at the SCVMM , information of SCVMM clouds discovered by ASR can be viewed using Get-AzureSiteRecoveryProtectionContainer. You can use either SCVMM cloud name or SCVMM cloud ID to filter the required cloud.
List Virtual Machines
The virtual machines can be viewed in the context of the Protection Container. The information of the SCVMM virtual machine discovered by ASR can be viewed using Get-AzureSiteRecoveryProtectionEntity. Similar to Protection Container one can filter the protection entity using SCVMM VMID or Virtual Machine name.
Protection of the Virtual Machines
Protection entity list returns both protected and unprotected virtual machines. Protection management can be performed on the protection entity using Set-AzureSiteRecoveryProtectionEntity. This is an asynchronous operation which returns an Azure Site Recovery Job. The job status can be further tracked to completion using Get-AzureSiteRecoveryJobGet-AzureSiteRecoveryJob.
A simple sample script snippet for the same is below:
param ( [parameter(Mandatory=$TRUE, HelpMessage="SCVMM Cloud Name")] [ValidateNotNullOrEmpty()] [string] $ProtectedContainerName, [parameter(Mandatory=$TRUE, HelpMessage="List of VM names in the SCVMM cloud")] [ValidateNotNullOrEmpty()] [string[]] $VMList, [parameter(Mandatory=$TRUE, HelpMessage="Protection State")] [ValidateNotNullOrEmpty()] [ValidateSet('ENABLE','DISABLE')] [string] $ProtectionState ) $ProtectedContainers = Get-AzureSiteRecoveryProtectionContainer | %{ $_.Name } if(!$ProtectedContainers.Contains($ProtectedContainerName)) { Write-Error "PROTECTED CONTAINER $CloudName NOT FOUND IN ASR" return; } $ASRProtectedContainer = Get-AzureSiteRecoveryProtectionContainer -Name $ProtectedContainerName Write-Output "ProtectedContainer " $ASRProtectedContainer $JobsList = $VMList | %{ Write-Host "Starting $ProtectionState Protections on $_"; Get-AzureSiteRecoveryProtectionEntity -Name $_ -ProtectionContainer $ASRProtectedContainer | Set-AzureSiteRecoveryProtectionEntity -Protection $ProtectionState -WaitForCompletion } $hasFailed = $FALSE foreach($Job in $JobsList) { $JobDetails = Get-AzureSiteRecoveryJob -Job $Job if($JobDetails.Errors.Count -ne 0) { $hasFailed = $TRUE Write-Host "JobID $Job.Id Failed" foreach($JobError in $JobDetails.Errors) { Write-Host $JobError.ServiceErrorDetails Write-Host $JobError.ProviderErrorDetails Write-Host $JobError } } } Write-Host "PROPERTIES AFTER $ProtectionState DR OPERATION" $VMList | %{ Get-AzureSiteRecoveryProtectionEntity -Name $_ -ProtectionContainer $ASRProtectedContainer } if(!$hasFailed) { Write-Host "ENABLE DR OF ALL VMs COMPLETED SUCCESSFULLY" }
Creation and management of Recovery Plan
After you’ve enabled protection for virtual machines you can create recovery plans. A recovery plan groups virtual machines together for the purposes of failover and recovery, and it specifies the order in which groups of virtual machines should fail over. Azure Site Recovery cmdlets allows users to download the exiting recovery plan created on Azure portal in form of XML file. The recovery plan XML file can be leveraged for creation of new recovery plan or updating of an existing recovery plan.
The recovery plan management cmdlets are listed as below:
A sample XML for the recovery Plan will look like below:
Failover
Azure Site Recovery supports 3 types of failovers – Test, Planned and Unplanned. All the failover operations are supported on both individual Virtual Machines and Recovery Plans. These capabilities are now available in PowerShell cmdlets as well. As ASR failovers are asynchronous operations, cmdlets execution of these will return an Azure Site Recovery Job in response. The job status can be further tracked to completion using Get-AzureSiteRecoveryJob.
A simple sample script snippet for the same is below:
param ( [parameter(Mandatory=$FALSE, HelpMessage="Name of the RP")] [ValidateNotNullOrEmpty()] [string] $RPName, [parameter(Mandatory=$TRUE, HelpMessage="Failover Type")] [ValidateNotNullOrEmpty()] [ValidateSet('PLANNED','UNPLANNED', 'TEST')] [string] $FailoverType, [parameter(Mandatory=$TRUE, HelpMessage="Failover direction")] [ValidateNotNullOrEmpty()] [ValidateSet('PrimaryToRecovery','RecoveryToPrimary')] [string] $FailoverDirection, [parameter(Mandatory=$TRUE, HelpMessage="Should do commit on the RP after failover")] [ValidateNotNullOrEmpty()] [bool] $ShouldCommit, [parameter(Mandatory=$TRUE, HelpMessage="Should do reverse replicate on the RP after commit")] [ValidateNotNullOrEmpty()] [bool] $ShouldReverseReplicate ) ## ## This routine checks for error in jobs. ## function WaitForJobCompletionAndCheck-JobErrors([string] $JobId) { $IsCompleted = $false while(!$IsCompleted) { $Job = Get-AzureSiteRecoveryJob -Id $JobId if($Job.State -eq "Succeeded") { $IsCompleted = $true Write-Output "Job with Id $JobId executed successfully." return } if($Job.State -eq "Failed") { $IsCompleted = $true; Write-Output "The Job Id $JobId has failed in execution" } if($Job.State -eq "Suspended" ) { Resume-AzureSiteRecoveryJob -Job $Job } else { Write-Output "The job $JobID is in progress" Start-Sleep -s 15 } } $hasFailed = $false $JobDetails = Get-AzureSiteRecoveryJob -Id $JobId if($JobDetails.Errors.Count -ne 0) { $hasFailed = $true Write-Error "JobID $JobId Failed" foreach($JobError in $JobDetails.Errors) { Write-Error $JobError.ServiceErrorDetails Write-Error $JobError.ProviderErrorDetails } } } $RecoveryPlans = Get-AzureSiteRecoveryRecoveryPlan | %{ $_.Name } if(!$RecoveryPlans.Contains($RPName)) { Write-Error "RECOVERY PLAN $RPName NOT FOUND IN ASR" return; } $RecoveryPlanObject = Get-AzureSiteRecoveryRecoveryPlan -Name $RPName Write-Output "RECOVERY PLAN DETAILS : " Write-Output $RecoveryPlanObject Write-Output "Starting RP $FailoverType Failover of $RPName :"; if($FailoverType.ToUpper() -eq "PLANNED") { $Job = Start-AzureSiteRecoveryPlannedFailoverJob -RecoveryPlan $RecoveryPlanObject -Direction $FailoverDirection } elseif($FailoverType.ToUpper() -eq "UNPLANNED") { $Job = Start-AzureSiteRecoveryUnplannedFailoverJob -RecoveryPlan $RecoveryPlanObject -Direction $FailoverDirection } elseif($FailoverType.ToUpper() -eq "TEST") { $Job = Start-AzureSiteRecoveryTestFailoverJob -RecoveryPlan $RecoveryPlanObject -Direction $FailoverDirection } else { Write-Error "Invalid RP Failover Type - $FailoverType" } WaitForJobCompletionAndCheck-JobErrors $Job.ID if($ShouldCommit) { Write-Output "Starting RP Commit Failover for $RPName"; $RecoveryPlanObject = Get-AzureSiteRecoveryRecoveryPlan -Name $RPName Write-Output $RecoveryPlanObject $JobsList = Start-AzureSiteRecoveryCommitFailoverJob -RecoveryPlan $RecoveryPlanObject WaitForJobCompletionAndCheck-JobErrors $JobsList.ID } if($ShouldReverseReplicate) { Write-Output "Starting RP Reverse Replication for $RPName"; $RecoveryPlanObject = Get-AzureSiteRecoveryRecoveryPlan -Name $RPName Write-Output $RecoveryPlanObject $JobsList = Update-AzureSiteRecoveryProtectionDirection -RecoveryPlan $RecoveryPlanObject -Direction $FailoverDirection WaitForJobCompletionAndCheck-JobErrors $JobsList.ID } $RecoveryPlanObject = Get-AzureSiteRecoveryRecoveryPlan -Name $RPName Write-Output $RecoveryPlanObject