Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 86 additions & 11 deletions check-plugins/network-io/network-io
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,7 +12,7 @@

import argparse
import sys

import re
import lib.args
import lib.base
import lib.cache
Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -124,6 +139,16 @@ def parse_args():
default=DEFAULT_WARN,
)

parser.add_argument(
'--interface-speed',
help='Set a fixed interface speed (max throughput). Use "<interface>:<speed>" for per-interface or just "<speed>" (or ":<speed>") 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

Expand All @@ -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 "<interface>:<speed>" or "<speed>"')
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')
)
Expand Down Expand Up @@ -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
Expand Down