Event Translator

The Event Translator can transform and enhance the data from Meridian events that other daemons generate. This feature enables better integration with external systems, based on data from sources internal and external to Meridian.

When an event is published on the event bus for which the event translator has configuration, the translator clones the event and changes the new event’s attributes (fields and parameters) as defined in the translator configuration. These transformations can come as a result of SQL queries, regular expression matches, and string literals that are then assigned to attributes of the new event.

The ${OPENNMS_HOME}/etc/translator-configuration.xml file contains elements and attributes that create and/or change the fields or parameters of one event and publish a new event with these changes.

Examples

Example 1: Associate traps with a node other than the SNMP manager

The following example associates an event with a different node. The typical case for this would be an SNMP manager that proxies informational messages from non-SNMP entities to Meridian via an SNMP trap. This lets you associate the traps with a node other than the SNMP manager (typically a passive node), making correlation much easier.

${OPENNMS_HOME}/etc/translator-configuration.xml
<?xml version="1.0" encoding="UTF-8"?>
<event-translator-configuration
xmlns="http://xmlns.opennms.org/xsd/translator-configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <translation>
    <event-translation-spec uei="uei.opennms.org/mib2opennms/tspEventPCRRepetitionError">
      <!-- Each event can have 1 or more mappings. -->
      <mappings>
        <mapping>
          <!-- This mapping uses the SQL value type to query the DB and change the nodeid of the new event -->
          <assignment type="field" name="nodeid">
            <value type="sql" result="select node.nodeid from node, ipInterface where node.nodeLabel=? and ipinterface.ipaddr=? and node.nodeId=ipinterface.nodeid and ipInterface.isManaged != 'D' and node.nodeType != 'D'" >
              <!-- These are sub value types that are used as parameters to the above sql as in JDBC speak -->
              <value type="parameter" name=".1.3.6.1.4.1.6768.6.2.2.5.0" matches="^([A-z]+) ([0-9]+).*" result="${1}-${2}" />
              <value type="constant" result="169.254.1.1" />
            </value>
          </assignment>
        </mapping>
      </mappings>
    </event-translation-spec>
  </translation>
</event-translator-configuration>

In this example, the nodeid will be replaced with the resulting nodeid from the SQL query when an event with the UEI uei.opennms.org/mib2opennms/tspEventPCRRepetitionError is received. The ? in the SQL query are populated with the values obtained from the nested value elements. The first of the nested value elements creates a result string from a regular expression match of the event parameter named .1.3.6.1.4.1.6768.6.2.2.5.0. This example uses the string DEMO 10 example server to represent the value of the parameter. The resulting match would produce DEMO-10. The second nested value is a constant and simply returns the value 169.254.1.1. These are assembled into the SQL query.

SELECT node.nodeid
FROM node, ipInterface
WHERE node.nodeLabel='DEMO-10'
    AND ipinterface.ipaddr='169.254.1.1'
    AND node.nodeId=ipinterface.nodeid
    AND ipInterface.isManaged != 'D'
    AND node.nodeType != 'D'

The value returned is then substituted for the existing nodeid into a new event cloned from the original event.

Example 2: Create a PassiveStatusKeeper update event

The PassiveStatusKeeper feature provides a way to track service outages for synthetic nodes that are not directly pollable. This example uses a trap from an Adtran TA 4303 to create a new passive status event.

To provide details for this device, we created SQL tables etlookup and ta4303 within the Meridian database to use as lookups.

${OPENNMS_HOME}/etc/translator-configuration.xml
<event-translation-spec uei="uei.opennms.org/vendor/adtran/traps/adta4303">
  <mappings>
    <mapping>
      <assignment type="field" name="uei">
        <value type="constant" result="uei.opennms.org/services/passiveServiceStatus" />(1)
      </assignment>
      <assignment type="field" name="passiveNodeLabel">
        <value type="constant" result="Switch - TA4303" />(2)
      </assignment>
      <assignment type="field" name="nodeid">
        <value type="constant" result="307" />(3)
      </assignment>
      <assignment type="parameter" name="passiveIpAddr">
        <value type="sql" result="select ta4303.ip from ta4303 where ta4303.slot=? and ta4303.port=? " >(4)
          <value type="parameter" name=".1.3.6.1.4.1.664.5.13.2.3.1.1" matches="^([0-9]+)" result="${1}" />
          <value type="parameter" name=".1.3.6.1.4.1.664.5.13.2.3.1.1" matches="^([0-9]+)" result="${2}" />
        </value>
      </assignment>
      <assignment type="parameter" name="portdesc">(5)
        <value type="sql" result="select ta4303.description from ta4303 where ta4303.slot=? and ta4303.port=? " >
          <value type="parameter" name=".1.3.6.1.4.1.664.5.13.2.3.1.1" matches="^([0-9]+)" result="${1}" />
          <value type="parameter" name=".1.3.6.1.4.1.664.5.13.2.3.1.1" matches="^([0-9]+)" result="${2}" />
        </value>
      </assignment>
      <assignment type="parameter" name="passiveServiceName">
        <value type="sql" result="select etlookup.output from etlookup where etlookup.variable='ta4303service' and etlookup.input=? " >(6)
          <value type="parameter" name="specific" matches="^([0-9]+)" result="${1}" />
        </value>
      </assignment>
      <assignment type="parameter" name="passiveStatus" >
        <value type="sql" result="select etlookup.output from etlookup where etlookup.variable='ta4303status' and etlookup.input=? " >(7)
          <value type="parameter" name="specific" matches="^([0-9]+)" result="${1}" />
        </value>
      </assignment>
    </mapping>
  </mappings>
</event-translation-spec>
1 The PassiveStatusKeeper looks for this specific UEI.
2 The passiveNodeLabel must match the label of the node. This example hard codes the label, but this can also be a lookup from the original event’s parameters.
3 In practice, you would not want to hard code the node ID on the event.
4 Since this is a passive node without a real IP address, this lookup uses the slot and port fields from the original event to query the database for a "dummy" IP assigned to the node.
5 Look up the port description from our SQL table. You can use this new parameter in the event and notifications as %parm[portdesc]%.
6 The name of the PassiveStatusMonitor service assigned to the node. If more than one passive service is assigned to the same interface, this field is used to trigger outages on a specific service.
7 Must be either "Up" or "Down" and is case sensitive.

Example 3: Include multiple category names in an event

If an SQL statement you want to read data with returns multiple rows, the event translator will give you only one result row for a new parameter. A workaround is to create an aggregate function in PostgreSQL that accumulates the output to one single row. A use case would be to include multiple categories' names into a nodeCategoryMembershipChanged event.

Create SQL aggregate
CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);
${OPENNMS_HOME}/etc/translator-configuration.xml
<event-translation-spec uei="uei.opennms.org/nodes/nodeCategoryMembershipChanged">
  <mappings>
    <mapping>
      <assignment name="uei" type="field" >
        <value type="constant" result="uei.opennms.org/test/nodeCategoryMembershipChanged" />
      </assignment>
      <assignment name="categories" type="parameter">
        <value type="sql" result="select array_accum(categoryname) from categories,category_node,node where node.nodeid=?::integer and node.nodeid=category_node.nodeid and category_node.categoryid=categories.categoryid;" >
          <value type="field" name="nodeid" matches=".*" result="${0}" />
        </value>
      </assignment>
    </mapping>
  </mappings>
</event-translation-spec>