Wednesday, February 24, 2016

OMS: Automated VM protection using Azure Recovery Services, Automation and Log Analytics

It’s me again, blogging from a random hotel room.
Last time we had a look into the combination of OMS and Azure in order to ensure availability of a Windows Server container hosted on a virtual machine in Azure.

(The templates and scripts will be published soon).

This time, I would like to focus on another scenario I think is very useful in the combination of Azure and OMS.

Recently, the GA of Azure Recovery Services were announced under the ARM APIs, which I talked about in this post and covered some considerations to be aware of -

In this blog post, I would like to cover a common scenario that we will run into every now and then when customers wants to protect virtual machines automatically to Azure in a programmatic way.


More and more customers are looking into how they can leverage the Azure cloud today, and one of the low-hanging fruits are services that can easily be plugged into existing services on-premises that will easily enable hybrid cloud scenarios, such as Business Continuity and Disaster Recovery. These services can be harnessed directly from Azure but provides you with a more comprehensive solution when used in conjunction with the entire OMS suite – that includes these services as well.
In a couple of minutes, you can have your services and applications running healthy as ever in an Azure region once this has been configured, in case of a failover.

In this article I will not go into design principals around the recovery processes (we’ll save that one for later), but rather cover a scenario that automatically will take care of some heavy lifting for you.

Use case

Many organizations have Hyper-V running as their primary hypervisor on-premises today, powering test, dev and production virtual machines. Since Azure has been able to democratize disaster recovery with their recovery services, people are looking into how to take advantage of this in a streamlined and efficient way. My goal here is to show how you can onboard and enable protection for newly created virtual machines on a Hyper-V host that has been registered to your Recovery Services Vault in Azure, by combining events that are logged into Log Analytics in OMS, monitored by a saved search that also has an associated alert with remediation attached to it.
This will invoke a Runbook created in Azure Automation that will enable replication on newly created virtual machines on that particular Hyper-V host and replicate to Azure as the recovery site.

Breakdown of the workflow

·       A VM gets created on the Hyper-V host. Regardless of how it’s created, this will log a specific informational event in the Hyper-V-VMMS-Admin log on the host, EventID 13002 that “A new virtual machine was created”

·       The OMS agent deployed on the host will fetch this and ingest this into Log Analytics

·       A search query is defined to monitor for this specific event on this specific host

·       An alert is created and associated with this query, so an e-mail will be sent when this occur

·       A runbook is created in Azure Automation that will search for newly discovered virtual machines on the registered Hyper-V host in the Azure Recovery Vault, look for VMs that isn’t protected and enable protection for them.

·       This runbook is associated with the alert and is part of the remediation process

Getting started

Before we can enable this scenario, we have to have some prerequisites in place:

·       OMS Workspace
·       Azure Automation account
·       OMS agent installed on the applicable Hyper-V hosts
·       Azure Recovery Vault in ARM
·       Runbooks

Assuming you have all of the above except the runbooks, I’ll cover the creation of the Azure Recovery Vault and the Runbook and stitch everything together.

Creating Azure Recovery Vault with Azure Resource Manager

The following PowerShell cmdlets will enable Azure Recovery Vault in your subscription and go through the creation of the Vault:

Note: You must install and register the agent on your Hyper-V host manually in this process, before proceeding with the rest of the script.

# Login to Azure and select Azure subscription

