Format with black

This commit is contained in:
Pim van Pelt
2023-01-08 13:05:42 +01:00
parent 72e9cf3503
commit 5e11539b44
8 changed files with 540 additions and 355 deletions

View File

@ -11,19 +11,23 @@ import logging
from agentx.agent import Agent
from agentx.dataset import DataSet
def setup_logging(debug=False):
if debug:
level = logging.DEBUG
else:
level = logging.INFO
logger = logging.getLogger('agentx')
logger = logging.getLogger("agentx")
logger.setLevel(level)
formatter = logging.Formatter('[%(levelname)-8s] %(name)17s - %(funcName)-15s: %(message)s')
formatter = logging.Formatter(
"[%(levelname)-8s] %(name)17s - %(funcName)-15s: %(message)s"
)
ch = logging.StreamHandler()
ch.setLevel(level)
ch.setFormatter(formatter)
logger.addHandler(ch)
AGENTX_EMPTY_PDU = 1
AGENTX_OPEN_PDU = 1
AGENTX_CLOSE_PDU = 2

View File

@ -12,14 +12,15 @@ import agentx
from agentx.dataset import DataSet
from agentx.network import Network
class NullHandler(logging.Handler):
def emit(self, record):
pass
class Agent(object):
def __init__(self, server_address='/var/agentx/master', period=30.0):
self.logger = logging.getLogger('agentx.agent')
def __init__(self, server_address="/var/agentx/master", period=30.0):
self.logger = logging.getLogger("agentx.agent")
self.logger.addHandler(NullHandler())
self._servingset = DataSet()
@ -27,7 +28,7 @@ class Agent(object):
self._lastupdate = 0
self._update_period = period # Seconds
self._net = Network(server_address = server_address)
self._net = Network(server_address=server_address)
self._oid_list = []
@ -41,43 +42,44 @@ class Agent(object):
return True
def run(self):
self.logger.info('Calling setup')
self.logger.info("Calling setup")
if not self.setup():
self.logger.error('Setup failed - exiting')
self.logger.error("Setup failed - exiting")
return
self.logger.info('Initial update')
self.logger.info("Initial update")
self._update()
while True:
if not self._net.is_connected():
self.logger.info('Opening AgentX connection')
self._net.start(self._oid_list)
self.logger.info("Opening AgentX connection")
self._net.start(self._oid_list)
if time.time() - self._lastupdate > self._update_period:
if not self._update():
self.logger.warning('Update failed, last successful update was %s' % self._lastupdate)
self.logger.warning(
"Update failed, last successful update was %s"
% self._lastupdate
)
time.sleep(1)
try:
self._net.run()
except Exception as e:
self.logger.error('An exception occurred: %s' % e)
self.logger.error('Reconnecting')
self.logger.error("An exception occurred: %s" % e)
self.logger.error("Reconnecting")
self._net.disconnect()
time.sleep(0.1)
def stop(self):
self.logger.debug('Stopping')
self.logger.debug("Stopping")
self._net.disconnect()
pass
def setup(self):
# Override this
pass
def update(self):
# Override this
pass
@ -88,5 +90,5 @@ class Agent(object):
for oid in oid_list:
if not oid in self._oid_list:
self.logger.debug('Adding %s to list' % oid)
self.logger.debug("Adding %s to list" % oid)
self._oid_list.append(oid)

View File

