SNMP Asset Provisioning Adapter

From OpenNMS
Jump to navigation Jump to search

Summary

OpenNMS can collect SNMP values and use them to populate asset records for systems that you are managing. This can be very useful for automatically populating asset fields in a large number of managed systems. Depending on the SNMP MIBs that your devices support, you could either fill in some of the existing asset fields (manufacturer, vendor, modelnumber, serialnumber, etc.) or construct a custom-formatted message for the longer comment field.

Configuration

To start using the SNMP asset adapter, you must install the opennms-snmp-asset-provisioning-adapter-[version].jar into OpenNMS's lib directory.

apt-get install opennms-plugin-provisioning-snmp-asset

After you do that, it is just a matter of defining the fields in the snmp-asset-adapter-configuration.xml configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<snmp-asset-adapter-configuration>
  <package name="ciscoWireless">
    <!-- A Cisco wireless sysoid, for example purposes only :) -->
    <sysoid>.1.3.6.1.4.1.9.1.379</sysoid>
    <assetField name="region" formatString="${gsmCountry}">
      <mibObjs>
        <!-- A Cisco 3G WAN adapter OID -->
        <mibObj oid=".1.3.6.1.4.1.9.9.661.1.3.2.1.8" alias="gsmCountry"/>
      </mibObjs>
    </assetField>
  </package>
  <package name="Cisco">
	<sysoidMask>.1.3.6.1.4.1.9.</sysoidMask>
        <assetField name="ram" formatString="${processorRam}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.4.1.9.3.6.6.0" alias="processorRam"/>
                </mibObjs>
        </assetField>
  </package>
</snmp-asset-adapter-configuration>

In this configuration example, every node whose sysoid equals .1.3.6.1.4.1.9.1.379 will be matched by the "ciscoWireless" package. This package is configured to set the value of the region asset field. The value that is set is defined by a formatted string. Tokens in the string using the ${token} syntax will be replaced by values that are defined by the list of mibObj parameters.

In this example, if an SNMP get of the OID value .1.3.6.1.4.1.9.9.661.1.3.2.1.8 returns something like "UK", then the "region" field in the asset database will end up being set to "UK" since there is just a single token in the formatting string.

It's that simple! You may want to snmpwalk your target nodes and see if there are any interesting identifiers or string values that you would like to see in an asset field first. Then just define them under a package that matches based on sysoid and you will be set to start collecting data.

Note: You may specify any number of <sysoid> tags, as well as <sysoidMask> tags.

Asset Field Names

Here is a list of all asset field names that can be populated. The names are case-sensitive.

  • additionalhardware
  • address1
  • address2
  • admin
  • assetNumber
  • autoenable
  • building
  • category
  • circuitId
  • city
  • comment
  • connection
  • cpu
  • dateInstalled
  • department
  • description
  • displayCategory
  • division
  • enable
  • floor
  • hdd1
  • hdd2
  • hdd3
  • hdd4
  • hdd5
  • hdd6
  • inputpower
  • lastModifiedBy
  • lastModifiedDate
  • lease
  • leaseExpires
  • maintcontract
  • maintContractExpiration
  • maintContractNumber
  • managedObjectInstance
  • managedObjectType
  • manufacturer
  • modelNumber
  • node
  • notifyCategory
  • numpowersupplies
  • operatingSystem
  • password
  • pollerCategory
  • port
  • rack
  • rackunitheight
  • ram
  • region
  • room
  • serialNumber
  • slot
  • snmpcommunity
  • state
  • storagectrl
  • supportPhone
  • thresholdCategory
  • username
  • vendor
  • vendorAssetNumber
  • vendorFax
  • vendorPhone
  • zip

Operation

The SNMP asset provisioning adapter is invoked every time a node is added or updated by provisiond. With the default provisiond configuration, the update will take place once every 24 hours.

You can reload the provisiond SnmpAssetProvisioningAdapter with this command (or just restart OpenNMS) /usr/share/opennms/bin# ./send-event.pl uei.opennms.org/internal/reloadDaemonConfig --parm 'daemonName Provisiond.SnmpAssetProvisioningAdapter'

