Sorting bits into bytes...

Mass notification creator for vROps

The VMware Cloud Foundation plan and preparation workbook contains alert notifications which should be configured in vROps. There are close to 40 notifications that need to be configured. If you need to configure multiple vROps installations on multiple VCF instances then that task becomes time-consuming and error prone. So, I decided to write a script that will create the notifications rules.

First I created a dummy notification. I will use this notification to figure out how the JSON body needs to look like when creating the notification via API.

Output:

"rules": [

    {

      "id": "298c9047-c74e-8672-afbc-779881a545c1",

      "name": "Kabir_Test",

      "pluginId": "77b13163-55ab-49ac-8327-227282340a49",

      "templateId": "3a985327-01df-4eaa-9cbb-97497bb3485d",

      "alertControlStates": [

        "OPEN"

      ],

      "alertStatuses": [

        "NEW",

        "CANCELED"

      ],

      "criticalities": [

        "CRITICAL"

      ],

      "resourceKindFilters": [

        {

          "resourceKind": "VirtualMachine",

          "adapterKind": "VMWARE"

        }

      ],

      "resourceFilters": [],

      "alertTypeFilters": [],

      "alertDefinitionIdFilters": {

        "values": [

          "AlertDefinition-VMWARE-VMReadLatencySwapping"

        ]

      },

      "properties": [

        {

          "name": "maxNotify",

          "value": "2"

        },

        {

          "name": "delay",

          "value": "10"

        },

        {

          "name": "emailaddr",

          "value": "no@spam.now"

        },

        {

          "name": "resend",

          "value": "10"

        },

        {

          "name": "description",

          "value": "Virtual machine has memory contention caused by swap wait and high disk read latency"

        }

      ]

    },

 

Now I can analyze this from top to bottom.

Output Remark
“id”: “298c9047-c74e-8672-afbc-779881a545c1”, vROps will automatically create an ID.
“name”: “Kabir_Test”, This value which will be used as the name of the notification.

 

CSV: notification_name

“pluginId”: “77b13163-55ab-49ac-8327-227282340a49”, The script will lookup the outbound instance name as provided in the CSV file.

CSV: outbound_instance_name

“templateId”: “3a985327-01df-4eaa-9cbb-97497bb3485d”, The script will lookup the template name as provided in the CSV file.

CSV: payload_template_name

      “alertControlStates”: [

“OPEN”

],

I didn’t have to change this. This value specifies when the notification must be send. I want it whenever I have an open alert, which basically applies on all new alerts.
      “alertStatuses”: [

“NEW”,

“CANCELED”

],

This value also specifies when the notification must be send. In my case when the alert is new and canceled.

CSV: alert_status

      “criticalities”: [

“CRITICAL”

],

Defined the criticalities of the alerts.

CSV: criticalities

      “resourceKindFilters”: [

{

“resourceKind”: “VirtualMachine”,

“adapterKind”: “VMWARE”

}

],

“resourceFilters”: [],

“alertTypeFilters”: [],

“alertDefinitionIdFilters”: {

“values”: [

“AlertDefinition-VMWARE-VMReadLatencySwapping”

]

},

The value for resouceKind, adapterKind and AlertDefinition get auto populated by the script based on the alert definition.

CSV: alert_definition_name

      “properties”: [

{

“name”: “maxNotify”,

“value”: “2”

},

This value defines the number of notifications a single alerts can send.

CSV: max_notification

          “name”: “delay”,

“value”: “10”

},

This value defines the delay from the moment the alert is first seen until the moment the notification is send

CSV: delay_to_notify

          “name”: “emailaddr”,

“value”: “no@spam.now”

},

The recipient(s).

CSV: recipients

          “name”: “resend”,

“value”: “10”

},

The time between resending the same notification

CSV: notify_again

          “name”: “description”,

“value”: “Virtual machine has memory contention caused by swap wait and high disk read latency”

}

The email subject of the notification

CSV: notification_name

 

The notifications will be created based on the alert definitions, which should be already defined and enabled in vROps. The name of the alert definitions must match both in the CSV file and in vROps. If the script fails to create the notification, then double check the alert definition name.

A couple of things to keep in mind.

  • The SMTP outbound setting must already be configured in vROps
  • Some elements can have multiple values. For example, the alert_status can have the following values: “NEW, ACTIVE, UPDATED, CANCELED”. In order to process them correctly the CSV value looks like: NEW”, “CANCELED

So without the starting and tailing ”

So here is my “mass” notification creator:

<#
Author: Kabir Ali - info@kablog.nl
Scriptname: MNC (Mass Notify Creator)
Version: 1.0 (Tested)
Date: March 29 2022
Why: I need to create around 40 notifications per vROps installation

#>

<#
Example:
.\MNC.ps1 -InputCSV ".\mass_notify.csv" -vROpsServer "vROps.local.domain" -vROpsUser "admin" -vROpsPass "VMware1!"

#>

Param (
    
    [Parameter(Mandatory = $true)][string]$InputCSV,
    [Parameter(Mandatory = $true)][string]$vROpsServer,
    [Parameter(Mandatory = $true)][string]$vROpsUser,
    [Parameter(Mandatory = $true)][string]$vROpsPass
)

# Building vROPS API string & invoking REST API
$vROPsURL = "https://" + $vROPsServer + "/suite-api/api/"
$vROPsAuthURL = "https://" + $vROPsServer + "/suite-api/api/auth/token/acquire"
$Type = "application/json"
# Creating JSON for Auth Body
$AuthJSON =
"{
  ""username"": ""$vROPSUser"",
  ""password"": ""$vROPsPass""
}"