@ -9,38 +9,36 @@ from __future__ import (
import time
import agentx
class DataSetError(Exception):
pass
class DataSet():
class DataSet:
def __init__(self):
self._data = {}
def set(self, oid, oid_type, value):
if oid_type.startswith('int'):
if oid_type.startswith("int"):
t = agentx.TYPE_INTEGER
elif oid_type.startswith('str'):
elif oid_type.startswith("str"):
t = agentx.TYPE_OCTETSTRING
elif oid_type.startswith('oid'):
elif oid_type.startswith("oid"):
t = agentx.TYPE_OBJECTIDENTIFIER
elif oid_type.startswith('ip'):
elif oid_type.startswith("ip"):
t = agentx.TYPE_IPADDRESS
elif oid_type == 'counter32' or oid_type == 'uint32' or oid_type == 'u32':
elif oid_type == "counter32" or oid_type == "uint32" or oid_type == "u32":
t = agentx.TYPE_COUNTER32
elif oid_type == 'gauge32':
elif oid_type == "gauge32":
t = agentx.TYPE_GAUGE32
elif oid_type.startswith('time') or oid_type.startswith('tick'):
elif oid_type.startswith("time") or oid_type.startswith("tick"):
t = agentx.TYPE_TIMETICKS
elif oid_type.startswith('opaque'):
elif oid_type.startswith("opaque"):
t = agentx.TYPE_OPAQUE
elif oid_type == 'counter64' or oid_type == 'uint64' or oid_type == 'u64':
elif oid_type == "counter64" or oid_type == "uint64" or oid_type == "u64":
t = agentx.TYPE_COUNTER64
else:
raise DataSetErrror('Invalid oid_type: %s' % (oid_type))
raise DataSetErrror("Invalid oid_type: %s" % (oid_type))
return
self._data[oid] = {
'name': oid,
'type': t,
'value': value
}
self._data[oid] = {"name": oid, "type": t, "value": value}

View File

@ -17,15 +17,17 @@ class NullHandler(logging.Handler):
def emit(self, record):
pass
logger = logging.getLogger('agentx.network')
logger = logging.getLogger("agentx.network")
logger.addHandler(NullHandler())
class NetworkError(Exception):
pass
class Network():
def __init__(self, server_address = '/var/agentx/master'):
class Network:
def __init__(self, server_address="/var/agentx/master"):
self.session_id = 0
self.transaction_id = 0
@ -35,8 +37,7 @@ class Network():
self.data_idx = []
self._connected = False
self._server_address = server_address
self._timeout = 0.1 # Seconds
self._timeout = 0.1 # Seconds
def connect(self):
if self._connected:
@ -44,12 +45,12 @@ class Network():
try:
logger.info("Connecting to %s" % self._server_address)
if self._server_address.startswith('/'):
if self._server_address.startswith("/"):
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.socket.connect(self._server_address)
else:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host, port=self._server_address.split(':')
host, port = self._server_address.split(":")
self.socket.connect((host, int(port)))
self.socket.settimeout(self._timeout)
@ -76,7 +77,9 @@ class Network():
self.data = newdata.copy()
del self.data_idx
self.data_idx = sorted(self.data.keys(), key=lambda k: tuple(int(part) for part in k.split('.')))
self.data_idx = sorted(
self.data.keys(), key=lambda k: tuple(int(part) for part in k.split("."))
)
def new_pdu(self, type):
pdu = PDU(type)
@ -93,15 +96,18 @@ class Network():
return pdu
def send_pdu(self, pdu):
if self.debug: pdu.dump()
if self.debug:
pdu.dump()
self.socket.send(pdu.encode())
def recv_pdu(self):
buf = self.socket.recv(100000)
if not buf: return None
if not buf:
return None
pdu = PDU()
pdu.decode(buf)
if self.debug: pdu.dump()
if self.debug:
pdu.dump()
return pdu
# =========================================
@ -109,7 +115,7 @@ class Network():
def _get_next_oid(self, oid, endoid):
if oid in self.data:
# Exact match found
#logger.debug('get_next_oid, exact match of %s' % oid)
# logger.debug('get_next_oid, exact match of %s' % oid)
idx = self.data_idx.index(oid)
if idx == (len(self.data_idx) - 1):
# Last Item in MIB, No match!
@ -117,11 +123,11 @@ class Network():
return self.data_idx[idx + 1]
else:
# No exact match, find prefix
#logger.debug('get_next_oid, no exact match of %s' % oid)
slist = oid.split('.')
elist = endoid.split('.')
# logger.debug('get_next_oid, no exact match of %s' % oid)
slist = oid.split(".")
elist = endoid.split(".")
for tmp_oid in self.data_idx:
tlist = tmp_oid.split('.')
tlist = tmp_oid.split(".")
for i in range(len(tlist)):
try:
sok = int(slist[i]) <= int(tlist[i])
@ -166,13 +172,13 @@ class Network():
def is_connected(self):
return self._connected
def run(self, timeout = 0.1):
def run(self, timeout=0.1):
if not self._connected:
raise NetworkError('Not connected')
raise NetworkError("Not connected")
if timeout != self._timeout:
self.socket.settimeout(timeout)
self._timeout = timeout
self.socket.settimeout(timeout)
self._timeout = timeout
try:
request = self.recv_pdu()
@ -195,11 +201,13 @@ class Network():
response.values.append(self.data[oid])
else:
logger.debug("OID Not Found!")
response.values.append({
'type': agentx.TYPE_NOSUCHOBJECT,
'name': rvalue[0],
'value': 0
})
response.values.append(
{
"type": agentx.TYPE_NOSUCHOBJECT,
"name": rvalue[0],
"value": 0,
}
)
elif request.type == agentx.AGENTX_GETNEXT_PDU:
logger.debug("Received GET_NEXT PDU")
@ -209,11 +217,13 @@ class Network():
if oid:
response.values.append(self.data[oid])
else:
response.values.append({
'type': agentx.TYPE_ENDOFMIBVIEW,
'name': rvalue[0],
'value': 0
})
response.values.append(
{
"type": agentx.TYPE_ENDOFMIBVIEW,
"name": rvalue[0],
"value": 0,
}
)
else:
logger.warn("Received unsupported PDU %d" % request.type)

View File

@ -12,10 +12,13 @@ import pprint
import logging
import agentx
class NullHandler(logging.Handler):
def emit(self, record):
pass
logger = logging.getLogger('agentx.pdu')
logger = logging.getLogger("agentx.pdu")
logger.addHandler(NullHandler())
@ -27,34 +30,32 @@ class PDU(object):
self.packet_id = 0
self.error = agentx.ERROR_NOAGENTXERROR
self.error_index = 0
self.decode_buf = ''
self.decode_buf = ""
self.state = {}
self.values = []
def dump(self):
name = agentx.PDU_TYPE_NAME[self.type]
logger.debug('PDU DUMP: New PDU')
logger.debug("PDU DUMP: New PDU")
logger.debug(
'PDU DUMP: Meta : [%s: %d %d %d]' %
(name, self.session_id, self.transaction_id, self.packet_id))
if 'payload_length' in self.state:
logger.debug('PDU DUMP: Length : %s' %
self.state['payload_length'])
if hasattr(self, 'response'):
logger.debug('PDU DUMP: Response : %s' % self.response)
if hasattr(self, 'values'):
logger.debug('PDU DUMP: Values : %s' %
pprint.pformat(self.values))
if hasattr(self, 'range_list'):
logger.debug('PDU DUMP: Range list: %s' %
pprint.pformat(self.range_list))
"PDU DUMP: Meta : [%s: %d %d %d]"
% (name, self.session_id, self.transaction_id, self.packet_id)
)
if "payload_length" in self.state:
logger.debug("PDU DUMP: Length : %s" % self.state["payload_length"])
if hasattr(self, "response"):
logger.debug("PDU DUMP: Response : %s" % self.response)
if hasattr(self, "values"):
logger.debug("PDU DUMP: Values : %s" % pprint.pformat(self.values))
if hasattr(self, "range_list"):
logger.debug("PDU DUMP: Range list: %s" % pprint.pformat(self.range_list))
# ====================================================
# encode functions
def encode_oid(self, oid, include=0):
oid = oid.strip()
oid = oid.split('.')
oid = oid.split(".")
oid = [int(i) for i in oid]
if len(oid) > 5 and oid[:4] == [1, 3, 6, 1]:
# prefix
@ -63,66 +64,70 @@ class PDU(object):
else:
# no prefix
prefix = 0
buf = struct.pack('BBBB', len(oid), prefix, include, 0)
buf = struct.pack("BBBB", len(oid), prefix, include, 0)
for i in range(len(oid)):
buf += struct.pack('!L', oid[i])
buf += struct.pack("!L", oid[i])
return buf
def encode_octet(self, octet):
octet = octet.encode("utf-8")
buf = struct.pack('!L', len(octet))
buf = struct.pack("!L", len(octet))
buf += octet
padding = (4 - (len(octet) % 4)) % 4
buf += chr(0).encode() * padding
return buf
def encode_value(self, type, name, value):
buf = struct.pack('!HH', type, 0)
buf = struct.pack("!HH", type, 0)
buf += self.encode_oid(name)
if type in [agentx.TYPE_INTEGER]:
buf += struct.pack('!l', value)
buf += struct.pack("!l", value)
elif type in [
agentx.TYPE_COUNTER32, agentx.TYPE_GAUGE32,
agentx.TYPE_TIMETICKS
agentx.TYPE_COUNTER32,
agentx.TYPE_GAUGE32,
agentx.TYPE_TIMETICKS,
]:
buf += struct.pack('!L', value)
buf += struct.pack("!L", value)
elif type in [agentx.TYPE_COUNTER64]:
buf += struct.pack('!Q', value)
buf += struct.pack("!Q", value)
elif type in [agentx.TYPE_OBJECTIDENTIFIER]:
buf += self.encode_oid(value)
elif type in [
agentx.TYPE_IPADDRESS, agentx.TYPE_OPAQUE,
agentx.TYPE_OCTETSTRING
agentx.TYPE_IPADDRESS,
agentx.TYPE_OPAQUE,
agentx.TYPE_OCTETSTRING,
]:
buf += self.encode_octet(value)
elif type in [
agentx.TYPE_NULL, agentx.TYPE_NOSUCHOBJECT,
agentx.TYPE_NOSUCHINSTANCE, agentx.TYPE_ENDOFMIBVIEW
agentx.TYPE_NULL,
agentx.TYPE_NOSUCHOBJECT,
agentx.TYPE_NOSUCHINSTANCE,
agentx.TYPE_ENDOFMIBVIEW,
]:
# No data
pass
else:
logger.error('Unknown Type:' % type)
logger.error("Unknown Type:" % type)
return buf
def encode_header(self, pdu_type, payload_length=0, flags=0):
flags = flags | 0x10 # Bit 5 = all ints in NETWORK_BYTE_ORDER
buf = struct.pack('BBBB', 1, pdu_type, flags, 0)
buf += struct.pack('!L', self.session_id) # sessionID
buf += struct.pack('!L', self.transaction_id) # transactionID
buf += struct.pack('!L', self.packet_id) # packetID
buf += struct.pack('!L', payload_length)
buf = struct.pack("BBBB", 1, pdu_type, flags, 0)
buf += struct.pack("!L", self.session_id) # sessionID
buf += struct.pack("!L", self.transaction_id) # transactionID
buf += struct.pack("!L", self.packet_id) # packetID
buf += struct.pack("!L", payload_length)
return buf
def encode(self):
buf = b''
buf = b""
if self.type == agentx.AGENTX_OPEN_PDU:
# timeout
buf += struct.pack('!BBBB', 5, 0, 0, 0)
buf += struct.pack("!BBBB", 5, 0, 0, 0)
# agent OID
buf += struct.pack('!L', 0)
buf += struct.pack("!L", 0)
# Agent Desc
buf += self.encode_octet('MyAgent')
buf += self.encode_octet("MyAgent")
elif self.type == agentx.AGENTX_PING_PDU:
# No extra data
@ -132,15 +137,14 @@ class PDU(object):
range_subid = 0
timeout = 5
priority = 127
buf += struct.pack('BBBB', timeout, priority, range_subid, 0)
buf += struct.pack("BBBB", timeout, priority, range_subid, 0)
# Sub Tree
buf += self.encode_oid(self.oid)
elif self.type == agentx.AGENTX_RESPONSE_PDU:
buf += struct.pack('!LHH', 0, self.error, self.error_index)
buf += struct.pack("!LHH", 0, self.error, self.error_index)
for value in self.values:
buf += self.encode_value(value['type'], value['name'],
value['value'])
buf += self.encode_value(value["type"], value["name"], value["value"])
else:
# Unsupported PDU type
@ -156,27 +160,27 @@ class PDU(object):
def decode_oid(self):
try:
t = struct.unpack('!BBBB', self.decode_buf[:4])
t = struct.unpack("!BBBB", self.decode_buf[:4])
self.decode_buf = self.decode_buf[4:]
ret = {
'n_subid': t[0],
'prefix': t[1],
'include': t[2],
'reserved': t[3],
"n_subid": t[0],
"prefix": t[1],
"include": t[2],
"reserved": t[3],
}
sub_ids = []
if ret['prefix']:
if ret["prefix"]:
sub_ids = [1, 3, 6, 1]
sub_ids.append(ret['prefix'])
for i in range(ret['n_subid']):
t = struct.unpack('!L', self.decode_buf[:4])
sub_ids.append(ret["prefix"])
for i in range(ret["n_subid"]):
t = struct.unpack("!L", self.decode_buf[:4])
self.decode_buf = self.decode_buf[4:]
sub_ids.append(t[0])
oid = '.'.join(str(i) for i in sub_ids)
return oid, ret['include']
oid = ".".join(str(i) for i in sub_ids)
return oid, ret["include"]
except Exception as e:
logger.exception('Invalid packing OID header')
logger.debug('%s' % pprint.pformat(self.decode_buf))
logger.exception("Invalid packing OID header")
logger.debug("%s" % pprint.pformat(self.decode_buf))
def decode_search_range(self):
start_oid, include = self.decode_oid()
@ -193,115 +197,122 @@ class PDU(object):
def decode_octet(self):
try:
t = struct.unpack('!L', self.decode_buf[:4])
t = struct.unpack("!L", self.decode_buf[:4])
l = t[0]
self.decode_buf = self.decode_buf[4:]
padding = 4 - (l % 4)
buf = self.decode_buf[:l]
self.decode_buf = self.decode_buf[l + padding:]
self.decode_buf = self.decode_buf[l + padding :]
return buf
except Exception as e:
logger.exception('Invalid packing octet header')
logger.exception("Invalid packing octet header")
def decode_value(self):
try:
vtype, _ = struct.unpack('!HH', self.decode_buf[:4])
vtype, _ = struct.unpack("!HH", self.decode_buf[:4])
self.decode_buf = self.decode_buf[4:]
except Exception as e:
logger.exception('Invalid packing value header')
logger.exception("Invalid packing value header")
oid, _ = self.decode_oid()
if vtype in [
agentx.TYPE_INTEGER, agentx.TYPE_COUNTER32,
agentx.TYPE_GAUGE32, agentx.TYPE_TIMETICKS
agentx.TYPE_INTEGER,
agentx.TYPE_COUNTER32,
agentx.TYPE_GAUGE32,
agentx.TYPE_TIMETICKS,
]:
data = struct.unpack('!L', self.decode_buf[:4])
data = struct.unpack("!L", self.decode_buf[:4])
data = data[0]
self.decode_buf = self.decode_buf[4:]
elif vtype in [agentx.TYPE_COUNTER64]:
data = struct.unpack('!Q', self.decode_buf[:8])
data = struct.unpack("!Q", self.decode_buf[:8])
data = data[0]
self.decode_buf = self.decode_buf[8:]
elif vtype in [agentx.TYPE_OBJECTIDENTIFIER]:
data, _ = self.decode_oid()
elif vtype in [
agentx.TYPE_IPADDRESS, agentx.TYPE_OPAQUE,
agentx.TYPE_OCTETSTRING
agentx.TYPE_IPADDRESS,
agentx.TYPE_OPAQUE,
agentx.TYPE_OCTETSTRING,
]:
data = self.decode_octet()
elif vtype in [
agentx.TYPE_NULL, agentx.TYPE_NOSUCHOBJECT,
agentx.TYPE_NOSUCHINSTANCE, agentx.TYPE_ENDOFMIBVIEW
agentx.TYPE_NULL,
agentx.TYPE_NOSUCHOBJECT,
agentx.TYPE_NOSUCHINSTANCE,
agentx.TYPE_ENDOFMIBVIEW,
]:
# No data
data = None
else:
logger.error('Unknown Type: %s' % vtype)
return {'type': vtype, 'name': oid, 'data': data}
logger.error("Unknown Type: %s" % vtype)
return {"type": vtype, "name": oid, "data": data}
def decode_header(self):
try:
t = struct.unpack('!BBBBLLLL', self.decode_buf[:20])
t = struct.unpack("!BBBBLLLL", self.decode_buf[:20])
self.decode_buf = self.decode_buf[20:]
ret = {
'version': t[0],
'pdu_type': t[1],
'pdu_type_name': agentx.PDU_TYPE_NAME[t[1]],
'flags': t[2],
'reserved': t[3],
'session_id': t[4],
'transaction_id': t[5],
'packet_id': t[6],
'payload_length': t[7],
"version": t[0],
"pdu_type": t[1],
"pdu_type_name": agentx.PDU_TYPE_NAME[t[1]],
"flags": t[2],
"reserved": t[3],
"session_id": t[4],
"transaction_id": t[5],
"packet_id": t[6],
"payload_length": t[7],
}
self.state = ret
self.type = ret['pdu_type']
self.session_id = ret['session_id']
self.packet_id = ret['packet_id']
self.transaction_id = ret['transaction_id']
self.decode_buf = self.decode_buf[:ret['payload_length']]
if ret['flags'] & 0x08: # content present
self.type = ret["pdu_type"]
self.session_id = ret["session_id"]
self.packet_id = ret["packet_id"]
self.transaction_id = ret["transaction_id"]
self.decode_buf = self.decode_buf[: ret["payload_length"]]
if ret["flags"] & 0x08: # content present
context = self.decode_octet()
logger.debug('Context: %s' % context)
logger.debug("Context: %s" % context)
return ret
except Exception as e:
logger.exception('Invalid packing: %d' % len(self.decode_buf))
logger.debug('%s' % pprint.pformat(self.decode_buf))
logger.exception("Invalid packing: %d" % len(self.decode_buf))
logger.debug("%s" % pprint.pformat(self.decode_buf))
def decode(self, buf):
self.set_decode_buf(buf)
ret = self.decode_header()
if ret['pdu_type'] == agentx.AGENTX_RESPONSE_PDU:
if ret["pdu_type"] == agentx.AGENTX_RESPONSE_PDU:
# Decode Response Header
t = struct.unpack('!LHH', self.decode_buf[:8])
t = struct.unpack("!LHH", self.decode_buf[:8])
self.decode_buf = self.decode_buf[8:]
self.response = {
'sysUpTime': t[0],
'error': t[1],
'error_name': agentx.ERROR_NAMES[t[1]],
'index': t[2],
"sysUpTime": t[0],
"error": t[1],
"error_name": agentx.ERROR_NAMES[t[1]],
"index": t[2],
}
# Decode VarBindList
self.values = []
while len(self.decode_buf):
self.values.append(self.decode_value())
elif ret['pdu_type'] == agentx.AGENTX_GET_PDU:
elif ret["pdu_type"] == agentx.AGENTX_GET_PDU:
self.range_list = self.decode_search_range_list()
elif ret['pdu_type'] == agentx.AGENTX_GETNEXT_PDU:
elif ret["pdu_type"] == agentx.AGENTX_GETNEXT_PDU:
self.range_list = self.decode_search_range_list()
elif ret['pdu_type'] == agentx.AGENTX_TESTSET_PDU:
elif ret["pdu_type"] == agentx.AGENTX_TESTSET_PDU:
# Decode VarBindList
self.values = []
while len(self.decode_buf):
self.values.append(self.decode_value())
elif ret['pdu_type'] in [
agentx.AGENTX_COMMITSET_PDU, agentx.AGENTX_UNDOSET_PDU,
agentx.AGENTX_CLEANUPSET_PDU
elif ret["pdu_type"] in [
agentx.AGENTX_COMMITSET_PDU,
agentx.AGENTX_UNDOSET_PDU,
agentx.AGENTX_CLEANUPSET_PDU,
]:
pass
else:
pdu_type_str = agentx.PDU_TYPE_NAME.get(
ret['pdu_type'], 'Unknown:' + str(ret['pdu_type']))
logger.error('Unsupported PDU type:' + pdu_type_str)
ret["pdu_type"], "Unknown:" + str(ret["pdu_type"])
)
logger.error("Unsupported PDU type:" + pdu_type_str)