Cookbook
Subscribe

From OpenNMS

Revision as of 17:45, 4 March 2012 by Sob (Talk | contribs)

Jump to: navigation, search


Cookbook of device examples.

Contents

Foundry MLX

Checking temperature

There are two tables that contain the data we're interested in:

   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr  .1.3.6.1.4.1.1991.1.1.2.13.1.1.3
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue        .1.3.6.1.4.1.1991.1.1.2.13.1.1.4

Let's take a look at the data. snAgentTempSensorDescr:

   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.1.1 = STRING: "Line module 1, sensor 1 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.1.2 = STRING: "Line module 1, sensor 2 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.1.4 = STRING: "Line module 1, sensor 4 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.1.5 = STRING: "Line module 1, sensor 5 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.2.1 = STRING: "Line module 2, sensor 1 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.2.2 = STRING: "Line module 2, sensor 2 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.2.4 = STRING: "Line module 2, sensor 4 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.2.5 = STRING: "Line module 2, sensor 5 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.3.1 = STRING: "Line module 3, sensor 1 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.3.2 = STRING: "Line module 3, sensor 2 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.3.4 = STRING: "Line module 3, sensor 4 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.3.5 = STRING: "Line module 3, sensor 5 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.9.1 = STRING: "Standby management module temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.9.2 = STRING: "Standby management module temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.10.1 = STRING: "Active management module temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.10.2 = STRING: "Active management module temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.11.1 = STRING: "Switch Fabric module 1, sensor 1 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.12.1 = STRING: "Switch Fabric module 2, sensor 1 temperature"
   FOUNDRY-SN-AGENT-MIB::snAgentTempSensorDescr.13.1 = STRING: "Switch Fabric module 3, sensor 1 temperature"

N.B. The MIB states that for snAgentTempValue "Each unit is 0.5 degrees Celcius" so the values below are double their real value:

   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.1.1 = INTEGER: 78
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.1.2 = INTEGER: 96
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.1.4 = INTEGER: 68
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.1.5 = INTEGER: 89
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.2.1 = INTEGER: 99
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.2.2 = INTEGER: 114
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.2.4 = INTEGER: 0
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.2.5 = INTEGER: 0
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.3.1 = INTEGER: 65
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.3.2 = INTEGER: 97
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.3.4 = INTEGER: 0
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.3.5 = INTEGER: 0
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.9.1 = INTEGER: 100
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.9.2 = INTEGER: 100
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.10.1 = INTEGER: 78
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.10.2 = INTEGER: 105
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.11.1 = INTEGER: 56
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.12.1 = INTEGER: 62
   FOUNDRY-SN-AGENT-MIB::snAgentTempValue.13.1 = INTEGER: 72

So we're looking at two digit instance numbers such as 1.1, 1.2, 10.25 etc.

Having looked at how we got the required information from the switch, let's now examine how we put that into Open NMS.

Edit datacollection/foundry.xml and add the following above the group definitions:

 <resourceType name="snAgentTempSensorId" label="Foundry temperature sensors" resourceLabel="${snAgentTempSensorDescr}">
   <persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
   <storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
 </resourceType>

Now add the following in to the group 'foundry-sys':

   <mibObj oid=".1.3.6.1.4.1.1991.1.1.2.13.1.1.3"  instance="snAgentTempSensorId"  alias="snAgentTempSensorDescr"  type="string" />
   <mibObj oid=".1.3.6.1.4.1.1991.1.1.2.13.1.1.4"  instance="snAgentTempSensorId"  alias="snAgentTempValue"        type="integer" />

The first block is a representation of the instance number and the second are the two tables we're interested in.

