This is a pure python script for polling BGP Peer states where the BGP4-MIB is available for polling.
It will report the current state of all BGP peers, and send a warning if any state other than "ESTABLISHED" is polled. This has been tested against Cisco routers , but it should work for any router/switch running IEEE MIBS
Disclaimer: Use at your own risk, preferably after testing thoroughly.
This script was tested on the local probe. See PRTG documentation for running python scripts on a remote probe

Steps:

Pip upgrade and install pysnmp
Open a command prompt, change directory to the following: cd C:\Program Files (x86)\PRTG Network Monitor\python\Scripts Run the following commands to upgrade pip and install pysnmp and pysnmp SMIs pip install pip --upgrade pip install pysnmp pysmi
Copy the following text into a text file, and save it as C:\Program Files (x86)\PRTG Network Monitor\lookups\custom\customsensor.bgp4.peerstatus.ovl

<?xml version="1.0" encoding="UTF-8"?>
<ValueLookup id="customsensor.bgp4.peerstatus" desiredValue="6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PaeValueLookup.xsd">
	<Lookups>
		<SingleInt state="Error" value="1">Idle</SingleInt>
		<SingleInt state="Error" value="2">Connect</SingleInt>
		<SingleInt state="Error" value="3">Active</SingleInt>
		<SingleInt state="Error" value="4">Open Sent</SingleInt>
		<SingleInt state="Error" value="5">Open Confirm</SingleInt>
		<SingleInt state="Ok" value="6">Established</SingleInt>
	</Lookups>
</ValueLookup>

Load Lookups in the PRTG Web Dashboard:
Setup > System Administration > Load Lookups and File Lists > Go!

Copy the following text into a text file, and save it as C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\python\bgp_peers.py

from pysnmp.hlapi import *
from prtg.sensor.result import CustomSensorResult
from prtg.sensor.units import ValueUnit
import sys
import re
import json

prtg_params = json.loads(sys.argv[1])


def bgp_peer_walk(host):
  oid = '.1.3.6.1.2.1.15.3.1.2'
  reg_ex = re.compile('[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ = [1-6]')
  bgp_peer_dict = {}

  for (errorIndication,
   errorStatus,
   errorIndex,
   varBinds) in nextCmd(SnmpEngine(), 
                        CommunityData(prtg_params['snmpcommv2']),
                        UdpTransportTarget((host, 161)),
                        ContextData(),                                                           
                        ObjectType(ObjectIdentity(oid)),
                        lexicographicMode=False):
    if errorIndication:
      csr = CustomSensorResult(text="Python Script pysnmp error")
      csr.error = f"Python Script pysnmp error: {errorIndication}"
      print(csr.json_result)
      sys.exit()
    elif errorStatus:
      csr = CustomSensorResult(text="Python Script pysnmp error")
      csr.error = f"Python Script pysnmp error: {errorStatus}"
      print(csr.json_result)            
      sys.exit()
    else:
      for varBind in varBinds:
        bgp_peers = reg_ex.search(str(varBind))
        ip, state = str(bgp_peers.group(0)).split(' = ')
        bgp_peer_dict[ip] = state
  return(bgp_peer_dict)

def build_csr(peer_dict):
  try:
    csr = CustomSensorResult()
    for peer in peer_dict:
      if peer_dict[peer] is '6':
        csr.add_channel(name = peer, value = 6, unit = ValueUnit.CUSTOM, is_warning = 0, value_lookup="customsensor.bgp4.peerstatus")
      if peer_dict[peer] is '5':
        csr.add_channel(name = peer, value = 5, unit = ValueUnit.CUSTOM, is_warning = 1, value_lookup="customsensor.bgp4.peerstatus")
      if peer_dict[peer] is '4':
        csr.add_channel(name = peer, value = 4, unit = ValueUnit.CUSTOM, is_warning = 1, value_lookup="customsensor.bgp4.peerstatus")
      if peer_dict[peer] is '3':
        csr.add_channel(name = peer, value = 3, unit = ValueUnit.CUSTOM, is_warning = 1, value_lookup="customsensor.bgp4.peerstatus")
      if peer_dict[peer] is '2':
        csr.add_channel(name = peer, value = 2, unit = ValueUnit.CUSTOM, is_warning = 1, value_lookup="customsensor.bgp4.peerstatus")
      if peer_dict[peer] is '1':
        csr.add_channel(name = peer, value = 1, unit = ValueUnit.CUSTOM, is_warning = 1, value_lookup="customsensor.bgp4.peerstatus")
    print(csr.json_result)
  except Exception as e:
    csr = CustomSensorResult(text="Python build_csr execution error")
    csr.error = f"Python Script execution error: {e}"
    print(csr.json_result)

build_csr(bgp_peer_walk(prtg_params['host']))


To setup the sensor, Click Add Sensor, and search for Python Script Advanced.
On the configuration page, rename the Sensor, select the Transmit SNMP credentials bullet, and click save.


Article Comments

Hello Ted,

Thank you very much for sharing your script with the community.

Have a great day.

Regards.


Mar, 2021 - Permalink