Compare commits
16 Commits
bfbaf70430
...
main
Author | SHA1 | Date | |
---|---|---|---|
a327aed72e | |||
c0dfb9b628 | |||
57c04685a1 | |||
e3b9e11533 | |||
9d8aa63bed | |||
373fac3184
|
|||
1d93319c92
|
|||
af30d5ec57 | |||
e5d167dcda | |||
613c2be109 | |||
b371796690 | |||
8b29d8808c | |||
30da4ed974 | |||
b5e8a63013 | |||
679b9492d7 | |||
1e97ef3b2e |
14
snippets/ntp/test02.py
Normal file
14
snippets/ntp/test02.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import ntp.packet
|
||||||
|
import json
|
||||||
|
|
||||||
|
session = ntp.packet.ControlSession()
|
||||||
|
session.openhost('localhost')
|
||||||
|
|
||||||
|
peers = session.readstat()
|
||||||
|
|
||||||
|
|
||||||
|
for p in peers:
|
||||||
|
vars = session.readvar(p.associd, ['srchost', 'srcadr', 'refid', 'stratum', 'hmode', 'rec', 'reach', 'hpoll', 'ppoll', 'delay', 'offset', 'jitter'])
|
||||||
|
peerSelectStatus = " x.-+#*o"[(session.rstatus >>8) & 0x07]
|
||||||
|
print(f"{p.associd}, {peerSelectStatus}, {session.rstatus:04x}: {dict(vars)}")
|
||||||
|
|
@ -16,8 +16,9 @@ hottis MODULE-IDENTITY
|
|||||||
::= { enterprises 9676 }
|
::= { enterprises 9676 }
|
||||||
|
|
||||||
hottisNtpsec OBJECT IDENTIFIER ::= { hottis 123 }
|
hottisNtpsec OBJECT IDENTIFIER ::= { hottis 123 }
|
||||||
local OBJECT IDENTIFIER ::= { hottisNtpsec 1 }
|
local OBJECT IDENTIFIER ::= { hottisNtpsec 1 }
|
||||||
peers OBJECT IDENTIFIER ::= { hottisNtpsec 2 }
|
system OBJECT IDENTIFIER ::= { hottisNtpsec 2 }
|
||||||
|
peers OBJECT IDENTIFIER ::= { hottisNtpsec 3 }
|
||||||
|
|
||||||
|
|
||||||
ntpsecLocalLeap OBJECT-TYPE
|
ntpsecLocalLeap OBJECT-TYPE
|
||||||
@ -183,54 +184,54 @@ ntpsecPeerNumber OBJECT-TYPE
|
|||||||
::= { peers 1 }
|
::= { peers 1 }
|
||||||
|
|
||||||
ntpsecPeerTable OBJECT-TYPE
|
ntpsecPeerTable OBJECT-TYPE
|
||||||
SYNTAX SEQUENCE OF PeerEntry
|
SYNTAX SEQUENCE OF ntpsecPeerEntry
|
||||||
MAX-ACCESS not-accessible
|
MAX-ACCESS not-accessible
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Tabelle mit NTP-Peers."
|
DESCRIPTION "Tabelle mit NTP-Peers."
|
||||||
::= { peers 2 }
|
::= { peers 2 }
|
||||||
|
|
||||||
ntpsecPeer OBJECT-TYPE
|
ntpsecPeerEntry OBJECT-TYPE
|
||||||
SYNTAX PeerEntry
|
SYNTAX PeerEntry
|
||||||
MAX-ACCESS not-accessible
|
MAX-ACCESS not-accessible
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Eintrag für einen einzelnen NTP-Peer."
|
DESCRIPTION "Eintrag für einen einzelnen NTP-Peer."
|
||||||
INDEX { associd }
|
INDEX { ntpsecPeerIndex }
|
||||||
::= { ntpsecPeerTable 1 }
|
::= { ntpsecPeerTable 1 }
|
||||||
|
|
||||||
ntpsecPeerEntry ::= SEQUENCE {
|
ntpsecPeerEntry ::= SEQUENCE {
|
||||||
index INTEGER,
|
ntpsecPeerIndex INTEGER,
|
||||||
associd INTEGER,
|
ntpsecPeerAssocid INTEGER,
|
||||||
srcadr IpAddress,
|
ntpsecPeerSrcadr IpAddress,
|
||||||
srcport INTEGER,
|
ntpsecPeerSrcport INTEGER,
|
||||||
dstadr IpAddress,
|
ntpsecPeerDstadr IpAddress,
|
||||||
dstport INTEGER,
|
ntpsecPeerDstport INTEGER,
|
||||||
leap INTEGER,
|
ntpsecPeerLeap INTEGER,
|
||||||
hmode INTEGER,
|
ntpsecPeerHmode INTEGER,
|
||||||
stratum INTEGER,
|
ntpsecPeerStratum INTEGER,
|
||||||
ppoll INTEGER,
|
ntpsecPeerPpoll INTEGER,
|
||||||
hpoll INTEGER,
|
ntpsecPeerHpoll INTEGER,
|
||||||
precision INTEGER,
|
ntpsecPeerPrecision INTEGER,
|
||||||
rootdelay INTEGER,
|
ntpsecPeerRootdelay INTEGER,
|
||||||
rootdisp INTEGER,
|
ntpsecPeerRootdisp INTEGER,
|
||||||
refid DisplayString,
|
ntpsecPeerRefid DisplayString,
|
||||||
reftime DisplayString,
|
ntpsecPeerReftime DisplayString,
|
||||||
rec DisplayString,
|
ntpsecPeerRec DisplayString,
|
||||||
xmt DisplayString,
|
ntpsecPeerXmt DisplayString,
|
||||||
reach INTEGER,
|
ntpsecPeerReach INTEGER,
|
||||||
unreach INTEGER,
|
ntpsecPeerUnreach INTEGER,
|
||||||
delay_s DisplayString,
|
ntpsecPeerDelay_s DisplayString,
|
||||||
delay INTEGER,
|
ntpsecPeerDelay INTEGER,
|
||||||
offset INTEGER,
|
ntpsecPeerOffset INTEGER,
|
||||||
jitter INTEGER,
|
ntpsecPeerJitter INTEGER,
|
||||||
dispersion INTEGER,
|
ntpsecPeerDispersion INTEGER,
|
||||||
keyid INTEGER,
|
ntpsecPeerKeyid INTEGER,
|
||||||
filtdelay DisplayString,
|
ntpsecPeerFiltdelay DisplayString,
|
||||||
filtoffset DisplayString,
|
ntpsecPeerFiltoffset DisplayString,
|
||||||
pmode INTEGER,
|
ntpsecPeerPmode INTEGER,
|
||||||
filtdisp DisplayString,
|
ntpsecPeerFiltdisp DisplayString,
|
||||||
flash INTEGER,
|
ntpsecPeerFlash INTEGER,
|
||||||
headway INTEGER,
|
ntpsecPeerHeadway INTEGER,
|
||||||
ntscookies INTEGER
|
ntpsecPeerNtscookies INTEGER
|
||||||
}
|
}
|
||||||
|
|
||||||
ntpsecPeerIndex OBJECT-TYPE
|
ntpsecPeerIndex OBJECT-TYPE
|
||||||
@ -238,41 +239,41 @@ ntpsecPeerIndex OBJECT-TYPE
|
|||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Peer-Index."
|
DESCRIPTION "Peer-Index."
|
||||||
::= { ntpsecPeer 1 }
|
::= { ntpsecPeerEntry 1 }
|
||||||
|
|
||||||
ntpsecPeerAssocId OBJECT-TYPE
|
ntpsecPeerAssocId OBJECT-TYPE
|
||||||
SYNTAX INTEGER
|
SYNTAX INTEGER
|
||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Peer-Identifikationsnummer."
|
DESCRIPTION "Peer-Identifikationsnummer."
|
||||||
::= { ntpsecPeer 2 }
|
::= { ntpsecPeerEntry 2 }
|
||||||
|
|
||||||
ntpsecPeerSrcAdr OBJECT-TYPE
|
ntpsecPeerSrcAdr OBJECT-TYPE
|
||||||
SYNTAX DisplayString
|
SYNTAX DisplayString
|
||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Quell-IP-Adresse des Peers."
|
DESCRIPTION "Quell-IP-Adresse des Peers."
|
||||||
::= { ntpsecPeer 3 }
|
::= { ntpsecPeerEntry 3 }
|
||||||
|
|
||||||
ntpsecPeerSrcPort OBJECT-TYPE
|
ntpsecPeerSrcPort OBJECT-TYPE
|
||||||
SYNTAX INTEGER
|
SYNTAX INTEGER
|
||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Quellport des Peers."
|
DESCRIPTION "Quellport des Peers."
|
||||||
::= { ntpsecPeer 4 }
|
::= { ntpsecPeerEntry 4 }
|
||||||
|
|
||||||
ntpsecPeerDstAdr OBJECT-TYPE
|
ntpsecPeerDstAdr OBJECT-TYPE
|
||||||
SYNTAX DisplayString
|
SYNTAX DisplayString
|
||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Ziel-IP-Adresse des Peers."
|
DESCRIPTION "Ziel-IP-Adresse des Peers."
|
||||||
::= { ntpsecPeer 5 }
|
::= { ntpsecPeerEntry 5 }
|
||||||
|
|
||||||
ntpsecPeerDstPort OBJECT-TYPE
|
ntpsecPeerDstPort OBJECT-TYPE
|
||||||
SYNTAX INTEGER
|
SYNTAX INTEGER
|
||||||
MAX-ACCESS read-only
|
MAX-ACCESS read-only
|
||||||
STATUS current
|
STATUS current
|
||||||
DESCRIPTION "Zielport des Peers."
|
DESCRIPTION "Zielport des Peers."
|
||||||
::= { ntpsecPeer 6 }
|
::= { ntpsecPeerEntry 6 }
|
||||||
|
|
||||||
END
|
END
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pass_valueimport ntp.packe0
|
import ntp.packet
|
||||||
|
import ntp.ntpc
|
||||||
import threading
|
import threading
|
||||||
from contextlib import AbstractContextManager
|
from contextlib import AbstractContextManager
|
||||||
import time
|
import time
|
||||||
@ -10,18 +11,17 @@ import grp
|
|||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import pyagentx
|
import pyagentx
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
LOGGING_LEVEL=logging.DEBUG
|
|
||||||
|
|
||||||
BASE_OID_ENTERPRISE = '1.3.6.1.4.1'
|
BASE_OID_ENTERPRISE = '1.3.6.1.4.1'
|
||||||
BASE_OID_HOTTIS = BASE_OID_ENTERPRISE + '.9676'
|
BASE_OID_HOTTIS = BASE_OID_ENTERPRISE + '.9676'
|
||||||
BASE_OID_HOTTIS_NTPSEC = BASE_OID_HOTTIS + '.123'
|
BASE_OID_HOTTIS_NTPSEC = BASE_OID_HOTTIS + '.123'
|
||||||
|
|
||||||
# just the prefix where the objects are below
|
# just the prefix where the objects are below
|
||||||
LOCAL_PREFIX = '1'
|
SYSINFO_PREFIX = '1'
|
||||||
|
SYSSTATS_PREFIX = '2'
|
||||||
PEERS_PREFIX = '2'
|
PEERS_PREFIX = '3'
|
||||||
NUMBER_OF_PEERS_PREFIX = PEERS_PREFIX + '.1'
|
NUMBER_OF_PEERS_PREFIX = PEERS_PREFIX + '.1'
|
||||||
|
|
||||||
# this is for a table
|
# this is for a table
|
||||||
@ -40,63 +40,52 @@ def int_scale1M(x):
|
|||||||
def pass_value(x):
|
def pass_value(x):
|
||||||
return x
|
return x
|
||||||
|
|
||||||
LOCAL_SERVER_KEYS = [
|
def string_ntp_seconds(x):
|
||||||
|
return ntp.ntpc.prettydate(x).split(' ')[1]
|
||||||
|
|
||||||
|
|
||||||
|
SYSINFO_KEYS = [
|
||||||
|
['peeradr', pyagentx.TYPE_OCTETSTRING, pass_value],
|
||||||
|
['peermode', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['leap', pyagentx.TYPE_INTEGER, pass_value],
|
['leap', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['stratum', pyagentx.TYPE_INTEGER, pass_value],
|
['stratum', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['precision', pyagentx.TYPE_INTEGER, pass_value],
|
['precision', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['rootdelay', pyagentx.TYPE_INTEGER, int_scale1M],
|
['rootdelay', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['rootdisp', pyagentx.TYPE_INTEGER, int_scale1k],
|
['rootdisp', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
|
['rootdist', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['refid', pyagentx.TYPE_OCTETSTRING, pass_value],
|
['refid', pyagentx.TYPE_OCTETSTRING, pass_value],
|
||||||
['reftime', pyagentx.TYPE_OCTETSTRING, pass_value],
|
['reftime', pyagentx.TYPE_OCTETSTRING, string_ntp_seconds],
|
||||||
['tc', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['peer', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['offset', pyagentx.TYPE_INTEGER, int_scale1M],
|
|
||||||
['frequency', pyagentx.TYPE_INTEGER, int_scale1k],
|
|
||||||
['sys_jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
['sys_jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['clk_jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
['clk_jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['clock', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['processor', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['system', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['version', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['clk_wander', pyagentx.TYPE_INTEGER, int_scale1M],
|
['clk_wander', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['tai', pyagentx.TYPE_INTEGER, pass_value],
|
]
|
||||||
['leapsec', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['expire', pyagentx.TYPE_OCTETSTRING, pass_value],
|
SYSSTATS_KEYS = [
|
||||||
['mintc', pyagentx.TYPE_INTEGER, pass_value]
|
['ss_uptime', pyagentx.TYPE_INTEGER, pass_value ],
|
||||||
|
['ss_numctlreq', pyagentx.TYPE_INTEGER, pass_value ],
|
||||||
|
['ss_reset', pyagentx.TYPE_INTEGER, pass_value ],
|
||||||
|
['ss_received', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_badformat', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_declined', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_restricted', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_limited', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_kodsent', pyagentx.TYPE_COUNTER64, pass_value ],
|
||||||
|
['ss_processed', pyagentx.TYPE_COUNTER64, pass_value ]
|
||||||
]
|
]
|
||||||
|
|
||||||
PEER_KEYS = [
|
PEER_KEYS = [
|
||||||
|
['srchost', pyagentx.TYPE_OCTETSTRING, pass_value],
|
||||||
['srcadr', pyagentx.TYPE_OCTETSTRING, pass_value],
|
['srcadr', pyagentx.TYPE_OCTETSTRING, pass_value],
|
||||||
['srcport', pyagentx.TYPE_INTEGER, pass_value],
|
['refid', pyagentx.TYPE_OCTETSTRING, pass_value],
|
||||||
['dstadr', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['dstport', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['leap', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['hmode', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['stratum', pyagentx.TYPE_INTEGER, pass_value],
|
['stratum', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
|
['hmode', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['ppoll', pyagentx.TYPE_INTEGER, pass_value],
|
['ppoll', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['hpoll', pyagentx.TYPE_INTEGER, pass_value],
|
['hpoll', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['precision', pyagentx.TYPE_INTEGER, pass_value],
|
['rec', pyagentx.TYPE_OCTETSTRING, string_ntp_seconds],
|
||||||
['rootdelay', pyagentx.TYPE_INTEGER, int_scale1k],
|
|
||||||
['rootdisp', pyagentx.TYPE_INTEGER, int_scale1k],
|
|
||||||
['refid', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['reftime', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['rec', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['xmt', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['reach', pyagentx.TYPE_INTEGER, pass_value],
|
['reach', pyagentx.TYPE_INTEGER, pass_value],
|
||||||
['unreach', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['delay-s', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['delay', pyagentx.TYPE_INTEGER, int_scale1k],
|
['delay', pyagentx.TYPE_INTEGER, int_scale1k],
|
||||||
['offset', pyagentx.TYPE_INTEGER, int_scale1M],
|
['offset', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
['jitter', pyagentx.TYPE_INTEGER, int_scale1M],
|
||||||
['dispersion', pyagentx.TYPE_INTEGER, int_scale1k],
|
|
||||||
['keyid', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['filtdelay', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['filtoffset', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['pmode', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['filtdisp', pyagentx.TYPE_OCTETSTRING, pass_value],
|
|
||||||
['flash', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['headway', pyagentx.TYPE_INTEGER, pass_value],
|
|
||||||
['ntscookies', pyagentx.TYPE_INTEGER, pass_value]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -125,32 +114,39 @@ class NtpDataCollector(threading.Thread):
|
|||||||
self.period = period
|
self.period = period
|
||||||
self.stop_event = threading.Event()
|
self.stop_event = threading.Event()
|
||||||
|
|
||||||
self.session = ntp.packet.ControlSession()
|
|
||||||
self.session.openhost(self.ntpserver)
|
|
||||||
|
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while not self.stop_event.is_set():
|
while not self.stop_event.is_set():
|
||||||
logger.debug('Query ntp server')
|
try:
|
||||||
|
logger.debug('Query ntp server')
|
||||||
|
tmp_data_store = {}
|
||||||
|
|
||||||
ntpserver_vars = self.session.readvar(0)
|
session = ntp.packet.ControlSession()
|
||||||
logger.debug(f"{ntpserver_vars=}")
|
session.openhost(self.ntpserver)
|
||||||
|
|
||||||
tmp_data_store = {}
|
sysinfo_vars = session.readvar(0, [ x[0] for x in SYSINFO_KEYS ])
|
||||||
tmp_data_store['local'] = dict(ntpserver_vars)
|
logger.debug(f"{sysinfo_vars=}")
|
||||||
|
tmp_data_store['sysinfo'] = dict(sysinfo_vars)
|
||||||
|
|
||||||
peers = self.session.readstat()
|
sysstats_vars = session.readvar(0, [ x[0] for x in SYSSTATS_KEYS ])
|
||||||
tmp_data_store['peers'] = {}
|
logger.debug(f"{sysstats_vars=}")
|
||||||
for peer in peers:
|
tmp_data_store['sysstats'] = dict(sysstats_vars)
|
||||||
peer_vars = self.session.readvar(peer.associd)
|
|
||||||
tmp_data_store['peers'][peer.associd] = dict(peer_vars)
|
|
||||||
logger.debug(f"{peer.associd=}, {peer_vars=}")
|
|
||||||
|
|
||||||
with globalDataStore as ds:
|
peers = session.readstat()
|
||||||
ds.update_data(tmp_data_store)
|
tmp_data_store['peers'] = {}
|
||||||
|
for peer in peers:
|
||||||
|
peer_vars = session.readvar(peer.associd, [ x[0] for x in PEER_KEYS ])
|
||||||
|
tmp_data_store['peers'][peer.associd] = dict(peer_vars)
|
||||||
|
logger.debug(f"{peer.associd=}, {peer_vars=}")
|
||||||
|
|
||||||
|
with globalDataStore as ds:
|
||||||
|
ds.update_data(tmp_data_store)
|
||||||
|
except ntp.packet.ControlException as e:
|
||||||
|
logger.error(f"ntp.packet.ControlException while querying NTP server: {str(e)}")
|
||||||
|
finally:
|
||||||
|
time.sleep(self.period)
|
||||||
|
|
||||||
time.sleep(self.period)
|
|
||||||
logger.info('NtpDataCollector terminating')
|
logger.info('NtpDataCollector terminating')
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -163,15 +159,31 @@ class NtpsecDataUpdater(pyagentx.Updater):
|
|||||||
with globalDataStore as ds:
|
with globalDataStore as ds:
|
||||||
if ds.data:
|
if ds.data:
|
||||||
try:
|
try:
|
||||||
|
logger.debug("Updating data store")
|
||||||
for index, data_spec in enumerate(LOCAL_SERVER_KEYS, start=1):
|
for index, data_spec in enumerate(SYSINFO_KEYS, start=1):
|
||||||
# logger.debug(f"local: {index=} {data_spec=}")
|
# logger.debug(f"local: {index=} {data_spec=}")
|
||||||
oid_prefix = f"{LOCAL_PREFIX}.{index}"
|
try:
|
||||||
self._data[oid_prefix] = {
|
oid_prefix = f"{SYSINFO_PREFIX}.{index}"
|
||||||
'name': oid_prefix,
|
self._data[oid_prefix] = {
|
||||||
'type': data_spec[1],
|
'name': oid_prefix,
|
||||||
'value': data_spec[2](ds.data['local'][data_spec[0]])
|
'type': data_spec[1],
|
||||||
}
|
'value': data_spec[2](ds.data['sysinfo'][data_spec[0]])
|
||||||
|
}
|
||||||
|
except KeyError as e:
|
||||||
|
logger.error(f"key {data_spec[0]} missing in local, skip it: {str(e)}")
|
||||||
|
|
||||||
|
for index, data_spec in enumerate(SYSSTATS_KEYS, start=1):
|
||||||
|
# logger.debug(f"local: {index=} {data_spec=}")
|
||||||
|
try:
|
||||||
|
oid_prefix = f"{SYSSTATS_PREFIX}.{index}"
|
||||||
|
self._data[oid_prefix] = {
|
||||||
|
'name': oid_prefix,
|
||||||
|
'type': data_spec[1],
|
||||||
|
'value': data_spec[2](ds.data['sysstats'][data_spec[0]])
|
||||||
|
}
|
||||||
|
except KeyError as e:
|
||||||
|
logger.error(f"key {data_spec[0]} missing in local, skip it: {str(e)}")
|
||||||
|
|
||||||
number_of_peers = len(ds.data['peers'])
|
number_of_peers = len(ds.data['peers'])
|
||||||
# logger.debug(f"number of peers: {number_of_peers}")
|
# logger.debug(f"number of peers: {number_of_peers}")
|
||||||
number_of_peers_oid_prefix = f"{NUMBER_OF_PEERS_PREFIX}"
|
number_of_peers_oid_prefix = f"{NUMBER_OF_PEERS_PREFIX}"
|
||||||
@ -196,25 +208,29 @@ class NtpsecDataUpdater(pyagentx.Updater):
|
|||||||
}
|
}
|
||||||
for key_index, data_spec in enumerate(PEER_KEYS, start=3):
|
for key_index, data_spec in enumerate(PEER_KEYS, start=3):
|
||||||
# logger.debug(f"peer: {associd=} {key_index=} {data_spec=}")
|
# logger.debug(f"peer: {associd=} {key_index=} {data_spec=}")
|
||||||
oid_prefix = f"{TABLE_OF_PEERS_PREFIX}.{key_index}.{peer_index}"
|
try:
|
||||||
self._data[oid_prefix] = {
|
oid_prefix = f"{TABLE_OF_PEERS_PREFIX}.{key_index}.{peer_index}"
|
||||||
'name': oid_prefix,
|
self._data[oid_prefix] = {
|
||||||
'type': data_spec[1],
|
'name': oid_prefix,
|
||||||
'value': data_spec[2](peer[data_spec[0]])
|
'type': data_spec[1],
|
||||||
}
|
'value': data_spec[2](peer[data_spec[0]])
|
||||||
|
}
|
||||||
|
except KeyError as e:
|
||||||
|
logger.error(f"key {data_spec[0]} missing in peer {associd}, skip it: {str(e)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to update: {type(e)} {e}")
|
logger.error(f"Failed to update: {type(e)} {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NtpsecAgent(pyagentx.Agent):
|
class NtpsecAgent(pyagentx.Agent):
|
||||||
def __init__(self, agent_id='NtpsecAgent', socket_path=None):
|
def __init__(self, period=1, agent_id='NtpsecAgent', socket_path=None):
|
||||||
logger.info('Agent created')
|
logger.info('Agent created')
|
||||||
|
self.period = period
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
logger.info('Agent setup')
|
logger.info('Agent setup')
|
||||||
self.register(BASE_OID_HOTTIS_NTPSEC, NtpsecDataUpdater, freq=1)
|
self.register(BASE_OID_HOTTIS_NTPSEC, NtpsecDataUpdater, freq=self.period)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -239,8 +255,6 @@ def daemonize(pid_filename):
|
|||||||
os.dup2(log.fileno(), sys.stdout.fileno())
|
os.dup2(log.fileno(), sys.stdout.fileno())
|
||||||
os.dup2(log.fileno(), sys.stderr.fileno())
|
os.dup2(log.fileno(), sys.stderr.fileno())
|
||||||
|
|
||||||
logger.removeHandler(stdout_handler)
|
|
||||||
pyagentx.setup_logging(debug=True)
|
|
||||||
|
|
||||||
def set_user_group(user, group):
|
def set_user_group(user, group):
|
||||||
if group:
|
if group:
|
||||||
@ -258,10 +272,10 @@ def set_user_group(user, group):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
os.setuid(uid)
|
os.setuid(uid)
|
||||||
|
|
||||||
|
def setup_logging(verbose):
|
||||||
if __name__ == '__main__':
|
log_level = logging.DEBUG if verbose else logging.INFO
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=LOGGING_LEVEL,
|
level=log_level,
|
||||||
format="%(name)s - %(levelname)s - %(message)s",
|
format="%(name)s - %(levelname)s - %(message)s",
|
||||||
handlers=[logging.handlers.SysLogHandler(address='/dev/log')]
|
handlers=[logging.handlers.SysLogHandler(address='/dev/log')]
|
||||||
)
|
)
|
||||||
@ -269,13 +283,18 @@ if __name__ == '__main__':
|
|||||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
stdout_handler.setFormatter(formatter)
|
stdout_handler.setFormatter(formatter)
|
||||||
|
pyagentx.setup_logging(debug=verbose)
|
||||||
logger.addHandler(stdout_handler)
|
logger.addHandler(stdout_handler)
|
||||||
|
return logger
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
pid_filename = '/tmp/agentx-ntpsec.pid'
|
pid_filename = '/tmp/agentx-ntpsec.pid'
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='snmpd agentx extension for ntpsec')
|
parser = argparse.ArgumentParser(description='snmpd agentx extension for ntpsec')
|
||||||
parser.add_argument('--period', '-p',
|
parser.add_argument('--period', '-p',
|
||||||
help='Period to query the NTP server, in seconds, default 60s',
|
help='Period to query the NTP server, in seconds, default 60s',
|
||||||
|
type=int,
|
||||||
required=False,
|
required=False,
|
||||||
default=60)
|
default=60)
|
||||||
parser.add_argument('--ntpserver', '-n',
|
parser.add_argument('--ntpserver', '-n',
|
||||||
@ -299,39 +318,29 @@ if __name__ == '__main__':
|
|||||||
help="Set gid of process",
|
help="Set gid of process",
|
||||||
required=False,
|
required=False,
|
||||||
default='')
|
default='')
|
||||||
|
parser.add_argument('--verbose', '-v',
|
||||||
|
help='Enable debug output',
|
||||||
|
required=False,
|
||||||
|
action='store_true',
|
||||||
|
default=False)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.daemonize:
|
if args.daemonize:
|
||||||
daemonize(pid_filename)
|
daemonize(pid_filename)
|
||||||
set_user_group(args.user, args.group)
|
set_user_group(args.user, args.group)
|
||||||
|
logger = setup_logging(args.verbose)
|
||||||
|
|
||||||
if args.group:
|
|
||||||
try:
|
|
||||||
gid = grp.getgrnam(args.group).gr_gid
|
|
||||||
except KeyError:
|
|
||||||
logger.error(f"Group {args.group} does not exist")
|
|
||||||
sys.exit(1)
|
|
||||||
os.setgid(gid)
|
|
||||||
if args.user:
|
|
||||||
try:
|
|
||||||
uid = pwd.getpwnam(args.user).pw_uid
|
|
||||||
except KeyError:
|
|
||||||
logger.error(f"user {args.user} does not exist")
|
|
||||||
sys.exit(1)
|
|
||||||
os.setuid(uid)
|
|
||||||
|
|
||||||
|
|
||||||
ntpserver = args.ntpserver
|
ntpserver = args.ntpserver
|
||||||
period = args.period
|
period = args.period
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
globalDataStore = DataStore()
|
globalDataStore = DataStore()
|
||||||
ndc = NtpDataCollector(ntpserver=ntpserver, period=period)
|
ndc = NtpDataCollector(ntpserver=ntpserver, period=period)
|
||||||
ndc.start()
|
ndc.start()
|
||||||
|
|
||||||
nsax = NtpsecAgent()
|
nsax = NtpsecAgent(period=period)
|
||||||
nsax.start()
|
nsax.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unhandled exception: {e}")
|
logger.error(f"Unhandled exception: {e}")
|
||||||
|
15
src/snmp-agentx-ntpsec.service
Normal file
15
src/snmp-agentx-ntpsec.service
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AgentX NTPsec Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/python3 /usr/local/bin/agentx-ntpsec.py -u Debian-snmp -g Debian-snmp -p 30 --pid /run/agentx-ntpsec.pid
|
||||||
|
User=Debian-snmp
|
||||||
|
Group=Debian-snmp
|
||||||
|
PIDFile=/run/agentx-ntpsec.pid
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user