parent
0ec63d56dd
commit
ad746e3fea
|
@ -0,0 +1,5 @@
|
||||||
|
*.mkp
|
||||||
|
.coverage
|
||||||
|
__pycache__
|
||||||
|
*.log
|
||||||
|
dist/*
|
|
@ -0,0 +1,29 @@
|
||||||
|
# CheckMK extension for monitoring the Wi-Fi interface status @openfest.org
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Monitors several 802.11 interface parameters:
|
||||||
|
|
||||||
|
- Associated station count
|
||||||
|
- Noise Floor
|
||||||
|
- Channel Usage (channel busy time / total channel time)
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
We use a simple library to pack the extension into a `.mkp` file without setting up a full CheckMK development server.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
./build.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The build artifacts are at `dist/`.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Copy the `mkp` file to the monitoring server and execute:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkp install [output_file].mkp
|
||||||
|
mkp enable [plugin_name] [version]
|
||||||
|
```
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from .agent_based_api.v1 import *
|
||||||
|
|
||||||
|
def check_wifi_status(item, section):
|
||||||
|
print(item)
|
||||||
|
print(section)
|
||||||
|
|
||||||
|
for interface in section:
|
||||||
|
if interface['name'] == item:
|
||||||
|
usage = interface['delta_ch_time_busy'] / interface['delta_ch_time'] * 100
|
||||||
|
yield Metric("delta_ch_time", interface['delta_ch_time_busy'])
|
||||||
|
yield Metric("delta_ch_time_busy", interface['delta_ch_time_busy'])
|
||||||
|
yield Metric("channel_usage", usage, levels=(0,100))
|
||||||
|
yield Metric("noise_floor", interface['noise'], levels=(-120,0))
|
||||||
|
yield Metric("client_count", interface['client_count'], levels=(0,None))
|
||||||
|
|
||||||
|
if usage < 30:
|
||||||
|
yield Result(state = State.OK, summary = f"Clients: {interface['client_count']}, Channel usage: {usage:.02f}%")
|
||||||
|
elif usage < 60:
|
||||||
|
yield Result(state = State.WARN, summary = f"Clients: {interface['client_count']}, Channel usage: {usage:.02f}%")
|
||||||
|
else:
|
||||||
|
yield Result(state = State.CRIT, summary = f"Clients: {interface['client_count']}, Channel usage: {usage:.02f}%")
|
||||||
|
|
||||||
|
def discover_wifi_status(section):
|
||||||
|
print(section)
|
||||||
|
for interface in section:
|
||||||
|
yield Service(item=interface['name'])
|
||||||
|
|
||||||
|
def parse_wifi_interfaces(string_table):
|
||||||
|
# format: "$interface;$ch_time;$ch_time_busy;$noise;$delta_ch_time;$delta_ch_time_busy,$client_count"
|
||||||
|
return [{
|
||||||
|
'name': row[0],
|
||||||
|
'ch_time' : int(row[1]),
|
||||||
|
'ch_time_busy' : int(row[2]),
|
||||||
|
'noise' : int(row[3]),
|
||||||
|
'delta_ch_time' : int(row[4]),
|
||||||
|
'delta_ch_time_busy' : int(row[5]),
|
||||||
|
'client_count' : int(row[6]),
|
||||||
|
} for row in string_table]
|
||||||
|
|
||||||
|
register.agent_section(
|
||||||
|
name = "wifi_interfaces",
|
||||||
|
parse_function = parse_wifi_interfaces,
|
||||||
|
)
|
||||||
|
|
||||||
|
register.check_plugin(
|
||||||
|
name="wifi_interface_status",
|
||||||
|
service_name="Wi-Fi Interface %s",
|
||||||
|
discovery_function=discover_wifi_status,
|
||||||
|
sections=['wifi_interfaces'],
|
||||||
|
check_function=check_wifi_status
|
||||||
|
)
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
CACHE_FILE=/usr/lib/check_mk_agent/plugins/wifi_interfaces.cache
|
||||||
|
|
||||||
|
echo "<<<wifi_interfaces:sep(59)>>>" # 59 = ascii semi-colon (;)
|
||||||
|
|
||||||
|
interfaces=$(ls /sys/class/net | grep -iE 'phy.+')
|
||||||
|
|
||||||
|
# Create empty file if it does not exist
|
||||||
|
# First plugin run may produce garbage data or not run at all, which is OK
|
||||||
|
# Cache file format: $interface,$time,$busy
|
||||||
|
touch $CACHE_FILE
|
||||||
|
cached_output="$(cat "$CACHE_FILE")"
|
||||||
|
echo -n "" > "$CACHE_FILE"
|
||||||
|
|
||||||
|
for interface in $interfaces
|
||||||
|
do
|
||||||
|
ch_time_old="$(echo "$cached_output" | awk -v interface="$interface" -F';' '$1 ~ interface { print $2 }')"
|
||||||
|
ch_time_busy_old="$(echo "$cached_output" | awk -v interface="$interface" -F';' '$1 ~ interface { print $3 }')"
|
||||||
|
|
||||||
|
output="$(ethtool -S "$interface")"
|
||||||
|
|
||||||
|
ch_time="$(echo "$output" | awk -F ': ' '/ch_time:/{ print $2 }')"
|
||||||
|
ch_time_busy="$(echo "$output" | awk -F ': ' '/ch_time_busy:/{ print $2 }')"
|
||||||
|
echo "$interface;$ch_time;$ch_time_busy" >> "$CACHE_FILE"
|
||||||
|
|
||||||
|
# The noise is represented as an unsigned byte, we need a signed one. Thus, we subtract 2**7.
|
||||||
|
noise="$(expr $(echo "$output" | awk -F ': ' '/noise:/{ print $2 }') - 256)"
|
||||||
|
client_count="$(iw dev $interface station dump | wc -l)"
|
||||||
|
|
||||||
|
# We calculate the deltas to use for alarms locally; fields are u64
|
||||||
|
delta_ch_time=$(expr $(expr $ch_time - $ch_time_old) % 18446744073709551616)
|
||||||
|
delta_ch_time_busy=$(expr $(expr $ch_time_busy - $ch_time_busy_old) % 18446744073709551616)
|
||||||
|
|
||||||
|
|
||||||
|
echo "$interface;$ch_time;$ch_time_busy;$noise;$delta_ch_time;$delta_ch_time_busy;$client_count"
|
||||||
|
done
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import mkp
|
||||||
|
|
||||||
|
mkp.dist({'author': 'Albert Stefanov <aastefanov@outlook.com>',
|
||||||
|
'description': 'Agent-based plugin for checking OpenWRT Wi-Fi interfaces status, for use @openfest.org',
|
||||||
|
'name': 'wifi_interfaces',
|
||||||
|
'title': 'OpenWRT Wi-Fi Interfaces',
|
||||||
|
'download_url': 'https://github.com/openfest/openfest-network-2023',
|
||||||
|
'version': '0.0.1',
|
||||||
|
'version.min_required': '2.0.0',
|
||||||
|
},
|
||||||
|
path='.')
|
|
@ -0,0 +1 @@
|
||||||
|
mkp @ git+https://github.com/inettgmbh/python-mkp@directories
|
|
@ -0,0 +1,75 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import cmk.utils.render
|
||||||
|
|
||||||
|
from cmk.gui.i18n import _
|
||||||
|
from cmk.gui.plugins.metrics.utils import (
|
||||||
|
graph_info,
|
||||||
|
indexed_color,
|
||||||
|
metric_info,
|
||||||
|
parse_color_into_hexrgb,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
metric_info["channel_usage"] = {
|
||||||
|
"title": _("Channel Usage"),
|
||||||
|
"unit": "%",
|
||||||
|
"color": "11/a",
|
||||||
|
}
|
||||||
|
|
||||||
|
metric_info["noise_floor"] = {
|
||||||
|
"title": _("Noise Floor"),
|
||||||
|
"unit": "db",
|
||||||
|
"color": "11/b",
|
||||||
|
}
|
||||||
|
|
||||||
|
metric_info["delta_ch_time"] = {
|
||||||
|
"title": _("Channel Time delta"),
|
||||||
|
"unit": "",
|
||||||
|
"color": "33/a",
|
||||||
|
}
|
||||||
|
|
||||||
|
metric_info["delta_ch_time_busy"] = {
|
||||||
|
"title": _("Channel Busy Time delta"),
|
||||||
|
"unit": "",
|
||||||
|
"color": "13/a",
|
||||||
|
}
|
||||||
|
|
||||||
|
metric_info["client_count"] = {
|
||||||
|
"title": _("Client Count"),
|
||||||
|
"unit": "count",
|
||||||
|
"color": "13/b",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
graph_info["channel_usage"] = {
|
||||||
|
"title": _("Channel Usage"),
|
||||||
|
"metrics": [
|
||||||
|
("channel_usage", "line")
|
||||||
|
],
|
||||||
|
"range": (0, 100),
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_info["client_count"] = {
|
||||||
|
"title": _("Client Count"),
|
||||||
|
"metrics": [
|
||||||
|
("client_count", "line")
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_info["noise_floor"] = {
|
||||||
|
"title": _("Noise Floor"),
|
||||||
|
"metrics": [
|
||||||
|
("noise_floor", "line")
|
||||||
|
],
|
||||||
|
"range": (-120, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_info["channel_times"] = {
|
||||||
|
"title": _("Channel Times"),
|
||||||
|
"metrics": [
|
||||||
|
("delta_ch_time", "stack"),
|
||||||
|
("delta_ch_time_busy", "stack")
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from cmk.gui.plugins.metrics import (
|
||||||
|
perfometer_info
|
||||||
|
)
|
||||||
|
|
||||||
|
perfometer_info.append({
|
||||||
|
'type': 'dual',
|
||||||
|
'perfometers': [
|
||||||
|
{
|
||||||
|
'type': 'linear',
|
||||||
|
'segments': ['client_count'],
|
||||||
|
'total': 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'linear',
|
||||||
|
'segments': ['channel_usage'],
|
||||||
|
'total': 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
Loading…
Reference in New Issue