Importing Nodes From Netbox via PRIS

This is a sample PRIS requisition for importing devices from the Netbox IP and data center management system. You will need to import the PostgreSQL JDBC driver into the ‘’$PRIS_HOME/lib’’ folder for this to work. Make sure to replace the server name and PostgreSQL username/password, and to follow the instructions to create two custom fields in NetBox.

We are using NetBox where a site corresponds to a physical address and a rack group corresponds to a room.

Disclaimer: This was written for Netbox 2.4. It should still work as of 2.5+

### File: netbox/
source = jdbc

netbox.server = YOUR-NETBOX-URL
netbox.url = http://${netbox.server}/dcim/devices/

# This requisition will create a JDBC connection to the Netbox database to query devices to be provisioned into OpenNMS.
# It is set to filter only devices that are marked as "Active" with a primary IPv4 address and a custom "Monitor" field.

# Create the custom Netbox fields as described below, and update the values below with their ID from the extras_customfield table.
# Since NetBox does not have separate fields for address/city/state/zip, this assumes the use of a coma delimiter inside the site address field.
# Boolean field to indicate if the device should be "Monitored".
netbox.monitor = NETBOX-MONITOR-FIELD_ID
# Selection field to choose a category to assign to the node.
netbox.category = NETBOX-CATEGORY-FIELD_ID

source.driver = org.postgresql.Driver
source.url = jdbc:postgresql://${netbox.server}/netbox
source.password = NETBOX-SQL-PASSWORD

source.selectStatement = SELECT AS foreign_id, \ AS node_label, \
    (case when ip4.address is null then host(ip6.address) else host(ip4.address) end) AS ip_address, \ AS asset_building, \ AS asset_room, \
    trim(both from (split_part(site.physical_address, ',', 1))) AS asset_address1, \
    trim(both from (split_part(site.physical_address, ',', 2))) AS asset_city, \
    trim(both from (split_part(site.physical_address, ',', 3))) AS asset_state, \
    trim(both from (split_part(site.physical_address, ',', 4))) AS asset_zip, \ AS asset_rack, \ AS asset_manufacturer, \
    d.asset_tag AS asset_assetnumber, \
    dt.model AS asset_model, \
    d.serial AS asset_serial, \
    '<a href=${netbox.url}' || || ' target="_blank">'|| '${netbox.url}' || || '</a>'  AS asset_description, \
    c2.value AS asset_Category, \
    dr.slug AS Cat, \
    'P' AS mgmttype, \
    1 AS interfacestatus \
   FROM dcim_device d \
     LEFT OUTER JOIN extras_customfieldvalue v ON = v.obj_id AND v.field_id = ${netbox.monitor} \
     LEFT OUTER JOIN ipam_ipaddress ip4 ON d.primary_ip4_id = \
     LEFT OUTER JOIN ipam_ipaddress ip6 ON d.primary_ip6_id = \
     LEFT OUTER JOIN dcim_site site ON d.site_id = \
     LEFT OUTER JOIN dcim_devicetype dt ON d.device_type_id = \
     LEFT OUTER JOIN dcim_devicerole dr ON d.device_role_id = \
     LEFT OUTER JOIN dcim_manufacturer m ON dt.manufacturer_id = \
     LEFT OUTER JOIN dcim_rack r ON d.rack_id = \
     LEFT OUTER JOIN dcim_rackgroup rg ON r.group_id = \
     LEFT OUTER JOIN extras_customfieldvalue c ON = c.obj_id AND c.field_id = ${netbox.category} \
     LEFT OUTER JOIN extras_customfieldchoice c2 ON c.serialized_value::int = \
  WHERE d.status = 1 AND v.serialized_value = '1' AND (d.primary_ip4_id > 0 or d.primary_ip6_id > 0) \

### default no-operation mapper
mapper = echo

Once this is setup and working, you will also need to create a provisiond requisition schedule to have the import run on a regular basis. Here is a sample for a four hour refresh.

<requisition-def import-name="netbox" import-url-resource="http://HOSTNAME:8000/requisitions/netbox">
    <cron-schedule>0 0 0/4 * * ? *</cron-schedule>

NetBox Report Definition

NetBox has a Report feature to run a Python script as validation against nodes. The following report file will run from NetBox and use the OpenNMS REST API to verify if the device has been provisioned into OpenNMS.

### File: netbox/reports/
from dcim.constants import DEVICE_STATUS_ACTIVE
from dcim.models import Device
from extras.reports import Report
import requests
from extras.models import CustomFieldValue
from ipam.constants import *
from ipam.models import IPAddress

USERNAME = 'username'
PASSWORD = 'password'
BASE_URL = 'https://hostname:8443/opennms/rest/nodes?label='

class Check_OpenNMS_Provisioning(Report):
    description = "Check if device is imported into OpenNMS"

    def test_opennms_provisioned(self):
        for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE):
            for monitor in CustomFieldValue.objects.filter(
                if monitor.value is True:
                    if device.primary_ip4_id is not None:
                        url = BASE_URL +
                        response = requests.get(url, auth=(USERNAME, PASSWORD))
                        if response.text == '<?xml version="1.0" encoding="UTF-8"?><nodes offset="0" totalCount="0"/>':
                            self.log_warning(device, "Device not provisioned in OpenNMS")
                        self.log_failure(device, "No primary IPv4 address")

    def test_monitoring_enabled(self):
        for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE):
            for monitor in CustomFieldValue.objects.filter(
                if monitor.value is True:
                    if device.primary_ip4_id is not None:
                elif monitor.value is None:
                    self.log_warning(device, "Monitoring field not set")
                    self.log_info(device, "Device does not have Monitoring enabled")

Be sure to change the Netbox custom “monitor” field ID, host name, username, and password variables with correct values for your OpenNMS instance and place this in your netbox/reports folder. This report will need to be triggered from the command line. On CentOS, the command is: python3 /opt/netbox/netbox/ RunReport opennms_reports.