image_thumb8
In a previous post I talked about Operations Management Suite aka Log Analytics and how it can help you achieve a better understanding of what’s happening on your on-premise and cloud resources. In this blog post I will show you how to enroll your Azure VMs in OMS.

There are four ways you can enroll your Azure virtual machines in OMS:

PowerShell. (Saw that coming didn’t you?)
Installing OMS Agent at provisioning time using an ARM JSON Template.
Connecting the Azure VMs to OMS from the portal.
Manually installing the Windows / Linux agent.

Let’s tackle the first three scenarios, shall we?

1. To connect your Azure VMs to OMS, I created a very simple interactive script that can help you do this operation with ease. Make sure that you have the latest Azure PS cmdlets installed.

function script:Connect-AzureVMstoOMS 
{
  <#
      .SYNOPSIS
      This script will allow you to en-roll multiple or all VMs from your 
      Azure Subscription in Operations Management Suite

      .DESCRIPTION
      The purpose of this script is to ease the enrollment process of Azure VMs in in a specific 
      OMS account. 
      The script requires the user to already be logged in on his Azure subscription.
      The script works with Windows or Linux VMs
      If the currently selected Azure Subscription does not have an OMS account then the user has
      the option to provide a OMS WorkSpace ID and a WorkSpace Key.
  
      .PARAMETER SelectionMethod
      Mandatory Parameter -Selection Method is used to select which VMs
      you want be en-rolled in OMS or all of them. Mandatory Values = Multiple / All

      .PARAMETER OMSWorkSpaceID
      Optional Parameter -If an OMS account doesn't exist in the specified Azure Subscription 
      then a Workspace ID is required.

      .PARAMETER OMSWorkSpaceKey
      Optional Parameter -If an OMS account doesn't exist in the specified Azure Subscription 
      then a Workspace Key is required.

      .EXAMPLE
      Connect-AzureVMstoOM -SelectionMethod Multiple -OMSWorkSpaceID Value -OMSWorkSpaceKey Value
      The script is executed and prompts the user which VMs he should en-roll in a OMS account 
      which was provided
      
      Connect-AzureVMstoOM -SelectionMethod All
      The script will en-roll all the VMs from the selected Azure subscription in the OMS account 
      that's present in the subscription.

  #>



  param(
    [Parameter(Mandatory = $true,HelpMessage = 'The input for this parameter is Multiple or All. 
    The value  allows you to select a number of VMs that you want to enroll in OMS. 
    The value  will enroll all VMs Windows / Linux VMs in OMS')]
    [ValidateSet('Multiple','All')]
    [string]
    $SelectionMethod,
    
    [String]
    $OMSWorkSpaceID,
    
    [String]
    $OMSWorkSpaceKey
    
  )
           
  try
  {
    $Subscription = Get-AzureRmContext
  }
  catch
  {
    Write-Error -Message "No Azure Context was found.
    Please run Login-AzureRmAccount and select an Azure subscription"
  }


  
  if(($OMSWorkSpaceID -eq '') -and ($OMSWorkSpaceKey -eq ''))
  {   
    if ((Get-AzureRmOperationalInsightsWorkspace).Count -gt 1)
    {
      $OMSWorkSpace = Get-AzureRmOperationalInsightsWorkspace | Out-GridView -OutputMode Single
    }
    else
    {
      $OMSWorkSpace = Get-AzureRmOperationalInsightsWorkspace
    }
      
    if ($OMSWorkSpace -eq $null)
    {
      Write-Error -Message ('Cannot find an OMS account in the current subscription.
                            Subscription Name = {0} 
                            Subscription ID = {1}' `
                            -f $Subscription.Subscription.SubscriptionName, `
                               $Subscription.Subscription.SubscriptionID) `
                            -Category ObjectNotFound
      break
    }
    $OMSWorkSpaceID = $OMSWorkSpace.CustomerId
    $OMSWorkSpaceKey = (Get-AzureRmOperationalInsightsWorkspaceSharedKeys `
                        -ResourceGroupName $OMSWorkSpace.ResourceGroupName `
                        -Name $OMSWorkSpace.Name).PrimarySharedKey
  }
    
  
  switch ($SelectionMethod){
  
    'Multiple'
    {
      $VMs = Get-AzureRmVM | Out-GridView -OutputMode Multiple
    }
    'All'
    {
      $VMs = Get-AzureRmVM
    }
  }
  foreach ($VM in $VMs)
  {
    if ($VM.StorageProfile.OsDisk.OsType -eq 'Windows')
    {
      Write-Verbose -Message ('Installing Windows OMS Agent on {0}' -f $VM.Name)
      Set-AzureRmVMExtension -ResourceGroupName $VM.ResourceGroupName `
                             -VMName $VM.Name `
                             -Name 'MicrosoftMonitoringAgent' `
                             -Publisher 'Microsoft.EnterpriseCloud.Monitoring' `
                             -ExtensionType 'MicrosoftMonitoringAgent' `
                             -TypeHandlerVersion '1.0' `
                             -Location $VM.Location `
                             -SettingString "{'workspaceId': '$OMSWorkSpaceID'}" `
                             -ProtectedSettingString "{'workspaceKey': '$OMSWorkSpaceKey'}"
    }
    elseif ($VM.StorageProfile.OsDisk.OsType -eq 'Linux')
    {
      Write-Verbose -Message ('Installing Linux OMS Agent on {0}.Name' -f $VM.Name)
      Set-AzureRmVMExtension -ResourceGroupName $VM.ResourceGroupName `
                             -VMName $VM.Name -Name 'OmsAgentForLinux' `
                             -Publisher 'Microsoft.EnterpriseCloud.Monitoring' `
                             -ExtensionType 'OmsAgentForLinux' `
                             -TypeHandlerVersion '1.0' `
                             -Location $VM.Location `
                             -SettingString "{'workspaceId': '$OMSWorkSpaceID'}" `
                             -ProtectedSettingString "{'workspaceKey': '$OMSWorkSpaceKey'}"
    }
  }
}

2. To enroll a VM at provisioning time you need to deploy it using an ARM Template. I suggest using Visual Studio with the latest Azure SDK in order to ease the template creation process. With Visual Studio you have a graphical interface that allows you to add and nest resources as you please. Try it, you will love it 🙂

Here’s an example ARM template that handles both Linux and Windows scenarios:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspaceId": {
      "type": "string",
      "metadata": {
        "description": "Workspace ID"
      }
    },
    "workspaceKey": {
      "type": "securestring",
      "metadata": {
        "description": "Workspace Key"
      }
    },
    "vmName": {
      "type": "string",
      "metadata": {
        "description": "Virtual Machine name."
      }
    },

    "osType": {
      "type": "string",
      "allowedValues": [
        "Windows",
        "Linux"
      ],
      "metadata": {
        "description": "This is the OS that your VM will be running"
      }
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "User name for the Virtual Machine."
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Password for the Virtual Machine."
      }
    },
    "dnsLabelPrefix": {
      "type": "string",
      "metadata": {
        "description": "DNS Label for the Public IP. Must be lowercase. It should match with the following regular expression: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$ or it will raise an error."
      }
    }
  },
  "variables": {

    "computeApiVersion": "2016-03-30",
    "networkApiVersion": "2016-06-01",
    "storageApiVersion": "2016-01-01",

    "location": "[resourceGroup().location]",
    "storageAccountType": "Standard_LRS",
    "saVhdName": "[concat(parameters('vmName'), uniqueString(resourceGroup().id))]",

    "nicName": "[concat(parameters('vmName'), '.vmNIC')]",
    "addressPrefix": "10.0.0.0/16",
    "subnetName": "Subnet",
    "subnetPrefix": "10.0.0.0/24",
    "publicIPAddressName": "[concat(parameters('vmName'), '.PublicIP')]",
    "publicIPAddressType": "Dynamic",
    "vmSize": "Standard_D1_v2",
    "virtualNetworkName": "[concat(parameters('vmName'), '.VNET')]",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",

    "Windows": {
      "imagePublisher": "MicrosoftWindowsServer",
      "imageOffer": "WindowsServer",
      "imageVersion": "2016-Datacenter",
      "omsType": "MicrosoftMonitoringAgent"
    },
    "Linux": {
      "imagePublisher": "Canonical",
      "imageOffer": "UbuntuServer",
      "imageVersion": "16.04.0-LTS",
      "omsType": "OmsAgentForLinux"

    },
    "OMSSettings": "[variables(parameters('osType'))]"
  },
  "resources": [
    {
      "apiVersion": "[variables('storageApiVersion')]",
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('saVhdName')]",
      "location": "[variables('location')]",
      "sku": {
        "name": "[variables('storageAccountType')]"
      },
      "kind": "Storage",
      "properties": {}
    },
    {
      "apiVersion": "[variables('networkApiVersion')]",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[variables('publicIPAddressName')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "[parameters('dnsLabelPrefix')]"
        }
      }
    },
    {
      "apiVersion": "[variables('networkApiVersion')]",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[variables('virtualNetworkName')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "[variables('networkApiVersion')]",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('nicName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
        "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
              },
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    },
    {
      "apiVersion": "[variables('computeApiVersion')]",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[parameters('vmName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', variables('saVhdName'))]",
        "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[variables('vmSize')]"
        },
        "osProfile": {
          "computername": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "[variables('OMSSettings').imagePublisher]",
            "offer": "[variables('OMSSettings').imageOffer]",
            "sku": "[variables('OMSSettings').imageVersion]",
            "version": "latest"
          },
          "osDisk": {
            "name": "osdisk",
            "vhd": {
              "uri": "[concat('http://', variables('saVhdName'), '.blob.core.windows.net/vhds/', concat(concat( parameters('vmName') ), '-osdisk.vhd'))]"
            },
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": "true",
            "storageUri": "[concat('http://', variables('saVhdName'), '.blob.core.windows.net')]"
          }
        }
      },
      "resources": [
        {
          "name": "Microsoft.EnterpriseCloud.Monitoring",
          "type": "extensions",
          "location": "[resourceGroup().location]",
          "apiVersion": "2015-06-15",
          "dependsOn": [
            "[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
          ],
          "tags": {
            "displayName": "OMSEnroll"
          },
          "properties": {
            "publisher": "Microsoft.EnterpriseCloud.Monitoring",
            "type": "[variables('OMSSettings').omsType]",
            "typeHandlerVersion": "1.0",
            "autoUpgradeMinorVersion": true,
            "settings": {
              "workspaceId": "[parameters('workspaceId')]"
            },
            "protectedSettings": {
              "workspaceKey": "[parameters('workspaceKey')]"
            }
          }
        }
      ]
    }
  ]
  }

3. Enrolling VMs from the Azure Portal is very a very simple operation. You basically go to your Log Analytics resource located in your Azure subscription, select Virtual Machines and press connect on each virtual machine that shows the status “Not Connected”. The downside of doing it this way, is that if you have a lot of VMs that you want to enroll in your Log Analytics account, then it will take a lot of clicking.

oms-enroll3

Pin It on Pinterest