Replace the pyagentx threaded version with a much simpler, non-threaded version.

This commit is contained in:
Pim van Pelt
2021-09-11 12:19:38 +00:00
parent 842bce9d6e
commit 8c9c1e2b4a
13 changed files with 507 additions and 1089 deletions

View File

@ -3,515 +3,151 @@
from vppstats import VPPStats
from vppapi import VPPApi
import time
import pyagentx
import logging
import threading
import agentx
class MyAgent(agentx.Agent):
def setup(self):
global vppstat, vpp, logger
self.logger.info("Connecting to VPP Stats...")
vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
if not vppstat.connect():
self.logger.error("Can't connect to VPP Stats API, bailing")
return False
vpp = VPPApi(clientname='vpp-snmp-agent')
if not vpp.connect():
logger.error("Can't connect to VPP API, bailing")
return False
self.register('1.3.6.1.2.1.2.2.1')
self.register('1.3.6.1.2.1.31.1.1.1')
return True
class NullHandler(logging.Handler):
def emit(self, record):
pass
logger = logging.getLogger('pyagentx.vppstats')
logger.addHandler(NullHandler())
class ifName(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_OCTETSTRING(str(i + 1), vppstat['/if/names'][i])
class ifIndex(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_INTEGER(str(i + 1), i + 1)
class ifType(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
t = 6 # ethermet-csmacd
if vppstat['/if/names'][i].startswith("loop"):
t = 24 # softwareLoopback
self.set_INTEGER(str(i + 1), t)
class ifMtu(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ds = agentx.DataSet()
ifaces = vpp.get_ifaces()
self.logger.debug("%d VPP interfaces retrieved" % len(ifaces))
self.logger.debug("%d VPP Stats interfaces retrieved" % len(vppstat['/if/names']))
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
idx = 1000+i
ds.set('1.3.6.1.2.1.2.2.1.1.%u' % (idx), 'int', idx)
ds.set('1.3.6.1.2.1.2.2.1.2.%u' % (idx), 'str', ifname)
if ifname.startswith("loop"):
ds.set('1.3.6.1.2.1.2.2.1.3.%u' % (idx), 'int', 24) # softwareLoopback
else:
ds.set('1.3.6.1.2.1.2.2.1.3.%u' % (idx), 'int', 6) # ethermet-csmacd
mtu = 0
if not ifname in ifaces:
logger.warning("Could not get MTU for interface %s", ifname)
self.logger.warning("Could not get MTU for interface %s", ifname)
else:
mtu = ifaces[ifname].mtu[0]
self.set_INTEGER(str(i + 1), mtu)
ds.set('1.3.6.1.2.1.2.2.1.4.%u' % (idx), 'int', mtu)
class ifSpeed(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ifaces = vpp.get_ifaces()
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
speed = 0
if ifname.startswith("loop") or ifname.startswith("tap"):
speed = 1000000000
elif not ifname in ifaces:
logger.warning("Could not get link speed for interface %s",
ifname)
self.logger.warning("Could not get link speed for interface %s", ifname)
else:
speed = ifaces[ifname].link_speed * 1000
if speed >= 2**32:
speed = 2**32 - 1
self.set_GAUGE32(str(i + 1), speed)
ds.set('1.3.6.1.2.1.2.2.1.5.%u' % (idx), 'gauge32', speed)
class ifAdminStatus(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ifaces = vpp.get_ifaces()
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
state = 3 # testing
if not ifname in ifaces:
logger.warning("Could not get AdminStatus for interface %s",
ifname)
else:
if int(ifaces[ifname].flags) & 2:
state = 1 # up
else:
state = 2 # down
self.set_INTEGER(str(i + 1), state)
class ifOperStatus(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ifaces = vpp.get_ifaces()
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
state = 3 # testing
if not ifname in ifaces:
logger.warning("Could not get OperStatus for interface %s",
ifname)
else:
if int(ifaces[ifname].flags) & 1:
state = 1 # up
else:
state = 2 # down
self.set_INTEGER(str(i + 1), state)
class ifPhysAddress(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ifaces = vpp.get_ifaces()
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
mac = "00:00:00:00:00:00"
if not ifname in ifaces:
logger.warning("Could not get PhysAddress for interface %s",
ifname)
self.logger.warning("Could not get PhysAddress for interface %s", ifname)
else:
mac = str(ifaces[ifname].l2_address)
self.set_OCTETSTRING(str(i + 1), mac)
ds.set('1.3.6.1.2.1.2.2.1.6.%u' % (idx), 'str', mac)
admin_status = 3 # testing
if not ifname in ifaces:
self.logger.warning("Could not get AdminStatus for interface %s", ifname)
else:
if int(ifaces[ifname].flags) & 2:
admin_status = 1 # up
else:
admin_status = 2 # down
ds.set('1.3.6.1.2.1.2.2.1.7.%u' % (idx), 'int', admin_status)
class ifAlias(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
oper_status = 3 # testing
if not ifname in ifaces:
self.logger.warning("Could not get OperStatus for interface %s", ifname)
else:
if int(ifaces[ifname].flags) & 1:
oper_status = 1 # up
else:
oper_status = 2 # down
ds.set('1.3.6.1.2.1.2.2.1.8.%u' % (idx), 'int', oper_status)
for i in range(len(vppstat['/if/names'])):
self.set_OCTETSTRING(str(i + 1), vppstat['/if/names'][i])
ds.set('1.3.6.1.2.1.2.2.1.9.%u' % (idx), 'ticks', 0)
ds.set('1.3.6.1.2.1.2.2.1.10.%u' % (idx), 'u32', vppstat['/if/rx'][:, i].sum_octets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.11.%u' % (idx), 'u32', vppstat['/if/rx'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.12.%u' % (idx), 'u32', vppstat['/if/rx-multicast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.13.%u' % (idx), 'u32', vppstat['/if/rx-no-buf'][:, i].sum() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.14.%u' % (idx), 'u32', vppstat['/if/rx-error'][:, i].sum() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.16.%u' % (idx), 'u32', vppstat['/if/tx'][:, i].sum_octets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.17.%u' % (idx), 'u32', vppstat['/if/tx'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.18.%u' % (idx), 'u32', vppstat['/if/tx-multicast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.19.%u' % (idx), 'u32', vppstat['/if/drops'][:, i].sum() % 2**32)
ds.set('1.3.6.1.2.1.2.2.1.20.%u' % (idx), 'u32', vppstat['/if/tx-error'][:, i].sum() % 2**32)
class ifInMulticastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
ds.set('1.3.6.1.2.1.31.1.1.1.1.%u' % (idx), 'str', ifname)
ds.set('1.3.6.1.2.1.31.1.1.1.2.%u' % (idx), 'u32', vppstat['/if/rx-multicast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.31.1.1.1.3.%u' % (idx), 'u32', vppstat['/if/rx-broadcast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.31.1.1.1.4.%u' % (idx), 'u32', vppstat['/if/tx-multicast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.31.1.1.1.5.%u' % (idx), 'u32', vppstat['/if/tx-broadcast'][:, i].sum_packets() % 2**32)
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/rx-multicast'][:, i].sum_packets() % 2**32)
ds.set('1.3.6.1.2.1.31.1.1.1.6.%u' % (idx), 'u64', vppstat['/if/rx'][:, i].sum_octets())
ds.set('1.3.6.1.2.1.31.1.1.1.7.%u' % (idx), 'u64', vppstat['/if/rx'][:, i].sum_packets())
ds.set('1.3.6.1.2.1.31.1.1.1.8.%u' % (idx), 'u64', vppstat['/if/rx-multicast'][:, i].sum_packets())
ds.set('1.3.6.1.2.1.31.1.1.1.9.%u' % (idx), 'u64', vppstat['/if/rx-broadcast'][:, i].sum_packets())
ds.set('1.3.6.1.2.1.31.1.1.1.10.%u' % (idx), 'u64', vppstat['/if/tx'][:, i].sum_octets())
ds.set('1.3.6.1.2.1.31.1.1.1.11.%u' % (idx), 'u64', vppstat['/if/tx'][:, i].sum_packets())
ds.set('1.3.6.1.2.1.31.1.1.1.12.%u' % (idx), 'u64', vppstat['/if/tx-multicast'][:, i].sum_packets())
ds.set('1.3.6.1.2.1.31.1.1.1.13.%u' % (idx), 'u64', vppstat['/if/tx-broadcast'][:, i].sum_packets())
class ifInBroadcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/rx-broadcast'][:, i].sum_packets() % 2**32)
class ifOutMulticastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/tx-multicast'][:, i].sum_packets() % 2**32)
class ifOutBroadcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/tx-broadcast'][:, i].sum_packets() % 2**32)
class ifHCInOctets(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1), vppstat['/if/rx'][:,
i].sum_octets())
class ifHCInUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1), vppstat['/if/rx'][:,
i].sum_packets())
class ifHCInMulticastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1),
vppstat['/if/rx-multicast'][:, i].sum_packets())
class ifHCInBroadcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1),
vppstat['/if/rx-broadcast'][:, i].sum_packets())
class ifHCOutOctets(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1), vppstat['/if/tx'][:,
i].sum_octets())
class ifHCOutUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1), vppstat['/if/tx'][:,
i].sum_packets())
class ifHCOutMulticastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1),
vppstat['/if/tx-multicast'][:, i].sum_packets())
class ifHCOutBroadcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER64(str(i + 1),
vppstat['/if/tx-broadcast'][:, i].sum_packets())
class ifHighSpeed(pyagentx.Updater):
def update(self):
global vppstat, vpp
vppstat.connect()
vpp.connect()
ifaces = vpp.get_ifaces()
for i in range(len(vppstat['/if/names'])):
ifname = vppstat['/if/names'][i]
speed = 0
if ifname.startswith("loop") or ifname.startswith("tap"):
speed = 1000
elif not ifname in ifaces:
logger.warning("Could not get link speed for interface %s",
ifname)
self.logger.warning("Could not get link speed for interface %s", ifname)
else:
speed = int(ifaces[ifname].link_speed / 1000)
self.set_GAUGE32(str(i + 1), speed)
class ifPromiscuousMode(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
# Hardcode to false(2)
self.set_INTEGER(str(i + 1), 2)
class ifConnectorPresent(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
# Hardcode to true(1)
self.set_INTEGER(str(i + 1), 1)
class ifCounterDiscontinuityTime(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
# Hardcode to Timeticks: (0) 0:00:00.00
self.set_TIMETICKS(str(i + 1), 0)
class ifInOctets(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/rx'][:, i].sum_octets() % 2**32)
class ifInUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/rx'][:, i].sum_packets() % 2**32)
class ifInNUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/rx-multicast'][:, i].sum_packets() % 2**32)
class ifInDiscards(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/rx-no-buf'][:, i].sum() % 2**32)
class ifInErrors(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/rx-error'][:, i].sum() % 2**32)
class ifOutOctets(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/tx'][:, i].sum_octets() % 2**32)
class ifOutUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/tx'][:, i].sum_packets() % 2**32)
class ifOutNUcastPkts(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(
str(i + 1),
vppstat['/if/tx-multicast'][:, i].sum_packets() % 2**32)
class ifOutDiscards(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/drops'][:, i].sum() % 2**32)
class ifOutErrors(pyagentx.Updater):
def update(self):
global vppstat
vppstat.connect()
for i in range(len(vppstat['/if/names'])):
self.set_COUNTER32(str(i + 1),
vppstat['/if/tx-error'][:, i].sum() % 2**32)
class MyAgent(pyagentx.Agent):
def setup(self):
# iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry
self.register('1.3.6.1.2.1.2.2.1.1', ifIndex)
self.register('1.3.6.1.2.1.2.2.1.2', ifName)
self.register('1.3.6.1.2.1.2.2.1.3', ifType)
self.register('1.3.6.1.2.1.2.2.1.4', ifMtu)
self.register('1.3.6.1.2.1.2.2.1.5', ifSpeed)
self.register('1.3.6.1.2.1.2.2.1.6', ifPhysAddress)
self.register('1.3.6.1.2.1.2.2.1.7', ifAdminStatus)
self.register('1.3.6.1.2.1.2.2.1.8', ifOperStatus)
self.register('1.3.6.1.2.1.2.2.1.9', ifCounterDiscontinuityTime)
self.register('1.3.6.1.2.1.2.2.1.10', ifInOctets)
self.register('1.3.6.1.2.1.2.2.1.11', ifInUcastPkts)
self.register('1.3.6.1.2.1.2.2.1.12', ifInNUcastPkts)
self.register('1.3.6.1.2.1.2.2.1.13', ifInDiscards)
self.register('1.3.6.1.2.1.2.2.1.14', ifInErrors)
self.register('1.3.6.1.2.1.2.2.1.16', ifOutOctets)
self.register('1.3.6.1.2.1.2.2.1.17', ifOutUcastPkts)
self.register('1.3.6.1.2.1.2.2.1.18', ifOutNUcastPkts)
self.register('1.3.6.1.2.1.2.2.1.19', ifOutDiscards)
self.register('1.3.6.1.2.1.2.2.1.20', ifOutErrors)
# iso.org.dod.internet.mgmt.mib_2.ifMIB.ifMIBObjects.ifXTable.ifXEntry
self.register('1.3.6.1.2.1.31.1.1.1.1', ifName)
self.register('1.3.6.1.2.1.31.1.1.1.2', ifInMulticastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.3', ifInBroadcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.4', ifOutMulticastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.5', ifOutBroadcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.6', ifHCInOctets)
self.register('1.3.6.1.2.1.31.1.1.1.7', ifHCInUcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.8', ifHCInMulticastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.9', ifHCInBroadcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.10', ifHCOutOctets)
self.register('1.3.6.1.2.1.31.1.1.1.11', ifHCOutUcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.12', ifHCOutMulticastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.13', ifHCOutBroadcastPkts)
self.register('1.3.6.1.2.1.31.1.1.1.15', ifHighSpeed)
self.register('1.3.6.1.2.1.31.1.1.1.16', ifPromiscuousMode)
self.register('1.3.6.1.2.1.31.1.1.1.17', ifConnectorPresent)
self.register('1.3.6.1.2.1.31.1.1.1.18', ifAlias)
self.register('1.3.6.1.2.1.31.1.1.1.19', ifCounterDiscontinuityTime)
ds.set('1.3.6.1.2.1.31.1.1.1.15.%u' % (idx), 'gauge32', speed)
ds.set('1.3.6.1.2.1.31.1.1.1.16.%u' % (idx), 'int', 2) # Hardcode to false(2)
ds.set('1.3.6.1.2.1.31.1.1.1.17.%u' % (idx), 'int', 1) # Hardcode to true(1)
ds.set('1.3.6.1.2.1.31.1.1.1.18.%u' % (idx), 'str', ifname)
ds.set('1.3.6.1.2.1.31.1.1.1.19.%u' % (idx), 'ticks', 0) # Hardcode to Timeticks: (0) 0:00:00.00
return ds
def main():
global vppstat, vpp, logger
pyagentx.setup_logging(debug=False)
vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
vppstat.connect()
vpp = VPPApi()
if not vpp.connect():
logger.error("Can't connect to VPP API, bailing")
return
agentx.setup_logging(debug=False)
try:
a = MyAgent(server_address='/run/vpp/agentx.sock')
a.start()
a.run()
except Exception as e:
print("Unhandled exception:", e)
a.stop()
except KeyboardInterrupt:
a.stop()
vppstat.disconnect()
vpp.disconnect()
if __name__ == "__main__":
main()