# Bypass SSL certificate verification
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
# Authenticating with API
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Try {
    $vROPSSessionResponse = Invoke-RestMethod -Method POST -Uri $vROPsAuthURL -Body $AuthJSON -ContentType $Type
}
Catch {
    $_.Exception.ToString()
    $error[0] | Format-List -Force
    Write-Output "Failed connecting to vROPs: $vROPsServer ... Exiting..."
}
# Extracting the session ID from the response
$vROPSSessionHeader = @{"X-vRealizeOps-API-use-unsupported"="true"
"Authorization"="vRealizeOpsToken "+$vROPSSessionResponse.'auth-token'.token
"Accept"="application/json"}

# Reset counters
$api_success = 0
$api_failed = 0

# Get all the alert definitions in vROps
$uri_alertdefs = $vROPsURL+"alertdefinitions?pageSize=2000"
[array]$all_alert_definitions = (Invoke-RestMethod -Method GET -Uri $uri_alertdefs -Headers $vROPSSessionHeader -ContentType $type).alertDefinitions
write-host "Number of alert definitions found :" $all_alert_definitions.count -ForegroundColor Green

# vROps alert url that will be used to create the notifications
$uri_notifications = $vROPsURL+"notifications/rules/"

# Read VCSV-file
$csv_input = Import-Csv D:\vcf\scripts\mass_notify_creator\mass_alert_list.csv -Delimiter ";"
write-host "Number of notifications to create:" $csv_input.count -ForegroundColor Green
sleep 1
foreach ($csv_alert in $csv_input){
    write-host "Processing:" $csv_alert.alert_definition_name -ForegroundColor Green
    # Find ID of the outbound instance configured
    $uri_alertplugins = $vROPsURL+"alertplugins"
    $all_alertplugin_ids = (Invoke-RestMethod -Method GET -Uri $uri_alertplugins -Headers $vROPSSessionHeader -ContentType $type).notificationPluginInstances
    $alertplugin_id = (($all_alertplugin_ids | where {$_.name -like $csv_alert.outbound_instance_name}).pluginId)

    # Find ID of the payload template
    $uri_template_id = "https://" + $vROPsServer + "/suite-api/internal/notifications/templates?name=" +$csv_alert.payload_template_name
    $templateId = (Invoke-RestMethod -Method GET -Uri $uri_template_id -Headers $vROPSSessionHeader -ContentType $type).notificationTemplates.templateId

    # Match alert definition for the correct adapterKind, resourceKind and ID
    $alert_definition_id = (($all_alert_definitions | where {$_.name -eq $csv_alert.alert_definition_name}).id)
    if ($alert_definition_id -eq $null) {
        write-host "Failed finding alert definition for:" $csv_alert.alert_definition_name -ForegroundColor Red
        continue
    }
    $alert_definition_adapterKindKey = (($all_alert_definitions | where {$_.name -eq $csv_alert.alert_definition_name}).adapterKindKey)
    $alert_definition_resourceKindKey = (($all_alert_definitions | where {$_.name -eq $csv_alert.alert_definition_name}).resourceKindKey)
    
    # Populate the JSON to send to vROps
    $jsonbody = '{
        "name": "'+$csv_alert.notification_name+'",
        "pluginId": "'+$alertplugin_id+'",
        "templateId": "'+$templateId+'",
        "alertControlStates": [
            "OPEN"
        ],
        "alertStatuses": [
            "'+$csv_alert.alert_status+'"
        ],
        "criticalities": [
            "'+$csv_alert.criticalities+'"
        ],
        "resourceKindFilters": [
            {
                "resourceKind": "'+$alert_definition_resourceKindKey+'",
                "adapterKind": "'+$alert_definition_adapterKindKey+'"
            }
        ],
        "resourceFilters": [],
        "alertTypeFilters": [],
        "alertDefinitionIdFilters": {
        "values": [
            "'+$alert_definition_id+'"
        ]
        },
        "properties": [
        {
            "name": "maxNotify",
            "value": "'+$csv_alert.max_notification+'"
        },
        {
            "name": "delay",
            "value": "'+$csv_alert.delay_to_notify+'"
        },
        {
            "name": "emailaddr",
            "value": "'+$csv_alert.recipients+'"
        },
        {
            "name": "resend",
            "value": "'+$csv_alert.notify_again+'"
        },
        {
            "name": "description",
            "value": "'+$csv_alert.alert_definition_name+'"
        }
      ]
    }'
    try {
    Invoke-RestMethod -Method POST -Uri $uri_notifications -Body $jsonbody -Headers $vROPSSessionHeader -ContentType $type
    $api_success = $api_success + 1
    }
    Catch {
        $_.Exception.ToString()
        $error[0] | Format-List -Force
        Write-host "Failed creating notification." $csv_alert.alert_definition_name -ForegroundColor Red
        $api_failed = $api_failed + 1
        Sleep 3
    }
    # Fix timeout issues
    sleep 1
    # Clear vars for next loop
    $alert_definition_id = $null
    $alert_definition_adapterKindKey = $null
    $alert_definition_resourceKindKey = $null
}
Write-Host "Out of" $csv_input.count "notifications" $api_success "got created successfully and" $api_failed "failed" -ForegroundColor Yellow
# Close session and done
Invoke-RestMethod -Method POST -Uri https://$vROPsServer/suite-api/api/auth/token/release -Headers $vROPSSessionHeader -ContentType $type

 

As an example you can use this CSV file: mass_notify.csv

Thank you for reading and I hope this helps!

Leave a Reply