IMPORT the provisioning requisition (use the web UI, go to Admin->Manage Provisioning Requistions link and click the Synchronize button.) Note, by default the SnmpAssetProvisionAdapter runs 5 minutes "after" a Provisiond nodeScanCompleted is sent (that is when your provisioning import is done.) Watch the log entries in /logs/daemon/provisiond.log. You will need to set the log level in log4j2.xml (log4j.properties prior OpenNMS 14) to DEBUG for provisiond to see the Adapters messages. Look for the import requisition is done (nodeScanCompleted). The asset adapter indicates it will run in 300 seconds.

Troubleshooting

In log4j2.xml ((log4j.properties prior OpenNMS 14), increase the log level to DEBUG for provisiond. Look for messages from SnmpAssetProvisioningAdapter.

Bugs Addressed By This Feature

Bug 2194: Auto assign asset columns

Bug 3384: Display collected info on Node page?

Bug 3537: Automatically populating asset fields

Use Cases

Cisco Hardware Inventory

We had a need to produce a report to determine IOS versions for upgrade planning. Relevant data needed was at least a model number, IOS version, RAM and Flash memory.

Collecting this data and storing as a useful database field is somewhat of an art and highly custom to your operation. Things like possible index values and the inconsistency that different Cisco hardware uses to store values (if at all) come into play and require a lot of work to ensure data is found.

The work put into digging data out of MIBs pays off when the Jasper Report phase begins.

Here is the start of a provisioning adapter config used. Flash memory gets the hdd1 column for storage.

<?xml version="1.0" encoding="UTF-8"?>
<snmp-asset-adapter-configuration>
  <package name="Cisco">
        <sysoidMask>.1.3.6.1.4.1.9.</sysoidMask>
        <assetField name="description" formatString="${entPhysicalDescr}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.2.1" alias="entPhysicalDescr"/>
                </mibObjs>
        </assetField>
        <assetField name="manufacturer" formatString="${entPhysicalMfgName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.12.1" alias="entPhysicalMfgName"/>
                </mibObjs>
        </assetField>
        <assetField name="serialNumber" formatString="${entPhysicalSerialNum}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.11.1" alias="entPhysicalSerialNum"/>
                </mibObjs>
        </assetField>
        <assetField name="modelNumber" formatString="${entPhysicalModelName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.13.1" alias="entPhysicalModelName"/>
                </mibObjs>
        </assetField>
        <assetField name="ram" formatString="${processorRam}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.4.1.9.3.6.6.0" alias="processorRam"/>
                </mibObjs>
        </assetField>
        <assetField name="hdd1" formatString="${flashSize}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.4.1.9.9.10.1.1.2.1.2.1" alias="flashSize"/>
                </mibObjs>
        </assetField>
        <assetField name="hdd2" formatString="${flashSize2}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.4.1.9.9.10.1.1.2.1.2.2" alias="flashSize2"/>
                </mibObjs>
        </assetField>
  </package>
  <package name="Cisco3750">
        <sysoid>.1.3.6.1.4.1.9.1.516</sysoid>
        <assetField name="manufacturer" formatString="${entPhysicalMfgName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.12.1001" alias="entPhysicalMfgName"/>
                </mibObjs>
        </assetField>
        <assetField name="serialNumber" formatString="${entPhysicalSerialNum}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.11.1001" alias="entPhysicalSerialNum"/>
                </mibObjs>
        </assetField>
        <assetField name="modelNumber" formatString="${entPhysicalModelName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.13.1001" alias="entPhysicalModelName"/>
                </mibObjs>
        </assetField>
  </package>
  <package name="Cisco-WS3750G-48TS-S">
        <sysoid>.1.3.6.1.4.1.9.5.46</sysoid>
        <assetField name="manufacturer" formatString="${entPhysicalMfgName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.12.1001" alias="entPhysicalMfgName"/>
                </mibObjs>
        </assetField>
        <assetField name="serialNumber" formatString="${entPhysicalSerialNum}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.11.1001" alias="entPhysicalSerialNum"/>
                </mibObjs>
        </assetField>
        <assetField name="modelNumber" formatString="${entPhysicalModelName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.13.1001" alias="entPhysicalModelName"/>
                </mibObjs>
        </assetField>
  </package>
  <package name="CiscoAironet1400">
        <sysoid>.1.3.6.1.4.1.9.1.533</sysoid>
        <assetField name="modelNumber" formatString="${entPhysicalModelName}">
                <mibObjs>
                        <mibObj oid=".1.3.6.1.2.1.47.1.1.1.1.2.1" alias="entPhysicalModelName"/>
                </mibObjs>
        </assetField>
  </package>

...

It would be more efficient to be able to AND/OR sysoids to create packages like "index1001" and add models that follow, but for now sysoids need individual packages to work.

IOS version does exist in an OID by itself in some of the hardware, but the consistency breaks down fast enough with increasing varieties of hardware that it is easier to create a vacuumd statement to parse the version from sysdescription. Even that is inconsistent, so this configuration takes provisioning requisitions of "Network" and "Security" to parse the line differently between Cisco IOS and Cisco ASA IOS.

(yes the regex should probably be anchored better)

  <statement>
        <!-- parse IOS version from sysDescription and update asset operating system -->
                UPDATE assets 
                SET operatingsystem= substring(nodesysdescription FROM '.*Version (\S+),')
                FROM node
                WHERE assets.nodeid=node.nodeid AND foreignsource NOT LIKE 'Security';
  </statement>

  <statement>
        <!-- parse IOS version from sysDescription and update asset operating system (for ASA)-->
                UPDATE assets
                SET operatingsystem= substring(nodesysdescription FROM '.*Version (\S+)')
                FROM node
                WHERE assets.nodeid=node.nodeid AND foreignsource like 'Security';
  </statement>

For HP Proliant Servers

Not all field are working, this will be updated. Working fields in this config: Model Number, Serial Number, Asset Numer=Hostname. The asset fields are filled for servers within 'Provisioning Requisitions'. Works not with auto discoverd devices.

 <package name="Proliant">
  <sysoid>.1.3.6.1.4.1.311.1.1.3.1.2</sysoid>
   <assetField name="description" formatString="${Hostname}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.2.1.1.5.0" alias="Hostname"/>
     </mibObjs>
   </assetField>
   <assetField name="assetNumber" formatString="${Asset}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.2.1.1.5.0" alias="Asset"/>
     </mibObjs>
   </assetField>
   <assetField name="vendorassetNumber" formatString="${Asset}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.4.1.232.2.2.2.5.0" alias="Asset"/>
     </mibObjs>
   </assetField>
   <assetField name="modelNumber" formatString="${Model}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.4.1.232.2.2.4.2.0" alias="Model"/>
     </mibObjs>
   </assetField>
   <assetField name="serialNumber" formatString="${Serial}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.4.1.232.2.2.2.5.0" alias="Serial"/>
     </mibObjs>
   </assetField>
   <assetField name="division" formatString="${Location}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.2.1.1.6.0" alias="Location"/>
     </mibObjs>
   </assetField>
   <assetField name="dateInstalled" formatString="${DataInstalled}">
     <mibObjs>
       <mibObj oid="1.3.6.1.2.1.25.1.1.0" alias="DataInstalled"/>
     </mibObjs>
   </assetField>
   <assetField name="operatingSystem" formatString="${OperatingSystem}">
     <mibObjs>
       <mibObj oid=".1.3.6.1.4.1.232.11.2.2.1.0" alias="OperatingSystem"/>
     </mibObjs>
   </assetField>
 </package>

In the log /var/log/opennms/daemon/provisiond

2013-07-05 08:50:05,186 DEBUG [pool-6-thread-1] Snmp4JStrategy: get: OID: [.1.3.6.1.4.1.232.2.2.4.2.0] for Agent:AgentConfig[Address: 192.168.51.41, ProxyForAddress: null, Port: 161, Community: snmpstring,$
2013-07-05 08:50:05,189 DEBUG [pool-6-thread-1] Snmp4JStrategy: processResponse: SNMP operation successful, value: [ProLiant DL360 G5]
2013-07-05 08:50:05,189 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: fetchSnmpAssetString: Fetched asset properties from SNMP agent:
  Model => ProLiant DL360 G5

2013-07-05 08:50:05,189 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: doUpdate: Setting asset field "modelNumber" to value: ProLiant DL360 G5
2013-07-05 08:50:05,191 DEBUG [pool-6-thread-1] Snmp4JStrategy: get: OID: [.1.3.6.1.4.1.232.2.2.2.5.0] for Agent:AgentConfig[Address: 192.168.51.41, ProxyForAddress: null, Port: 161, Community: snmpstring,$
2013-07-05 08:50:05,193 DEBUG [pool-6-thread-1] Snmp4JStrategy: processResponse: SNMP operation successful, value: [CZJ7250]
2013-07-05 08:50:05,193 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: fetchSnmpAssetString: Fetched asset properties from SNMP agent:
  Serial => CZJ7250

2013-07-05 08:50:05,193 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: doUpdate: Setting asset field "serialNumber" to value: CZJ7250
2013-07-05 08:50:05,194 DEBUG [pool-6-thread-1] Snmp4JStrategy: get: OID: [.1.3.6.1.2.1.1.6.0] for Agent:AgentConfig[Address: 192.168.51.41, ProxyForAddress: null, Port: 161, Community: snmpstring, Timeout$
2013-07-05 08:50:05,201 DEBUG [pool-6-thread-1] Snmp4JStrategy: processResponse: SNMP operation successful, value: [Almere]
2013-07-05 08:50:05,202 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: fetchSnmpAssetString: Fetched asset properties from SNMP agent:
  Location => Almere

2013-07-05 08:50:05,202 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: doUpdate: Setting asset field "division" to value: Almere
2013-07-05 08:50:05,203 DEBUG [pool-6-thread-1] Snmp4JStrategy: get: OID: [.1.3.6.1.4.1.232.11.2.2.1.0] for Agent:AgentConfig[Address: 192.168.51.41, ProxyForAddress: null, Port: 161, Community: snmpstring$
2013-07-05 08:50:05,208 DEBUG [pool-6-thread-1] Snmp4JStrategy: processResponse: SNMP operation successful, value: [Windows Server 2008 R2, x64 Enterprise Edition Service Pack 1]
2013-07-05 08:50:05,208 DEBUG [pool-6-thread-1] SnmpAssetProvisioningAdapter: fetchSnmpAssetString: Fetched asset properties from SNMP agent:
  DataInstalled => Windows Server 2008 R2, x64 Enterprise Edition Service Pack 1

Setting Asset Location

With PostGRE SQL statements in vacuumd-configuration.xml set the asset location information with the node location value (from SNMP).

File: /etc/opennms/vacuumd-configuration.xml
  <statement>
    <!-- this updates the assets adress info based on the nodesyslocation from SNMP -->
    <!-- Address to GPS location: http://www.mygeoposition.com/ -->
    UPDATE assets a SET address1='Street 10',zip='1111 AA',city='Almere',longitude='52.11111',latitude='4.11111' FROM node n WHERE a.nodeid=n.nodeid and n.nodesyslocation='Almere';

    UPDATE assets a SET address1='Street 20',zip='2222 BB',city='Amsterdam',longitude='52.22222',latitude='4.22222' FROM node n WHERE a.nodeid=n.nodeid and n.nodesyslocation='Datacentre-1';

    UPDATE assets a SET address1='Street 30',zip='3333 CC',city='Amsterdam',longitude='52.33333',latitude='4.33333' FROM node n WHERE a.nodeid=n.nodeid and n.nodesyslocation='Datacentre-2';
 </statement>