mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
Plugin olsrd: port to python3 and support micropython without micropython-lib
The code was python3-compatible before, thus it was just a matter of changing "python" to "python3". The micropython approach previously relied on micropython-lib being installed. Now the basic micropython package (on OpenWrt) is sufficient.
This commit is contained in:
parent
76d875fd55
commit
eba742cea2
1 changed files with 90 additions and 26 deletions
|
@ -35,14 +35,13 @@ Collect basic information about the neighbours of an OLSR node:
|
||||||
|
|
||||||
This plugin works with the following python interpreters:
|
This plugin works with the following python interpreters:
|
||||||
|
|
||||||
* Python 2
|
|
||||||
* Python 3
|
* Python 3
|
||||||
* micropython (e.g. OpenWrt)
|
* micropython (e.g. OpenWrt)
|
||||||
|
|
||||||
|
|
||||||
=head1 VERSION
|
=head1 VERSION
|
||||||
|
|
||||||
0.4
|
0.5
|
||||||
|
|
||||||
|
|
||||||
=head1 AUTHOR
|
=head1 AUTHOR
|
||||||
|
@ -84,7 +83,7 @@ MICROPYTHON_BIN=$(which micropython || true)
|
||||||
if [ -n "$MICROPYTHON_BIN" ]; then
|
if [ -n "$MICROPYTHON_BIN" ]; then
|
||||||
"$MICROPYTHON_BIN" -X "heapsize=${MICROPYTHON_HEAP:-512k}" "$0" "$@"
|
"$MICROPYTHON_BIN" -X "heapsize=${MICROPYTHON_HEAP:-512k}" "$0" "$@"
|
||||||
else
|
else
|
||||||
python "$0" "$@"
|
python3 "$0" "$@"
|
||||||
fi
|
fi
|
||||||
exit $?
|
exit $?
|
||||||
|
|
||||||
|
@ -93,14 +92,78 @@ exit $?
|
||||||
true <<EOF
|
true <<EOF
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import socket
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
from os import linesep
|
||||||
|
except ImportError:
|
||||||
|
linesep = "\n"
|
||||||
|
|
||||||
plugin_version = "0.4"
|
# import "os" from standard library or "uos" from micropython
|
||||||
|
try:
|
||||||
|
from os import access, getenv, getpid, system, unlink
|
||||||
|
except ImportError:
|
||||||
|
from uos import getenv, system, unlink
|
||||||
|
import ffi
|
||||||
|
libc = ffi.open('libc.so')
|
||||||
|
getpid = libc.func("i", "getpid", "")
|
||||||
|
access_raw = libc.func("i", "access", "si")
|
||||||
|
|
||||||
|
def access(path, mode):
|
||||||
|
return access_raw(path, mode) == 0
|
||||||
|
|
||||||
|
# import "socket" from standard library or "usocket" from micropython
|
||||||
|
try:
|
||||||
|
import socket
|
||||||
|
from socket import socket as socket_cls
|
||||||
|
from socket import create_connection
|
||||||
|
except ImportError:
|
||||||
|
import usocket as socket
|
||||||
|
from usocket import socket as orginal_socket_cls
|
||||||
|
|
||||||
|
def _resolve_addr(addr):
|
||||||
|
if isinstance(addr, (bytes, bytearray)):
|
||||||
|
return addr
|
||||||
|
family = socket.AF_INET
|
||||||
|
if len(addr) != 2:
|
||||||
|
family = socket.AF_INET6
|
||||||
|
if addr[0] == "":
|
||||||
|
a = "0.0.0.0" if family == socket.AF_INET else "::"
|
||||||
|
else:
|
||||||
|
a = addr[0]
|
||||||
|
a = socket.getaddrinfo(a, addr[1], family)
|
||||||
|
return a[0][4]
|
||||||
|
|
||||||
|
def create_connection(addr, timeout=None, source_address=None):
|
||||||
|
s = socket_cls()
|
||||||
|
ais = socket.getaddrinfo(addr[0], addr[1])
|
||||||
|
for ai in ais:
|
||||||
|
try:
|
||||||
|
s.connect(ai[4])
|
||||||
|
return s
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class socket_cls(orginal_socket_cls):
|
||||||
|
def accept(self):
|
||||||
|
s, addr = super().accept()
|
||||||
|
addr = socket.sockaddr(addr)
|
||||||
|
return (s, (socket.inet_ntop(addr[0], addr[1]), addr[2]))
|
||||||
|
|
||||||
|
def bind(self, addr):
|
||||||
|
return super().bind(_resolve_addr(addr))
|
||||||
|
|
||||||
|
def connect(self, addr):
|
||||||
|
return super().connect(_resolve_addr(addr))
|
||||||
|
|
||||||
|
def sendall(self, *args):
|
||||||
|
return self.send(*args)
|
||||||
|
|
||||||
|
def sendto(self, data, addr):
|
||||||
|
return super().sendto(data, _resolve_addr(addr))
|
||||||
|
|
||||||
|
|
||||||
|
plugin_version = "0.5"
|
||||||
|
|
||||||
LQ_GRAPH_CONFIG = """
|
LQ_GRAPH_CONFIG = """
|
||||||
graph_title {title}
|
graph_title {title}
|
||||||
|
@ -124,7 +187,7 @@ lq{suffix}.min 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NEIGHBOUR_COUNT_CONFIG = """
|
NEIGHBOUR_COUNT_CONFIG = """
|
||||||
graph_title Reachable nodes via neighbours
|
graph_title Reachable nodes via OLSR neighbours
|
||||||
graph_vlabel Number of Nodes
|
graph_vlabel Number of Nodes
|
||||||
graph_category network
|
graph_category network
|
||||||
graph_info Count the number of locally known routes passing through each direct neighbour. \
|
graph_info Count the number of locally known routes passing through each direct neighbour. \
|
||||||
|
@ -151,9 +214,6 @@ graph_scale no
|
||||||
|
|
||||||
NEIGHBOUR_PING_VALUE = """neighbour_{host_fieldname}.label {host}"""
|
NEIGHBOUR_PING_VALUE = """neighbour_{host_fieldname}.label {host}"""
|
||||||
|
|
||||||
# micropython (as of 2015) does not contain "os.linesep"
|
|
||||||
LINESEP = getattr(os, "linesep", "\n")
|
|
||||||
|
|
||||||
|
|
||||||
def get_clean_fieldname(name):
|
def get_clean_fieldname(name):
|
||||||
chars = []
|
chars = []
|
||||||
|
@ -166,9 +226,9 @@ def get_clean_fieldname(name):
|
||||||
|
|
||||||
|
|
||||||
def query_olsrd_txtservice(section=""):
|
def query_olsrd_txtservice(section=""):
|
||||||
host = os.getenv("OLSRD_HOST", "localhost")
|
host = getenv("OLSRD_HOST") or "127.0.0.1"
|
||||||
port = os.getenv("OLSRD_TXTINFO_PORT", "2006")
|
port = getenv("OLSRD_TXTINFO_PORT") or "2006"
|
||||||
conn = socket.create_connection((host, port), 1.0)
|
conn = create_connection((host, port), 1.0)
|
||||||
try:
|
try:
|
||||||
# Python3
|
# Python3
|
||||||
request = bytes("/%s" % section, "ascii")
|
request = bytes("/%s" % section, "ascii")
|
||||||
|
@ -182,8 +242,12 @@ def query_olsrd_txtservice(section=""):
|
||||||
for line in fconn.readlines():
|
for line in fconn.readlines():
|
||||||
if in_header:
|
if in_header:
|
||||||
if not line.strip():
|
if not line.strip():
|
||||||
# the empty line marks the end of the header
|
# the empty line marks the end of the http-like header
|
||||||
in_header = False
|
in_header = False
|
||||||
|
elif line.startswith("Table:"):
|
||||||
|
# since olsr v0.9.6 there is no http-like header anymore
|
||||||
|
in_header = False
|
||||||
|
in_body_count = 1
|
||||||
# ignore header lines (nothing to be done)
|
# ignore header lines (nothing to be done)
|
||||||
else:
|
else:
|
||||||
# skip the first two body lines - they are table headers
|
# skip the first two body lines - they are table headers
|
||||||
|
@ -258,23 +322,23 @@ def get_olsr_links():
|
||||||
|
|
||||||
def _read_file(filename):
|
def _read_file(filename):
|
||||||
try:
|
try:
|
||||||
return open(filename, "r").read().split(LINESEP)
|
return open(filename, "r").read().split(linesep)
|
||||||
except OSError:
|
except OSError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def get_ping_times(hosts):
|
def get_ping_times(hosts):
|
||||||
tempfile = "/tmp/munin-olsrd-{pid}.tmp".format(pid=os.getpid())
|
tempfile = "/tmp/munin-olsrd-{pid}.tmp".format(pid=getpid())
|
||||||
command = ('for host in {hosts}; do echo -n "$host "; '
|
command = ('for host in {hosts}; do echo -n "$host "; '
|
||||||
'ping -c 1 -w 1 "$host" | grep /avg/ || echo; done >{tempfile}'
|
'ping -c 1 -w 1 "$host" | grep /avg/ || echo; done >{tempfile}'
|
||||||
.format(hosts=" ".join(hosts), tempfile=tempfile))
|
.format(hosts=" ".join(hosts), tempfile=tempfile))
|
||||||
# micropython supports only "os.system" (as of 2015) - thus we need to stick with it for
|
# micropython supports only "os.system" (as of 2015) - thus we need to stick with it for
|
||||||
# OpenWrt.
|
# OpenWrt.
|
||||||
returncode = os.system(command)
|
returncode = system(command)
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
return {}
|
return {}
|
||||||
lines = _read_file(tempfile)
|
lines = _read_file(tempfile)
|
||||||
os.unlink(tempfile)
|
unlink(tempfile)
|
||||||
# example output for one host:
|
# example output for one host:
|
||||||
# 192.168.2.41 round-trip min/avg/max = 4.226/4.226/4.226 ms
|
# 192.168.2.41 round-trip min/avg/max = 4.226/4.226/4.226 ms
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -293,11 +357,11 @@ def do_config():
|
||||||
# link quality with regard to neighbours
|
# link quality with regard to neighbours
|
||||||
print("multigraph olsr_link_quality")
|
print("multigraph olsr_link_quality")
|
||||||
print(LQ_GRAPH_CONFIG.format(title="OLSR Link Quality"))
|
print(LQ_GRAPH_CONFIG.format(title="OLSR Link Quality"))
|
||||||
for link in links:
|
for index, link in enumerate(links):
|
||||||
print(LQ_VALUES_CONFIG.format(
|
print(LQ_VALUES_CONFIG.format(
|
||||||
label=link["remote"],
|
label=link["remote"],
|
||||||
suffix="_{host}".format(host=get_clean_fieldname(link["remote"])),
|
suffix="_{host}".format(host=get_clean_fieldname(link["remote"])),
|
||||||
draw_type="AREASTACK"))
|
draw_type=("AREA" if index == 0 else "AREASTACK")))
|
||||||
for link in links:
|
for link in links:
|
||||||
print("multigraph olsr_link_quality.host_{remote}"
|
print("multigraph olsr_link_quality.host_{remote}"
|
||||||
.format(remote=get_clean_fieldname(link["remote"])))
|
.format(remote=get_clean_fieldname(link["remote"])))
|
||||||
|
@ -315,7 +379,7 @@ def do_config():
|
||||||
|
|
||||||
# neighbour ping
|
# neighbour ping
|
||||||
print("multigraph olsr_neighbour_ping")
|
print("multigraph olsr_neighbour_ping")
|
||||||
print(NEIGHBOUR_PING_CONFIG.format(title="Ping time of neighbours"))
|
print(NEIGHBOUR_PING_CONFIG.format(title="Ping time of OLSR neighbours"))
|
||||||
for link in links:
|
for link in links:
|
||||||
print(NEIGHBOUR_PING_VALUE
|
print(NEIGHBOUR_PING_VALUE
|
||||||
.format(host=link["remote"], host_fieldname=get_clean_fieldname(link["remote"])))
|
.format(host=link["remote"], host_fieldname=get_clean_fieldname(link["remote"])))
|
||||||
|
@ -375,11 +439,11 @@ if __name__ == "__main__":
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
if sys.argv[1] == "config":
|
if sys.argv[1] == "config":
|
||||||
do_config()
|
do_config()
|
||||||
if os.getenv("MUNIN_CAP_DIRTYCONFIG") == "1":
|
if getenv("MUNIN_CAP_DIRTYCONFIG") == "1":
|
||||||
do_fetch()
|
do_fetch()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif sys.argv[1] == "autoconf":
|
elif sys.argv[1] == "autoconf":
|
||||||
if os.path.exists(os.getenv('OLSRD_BIN_PATH', '/usr/sbin/olsrd')):
|
if access(getenv('OLSRD_BIN_PATH') or '/usr/sbin/olsrd', 0):
|
||||||
print('yes')
|
print('yes')
|
||||||
else:
|
else:
|
||||||
print('no')
|
print('no')
|
||||||
|
@ -392,7 +456,7 @@ if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# unknown argument
|
# unknown argument
|
||||||
sys.stderr.write("Unknown argument{eol}".format(eol=LINESEP))
|
sys.stderr.write("Unknown argument{eol}".format(eol=linesep))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
do_fetch()
|
do_fetch()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue