Feature Hardware Inventory

This feature provides a way to discover the hardware inventory through
the ENTITY-MIB from any device that supports SNMP and persist it on the
database.

It also provides a way to configure custom vendor attributes (i.e. any
column from an SNMP Table indexed by the entPhysicalIndex) to persist
them as additional attributes to each hardware entity object that
support this attribute. It is possible to override one of the standard
fields from the entPhysicalTable using a custom attribute through the
configuration file.

The auto-discover of the hardware inventory is done through an optional
provisioning adapter that must be installed separately
(opennms-plugin-provisioning-snmp-hardware-inventory). This adapter is
going to run every time the requisition is synchronized, and it will
persist the inventory only if it doesn't exist or if the retrieved
structure is different from the existing one. The adapter should send an
event every time the inventory is changed for a node or if there was a
problem retrieving or persisting the data.

The hardware inventory on the ENTITY-MIB is a hierarchical structure,
and it is stored on that way. The information is exposed through the
WebUI and through a ReST API. This API also provides a way to replace an
existing hardware element or for creating the whole inventory structure
from scratch (which is useful if the target node doesn't support SNMP or
if it doesn't implement the ENTITY-MIB).

* All the base attributes are named exactly like in
* ENTITY-MIB::entPhysicalTable.
* The vendor attributes are contained under the "ventorAttributes" tags,
* and contain the name of the attribute, the source OID and the value.
* Each entity has a children tag on which are listed all the child
* entities.
* Each entity tag contains 3 attributes:
    - entPhysicalIndex
    - parentPhysicalIndex (which is the entPhysicalIndex of the parent
      for reference purpose)
    - nodeId (the ID of the container node for reference purpose)

It is also possible to perform the following operations through ReST:

* Get a specific entity

GET
/opennms/rest/nodes/{nodeSource}/hardwareInventory/{entPhysicalIndex}

To retrieve a specific node. If it is not specified the root entity is
going to be returned.

* Save a new hardware inventory structure:

POST /opennms/rest/nodes/{nodeSource}/hardwareInventory

This will override completely the content of the database if exist.

* Add a child entity to an existing entity:

POST
/opennms/rest/nodes/{nodeSource}/hardwareInventory/{entPhysicalIndex}

If the given entity has the entPhysicalIndex of an existing child, this
child will be overridden, otherwise the child will be appended to the
parent.

* Delete an existing entity:

DELETE
/opennms/rest/nodes/{nodeSource}/hardwareInventory/{entPhysicalIndex}

If you provide the entPhysicalIndex of the root entity, all the hardware
inventory is going to be removed.

* Modify an existing entity:

PUT
/opennms/rest/nodes/{nodeSource}/hardwareInventory/{entPhysicalIndex}

This request expects a form-url-encoded list of fields that need to be
modified. It is also possible to add new custom attributes using this
form.

Events/Alarms/Notifications:

A new set of placeholders have been added to OpenNMS to enrich the
content of the events, alarms and notifications.

Because of the hierarchical nature of the hardware entities, it is
required to provide two fields in order to obtain the value of the
required attribute.
This two fields are either the entPhysicalIndex or the entPhysicalName
and the name of the attribute (which could be either one of the base
attributes or a vendor attribute).

The entPhysicalIndex guarantees that you are going to get always the
same entity. Using entPhysicalName is not a unique way to identify an
entity. For this reason the first entity that match the given
entPhysicalName will be used.
It is also possible to specify a regular expression against the
entPhysicalName and the first match will be used. To identify a regular
expression the field should start with ‘~’.

Possible structure of the placeholders:
- %hardware[{entPhysicalIndex}:{attributeName}]%
- %hardware[{entPhysicalName}:{attributeName}]%
- %hardware[~{regexOverEntPhysicalName}:{attributeName}]%