diff --git a/check-plugins/network-io/network-io b/check-plugins/network-io/network-io index 24b937b13..485055868 100755 --- a/check-plugins/network-io/network-io +++ b/check-plugins/network-io/network-io @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/lib64/linuxfabrik-monitoring-plugins/venv/bin/python # -*- coding: utf-8; py-indent-offset: 4 -*- # # Author: Linuxfabrik GmbH, Zurich, Switzerland @@ -12,7 +12,7 @@ import argparse import sys - +import re import lib.args import lib.base import lib.cache @@ -48,6 +48,21 @@ DEFAULT_IGNORE = [ ] DEFAULT_NO_MATCH_SEVERITY = 'ok' +def parse_speed_units(speed): + """Parse the unit and convert speed from bit to byte""" + if speed.endswith("k"): + return int(speed[0:-1]) * 1000 / 8 + elif speed.endswith("m"): + return int(speed[0:-1]) * 1000 ** 2 / 8 + elif speed.endswith("g"): + return int(speed[0:-1]) * 1000 ** 3 / 8 + elif speed.endswith("t"): + return int(speed[0:-1]) * 1000 ** 4 / 8 + else: + if re.search(r"\w$", speed): + lib.base.cu(f"Unsupported speed unit: {speed}") + sys.exit(STATE_UNKNOWN) + return int(speed) / 8 def parse_args(): """Parse command line arguments using argparse.""" @@ -124,6 +139,16 @@ def parse_args(): default=DEFAULT_WARN, ) + parser.add_argument( + '--interface-speed', + help='Set a fixed interface speed (max throughput). Use ":" for per-interface or just "" (or ":") to apply to all interfaces. ' + 'The speed is given in bits. Units can be: k, m, g, t. ' + 'Can be specified multiple times. Examples: --interface-speed eth0:1g --interface-speed 100m', + dest='INTERFACE_SPEED', + action='append', + default=[], + ) + args, _ = parser.parse_known_args() return args @@ -145,6 +170,39 @@ def main(): except SystemExit: sys.exit(STATE_UNKNOWN) + # parse interface speed mappings + iface_speeds = {} + global_iface_speed = None + for entry in args.INTERFACE_SPEED: + if not entry: + lib.base.cu(f'Invalid --interface-speed entry "{entry}", expected format ":" or ""') + sys.exit(STATE_UNKNOWN) + + # split into name:speed if possible. Accept either "name:speed", ":speed", or "speed" + if ':' in entry: + name_part, speed_part = entry.split(':', 1) + name = name_part.strip() or None + speed = speed_part.strip() + else: + name = None + speed = entry.strip() + + if not speed: + lib.base.cu(f'Invalid --interface-speed entry "{entry}", missing speed value') + sys.exit(STATE_UNKNOWN) + + try: + bit_per_second = parse_speed_units(speed) + except ValueError as e: + lib.base.cu(f'Invalid speed value in --interface-speed "{entry}": {e}') + sys.exit(STATE_UNKNOWN) + + if name is None: + # global speed for all interfaces (last one wins) + global_iface_speed = bit_per_second + else: + iface_speeds[name] = bit_per_second + conn = lib.base.coe( lib.db_sqlite.connect(filename='linuxfabrik-monitoring-plugins-network-io.db') ) @@ -257,30 +315,47 @@ def main(): lib.db_sqlite.close(conn) lib.base.oao('Waiting for more data.', state) - # store the max. measured throughput in cache + # store/get the max. measured throughput in cache or use user-provided interface speed throughput_db = lib.cache.get( f'network-io-{interface}-throughput-max', filename='linuxfabrik-monitoring-plugins-network-io.db', ) - if throughput_db is False: - # unknown interface, no value - throughput_max = ( - 10 * 1024 * 1024 - ) # interface should be capable of 10 MB/sec + + # precedence: per-interface CLI > global CLI > cache/discovery + if interface in iface_speeds: + throughput_max = int(iface_speeds[interface]) lib.cache.set( f'network-io-{interface}-throughput-max', throughput_max, filename='linuxfabrik-monitoring-plugins-network-io.db', ) - elif throughput1 > int(throughput_db): - throughput_max = throughput1 + elif global_iface_speed is not None: + throughput_max = int(global_iface_speed) lib.cache.set( f'network-io-{interface}-throughput-max', throughput_max, filename='linuxfabrik-monitoring-plugins-network-io.db', ) else: - throughput_max = int(throughput_db) + if throughput_db is False: + # unknown interface, no value + throughput_max = ( + 10 * 1024 * 1024 + ) # interface should be capable of 10 MB/sec + lib.cache.set( + f'network-io-{interface}-throughput-max', + throughput_max, + filename='linuxfabrik-monitoring-plugins-network-io.db', + ) + elif throughput1 > int(throughput_db): + throughput_max = throughput1 + lib.cache.set( + f'network-io-{interface}-throughput-max', + throughput_max, + filename='linuxfabrik-monitoring-plugins-network-io.db', + ) + else: + throughput_max = int(throughput_db) # per-second rates for the remaining cumulative counters (packets, # errors, drops), computed like the byte rates above instead of