diff --git a/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/BMC-CONTROLMEM-MIB.txt b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/BMC-CONTROLMEM-MIB.txt new file mode 100644 index 00000000..e4881d78 --- /dev/null +++ b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/BMC-CONTROLMEM-MIB.txt @@ -0,0 +1,461 @@ +BMC-CONTROLEM-MIB DEFINITIONS ::= BEGIN + +-- controlmemMIB MODULE-IDENTITY +-- LAST-UPDATED "200509251533Z" +-- ORGANIZATION "BMC Software" +-- CONTACT-INFO +-- "Contorl-M/Enterprise Manager development group at BMC Software" +-- DESCRIPTION +-- "Control-M/Enterprise Manager MIB" +-- REVISION "200509251533Z" +-- DESCRIPTION +-- "Initial version." +-- ::= { enterprises 1031 9 } + +IMPORTS + enterprises + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + TRAP-TYPE + FROM RFC-1215; + +--MIB module for Control-M/Enterprise Manager traps + +bmc OBJECT IDENTIFIER ::= { enterprises 1031 } + +controlmemMIB OBJECT IDENTIFIER ::= { bmc 9} + +--Control-M/Enterprise Manager Alert entity + +controlmAlert OBJECT IDENTIFIER ::= { controlmemMIB 1 } + +alertTrapUpdateType OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..1)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert update type + 'I' Insert - new alert + 'U' Update existing alert" + ::= { controlmAlert 1 } + + +alertTrapAlertId OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert id + Unique alert identifier" + ::= { controlmAlert 2 } + + +alertTrapControlM OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Control-M server name" + ::= { controlmAlert 3 } + + +alertTrapMemName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..30)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job member name" + ::= { controlmAlert 4 } + + +alertTrapOrderId OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..5)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job order id" + ::= { controlmAlert 5 } + + +alertTrapSeverity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..1)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert severity + 'R' - regular + 'U' - urgent + 'V' - very urgent" + ::= { controlmAlert 6 } + + +alertTrapTime OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..14)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert creation time (YYYYMMDDhhmmss)" + ::= { controlmAlert 8 } + + +alertTrapStatus OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..11)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert status (Not_Noticed, Noticed or Handled)" + ::= { controlmAlert 7 } + + +alertTrapNodeId OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..50)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job node id" + ::= { controlmAlert 16 } + + +alertTrapJobName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..64)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job name" + ::= { controlmAlert 15 } + + +alertTrapMessage OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert message" + ::= { controlmAlert 11 } + + +alertTrapApplication OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job application name" + ::= { controlmAlert 14 } + + +alertTrapGroup OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job sub application name" + ::= { controlmAlert 13 } + + +alertTrapType OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..1)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert type + B - BIM alert type + R or empty - regular alert type" + ::= { controlmAlert 17 } + + +alertTrapClosedFromEM OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..1)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Closed from Control-M/Enterprise Manager + Y - yes + N or empty - no" + ::= { controlmAlert 18 } + + +alertTrapTicketNumber OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..15)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Remedy ticket number" + ::= { controlmAlert 19 } + + +alertTrapRunCounter OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..11)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job's run counter" + ::= { controlmAlert 20 } + + +alertTrapUser OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..16)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Last updated by, user name" + ::= { controlmAlert 9 } + + +alertTrapUpdateTime OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..14)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Last time the alert was updated (YYYYMMDDhhmmss)" + ::= { controlmAlert 10 } + + +alertTrapOwner OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..8)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The user who runs the job" + ::= { controlmAlert 12 } + +alertTrapNotes OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..100)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert notes" + ::= { controlmAlert 21 } + + + +alertTrap TRAP-TYPE + ENTERPRISE controlmAlert + VARIABLES { + alertTrapUpdateType, + alertTrapAlertId, + alertTrapControlM, + alertTrapMemName, + alertTrapOrderId, + alertTrapSeverity, + alertTrapStatus, + alertTrapTime, + alertTrapUser, + alertTrapUpdateTime, + alertTrapMessage, + alertTrapOwner, + alertTrapGroup, + alertTrapApplication, + alertTrapJobName, + alertTrapNodeId, + alertTrapType, + alertTrapClosedFromEM, + alertTrapTicketNumber, + alertTrapRunCounter, + alertTrapNotes} + DESCRIPTION + "" + ::= 10 + + +controlmxAlert OBJECT IDENTIFIER ::= { controlmemMIB 2 } + +xAlertTrapCallType OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert update type + 'I' Insert - new alert + 'U' Update existing alert" + ::= { controlmxAlert 2 } + +xAlertTrapSerial OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Serial number" + ::= { controlmxAlert 3 } + +xAlertTrapCompType OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert id + Unique alert identifier" + ::= { controlmxAlert 4 } + + +xAlertTrapCompMachine OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Control-M server name" + ::= { controlmxAlert 5 } + + +xAlertTrapCompName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..32)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job member name" + ::= { controlmxAlert 6 } + + +xAlertTrapMessageId OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..20)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job order id" + ::= { controlmxAlert 7 } + + +xAlertTrapXSeverity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..1)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert severity + '0' - Undefined + '1' - Severe + '2' - Error + '3' - Warning" + ::= { controlmxAlert 8 } + + +xAlertTrapMessage OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert creation time (YYYYMMDDhhmmss)" + ::= { controlmxAlert 9 } + + +xAlertTrapXTime OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..14)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert status (Not_Noticed, Noticed or Handled)" + ::= { controlmxAlert 10 } + + +xAlertTrapXTimeOFLast OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..14)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job node id" + ::= { controlmxAlert 11 } + + +xAlertTrapCounter OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..64)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job name" + ::= { controlmxAlert 12 } + + +xAlertTrapStatus OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..11)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert message" + ::= { controlmxAlert 13 } + + +xAlertTrapNote OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job application name" + ::= { controlmxAlert 14 } + + +xAlertTrapKey1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job group name" + ::= { controlmxAlert 15 } + + +xAlertTrapKey2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Alert type + B - BIM alert type + R or empty - regular alert type" + ::= { controlmxAlert 16 } + + +xAlertTrapKey3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Closed from Control-M/Enterprise Manager + Y - yes + N or empty - no" + ::= { controlmxAlert 17 } + + +xAlertTrapKey4 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Remedy ticket number" + ::= { controlmxAlert 18 } + + +xAlertTrapKey5 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Job's run counter" + ::= { controlmxAlert 19 } + + +xAlertTrap TRAP-TYPE + ENTERPRISE controlmxAlert + VARIABLES { + xAlertTrapCallType, + xAlertTrapSerial, + xAlertTrapCompType, + xAlertTrapCompMachine, + xAlertTrapCompName, + xAlertTrapMessageId, + xAlertTrapXSeverity, + xAlertTrapMessage, + xAlertTrapXTime, + xAlertTrapXTimeOFLast, + xAlertTrapCounter, + xAlertTrapStatus, + xAlertTrapNote, + xAlertTrapKey1, + xAlertTrapKey2, + xAlertTrapKey3, + xAlertTrapKey4, + xAlertTrapKey5} + DESCRIPTION + "" + ::= 10 + + + +END \ No newline at end of file diff --git a/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/README.md b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/README.md new file mode 100644 index 00000000..f39ba5c1 --- /dev/null +++ b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/README.md @@ -0,0 +1,82 @@ +## Description + +This shell script ([**alerts_to_snmp**](alerts_to_snmp.sh)) sends Helix Control-M alerts data as SNMP traps. + +It parses the alert data coming from Helix Control-M (via the External Alerts service) and sends it as a SNMP v1 trap. This can be useful for integration with any application which supports incoming SNMP traps, and especially for customers migrating from Control-M which were using its SNMP notification capabilities. + +## Pre-requisites + +- Requires the **snmptrap** command line utility, which comes included in the "*net-snmp-utils*" package (see [net-snmp.org](http://www.net-snmp.org/)). As an example, to install it with "yum" package manager (any other required packages are installed too): + + ``` + # yum install net-snmp-utils + ``` + +- The provided [**MIB file**](BMC-CONTROLMEM-MIB.txt) (BMC-CONTROLMEM-MIB.txt) must be loaded in the SNMP destination host. + +## Instructions + +Before using the script, update the following variables: + +- **destination** : define the SNMP destination host(s). Use commas ( , ) as delimiter for multiple hosts, and colon ( : ) to use a specific port (default port is 162). Example: ``destination=myhost1,myhost2:2001,192.168.1.37`` + +- **alert_updates** : select whether you want to send or not updates of existing alerts (which happens when the alert "Status", "Urgency" or "Comment" are updated in Helix Control-M). + +## Additional information + +- The script uses the default alert field names for Helix Control-M. Therefore, it is NOT required to use a custom template to change the alert fields to their old names in Control-M (as detailed in ["Changing Field Names After Migrating from On-premises Control-M"](https://documents.bmc.com/supportu/API/Helix/en-US/Documentation/API_Services_RunServices_Alerts_Template_reference.htm#ChangingFieldNamesAfterMigratingfromOnpremisesControlM)). This means that Control-M users migrating to Helix Control-M can use the script without the need to modify the default alerts template. + +- The script sends all the alert fields received from Helix Control-M in the SNMP trap, including the "*notes*" field. Refer to the ["Alerts Template reference"](https://docs.bmc.com/docs/saas-api/alerts-template-reference-1144242602.html)) for more details. + +- This is an example of the "snmptrap" command line created by the script (showing only the first 2 alert fields - out of 21): + + ``` + snmptrap -v 1 -c public mysnmphost 1.3.6.1.4.1.1031.9.1 '' 6 10 '' 1.3.6.1.4.1.1031.9.1.1 s I 1.3.6.1.4.1.1031.9.1.2 s 25101 [...] + ``` + + - The SNMP v1 trap definition contains the `community` ("public"), the destination `host`, the `enterprise-OID` (as defined in the MIB file), the `agent` (IP address of the system generating the trap, empty to use the default value), the `generic-trap` number ("6" for traps defined in a custom MIB file), the `specific-trap` ("10" as defined in the MIB file for the TRAP-TYPE macro) and the `sysUpTime` of the generating application (empty to use the system generated value). + + - The "snmptrap" command line is then completed by adding all the alert fields, passed as the payload of the trap. Each of them include the specific `OID`, the `type` ("s" for string) and the `value`. + +- This is an example of all the data and details from the generated SNMP v1 trap: + + ``` + Message Type: Trap1Message + Time Received: 04/02/2024 17:52:49 + SNMP Version: One + Origin Address/Port: 192.168.1.37:50775 + Destination Address/Port: 192.168.1.37:162 + Community: public + Variable IIDs and Values: + 1.3.6.1.4.1.1031.9.1.1 (alertTrapUpdateType): I + 1.3.6.1.4.1.1031.9.1.2 (alertTrapAlertId): 25101 + 1.3.6.1.4.1.1031.9.1.3 (alertTrapControlM): IN01 + 1.3.6.1.4.1.1031.9.1.4 (alertTrapMemName): + 1.3.6.1.4.1.1031.9.1.5 (alertTrapOrderId): 0e4oe + 1.3.6.1.4.1.1031.9.1.6 (alertTrapSeverity): V + 1.3.6.1.4.1.1031.9.1.7 (alertTrapStatus): Not_Noticed + 1.3.6.1.4.1.1031.9.1.8 (alertTrapTime): 20240204165241 + 1.3.6.1.4.1.1031.9.1.9 (alertTrapUser): + 1.3.6.1.4.1.1031.9.1.10 (alertTrapUpdateTime): + 1.3.6.1.4.1.1031.9.1.11 (alertTrapMessage): Ended not OK + 1.3.6.1.4.1.1031.9.1.12 (alertTrapOwner): ctmagent + 1.3.6.1.4.1.1031.9.1.13 (alertTrapGroup): + 1.3.6.1.4.1.1031.9.1.14 (alertTrapApplication): dfe-demos + 1.3.6.1.4.1.1031.9.1.15 (alertTrapJobName): dfe-job-01 + 1.3.6.1.4.1.1031.9.1.16 (alertTrapNodeId): zzz-linux-agent-0 + 1.3.6.1.4.1.1031.9.1.17 (alertTrapType): R + 1.3.6.1.4.1.1031.9.1.18 (alertTrapClosedFromEM): + 1.3.6.1.4.1.1031.9.1.19 (alertTrapTicketNumber): + 1.3.6.1.4.1.1031.9.1.20 (alertTrapRunCounter): 00001 + 1.3.6.1.4.1.1031.9.1.21 (alertTrapNotes): + Agent IP:192.168.182.60 + Enterprise: 1.3.6.1.4.1.1031.9.1 + Generic Trap: 6 + Specific Trap: 10 + ``` + +## Versions + +| Date | Updated by | Changes | +| - | - | - | +| 2024-02-05 | David Fernández | First release | diff --git a/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/alerts_to_snmp.sh b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/alerts_to_snmp.sh new file mode 100644 index 00000000..352027c7 --- /dev/null +++ b/helix-control-m/2-external-monitoring-tools-examples/alerts-to-snmp/alerts_to_snmp.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# BMC Helix Control-M - External Alert Management service +# +# Sends Helix Control-M alerts as SNMP (v1) traps +# +# Notes : - Requires "snmptrap" (from "net-snmp-utils" package - see http://www.net-snmp.org) +# - The MIB file (BMC-CONTROLMEM-MIB) must be loaded in the SNMP destination host +# + +# SNMP destination host(s) +# Use commas (,) as delimiter for multiple hosts, and colon (:) to use a specific port (default 162) +# Example: myhost1,myhost2:2001,192.168.1.37 +destination=192.168.1.37 + +# SNMP base OID for Alerts (as defined in BMC-CONTROLMEM-MIB) - DO NOT MODIFY +base_oid=1.3.6.1.4.1.1031.9.1 + +# Send updates of existing alerts? (Y/N) +alert_updates="Y" + +# Declare array with all the alert field names +# Leave as is to use the default fields for HCTM alerts +field_names=("eventType" "id" "server" "fileName" "runId" "severity" "status" "time" "user" "updateTime" "message" "runAs" "subApplication" "application" "jobName" "host" "type" "closedByControlM" "ticketNumber" "runNo" "notes") + +# If alert updates are not needed, exit if "call_type" = "U" +if [ $alert_updates == "N" ] ; then + if [ $2 == "U" ] ; then exit 0 ; fi +fi + +# Parse fields names and values +num_fields=${#field_names[@]} +for i in ${!field_names[@]}; do + name1=${field_names[$i]} + name2=${field_names[$i+1]} + if [ $i != $((num_fields-1)) ] ; then + value=`echo $* | grep -oP "(?<=${name1}: ).*(?= ${name2}:)"` + else + # if last field, capture until EOL + value=`echo $* | grep -oP "(?<=${name1}: ).*(?)"` + fi + # Create the list of SNMP values to pass as parameters + # adding OID + type (s = string) + value + field_number=$((i+1)) + snmp_values=$snmp_values" "$base_oid.$field_number" s "\"$value\" +done + +# Send the SNMP trap(s) +for i in ${destination//,/ } ; do + bash -c "snmptrap -v 1 -c public $i $base_oid '' 6 10 '' $snmp_values" +done