Login-AzureRmAccount -Credential (get-credential -Credential

Select-AzureRmSubscription –SubscriptionID $subID

# Check to see if your Azure subscription is enabled with ASR resource providers

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.RecoveryServices"

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.SiteRecovery"

# Register ASR Resource Provider

Register-AzureRmResourceProvider -ProviderNamespace "Microsoft.SiteRecovery"

Register-AzureRmProviderFeature -FeatureName "betaAccess" -ProviderNamespace "Microsoft.RecoveryServices"

Register-AzureRmResourceProvider -ProviderNamespace "Microsoft.RecoveryServices"

# Verify to see that the RP is registered correctly

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.RecoveryServices"

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.SiteRecovery"

# Create a new ASR Recovery Vault

mkdir -Path "c:\ASRDemo"

$RG = "DRGroup"
$Location = "west europe"
$vault = "HyperV"
$path = "c:\ASRDemo"

New-AzureRmResourceGroup -Name $rg -Location $location

$vault = New-AzureRmRecoveryServicesVault -Name $vault -ResourceGroupName $rg -Location $location

$FilePath = Get-AzureRmRecoveryServicesVaultSettingsFile -Vault $vault -Path $path | % FilePath # changed this to make sure we get the right filepath

Import-AzureRmSiteRecoveryVaultSettingsFile -Path $FilePath

# Create a new Hyper-V Site in the ASR vault

$sitename = "KNHVSite"

New-AzureRmSiteRecoverySite -Name $sitename

# Query the job


# Generate and download registration key for the site (Copy the downloaded key to the Hyper-V host. You'll need the key to register the Hyper-V host to the site)

$SiteIdentifier = Get-AzureRmSiteRecoverySite -Name $sitename | Select -ExpandProperty SiteIdentifier

Get-AzureRmRecoveryServicesVaultSettingsFile -Vault $vault -SiteIdentifier $SiteIdentifier -SiteFriendlyName $sitename -Path $Path

# Download and install the agent on the Hyper-V host(s) from this URL:

# Verify that the Hyper-V host is registered in ASR


# Create storage account with Geo-redundant storage

$storageaccountID = New-AzureRmStorageAccount -ResourceGroupName $RG -Name "knasrdemo01" -Type Standard_GRS -Location $Location

# Create a replication policy and associate it with the protection container

$ReplicationFrequencyInSeconds = "300"
$PolicyName = “DefaultPolicy”
$Recoverypoints = 1
$storageaccountID = Get-AzureRmStorageAccount -Name "knasrdemo01" -ResourceGroupName $RG | Select -ExpandProperty Id

$PolicyResult = New-AzureRmSiteRecoveryPolicy -Name $PolicyName -ReplicationProvider “HyperVReplicaAzure” -ReplicationFrequencyInSeconds $ReplicationFrequencyInSeconds  -RecoveryPoints $Recoverypoints -ApplicationConsistentSnapshotFrequencyInHours 1 -RecoveryAzureStorageAccountId $storageaccountID

# Get the protection container and start the association

$protectionContainer = Get-AzureRmSiteRecoveryProtectionContainer

$Policy = Get-AzureRmSiteRecoveryPolicy -FriendlyName $PolicyName
$associationJob  = Start-AzureRmSiteRecoveryPolicyAssociationJob -Policy $Policy -PrimaryProtectionContainer $protectionContainer

Once this has been created and the Hyper-V host(s) are registered to Azure, you should be able to see the virtual machines on that host by executing the following cmdlet:

Get-AzureRmSiteRecoveryProtectionEntity -ProtectionContainer $protectionContainer | select friendlyname


Preparing Azure Automation

There’s a few things we need in order to successfully create and run our runbook in Azure Automation

·       Assets
o   Credentials
o   Variables
o   Modules
·       Runbook

For the assets, you can easily add the required assets by using PowerShell.
In my case, I need the credentials to login to an Azure subscription, and I also need to store the subscription ID in a variable.
This can be achieved using the following cmdlets:

Creating Automation Variable
New-AzureRmAutomationVariable -Name SubscriptionID -Encrypted $false -Value $Subscription -ResourceGroupName $RGName -AutomationAccountName $AAName

Creating Automation Credential
New-AzureRmAutomationCredential -Name AutoAdmin -ResourceGroupName $RGName -AutomationAccountName $AAName -Value $cred 

Uploading Automation Module

Normally you would use a cmdlet for uploading PowerShell modules to Azure Automation as well, but since we just want to grab a few of them directly from the available PowerShell Gallery in the AA itself, we quickly head over to the portal and grab them from there.

Install the following modules in this specific order.
Note: it can take several minutes before the modules are installed and ready. You might find yourself a cup of coffee while doing this, as some of these modules has dependencies of each other and won’t import before the dependencies has completed the import process

Creating the Runbook

Now that the prereqs are in place, it is time to author the Runbook that will do the following:


# Runbook for enabling DR on unprotected Hyper-V VMs

$Admin = Get-AutomationPSCredential -Name AzureAdmin
$Subscription = Get-AutomationVariable -Name SubscriptionID

Login-AzureRmAccount -Credential $Admin

Select-AzureRmSubscription -SubscriptionId $Subscription

# Fetching some variables for this particular setup

$RG = "DRGroup"
$Location = "west europe"
$vault = "HyperV"
$sitename = "KNHVSite"
$vault = Get-AzureRmRecoveryServicesVault -Name $vault -ResourceGroupName $rg
$storageaccount = "knasrdemo01"

# Creating a temp directory to store the VaultSettingsFile

$tempFileName = $env:TEMP

$FilePath = Get-AzureRmRecoveryServicesVaultSettingsFile -Vault $vault -Path $tempFileName | % FilePath # changed this to make sure we get the right filepath

Import-AzureRmSiteRecoveryVaultSettingsFile -Path $FilePath

$SiteIdentifier = Get-AzureRmSiteRecoverySite -Name $sitename | Select -ExpandProperty SiteIdentifier

Get-AzureRmRecoveryServicesVaultSettingsFile -Vault $vault -SiteIdentifier $SiteIdentifier -SiteFriendlyName $sitename -Path $tempFileName

$protectionContainer = Get-AzureRmSiteRecoveryProtectionContainer

# Get Storage Account

$storageaccountID = Get-AzureRmStorageAccount -Name $storageaccount -ResourceGroupName $RG | Select -ExpandProperty Id

# Get Recovery Policy

$policy = Get-AzureRmSiteRecoveryPolicy

# Enabling VMs for protection

$protectionEntity = Get-AzureRmSiteRecoveryProtectionEntity -ProtectionContainer $protectionContainer | Where-Object {$_.FriendlyName -like "*asr*" -and $_.ProtectionStatus -eq "Unprotected"}

foreach ($entity in $protectionEntity)
        if ($protectionEntity.ProtectionStatus -eq "Unprotected")
            Write-Output "They aren't protected!"
            Set-AzureRmSiteRecoveryProtectionEntity -ProtectionEntity $entity -Policy $Policy -Protection Enable -RecoveryAzureStorageAccountId $storageaccountID -OS Windows -OSDiskName $protectionEntity.Disks[0].Name -Verbose
            Write-Output "They were protected already :-)"

If you want to use this in your environment, ensure you are changing the variables to meet your needs.

Assuming you already have the host registered to the Workspace, you should do the following steps to be able to get the information you are looking for to enable this scenario where you want to leverage the runbook to protect newly created VMs.

Adding logs to OMS

In the OMS workspace, Click on ‘Settings’

Navigate to ‘Data’ and click on ‘Windows Event Logs’

Add the following log that will contain the information about creation of virtual machines on the host

Ensure that Error, Warning and Information is selected

Note: OMS doesn’t care about what has already happened, so only new events in this log will appear in OMS.

Next, go back and drill into ‘Log Search’

I use the following search to pinpoint the specific EventID and the Hyper-V host

EventID=13002 host11 | Select Computer, Activity, TimeGenerated, Message, EventLog

I have saved the search and categorized it as ‘Hyper’V.

Now, I want to enable alerting on this search, so I click on the search and then on the ‘Alert’ button

Assign a name to the alert and specify when the query should run and when an alert should be generated.

I then specify the recipient of the alert and give it a name.

As a last step, I connect the alert with the newly created Runbook in Azure Automation and ensure that it will be executed by using an Azure worker and click save.

Creating a new VM to trigger the alert

Heading over to my Hyper-V host I created some new virtual machines.

Coffee time

Since OMS will use this search query every 15 mins, I had enough time to make myself some coffee while waiting for the e-mail to drop in my inbox


Once the search query detect a new event, the alert is triggered and an e-mail is fired away to my inbox.


This should invoke the associated runbook for remediation, and when I check into the Job view in Azure, I can see that it has successfully been executed and also the output that tells me that replication has now been enabled on the unprotected VMs.

Verifying the remediation

Using PowerShell, I can access my Recovery Vault and check to see which VMs are in the process of being protected in Azure by using the following cmdlet:

Get-AzureRmSiteRecoveryProtectionEntity -ProtectionContainer $protectionContainer | select FriendlyName, ProtectionStateDescription

The output shows that several machines are already protected while the newly created VM is in the process of doing an initial replication

FriendlyName ProtectionStateDescription       
------------ --------------------------       
ASRGEN2-04   Protected                        
ASRGEN2-02   Protected                        
ASRGEN2-01   Initial replication is in progress
ASRGEN2-03   Protected                        

Closing note

This was yet another blog post that shows some of the capabilities of combining OMS, Azure and Azure Services together.
Moving forward, I will focus more on some of these scenarios to show where we have some gaps today, and how you can overcome those gaps with a little effort in engineering.

By the end of the day, we can more or less achieve whatever we want as long as there’s an API for it, and that’s exactly what this blog post was showing.


Thursday, February 18, 2016

Azure and OMS – Better Together

Azure and OMS – Better Together

Recently, Microsoft announced an enhancement to both Azure and OMS where you can now simply enable the OMS extension for your virtual machines and they will start to report directly to the OMS Workspace associated with that subscription.

In this blog post, I will walk you through a real-world example on how we integrated OMS with Azure to ensure availability for some Windows Server Containers as part of a project.


We wanted to be able to rapidly test and deploy Windows Server containers to Azure using Azure Resource Manager templates. This would of course lead to development of one or more ARM templates, leveraging custom script extension to perform the heavy lifting within the virtual machine(s).
If you are familiar with container technology and have followed the investment from Microsoft in this area lately, you have probably heard of the Azure Container Service that now is in the public preview. This is an end-to-end solution that you can spin up in Azure using a very abstracted template that will instantiate around 23 resources for you.
If you want to achieve the same with Windows Server Containers today, you must rely on your own ARM skills to make this happen, as the current Container Service is Linux-only.

Container technology is an additional layer of abstraction that you can host on a virtual machine, and whatever you put inside a container today should either be considered as stateless, or you should have externalized the state through the application layer.
In our case we were using stateless containers that would go down in case the container host (the virtual machine) went down or had a reboot in Azure.

With the capabilities available in Microsoft OMS today, this should be a real good use case to combine resources in Azure and OMS to ensure that if the specific event occurred, the container should be running and respond to requests in minutes.

Understanding the requirements

Windows Container is a part of Windows Server 2016 Technical Preview 4 today, which is an available image for you to use in Azure.
Although there’s two supported runtimes for containers in 2016, only Windows Server – and not Hyper-V Containers is supported, as the latter requires support for nested virtualization.
Further, the image in Azure is running Server Core – which also applies to the Windows Server Containers you can host there. In other words, there’s no graphical user interface J

When you use the image in Azure, you will get a default – empty Windows Server Core Image to use for your container exploration. If you want to add applications, server roles and more to a container, you need to be aware that you should treat your containers as Lego blocks.

In our case, there was a need to test several specific Web applications hosted on a Windows Server Containers.
This meant we had to build something that would spin up a new container image, add the Web-Server Role to it, and commit the container to the library as an image so that we could use that image when deploying the web applications on top of it.

From an ARM template perspective, that would mean that we would add a Custom Script Extension resource and associate it with the virtual machine resource.

The Custom Script Extension would then point to a repository that contains the script (PowerShell script in this case). The PowerShell script would support several input parameters so that the entire ARM template would be reusable for others who would like to deploy something similar in the same fashion.
The script would spin up and create containers, and ensure that the correct firewall settings and NAT rules were applied from the container host to the container(s), so the container could be publicly accessible from the outside, following the rules that were defined in the Network Security Group in the template.

So far, so great

From a deployment perspective, this should be good.
Since containers aren’t the same as virtual machines as you can run on your local Hyper-V, you will not get anything that reminds you of Live Migration in the current build. So for us to increase uptime and availability for the containers on the container host, OMS became very interesting.

With the OMS extension, we could easily associate the virtual machine with an OMS Workspace to retrieve critical information about our containers runtime environment.

Not only do we get the insight of our environment in OMS, but we can also leverage the agent to invoke another powerful Azure/OMS resource – Azure Automation.

The goal was now to monitor the virtual machine for specific events, and if the Log Search query would return such result in a given timeframe, we would link that result to an alert we have created in OMS.

From there, we could do remediation through an Azure Automation Runbook.

Since this was an event that was going on inside the operating system of the virtual machine, a Hybrid Worker was considered as the best solution, so that we could trigger Azure Automation to invoke the runbook within the Hybrid Worker context.

Since the OMS agent is also the same agent you would use for Hybrid Worker to Azure Automation, we only had to tell the agent where to register post deployment.

In order to handle this, another Extension (OMS agent) was added to the ARM template, instructed to be deployed before the Custom Script Extension who now also would be responsible for registering the OMS agent with Azure automation.


Generally speaking, people seems to be confused when it comes to OMS at its capabilities.
Out of the box you get an extreme amount of intel that you can leverage to act upon and become predictive in the way you do management of your resources, regardless of cloud, operating system and location.

This is brought to through Log Analytics, which now is a resource within the Azure Resource Manager API. Together with Log Analytics, you can use Azure Automation (tight integration) as well as Azure Site Recovery and Azure Backup – both who will reach the UX experience in the new portal in the near future.

Once you have connected sources to OMS, the data harvest can begin.

You can decide what type of data you will gather, and you can take advantage of existing solutions from a ‘Solution Gallery’ that gives you pre-defined searches, views and insight based on the solution it represent. Examples here are:

·         Change tracking
·         Security and Audit
·         System Update & Assessment
·         SQL Assessment
·         AD Assessment
·         Malware Assessment

These are just a few examples, and by using OMS – which is Management as a Service delivered from the cloud, you can expect the cloud cadence to be applied to these solutions, reducing Time-To-Market and Time-To-Value which is very good for your business.

The Solution

Azure Resource Manager template

The example Azure Resource Manager Template I will describe here is constructed so that it currently takes input parameters for:

·         Containerhost (name of the virtual machine that will host the container(s)
·         Containername (name of the container to instantiate)
·         vmSize (SKU)
·         adminaccount (administrator account for the container host vm)
·         adminpwd (password for the admin account)
·         vNetName (name of the virtual network to be created)
·         OMSWorkspaceID (the ID for your OMS Workspace)
·         OMSWorkspaceKey (the primary key for your OMS Workspace)
·         AAEndpoint (the endpoint to your Azure Automation account)
·         Token (the primary key for your Azure Automation account)

The resources that will be deployed (in this specific order) are:

·         Storage accounts, public IP address, network security group and availabilityset are deployed in parallel
·         Virtual network will start deployment as soon as the network security group has completed
·         Virtual network interface will start deploying when virtual network and public IP address has completed
·         Virtual machine will start deployment once storage accounts and virtual network interface has completed
·         Virtual machine extension (OMS agent) will start deployment when the virtual machine has completed
·         Virtual machine extension (Custom Script Extension) will start deployment once the OMS extension has completed

·         Once everything has deployed, we should receive an output from the template that will give us the URL to the deployed container, available on port 80

OMS Search

For OMS to find relevant information, the following search was used:

Type=SecurityEvent EventID=4608 OR EventID=1100 "4608 - Windows is starting up." contp4 | Select Computer, Activity, TimeGenerated

This search is targeting the specific virtual machine running the containers.

From this search, an alert was created that was linked to a runbook I had created to start any containers that had State –eq “Off”.

The runbook should then be executed by a Hybrid Worker, which would be the container host itself.


To test and verify that things are working, we would trigger a restart of the virtual machine in Azure.

Once the virtual machine has started, we can see that the following event has been logged to our OMS Workspace

This also results in an e-mail notification according to our configuration, and should also generate a webhook to invoke the remediation runbook that’s created in Azure Automation

By hitting the ULR to my container again, I can verify it is responding on port 80 and is brought up again just as expected.

Hopefully you found this blog post useful to show some of the capabilities by leveraging Microsoft OMS together with Azure services.

In the next blog post, I'll cover the ideal setup for Microsoft OMS for Service Providers.

(The templates, scripts and examples will be live on my account as soon as they are polished a bit. Check in there later or follow me on twitter @KristiaNese to get the latest updates)