mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
olsrd: various improvements
* support dirty config * add perldoc header * flake8 and shellcheck clean
This commit is contained in:
parent
9a6d3e449f
commit
04b9fc0463
@ -1,62 +1,88 @@
|
||||
#!/bin/sh
|
||||
# weird shebang? See below: "interpreter selection"
|
||||
#
|
||||
# Collect basic information about the neighbours of an OLSR node:
|
||||
# * link quality
|
||||
# * neighbour link quality
|
||||
# * number of nodes reachable behind each neighbour
|
||||
# * ping times of direct neighbours
|
||||
#
|
||||
# This plugin works with the following python interpreters:
|
||||
# * Python 2
|
||||
# * Python 3
|
||||
# * micropython
|
||||
#
|
||||
# Environment variables:
|
||||
# * OLSRD_HOST: name or IP of the host running the txtinfo plugin (default: localhost)
|
||||
# * OLSRD_TXTINFO_PORT: the port that the txtinfo plugin is listening to (default: 2006)
|
||||
# * OLSRD_BIN_PATH: name of the olsrd binary (only used for 'autoconf', defaults to /usr/sbin/olsrd)
|
||||
# * MICROPYTHON_HEAP: adjust this parameter for micropython if your olsr network contains
|
||||
# more than a few thousand nodes (default: 512k)
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2015 Lars Kruse <devel@sumpfralle.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Magic markers
|
||||
#%# capabilities=autoconf
|
||||
#%# family=auto
|
||||
|
||||
"""true"
|
||||
: <<=cut
|
||||
|
||||
=head1 NAME
|
||||
|
||||
olsrd - Monitor the state of an OLSR-based routing network
|
||||
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
Information is parsed from the output of "txtinfo" plugin for olsrd.
|
||||
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
Environment variables:
|
||||
|
||||
* OLSRD_HOST: name or IP of the host running the txtinfo plugin (default: localhost)
|
||||
* OLSRD_TXTINFO_PORT: the port that the txtinfo plugin is listening to (default: 2006)
|
||||
* OLSRD_BIN_PATH: name of the olsrd binary (only used for 'autoconf', default: /usr/sbin/olsrd)
|
||||
* MICROPYTHON_HEAP: adjust this parameter for micropython if your olsr network contains
|
||||
more than a few thousand nodes (default: 512k)
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Collect basic information about the neighbours of an OLSR node:
|
||||
|
||||
* link quality
|
||||
* neighbour link quality
|
||||
* number of nodes reachable behind each neighbour
|
||||
* ping times of direct neighbours
|
||||
|
||||
This plugin works with the following python interpreters:
|
||||
|
||||
* Python 2
|
||||
* Python 3
|
||||
* micropython (e.g. OpenWrt)
|
||||
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
0.4
|
||||
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Lars Kruse <devel@sumpfralle.de>
|
||||
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv3 or above
|
||||
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
# ****************** Interpreter Selection ***************
|
||||
# This unbelievable dirty hack allows to find a suitable python interpreter.
|
||||
# This is specifically useful for OpenWRT where typically only micropython is available.
|
||||
#
|
||||
# Additionally we need to run micropython with additional startup options.
|
||||
# This is necessary due to our demand for more than 128k heap (this default is sufficient for only 400 olsr nodes).
|
||||
# This is necessary due to our demand for more than 128k heap (this default is sufficient for only
|
||||
# 400 olsr nodes).
|
||||
#
|
||||
# This "execution hack" works as follows:
|
||||
# * the script is executed by busybox ash or another shell
|
||||
# * the above line (three quotes before and one quote after 'true') evaluates differently for shell and python:
|
||||
# * shell: run "true" (i.e. nothing happens)
|
||||
# * python: ignore everything up to the next three consecutive quotes
|
||||
# * the above line (three quotes before and one quote after 'true') evaluates differently for
|
||||
# shell and python:
|
||||
# * shell: run "true" (i.e. nothing happens)
|
||||
# * python: ignore everything up to the next three consecutive quotes
|
||||
# Thus we may place shell code here that will take care for selecting an interpreter.
|
||||
|
||||
# prefer micropython if it is available - otherwise fall back to any python (2 or 3)
|
||||
if which micropython >/dev/null; then
|
||||
/usr/bin/micropython -X "heapsize=${MICROPYTHON_HEAP:-512k}" "$0" "$@"
|
||||
MICROPYTHON_BIN=$(which micropython || true)
|
||||
if [ -n "$MICROPYTHON_BIN" ]; then
|
||||
"$MICROPYTHON_BIN" -X "heapsize=${MICROPYTHON_HEAP:-512k}" "$0" "$@"
|
||||
else
|
||||
python "$0" "$@"
|
||||
fi
|
||||
@ -68,19 +94,20 @@ true <<EOF
|
||||
"""
|
||||
|
||||
|
||||
plugin_version = "0.3"
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import socket
|
||||
import sys
|
||||
|
||||
|
||||
plugin_version = "0.4"
|
||||
|
||||
LQ_GRAPH_CONFIG = """
|
||||
graph_title {title}
|
||||
graph_vlabel Link Quality (-) / Neighbour Link Quality (+)
|
||||
graph_category network
|
||||
graph_info OLSR estimates the quality of a connection by the ratio of successfully received (link quality) and transmitted (neighbour link quality) hello packets.
|
||||
graph_info OLSR estimates the quality of a connection by the ratio of successfully received \
|
||||
(link quality) and transmitted (neighbour link quality) hello packets.
|
||||
"""
|
||||
|
||||
LQ_VALUES_CONFIG = """
|
||||
@ -100,7 +127,10 @@ NEIGHBOUR_COUNT_CONFIG = """
|
||||
graph_title Reachable nodes via neighbours
|
||||
graph_vlabel Number of Nodes
|
||||
graph_category network
|
||||
graph_info Count the number of locally known routes passing through each direct neighbour. This number is a good approximation of the number of mesh nodes reachable via this specific neighbour. MIDs (alternative addresses of an OLSR node) and HNAs (host network announcements) are ignored.
|
||||
graph_info Count the number of locally known routes passing through each direct neighbour. \
|
||||
This number is a good approximation for the number of mesh nodes reachable via this specific \
|
||||
neighbour. MIDs (alternative addresses of an OLSR node) and HNAs (host network announcements) are \
|
||||
ignored.
|
||||
"""
|
||||
|
||||
NEIGHBOUR_COUNT_VALUE = """
|
||||
@ -125,7 +155,14 @@ NEIGHBOUR_PING_VALUE = """neighbour_{host_fieldname}.label {host}"""
|
||||
LINESEP = getattr(os, "linesep", "\n")
|
||||
|
||||
|
||||
get_clean_fieldname = lambda name: "".join([(("a" <= char.lower() <= "z") or ((index == 0) or ("0" <= char <= "9"))) and char or "_" for index, char in enumerate(name)])
|
||||
def get_clean_fieldname(name):
|
||||
chars = []
|
||||
for index, char in enumerate(name):
|
||||
if ("a" <= char.lower() <= "z") or ((index == 0) or ("0" <= char <= "9")):
|
||||
chars.append(char)
|
||||
else:
|
||||
chars.append("_")
|
||||
return "".join(chars)
|
||||
|
||||
|
||||
def query_olsrd_txtservice(section=""):
|
||||
@ -228,9 +265,11 @@ def _read_file(filename):
|
||||
|
||||
def get_ping_times(hosts):
|
||||
tempfile = "/tmp/munin-olsrd-{pid}.tmp".format(pid=os.getpid())
|
||||
command = 'for host in {hosts}; do echo -n "$host "; ping -c 1 -w 1 "$host" | grep /avg/ || echo; done >{tempfile}'\
|
||||
.format(hosts=" ".join(hosts), tempfile=tempfile)
|
||||
# micropython supports only "os.system" (as of 2015) - thus we need to stick with it for openwrt
|
||||
command = ('for host in {hosts}; do echo -n "$host "; '
|
||||
'ping -c 1 -w 1 "$host" | grep /avg/ || echo; done >{tempfile}'
|
||||
.format(hosts=" ".join(hosts), tempfile=tempfile))
|
||||
# micropython supports only "os.system" (as of 2015) - thus we need to stick with it for
|
||||
# OpenWrt.
|
||||
returncode = os.system(command)
|
||||
if returncode != 0:
|
||||
return {}
|
||||
@ -248,71 +287,48 @@ def get_ping_times(hosts):
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# parse arguments
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1]=="config":
|
||||
links = list(get_olsr_links())
|
||||
def do_config():
|
||||
links = list(get_olsr_links())
|
||||
|
||||
# link quality with regard to neighbours
|
||||
print("multigraph olsr_link_quality")
|
||||
print(LQ_GRAPH_CONFIG.format(title="OLSR Link Quality"))
|
||||
is_first = True
|
||||
for link in links:
|
||||
print(LQ_VALUES_CONFIG.format(label=link["remote"],
|
||||
suffix="_{host}".format(host=get_clean_fieldname(link["remote"])),
|
||||
draw_type=("AREA" if is_first else "STACK")))
|
||||
is_first = False
|
||||
is_first = True
|
||||
for link in links:
|
||||
print("multigraph olsr_link_quality.host_{remote}".format(remote=get_clean_fieldname(link["remote"])))
|
||||
print(LQ_GRAPH_CONFIG.format(title="Link Quality towards {host}".format(host=link["remote"])))
|
||||
print(LQ_VALUES_CONFIG.format(label="Link Quality", suffix="", draw_type="AREA"))
|
||||
is_first = False
|
||||
# link quality with regard to neighbours
|
||||
print("multigraph olsr_link_quality")
|
||||
print(LQ_GRAPH_CONFIG.format(title="OLSR Link Quality"))
|
||||
for link in links:
|
||||
print(LQ_VALUES_CONFIG.format(
|
||||
label=link["remote"],
|
||||
suffix="_{host}".format(host=get_clean_fieldname(link["remote"])),
|
||||
draw_type="AREASTACK"))
|
||||
for link in links:
|
||||
print("multigraph olsr_link_quality.host_{remote}"
|
||||
.format(remote=get_clean_fieldname(link["remote"])))
|
||||
title = "Link Quality towards {host}".format(host=link["remote"])
|
||||
print(LQ_GRAPH_CONFIG.format(title=title))
|
||||
print(LQ_VALUES_CONFIG.format(label="Link Quality", suffix="", draw_type="AREA"))
|
||||
|
||||
# link count ("number of nodes behind each neighbour")
|
||||
print("multigraph olsr_neighbour_link_count")
|
||||
print(NEIGHBOUR_COUNT_CONFIG)
|
||||
is_first = True
|
||||
for link in links:
|
||||
print(NEIGHBOUR_COUNT_VALUE
|
||||
.format(host=link["remote"],
|
||||
host_fieldname=get_clean_fieldname(link["remote"]),
|
||||
draw_type=("AREA" if is_first else "STACK")))
|
||||
is_first = False
|
||||
# link count ("number of nodes behind each neighbour")
|
||||
print("multigraph olsr_neighbour_link_count")
|
||||
print(NEIGHBOUR_COUNT_CONFIG)
|
||||
for link in links:
|
||||
print(NEIGHBOUR_COUNT_VALUE
|
||||
.format(host=link["remote"], host_fieldname=get_clean_fieldname(link["remote"]),
|
||||
draw_type="AREASTACK"))
|
||||
|
||||
# neighbour ping
|
||||
print("multigraph olsr_neighbour_ping")
|
||||
print(NEIGHBOUR_PING_CONFIG.format(title="Ping time of neighbours"))
|
||||
for link in links:
|
||||
print(NEIGHBOUR_PING_VALUE
|
||||
.format(host=link["remote"],
|
||||
host_fieldname=get_clean_fieldname(link["remote"])))
|
||||
# neighbour pings - single subgraphs
|
||||
for link in links:
|
||||
remote = get_clean_fieldname(link["remote"])
|
||||
print("multigraph olsr_neighbour_ping.host_{remote}".format(remote=remote))
|
||||
print(NEIGHBOUR_PING_CONFIG.format(title="Ping time of {remote}".format(remote=remote)))
|
||||
print(NEIGHBOUR_PING_VALUE.format(host=link["remote"], host_fieldname=remote))
|
||||
# neighbour ping
|
||||
print("multigraph olsr_neighbour_ping")
|
||||
print(NEIGHBOUR_PING_CONFIG.format(title="Ping time of neighbours"))
|
||||
for link in links:
|
||||
print(NEIGHBOUR_PING_VALUE
|
||||
.format(host=link["remote"], host_fieldname=get_clean_fieldname(link["remote"])))
|
||||
# neighbour pings - single subgraphs
|
||||
for link in links:
|
||||
remote = get_clean_fieldname(link["remote"])
|
||||
print("multigraph olsr_neighbour_ping.host_{remote}".format(remote=remote))
|
||||
title = "Ping time of {remote}".format(remote=remote)
|
||||
print(NEIGHBOUR_PING_CONFIG.format(title=title))
|
||||
print(NEIGHBOUR_PING_VALUE.format(host=link["remote"], host_fieldname=remote))
|
||||
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "autoconf":
|
||||
if os.path.exists(os.getenv('OLSRD_BIN_PATH', '/usr/sbin/olsrd')):
|
||||
print('yes')
|
||||
else:
|
||||
print('no')
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "version":
|
||||
print('olsrd Munin plugin, version %s' % plugin_version)
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "":
|
||||
# ignore
|
||||
pass
|
||||
else:
|
||||
# unknown argument
|
||||
sys.stderr.write("Unknown argument{eol}".format(eol=LINESEP))
|
||||
sys.exit(1)
|
||||
|
||||
def do_fetch():
|
||||
# output values
|
||||
links = list(get_olsr_links())
|
||||
|
||||
@ -353,6 +369,34 @@ if __name__ == "__main__":
|
||||
print("multigraph olsr_neighbour_ping.host_{remote}".format(remote=remote))
|
||||
print("neighbour_{remote}.value {value}".format(remote=remote, value=value))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# parse arguments
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] == "config":
|
||||
do_config()
|
||||
if os.getenv("MUNIN_CAP_DIRTYCONFIG") == "1":
|
||||
do_fetch()
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "autoconf":
|
||||
if os.path.exists(os.getenv('OLSRD_BIN_PATH', '/usr/sbin/olsrd')):
|
||||
print('yes')
|
||||
else:
|
||||
print('no')
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "version":
|
||||
print('olsrd Munin plugin, version %s' % plugin_version)
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == "":
|
||||
# ignore
|
||||
pass
|
||||
else:
|
||||
# unknown argument
|
||||
sys.stderr.write("Unknown argument{eol}".format(eol=LINESEP))
|
||||
sys.exit(1)
|
||||
|
||||
do_fetch()
|
||||
|
||||
# final marker for shell / python hybrid script (see "Interpreter Selection")
|
||||
EOF = True
|
||||
EOF
|
||||
|
Loading…
Reference in New Issue
Block a user