Compare commits

16 Commits

Author SHA1 Message Date
a327aed72e Merge branch 'more_variables_and_other_approach' 2025-03-11 10:35:03 +01:00
c0dfb9b628 fix date formatting 2025-03-11 10:33:24 +01:00
57c04685a1 changes 2025-03-10 20:25:38 +01:00
e3b9e11533 peer variables 2025-03-10 14:48:00 +01:00
9d8aa63bed initial in new branch 2025-03-10 10:59:27 +01:00
373fac3184 use the bug tracking of gitea 2025-03-09 17:54:41 +01:00
1d93319c92 issues 2025-03-09 17:49:24 +01:00
af30d5ec57 error handling 2025-03-07 22:37:46 +01:00
e5d167dcda service file 2025-03-04 18:40:27 +01:00
613c2be109 arg parsing int 2025-03-02 22:34:11 +01:00
b371796690 adjust logging, 2 2025-03-02 22:31:54 +01:00
8b29d8808c adjust logging 2025-03-02 22:29:10 +01:00
30da4ed974 verbose switch 2025-03-02 22:19:15 +01:00
b5e8a63013 period for update too 2025-03-02 22:14:20 +01:00
679b9492d7 period fix 2025-03-01 23:50:09 +01:00
1e97ef3b2e changes 2025-02-25 14:00:28 +01:00
5 changed files with 183 additions and 144 deletions

14
snippets/ntp/test02.py Normal file
View 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)}")

View File

@ -17,7 +17,8 @@ hottis MODULE-IDENTITY
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

View File

@ -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():
try:
logger.debug('Query ntp server') logger.debug('Query ntp server')
ntpserver_vars = self.session.readvar(0)
logger.debug(f"{ntpserver_vars=}")
tmp_data_store = {} tmp_data_store = {}
tmp_data_store['local'] = dict(ntpserver_vars)
peers = self.session.readstat() session = ntp.packet.ControlSession()
session.openhost(self.ntpserver)
sysinfo_vars = session.readvar(0, [ x[0] for x in SYSINFO_KEYS ])
logger.debug(f"{sysinfo_vars=}")
tmp_data_store['sysinfo'] = dict(sysinfo_vars)
sysstats_vars = session.readvar(0, [ x[0] for x in SYSSTATS_KEYS ])
logger.debug(f"{sysstats_vars=}")
tmp_data_store['sysstats'] = dict(sysstats_vars)
peers = session.readstat()
tmp_data_store['peers'] = {} tmp_data_store['peers'] = {}
for peer in peers: for peer in peers:
peer_vars = self.session.readvar(peer.associd) peer_vars = session.readvar(peer.associd, [ x[0] for x in PEER_KEYS ])
tmp_data_store['peers'][peer.associd] = dict(peer_vars) tmp_data_store['peers'][peer.associd] = dict(peer_vars)
logger.debug(f"{peer.associd=}, {peer_vars=}") logger.debug(f"{peer.associd=}, {peer_vars=}")
with globalDataStore as ds: with globalDataStore as ds:
ds.update_data(tmp_data_store) 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:
oid_prefix = f"{SYSINFO_PREFIX}.{index}"
self._data[oid_prefix] = { self._data[oid_prefix] = {
'name': oid_prefix, 'name': oid_prefix,
'type': data_spec[1], 'type': data_spec[1],
'value': data_spec[2](ds.data['local'][data_spec[0]]) '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=}")
try:
oid_prefix = f"{TABLE_OF_PEERS_PREFIX}.{key_index}.{peer_index}" oid_prefix = f"{TABLE_OF_PEERS_PREFIX}.{key_index}.{peer_index}"
self._data[oid_prefix] = { self._data[oid_prefix] = {
'name': oid_prefix, 'name': oid_prefix,
'type': data_spec[1], 'type': data_spec[1],
'value': data_spec[2](peer[data_spec[0]]) '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}")

View 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