Restarting collectd or ONMS should result in files created within the directory for a node of this equipment type:

   ls -la /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/*/

   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/2.4/snAgentTempValue.jrb
   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/2.4/strings.properties
   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/2.5/snAgentTempValue.jrb
   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/2.5/strings.properties
   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/3.1/snAgentTempValue.jrb
   /opt/opennms/share/rrd/snmp/376/snAgentTempSensorId/3.1/strings.properties

We're now collecting temperature data for all of the things listed within the tables.

The last thing to add is the graphing for the data. Create snmp-graph.properties.d/foundry-graph.properties as follows:

   # Reports list for Foundry devices.
   reports=foundry.temperature.sensor

   # Temperature sensor graphs
   report.foundry.temperature.sensor.name=Temperature (Foundry)
   report.foundry.temperature.sensor.columns=snAgentTempValue
   report.foundry.temperature.sensor.propertiesValues=snAgentTempSensorDescr
   report.foundry.temperature.sensor.type=snAgentTempSensorId
   report.foundry.temperature.sensor.command=--title="{snAgentTempSensorDescr}" \
    --vertical-label="Temperature" \
    DEF:temp1={rrd1}:snAgentTempValue:AVERAGE \
    DEF:mintemp1={rrd1}:snAgentTempValue:MIN \
    DEF:maxtemp1={rrd1}:snAgentTempValue:MAX \
    CDEF:val1=temp1,0.5,* \
    CDEF:minVal1=mintemp1,0.5,* \
    CDEF:maxVal1=maxtemp1,0.5,* \
    LINE2:val1#00ff00:"Temperature" \
    GPRINT:val1:AVERAGE:"Avg \\: %8.2lf %s" \
    GPRINT:val1:MIN:"Min \\: %8.2lf %s" \
    GPRINT:val1:MAX:"Max \\: %8.2lf %s\\n"

Checking Juniper power supply status.

This solution requires Open NMS 1.9.92 or greater due to it's use of JEXL in the threshold (that's the new(java.lang.Double( bit).

Overview of the information available

This is not as simple as it may at first appear, there are a number of lookups that need to be performed before the status of the power supplies can be queried. The examples below use a Juniper MX960.

Let's first identify what we mean by power supply. The jnxModuleGeneric portion of the MIB defines the following items:

   JUNIPER-CHASSIS-DEFINES-MIB::jnxFPC    .1.3.6.1.4.1.2636.1.1.3.2.12.1
   JUNIPER-CHASSIS-DEFINES-MIB::jnxCBD    .1.3.6.1.4.1.2636.1.1.3.2.12.2
   JUNIPER-CHASSIS-DEFINES-MIB::jnxHM     .1.3.6.1.4.1.2636.1.1.3.2.12.3
   JUNIPER-CHASSIS-DEFINES-MIB::jnxPower  .1.3.6.1.4.1.2636.1.1.3.2.12.4
   JUNIPER-CHASSIS-DEFINES-MIB::jnxFan    .1.3.6.1.4.1.2636.1.1.3.2.12.5
   JUNIPER-CHASSIS-DEFINES-MIB::jnxFPB    .1.3.6.1.4.1.2636.1.1.3.2.12.6
   JUNIPER-CHASSIS-DEFINES-MIB::jnxCIP    .1.3.6.1.4.1.2636.1.1.3.2.12.7

That's types of generic modules within a Juiper chassis.

Now that know that JUNIPER-CHASSIS-DEFINES-MIB::jnxPower (.1.3.6.1.4.1.2636.1.1.3.2.12.4) is a power supply can now examine the types of modules in the chassis by looking at the following OID:

   JUNIPER-MIB::jnxContentsType           .1.3.6.1.4.1.2636.3.1.8.1.5

This gives us:

   JUNIPER-MIB::jnxContentsType.1.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxMidplaneMX960
   JUNIPER-MIB::jnxContentsType.2.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.3.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.4.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.5.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.4.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.2.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.3.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.4.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.5.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.1.6.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.2.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.3.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.4.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.5.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.4.2.6.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFan
   JUNIPER-MIB::jnxContentsType.7.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFPC
   JUNIPER-MIB::jnxContentsType.7.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFPC
   JUNIPER-MIB::jnxContentsType.7.3.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFPC
   JUNIPER-MIB::jnxContentsType.8.1.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXQDpcCombo10X1GE
   JUNIPER-MIB::jnxContentsType.8.1.2.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXQDpcCombo10X1GE
   JUNIPER-MIB::jnxContentsType.8.1.3.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXQDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.1.4.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXQDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.2.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.2.2.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.2.3.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.2.4.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicXDpc1X10GE
   JUNIPER-MIB::jnxContentsType.8.3.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPicType2Oc48SFP
   JUNIPER-MIB::jnxContentsType.9.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxHM
   JUNIPER-MIB::jnxContentsType.9.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxHM
   JUNIPER-MIB::jnxContentsType.10.1.1.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxFPB
   JUNIPER-MIB::jnxContentsType.12.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxCBD
   JUNIPER-MIB::jnxContentsType.12.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxCBD
   JUNIPER-MIB::jnxContentsType.12.3.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxCBD

Examining the above output, we can see that power supplies are:

   JUNIPER-MIB::jnxContentsType.2.1.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.2.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.3.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.4.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower
   JUNIPER-MIB::jnxContentsType.2.5.0.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxPower

Thus power supplies can be said to have the following instance numbers:

   2.1.0.0
   2.2.0.0
   2.3.0.0
   2.4.0.0
   2.5.0.0

We can now examine the jnxOperatingState MIB:

   JUNIPER-MIB::jnxOperatingState         .1.3.6.1.4.1.2636.3.1.13.1.6

By appending the instance number:

   JUNIPER-MIB::jnxOperatingState.2.1.0.0 = INTEGER: running(2)
   JUNIPER-MIB::jnxOperatingState.2.2.0.0 = INTEGER: running(2)
   JUNIPER-MIB::jnxOperatingState.2.3.0.0 = INTEGER: running(2)
   JUNIPER-MIB::jnxOperatingState.2.4.0.0 = INTEGER: running(2)

Operating state is defined as on of the following by the MIB:

   1 - unknown
   2 - running
   3 - ready
   4 - reset
   5 - runningAtFullSpeed
   6 - down
   7 - standby

The simplistic approach at this point would be to check for each of these values using either one or four queries to verify the status however this would be a mistake. Consider for a moment a Juniper router with only two power supplies. The simple approach would mean a different monitoring setup for each router based on the number of power supplies installed.

Instead, what we want is to establish which of the installed contents is a power supply and then query for the status of all available power supplies. Having looked at how we got the required information from the router, let's now examine how we put that into Open NMS.

Open NMS Power Supply Monitoring (The smart way)

N.B. for simplicity, we're only looking at the power supply monitoring however additional data is also collected within the files defined here (fan and routing engine status) in pretty much the same way. Look at the files to see how that works.

First, we need to edit the datacollection-config.xml file and add the following SNMP collection definition:

 <snmp-collection name="juniper-status" snmpStorageFlag="select">
   <rrd step="300">
     <rra>RRA:AVERAGE:0.5:1:2016</rra>
     <rra>RRA:AVERAGE:0.5:12:1488</rra>
     <rra>RRA:AVERAGE:0.5:288:366</rra>
     <rra>RRA:MAX:0.5:288:366</rra>
     <rra>RRA:MIN:0.5:288:366</rra>
   </rrd>

   <resourceType name="jnxContentsContainerIndex" label="Juniper Container Index">
     <persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
     <storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
   </resourceType>

   <groups>
     <group name="juniper-status" ifType="ignore">
       <mibObj oid=".1.3.6.1.4.1.2636.3.1.8.1.5"  instance="jnxContentsContainerIndex" alias="jnxContentsType"   type="string" />
       <mibObj oid=".1.3.6.1.4.1.2636.3.1.13.1.5" instance="jnxContentsContainerIndex" alias="jnxOperatingDescr" type="string" />
       <mibObj oid=".1.3.6.1.4.1.2636.3.1.13.1.6" instance="jnxContentsContainerIndex" alias="jnxOperatingState" type="gauge" />
     </group>
   </groups>

   <systems>
     <systemDef name="Juniper Routers">
     <sysoidMask>.1.3.6.1.4.1.2636.1.</sysoidMask>
       <collect>
         <includeGroup>juniper-status</includeGroup>
       </collect>
     </systemDef>
   </systems>
 </snmp-collection>

This will collect data from the definitions within the juniper status group, but will not store the data. Now we need to configure the thresholds by editing thresholds.xml:

       <group name="juniper-status" rrdRepository = "/opt/opennms/share/rrd/snmp/">

         <expression type="low" 
                    expression="new('java.lang.Double',((jnxOperatingState == 2 || jnxOperatingState == 3 || jnxOperatingState == 7) ? 10 : 0))" 
                    ds-type="jnxContentsContainerIndex"
                    ds-label="jnxOperatingDescr"
                    value="1"
                    rearm="1"
                    trigger="1"
                    triggeredUEI="uei.opennms.org/thresholds/juniper/powerStatusFailure"
                    rearmedUEI="uei.opennms.org/thresholds/juniper/powerStatusNormal"
                    filterOperator="or">
             <resource-filter field="jnxContentsType">^\Q.1.3.6.1.4.1.2636.1.1.3.2.7.5.0\E$</resource-filter>
             <resource-filter field="jnxContentsType">^\Q.1.3.6.1.4.1.2636.1.1.3.2.12.4\E$</resource-filter>
             <resource-filter field="jnxContentsType">^\Q.1.3.6.1.4.1.2636.1.1.3.2.31.1.1.0\E$</resource-filter>
         </expression>
       </group>

Now that the threshold has been defined, we need to enable that within the threshold daemon in threshd-configuration.xml:

   <package name="juniper-status">
       <filter>IPADDR != '0.0.0.0' &amp; nodeSysOID LIKE '.1.3.6.1.4.1.2636.1.%'</filter>
       <include-range begin="::1" end="ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" />
       <include-range begin="1.1.1.1" end="254.254.254.254"/>

       <service name="SNMP" interval="300000" user-defined="false" status="on">
           <parameter key="thresholding-group" value="juniper-status"/>
       </service>
   </package>

All of the thresholding is configured, we need to define events for them to fire. Create events/juniper-status.xml:

<events>
 <event>
   <uei>uei.opennms.org/thresholds/juniper/powerStatusFailure</uei>
   <event-label>Juniper Threshold: powerStatusFailure</event-label>

   <descr>
     <p>
       Failure of '%parm[label]%' (%parm[instance]%) reported.
     </p>
   </descr>

   <logmsg dest='logndisplay'>
         Power supply labelled '%parm[label]%' in %nodelabel% is reporting failure.
   </logmsg>

   <severity>Minor</severity>
   <alarm-data reduction-key="%uei%:%nodeid%:%parm[instance]%" alarm-type="1" auto-clean="false" />
 </event>

 <event>
   <uei>uei.opennms.org/thresholds/juniper/powerStatusNormal</uei>
   <event-label>Juniper Threshold: powerStatusNormal</event-label>

   <descr>
     <p>
       Recovery of '%parm[label]%' (%parm[instance]%) reported.
     </p>
   </descr>

   <logmsg dest='logndisplay'>
         The power supply labelled '%parm[label]%' in %nodelabel% is reporting recovery.
   </logmsg>

   <severity>Cleared</severity>
   <alarm-data reduction-key="%uei%:%nodeid%:%parm[instance]%" alarm-type="2" auto-clean="false" />
 </event>
</events>

This file needs to be included within eventconf.xml:

 <event-file>events/juniper-status.xml</event-file>

This principle is used for monitoring power supplies, fans and routing engines.

Open NMS Power Supply Monitoring (The dumb way)

The smart way is the ideal approach, however it may be necessary to do things the dumb way for some things. Here's an alternative poller based approach.

Edit poller-configuration.xml and add the following into the monitoring package:

   <service name="Juniper MX PSU0" interval="300000" user-defined="false" status="on">
     <parameter key="retry" value="2"/>
     <parameter key="timeout" value="3000"/>
     <parameter key="port" value="161"/>
     <parameter key="oid" value=".1.3.6.1.4.1.2636.3.1.13.1.6.2.1.0.0"/>
     <parameter key="operator" value="="/>
     <parameter key="operand" value="2"/>
   </service>

   <service name="Juniper MX PSU1" interval="300000" user-defined="false" status="on">
     <parameter key="retry" value="2"/>
     <parameter key="timeout" value="3000"/>
     <parameter key="port" value="161"/>
     <parameter key="oid" value=".1.3.6.1.4.1.2636.3.1.13.1.6.2.2.0.0"/>
     <parameter key="operator" value="="/>
     <parameter key="operand" value="2"/>
   </service>

   <service name="Juniper MX PSU2" interval="300000" user-defined="false" status="on">
     <parameter key="retry" value="2"/>
     <parameter key="timeout" value="3000"/>
     <parameter key="port" value="161"/>
     <parameter key="oid" value=".1.3.6.1.4.1.2636.3.1.13.1.6.2.3.0.0"/>
     <parameter key="operator" value="="/>
     <parameter key="operand" value="2"/>
   </service>

   <service name="Juniper MX PSU3" interval="300000" user-defined="false" status="on">
     <parameter key="retry" value="2"/>
     <parameter key="timeout" value="3000"/>
     <parameter key="port" value="161"/>
     <parameter key="oid" value=".1.3.6.1.4.1.2636.3.1.13.1.6.2.4.0.0"/>
     <parameter key="operator" value="="/>
     <parameter key="operand" value="2"/>
   </service>

Add the following to the poller config but after the package definition:

 <monitor service="Juniper MX PSU0" class-name="org.opennms.netmgt.poller.monitors.SnmpMonitor"/>
 <monitor service="Juniper MX PSU1" class-name="org.opennms.netmgt.poller.monitors.SnmpMonitor"/>
 <monitor service="Juniper MX PSU2" class-name="org.opennms.netmgt.poller.monitors.SnmpMonitor"/>
 <monitor service="Juniper MX PSU3" class-name="org.opennms.netmgt.poller.monitors.SnmpMonitor"/>

Within the provisioning group, add the following detectors:

 Name   Juniper MX PSU0
 Class  org.opennms.netmgt.provision.detector.snmp.SnmpDetector

   Key    oid
   Value  .1.3.6.1.4.1.2636.3.1.13.1.6.2.1.0.0

 Name   Juniper MX PSU1
 Class  org.opennms.netmgt.provision.detector.snmp.SnmpDetector

   Key    oid
   Value  .1.3.6.1.4.1.2636.3.1.13.1.6.2.2.0.0

 Name   Juniper MX PSU2
 Class  org.opennms.netmgt.provision.detector.snmp.SnmpDetector

   Key    oid
   Value  .1.3.6.1.4.1.2636.3.1.13.1.6.2.3.0.0

 Name   Juniper MX PSU3
 Class  org.opennms.netmgt.provision.detector.snmp.SnmpDetector

   Key    oid
   Value  .1.3.6.1.4.1.2636.3.1.13.1.6.2.4.0.0

Once this is done, the power supplies will be detected where they're available but it's also possible to manually add them as a service attached to a node. In this case, we're not going to do things this way as it's not dynamic enough.