oms-agent-deployment-mt-v2.ps1


<#PSScriptInfo
 
.VERSION 2.0
 
.GUID 5ee28a79-471c-4563-9664-a51245327fde
 
.AUTHOR Jozef_Hasaralejko@manulife.com
 
.COMPANYNAME Manulife
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>
 



<#
 
.DESCRIPTION
Modular script to deploy OMS agents in big environments
 
#>
 

Param()



#
# Modular script to deploy OMS agents in big environments
#
# - one or multiple subscription
# - skip Linux
# - show me planned action, but do not execute
# - multiple execution friendly
# - tons of logging
# - define deployment concurrency
#


#
# Initial environment cleanup
#

Remove-Variable * -ErrorAction SilentlyContinue

#
# Initialize variables
#

$classic_vms = @()
$arm_vms = @()
$cmd_queue = @()

# use 7 if you know what you are doing
# make sure you understand the implications

$i_know_what_am_doing = 0

# the variable controls Linux deployment

$skip_all_linux = "Skip-All-Linux" 
#$skip_all_linux = "Dont-Skip-All-Linux"

# max_vms controlls how many VM(s) would receive the OMS agent
# use this variable to control size of your deployment, good for testing
# stop deployment after you deploy max_vms

$max_vms = 9999             # deploy OMS on 9999 VM(s), change the number if you have more VM(s)
#$max_vms = 10 # deploy on 10 VM(s) and stop


<# EXAMPLE-1: Install OMS agent in a single subscription on just some of the machines
 
$process_subscriptions = @('subscription_name_here')
Select-AzureRmSubscription -SubscriptionName $process_subscriptions[0]
Select-AzureSubscription -SubscriptionName $process_subscriptions[0]
$arm_vms += Get-AzureRmVM -Name vm1_name_here -ResourceGroupName vm1_rg_here
$arm_vms += Get-AzureRmVM -Name vm2_name_here -ResourceGroupName vm2_rg_here
#>


<# EXAMPLE-2: Install OMS agent in a single subscription on just some of the machines
 
#$process_subscriptions = @('subscription_name_here')
#Select-AzureRmSubscription -SubscriptionName $process_subscriptions[0]
#Select-AzureSubscription -SubscriptionName $process_subscriptions[0]
#$classic_vms += Get-AzureVM -Name vm1_name_here -ServiceName vm1_rg_here
#>


<# EXAMPLE-3: Install OMS agent in a single subscription on all machines (arm and classic)
 
$process_subscriptions = @('subscription_name_here')
#>


# Define log files / what you see on the screen will go to a log file

$date = Get-Date -Format yyyyMMdd-hhmmss
$log_file = $PSScriptRoot + "\oms-agent-deployment-$date.out"
$log_file2 = $PSScriptRoot + "\oms-agent-deployment-hosts-$date.out"

# the script deploys OMS agent in concurrent fashion
# the variable defines maximum job concurrency

$max_jobs = 20

# the array describes which OMS workspace the subscription belongs
# we have way too many subscriptions and multiple OMS workspaces

$subsciption_oms = @{'subscription-1' = 'workspace-1';
                     'subscription-2' = 'workspace-1';
                     'subscription-3' = 'workspace-2';
                     'subscription-4' = 'workspace-2';
                     'subscription-5' = 'workspace-1';
                    }


$oms_config = @{'workspace-1' = `
                   @{'space_id' = 'workspace-1-id'; `
                     'space_key' = 'workspace-1-key';};
                'workspace-2' = `
                   @{'space_id' = 'workspace-2-id'; `
                     'space_key' = 'workspace-2-key';};
               } 

Function LOG($msg) {

    Write-Output $msg | Tee-Object -FilePath $log_file -Append

}

Function LOG2($msg) {

    $msg | Out-File -FilePath $log_file2 -Append

}

#
# Pre-execution validation
#

LOG "Using Log File: $log_file"
LOG ""

$context = Get-AzureRmContext

if( $context.Account -eq $null ) {
    LOG("")
    LOG("ERR: Please login into the environment first. Exiting...")
    exit(-1)
}

LOG "PLEASE VALIDATE INFORMATION BELOW" 
LOG "================================="
LOG ""


foreach($subscription in $process_subscriptions) {
    LOG "Subscription: $subscription"

    $oms = $subsciption_oms[$subscription]
    $oms_space = $oms_config[$oms]['space_id']
    $oms_key = $oms_config[$oms]['space_key']
    LOG " OMS portal: $oms"
    LOG " OMS space: $oms_space"
    LOG " OMS key: $oms_key"
    LOG ""
}

