#!/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 # # 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 . # # Magic markers #%# capabilities=autoconf #%# family=auto """true" # ****************** 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 "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 # 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" "$@" else python "$0" "$@" fi exit $? # For shell: ignore everything starting from here until the last line of this file. # This is necessary for syntax checkers that try to complain about invalid shell syntax below. true < 1: host = tokens[0] avg_ping = tokens[-2].split("/")[1] result[host] = float(avg_ping) return result if __name__ == "__main__": # parse arguments if len(sys.argv) > 1: if sys.argv[1]=="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 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 # 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)) 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) # output values links = list(get_olsr_links()) # overview graph for the link quality (ETX) of all neighbours print("multigraph olsr_link_quality") for link in links: print("lq_{remote}.value {lq:f}".format(lq=link["lq"], remote=get_clean_fieldname(link["remote"]))) print("nlq_{remote}.value {nlq:f}".format(nlq=link["nlq"], remote=get_clean_fieldname(link["remote"]))) # detailed ETX graph for each single neighbour link for link in links: print("multigraph olsr_link_quality.host_{remote}" .format(remote=get_clean_fieldname(link["remote"]))) print("lq.value {lq:f}".format(lq=link["lq"])) print("nlq.value {nlq:f}".format(nlq=link["nlq"])) # count the links/nodes behind each neighbour node print("multigraph olsr_neighbour_link_count") for link in links: print("neighbour_{host_fieldname}.value {value}" .format(value=link["route_count"], host_fieldname=get_clean_fieldname(link["remote"]))) # overview of ping roundtrip times print("multigraph olsr_neighbour_ping") ping_times = get_ping_times([link["remote"] for link in links]) for link in links: ping_time = ping_times.get(link["remote"], None) if ping_time is not None: print("neighbour_{remote}.value {value:.4f}" .format(value=ping_time, remote=get_clean_fieldname(link["remote"]))) # single detailed graphs for the ping time of each link for link in links: ping_time = ping_times.get(link["remote"], None) if ping_time is not None: remote = get_clean_fieldname(link["remote"]) print("multigraph olsr_neighbour_ping.host_{remote}".format(remote=remote)) print("neighbour_{remote}.value {value:.4f}".format(remote=remote, value=ping_time)) # final marker for shell / python hybrid script (see "Interpreter Selection") EOF = True EOF