$answer = Read-Host -Prompt "Is all in order? Can I execute? [Y/N] "
if($answer -cne "Y") {
    LOG "I understand ... Exiting!!!"
    exit(-1)
}

#
# MAIN PROGRAM
#

foreach($subscription in $process_subscriptions) {

    Select-AzureRmSubscription -SubscriptionName $subscription
    Select-AzureSubscription -SubscriptionName $subscription

    LOG "Processing subscription: $subscription"

    $oms = $subsciption_oms[$subscription]
    $oms_space = $oms_config[$oms]['space_id']
    $oms_key = $oms_config[$oms]['space_key']

    if($classic_vms.Count -or $arm_vms.Count) {
        LOG "ADHOC processing ... user provided list of machines"
    } else {
        $classic_vms = Get-AzureVM -WarningAction SilentlyContinue
        $arm_vms = Get-AzureRmVM -WarningAction SilentlyContinue
    }

    LOG "Processing Classic VM(s)"
    foreach($vm in $classic_vms) {
        
        $status = $vm.Status
        if($status -ne "ReadyRole") {
            LOG "Skipping ... VM $status ... $($vm.name)"
            continue
        } elseif($vm.GuestAgentStatus.Status -ne "Ready") {
            LOG "Skipping ... VM Agent not ready ... $($vm.GuestAgentStatus.Status) ... $($vm.name)"
            continue
        }
        
        $osDisk = $vm | Get-AzureOSDisk
        $vmOSType = $osDisk.OS

        if($vmOSType -eq "Windows") {
            if(($vm | Get-AzureVMExtension).Where({$_.ExtensionName -match 'MicrosoftMonitoringAgent'})) {
                LOG "Skipping ... Extension already installed ... $($vm.name) ... $vmOSType ... $vmSku"
            } else {
                LOG "Queueing ... $($vm.name) ... $vmOSType"
                LOG2 "Classic, $subscription, $($vm.name), $($vm.ServiceName), $vmOSType"
                $cmd_queue += "Get-AzureVM -ServiceName $($vm.ServiceName) -name $($vm.name) | Set-AzureVMExtension ``
                                                    -Publisher 'Microsoft.EnterpriseCloud.Monitoring' ``
                                                    -ExtensionName 'MicrosoftMonitoringAgent' ``
                                                    -Version '1.*' ``
                                                    -PublicConfiguration ""{'workspaceId': '$oms_space'}"" ``
                                                    -PrivateConfiguration ""{'workspaceKey': '$oms_key' }"" ``
                                                    | Update-AzureVM -Verbose -OutVariable +output -ErrorVariable +output"

            }

        } elseif($vmOSType -eq "Linux" -and $i_know_what_am_doing -eq 7){
            if(($vm | Get-AzureVMExtension).Where({$_.ExtensionName -match 'OmsAgentForLinux'})) {
                LOG "Skipping ... Extension already installed ... $($vm.name) ... $vmOSType"
            } else {
                LOG "Queueing ... $($vm.name) ... $vmOSType"
                LOG2 "Classic, $subscription, $($vm.name), $($vm.ServiceName), $vmOSType"
                $cmd_queue += "Get-AzureVM -ServiceName $($vm.ServiceName) -name $($vm.name) | Set-AzureVMExtension ``
                                                    -Publisher 'Microsoft.EnterpriseCloud.Monitoring' ``
                                                    -ExtensionName 'OmsAgentForLinux' -Version '1.*' ``
                                                    -PublicConfiguration ""{'workspaceId': '$oms_space'}"" ``
                                                    -PrivateConfiguration ""{'workspaceKey': '$workspaceKey' }"" ``
                                                    | Update-AzureVM -Verbose -OutVariable +output -ErrorVariable +output"

            }

        } else {
            LOG "Skipping ... We do it next time ... $($vm.name) ... $vmOSType"
        }
    }

    LOG "Processing ARM VM(s)"
    foreach($vm in $arm_vms) {
        
        $vm_status = Get-AzureRmVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status -WarningAction SilentlyContinue
        $status = $vm_status.Statuses[1].DisplayStatus
        Try {
            $vm_agent_status = $vm_status.VMAgent.Statuses[0].DisplayStatus
        }
        Catch {
            $vm_agent_status = "NO IDEA!!!"
        }

        if($status -ne "VM running") {
            LOG "Skipping ... VM $status ... $($vm.name)"
            continue
        } elseif($vm_agent_status -ne "Ready") {
            LOG "Skipping ... VM Agent not ready ... $vm_agent_status ... $($vm.name)"
            continue
        }

        $vmOSType = $vm.StorageProfile.OsDisk.OsType
        $vmOffer = $vm.StorageProfile.ImageReference.Offer
        $vmSku = $vm.StorageProfile.ImageReference.Sku

        if($vmOSType -eq "Windows") {
            if(($vm.Extensions).Where({$_.Id -match 'MicrosoftMonitoringAgent'})) {
                LOG "Skipping ... Extension already installed ... $($vm.name) ... $vmOSType ... $vmSku"
            } else {
                LOG "Queueing ... $($vm.name) ... $vmOSType ... $vmSku"
                LOG2 "ARM, $subscription, $($vm.name), $($vm.ResourceGroupName), $vmOSType"
                $cmd_queue += "Set-AzureRmVMExtension -ResourceGroupName $($vm.ResourceGroupName) ``
                                                      -VMName $($vm.Name) ``
                                                      -Name 'MicrosoftMonitoringAgent' ``
                                                      -Publisher 'Microsoft.EnterpriseCloud.Monitoring' ``
                                                      -ExtensionType 'MicrosoftMonitoringAgent' ``
                                                      -TypeHandlerVersion '1.0' ``
                                                      -Location $($vm.Location) ``
                                                      -SettingString ""{'workspaceId': '$oms_space'}"" ``
                                                      -ProtectedSettingString ""{'workspaceKey': '$oms_key'}"" ``
                                                      -OutVariable +output -ErrorVariable +output"

            }

        } elseif($vmOSType -eq "Linux" -and $vmOffer -eq "RHEL" -and $skip_all_linux -ne "Skip-All-Linux"){
            if(($vm.Extensions).Where({$_.Id -match 'OmsAgentForLinux'})) {
                LOG "Skipping ... Extension already installed ... $($vm.name) ... $vmOSType ... $vmSku"
                
            } else {
                LOG "Queueing ... $($vm.name) ... $vmOSType ... $vmSku"
                LOG2 "ARM, $subscription, $($vm.name), $($vm.ResourceGroupName), $vmOSType"
                $cmd_queue += "Set-AzureRmVMExtension -ResourceGroupName $($vm.ResourceGroupName) ``
                                   -VMName $($vm.Name) ``
                                   -Name 'OmsAgentForLinux' ``
                                   -Publisher 'Microsoft.EnterpriseCloud.Monitoring' ``
                                   -ExtensionType 'OmsAgentForLinux' ``
                                   -TypeHandlerVersion '1.0' ``
                                   -Location $($vm.Location) ``
                                   -SettingString ""{'workspaceId': '$oms_space'}"" -ProtectedSettingString ""{'workspaceKey': '$oms_key'}"" ``
                                   -OutVariable +output -ErrorVariable +output"

            }

        } else {
            LOG "Skipping ... We do it next time ... $($vm.name) ... $vmOSType ... $vmSku"
        } 
            
    }

    LOG ""
    LOG "Queueing done - Executing"
    LOG "========================="

    $answer = Read-Host -Prompt "Is all in order? Can I execute? [Y/N] "
    if($answer -cne "Y") {
        LOG "I understand ... Exiting!!!"
        exit(-1)
    }

    # !!! testing no execution !!!
    #exit(0)

    Get-RSJob | Remove-RSJob

    $index = 1
    $jobs = @()

    foreach($task in $cmd_queue) {
        
        $jobs += $task | Start-RSJob -ScriptBlock {
            $output = "EXEC: $($_)`r`n"
            $res = Invoke-Expression $_
            return $output
        }
        $index += 1

        if($index -ge $max_vms) {
            break
        }

        while((Get-RSJob | where {$_.State -eq "Running"}).Count -ge $max_jobs) {
            Start-Sleep 1
            $completed = Get-RSJob | where {$_.State -eq "Competed"}
            if($completed) {
                $completed | Receive-RSJob | Tee-Object -FilePath $log_file -Append
                $completed | Remove-RSJob
            }
        }
    }
    $jobs | Wait-RSJob | Receive-RSJob | Tee-Object -FilePath $log_file -Append

    $classic_vms = @()
    $arm_vms = @()
    $cmd_queue = @()
}