Added License, update to 0.79

This commit is contained in:
2021-06-28 12:48:35 +02:00
parent aeb423bf0b
commit a9251b6dfc
14 changed files with 655 additions and 73 deletions

View File

@ -1,6 +1,28 @@
#!/usr/bin/env python3
# -*- encoding: utf-8; py-indent-offset: 4 -*-
#
## MIT License
##
## Copyright (c) 2021 Bash Club
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in all
## copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
from cmk.gui.i18n import _
from .agent_based_api.v1 import (
@ -8,9 +30,13 @@ from .agent_based_api.v1 import (
register,
render,
Result,
IgnoreResults,
Service,
State,
TableRow,
Attributes
)
from .agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
from typing import Any, Dict, Mapping, Sequence, Optional
@ -38,6 +64,12 @@ def _safe_float(val):
except (TypeError,ValueError):
return 0
def _safe_int(val,default=0):
try:
return int(val)
except (TypeError,ValueError):
return default
def _unifi_status2state(status):
return {
"ok" : State.OK,
@ -59,6 +91,13 @@ def parse_unifi_nested_dict(string_table):
_ret[_line[0]][_line[1]] = _line[2]
return _ret
UNIFI_DEVICE_STATES = {
"0" : "disconnected",
"1" : "connected",
"2" : "pending"
}
############ Controller ############
def discovery_unifi_controller(section):
yield Service(item="Unifi Controller")
@ -88,6 +127,14 @@ def check_unifi_controller(item,section):
notice=_("Update available")
)
def inventory_unifi_controller(section):
yield Attributes(
path=["software","os"],
inventory_attributes={
"controller_version" : section.get("controller_version")
}
)
register.agent_section(
name = 'unifi_controller',
parse_function = parse_unifi_dict
@ -99,6 +146,12 @@ register.check_plugin(
discovery_function=discovery_unifi_controller,
check_function=check_unifi_controller,
)
register.inventory_plugin(
name = "unifi_controller",
inventory_function = inventory_unifi_controller
)
############ SITES ###########
def discovery_unifi_sites(section):
@ -107,15 +160,15 @@ def discovery_unifi_sites(section):
def check_unifi_sites(item,section):
site = next(filter(lambda x: x.desc == item,section.values()))
yield Metric("satisfaction",max(0,interfaces.saveint(site.satisfaction)))
yield Metric("satisfaction",max(0,_safe_int(site.satisfaction)))
if site.lan_status != "unknown":
yield Metric("lan_user_sta",interfaces.saveint(site.lan_num_user))
yield Metric("lan_guest_sta",interfaces.saveint(site.lan_num_guest))
yield Metric("if_in_octets",interfaces.saveint(site.lan_rx_bytes_r))
#yield Metric("if_in_bps",interfaces.saveint(site.lan_rx_bytes_r)*8)
yield Metric("if_out_octets",interfaces.saveint(site.lan_tx_bytes_r))
#yield Metric("if_out_bps",interfaces.saveint(site.lan_tx_bytes_r)*8)
yield Metric("lan_user_sta",_safe_int(site.lan_num_user))
yield Metric("lan_guest_sta",_safe_int(site.lan_num_guest))
yield Metric("if_in_octets",_safe_int(site.lan_rx_bytes_r))
#yield Metric("if_in_bps",_safe_int(site.lan_rx_bytes_r)*8)
yield Metric("if_out_octets",_safe_int(site.lan_tx_bytes_r))
#yield Metric("if_out_bps",_safe_int(site.lan_tx_bytes_r)*8)
yield Result(
state=_unifi_status2state(site.lan_status),
@ -127,11 +180,11 @@ def check_unifi_sites(item,section):
#)
if site.wlan_status != "unknown":
yield Metric("wlan_user_sta",interfaces.saveint(site.wlan_num_user))
yield Metric("wlan_guest_sta",interfaces.saveint(site.wlan_num_guest))
yield Metric("wlan_iot_sta",interfaces.saveint(site.wlan_num_iot))
yield Metric("wlan_if_in_octets",interfaces.saveint(site.wlan_rx_bytes_r))
yield Metric("wlan_if_out_octets",interfaces.saveint(site.wlan_tx_bytes_r))
yield Metric("wlan_user_sta",_safe_int(site.wlan_num_user))
yield Metric("wlan_guest_sta",_safe_int(site.wlan_num_guest))
yield Metric("wlan_iot_sta",_safe_int(site.wlan_num_iot))
yield Metric("wlan_if_in_octets",_safe_int(site.wlan_rx_bytes_r))
yield Metric("wlan_if_out_octets",_safe_int(site.wlan_tx_bytes_r))
yield Result(
state=_unifi_status2state(site.wlan_status),
summary=f"WLAN: {site.wlan_num_ap}/{site.wlan_num_adopted} AP ({site.wlan_status})"
@ -173,6 +226,36 @@ register.check_plugin(
check_function=check_unifi_sites,
)
############ DEVICE_SHORTLIST ##########
def inventory_unifi_device_shortlist(section):
for _name,_device in section.items():
yield TableRow(
path=["hardware","networkdevices"],
key_columns={"_name" : _name},
inventory_columns={
"serial" : _device.get("serial"),
"_state" : UNIFI_DEVICE_STATES.get(_device.state,"unknown"),
"vendor" : "ubiquiti",
"model" : _device.get("model_name",_device.get("model")),
"version" : _device.version,
"ip_address": _device.ip,
"mac" : _device.mac
}
)
register.agent_section(
name = 'unifi_device_shortlist',
parse_function = parse_unifi_nested_dict
)
register.inventory_plugin(
name = "unifi_device_shortlist",
inventory_function = inventory_unifi_device_shortlist
)
############ DEVICE ###########
def discovery_unifi_device(section):
yield Service(item="Unifi Device")
@ -188,29 +271,32 @@ def discovery_unifi_device(section):
yield Service(item="Speedtest")
def check_unifi_device(item,section):
if section.state != "1":
yield IgnoreResults(f"device not active State: {section.state}")
if item == "Unifi Device":
yield Result(
state=State.OK,
summary=f"Version: {section.version}"
)
if interfaces.saveint(section.upgradable) > 0:
if _safe_int(section.upgradable) > 0:
yield Result(
state=State.WARN,
notice=_("Update available")
)
if item == "Active-User":
_active_user = interfaces.saveint(section.user_num_sta)
_active_user = _safe_int(section.user_num_sta)
yield Result(
state=State.OK,
summary=f"{_active_user}"
)
if interfaces.saveint(section.guest_num_sta) > -1:
if _safe_int(section.guest_num_sta) > -1:
yield Result(
state=State.OK,
summary=f"Guest: {section.guest_num_sta}"
)
yield Metric("user_sta",_active_user)
yield Metric("guest_sta",interfaces.saveint(section.guest_num_sta))
yield Metric("guest_sta",_safe_int(section.guest_num_sta))
if item == "Uptime":
_uptime = int(section.uptime) if section.uptime else -1
if _uptime > 0:
@ -224,7 +310,7 @@ def check_unifi_device(item,section):
state=State.OK,
summary=f"{section.satisfaction}%"
)
yield Metric("satisfaction",max(0,interfaces.saveint(section.satisfaction)))
yield Metric("satisfaction",max(0,_safe_int(section.satisfaction)))
if item == "Temperature":
yield Metric("temp",_safe_float(section.general_temperature))
yield Result(
@ -264,6 +350,33 @@ def check_unifi_device(item,section):
summary=f"Device {section.uplink_device} Port: {section.uplink_remote_port}"
)
def inventory_unifi_device(section):
yield Attributes(
path=["software","os"],
inventory_attributes={
"version" : section.get("version")
}
)
yield Attributes(
path=["software","configuration","snmp_info"],
inventory_attributes = {
"name" : section.get("name"),
"contact" : section.get("snmp_contact"),
"location" : section.get("snmp_location")
}
)
_hwdict = {
"vendor" : "ubiquiti",
}
for _key in ("model","board_rev","serial","mac"):
_val = section.get(_key)
if _val:
_hwdict[_key] = _val
yield Attributes(
path=["hardware","system"],
inventory_attributes= _hwdict
)
register.agent_section(
name = 'unifi_device',
parse_function = parse_unifi_dict
@ -275,6 +388,12 @@ register.check_plugin(
discovery_function=discovery_unifi_device,
check_function=check_unifi_device,
)
register.inventory_plugin(
name = "unifi_device",
inventory_function = inventory_unifi_device
)
############ DEVICEPORT ###########
@dataclass
class unifi_interface(interfaces.Interface):
@ -290,34 +409,87 @@ class unifi_interface(interfaces.Interface):
dot1x_mode : Optional[str] = None
dot1x_status : Optional[str] = None
ip_address : Optional[str] = None
portconf : Optional[str] = None
def __post_init__(self) -> None:
self.finalize()
def _convert_unifi_counters_if(section: Section) -> interfaces.Section:
## 10|port_idx|10
## 10|port_poe|1
## 10|poe_caps|7
## 10|op_mode|switch
## 10|poe_mode|auto
## 10|anomalies|0
## 10|autoneg|1
## 10|dot1x_mode|unknown
## 10|dot1x_status|disabled
## 10|enable|1
## 10|full_duplex|1
## 10|is_uplink|0
## 10|jumbo|1
## 10|poe_class|Unknown
## 10|poe_current|0.00
## 10|poe_enable|0
## 10|poe_good|0
## 10|poe_power|0.00
## 10|poe_voltage|0.00
## 10|rx_broadcast|1290
## 10|rx_bytes|38499976384
## 10|rx_dropped|0
## 10|rx_errors|0
## 10|rx_multicast|16423
## 10|rx_packets|125489263
## 10|satisfaction|100
## 10|satisfaction_reason|0
## 10|speed|1000
## 10|stp_pathcost|20000
## 10|stp_state|forwarding
## 10|tx_broadcast|20791854
## 10|tx_bytes|238190158091
## 10|tx_dropped|0
## 10|tx_errors|0
## 10|tx_multicast|262691
## 10|tx_packets|228482694
## 10|tx_bytes_r|17729
## 10|rx_bytes_r|176941
## 10|bytes_r|194671
## 10|name|Port 10
## 10|aggregated_by|0
## 10|oper_status|1
## 10|admin_status|1
## 10|portconf|ALL
## unifi_interface(index='10', descr='Port 10', alias='Port 10', type='6', speed=1000000000, oper_status='1',
## in_octets=38448560321, in_ucast=125404491, in_mcast=16414, in_bcast=1290, in_discards=0, in_errors=0,
## out_octets=238185160794, out_ucast=228451699, out_mcast=262551, out_bcast=20783341, out_discards=0, out_errors=0,
## out_qlen=0, phys_address='', oper_status_name='up', speed_as_text='', group=None, node=None, admin_status='1',
## total_octets=276633721115, jumbo=True, satisfaction=100,
## poe_enable=False, poe_mode='auto', poe_good=None, poe_current=0.0, poe_power=0.0, poe_voltage=0.0, poe_class='Unknown',
## dot1x_mode='unknown',dot1x_status='disabled', ip_address='', portconf='ALL')
return [
unifi_interface(
index=str(netif.port_idx),
descr=netif.name,
alias=netif.name,
type='6',
speed=interfaces.saveint(netif.speed)*1000000,
speed=_safe_int(netif.speed)*1000000,
oper_status=netif.oper_status,
admin_status=netif.admin_status,
in_octets=interfaces.saveint(netif.rx_bytes),
in_ucast=interfaces.saveint(netif.rx_packets),
in_mcast=interfaces.saveint(netif.rx_multicast),
in_bcast=interfaces.saveint(netif.rx_broadcast),
in_discards=interfaces.saveint(netif.rx_dropped),
in_errors=interfaces.saveint(netif.rx_errors),
out_octets=interfaces.saveint(netif.tx_bytes),
out_ucast=interfaces.saveint(netif.tx_packets),
out_mcast=interfaces.saveint(netif.tx_multicast),
out_bcast=interfaces.saveint(netif.tx_broadcast),
out_discards=interfaces.saveint(netif.tx_dropped),
out_errors=interfaces.saveint(netif.tx_errors),
in_octets=_safe_int(netif.rx_bytes),
in_ucast=_safe_int(netif.rx_packets),
in_mcast=_safe_int(netif.rx_multicast),
in_bcast=_safe_int(netif.rx_broadcast),
in_discards=_safe_int(netif.rx_dropped),
in_errors=_safe_int(netif.rx_errors),
out_octets=_safe_int(netif.tx_bytes),
out_ucast=_safe_int(netif.tx_packets),
out_mcast=_safe_int(netif.tx_multicast),
out_bcast=_safe_int(netif.tx_broadcast),
out_discards=_safe_int(netif.tx_dropped),
out_errors=_safe_int(netif.tx_errors),
jumbo=True if netif.jumbo == "1" else False,
satisfaction=interfaces.saveint(netif.satisfaction) if netif.satisfaction and netif.oper_status == "1" else 0,
satisfaction=_safe_int(netif.satisfaction) if netif.satisfaction and netif.oper_status == "1" else 0,
poe_enable=True if netif.poe_enable == "1" else False,
poe_mode=netif.poe_mode,
poe_current=float(netif.poe_current) if netif.poe_current else 0,
@ -326,7 +498,8 @@ def _convert_unifi_counters_if(section: Section) -> interfaces.Section:
poe_class=netif.poe_class,
dot1x_mode=netif.dot1x_mode,
dot1x_status=netif.dot1x_status,
ip_address=netif.ip
ip_address=netif.ip,
portconf=netif.portconf
) for netif in parse_unifi_nested_dict(section).values()
]
@ -348,13 +521,19 @@ def check_unifi_network_port_if( ##fixme parsed_section_name
section: Section,
) -> CheckResult:
_converted_ifs = _convert_unifi_counters_if(section)
iface = next(filter(lambda x: item in (x.index,x.alias),_converted_ifs),None) ## fix Service Discovery appearance alias/descr
iface = next(filter(lambda x: _safe_int(item,-1) == _safe_int(x.index) or item == x.alias,_converted_ifs),None) ## fix Service Discovery appearance alias/descr
yield from interfaces.check_multiple_interfaces(
item,
params,
_converted_ifs,
)
if iface:
#pprint(iface)
if iface.portconf:
yield Result(
state=State.OK,
summary=f"Network: {iface.portconf}"
)
yield Metric("satisfaction",max(0,iface.satisfaction))
#pprint(iface)
if iface.poe_enable:
@ -371,6 +550,35 @@ def check_unifi_network_port_if( ##fixme parsed_section_name
summary=f"IP: {iface.ip_address}"
)
def inventory_unifi_network_ports(section):
_total_ethernet_ports = 0
_available_ethernet_ports = 0
for _iface in parse_unifi_nested_dict(section).values():
_total_ethernet_ports +=1
_available_ethernet_ports +=1 if _iface.oper_status == '2' else 0
yield TableRow(
path=["networking","interfaces"],
key_columns={"index" : _safe_int(_iface.port_idx)},
inventory_columns={
"description" : _iface.name,
"alias" : _iface.name,
"speed" : _safe_int(_iface.speed)*1000000,
"oper_status" : _safe_int(_iface.oper_status),
"admin_status" : _safe_int(_iface.admin_status),
"available" : _iface.oper_status == '2',
"vlans" : _iface.portconf,
"port_type" : 6,
}
)
yield Attributes(
path=["networking"],
inventory_attributes={
"available_ethernet_ports" : _available_ethernet_ports,
"total_ethernet_ports" : _total_ethernet_ports,
"total_interfaces" : _total_ethernet_ports
}
)
register.check_plugin(
name='unifi_network_ports_if',
@ -384,6 +592,12 @@ register.check_plugin(
check_default_parameters=interfaces.CHECK_DEFAULT_PARAMETERS,
check_function=check_unifi_network_port_if,
)
register.inventory_plugin(
name = "unifi_network_ports",
inventory_function = inventory_unifi_network_ports
)
############ DEVICERADIO ###########
def discovery_unifi_radios(section):
#pprint(section)
@ -396,12 +610,12 @@ def discovery_unifi_radios(section):
def check_unifi_radios(item,section):
_item = { "2.4Ghz" : "ng", "5Ghz" : "na" }.get(item)
radio = next(filter(lambda x: x.radio == _item,section.values()))
yield Metric("read_data",interfaces.saveint(radio.rx_bytes))
yield Metric("write_data",interfaces.saveint(radio.tx_bytes))
yield Metric("satisfaction",max(0,interfaces.saveint(radio.satisfaction)))
yield Metric("wlan_user_sta",interfaces.saveint(radio.user_num_sta))
yield Metric("wlan_guest_sta",interfaces.saveint(radio.guest_num_sta))
yield Metric("wlan_iot_sta",interfaces.saveint(radio.iot_num_sta))
yield Metric("read_data",_safe_int(radio.rx_bytes))
yield Metric("write_data",_safe_int(radio.tx_bytes))
yield Metric("satisfaction",max(0,_safe_int(radio.satisfaction)))
yield Metric("wlan_user_sta",_safe_int(radio.user_num_sta))
yield Metric("wlan_guest_sta",_safe_int(radio.guest_num_sta))
yield Metric("wlan_iot_sta",_safe_int(radio.iot_num_sta))
yield Result(
state=State.OK,
@ -440,41 +654,41 @@ def discovery_unifi_ssids(section):
def check_unifi_ssids(item,section):
ssid = section.get(item)
_channels = ",".join(list(filter(lambda x: interfaces.saveint(x) > 0,[ssid.ng_channel,ssid.na_channel])))
_channels = ",".join(list(filter(lambda x: _safe_int(x) > 0,[ssid.ng_channel,ssid.na_channel])))
yield Result(
state=State.OK,
summary=f"Channels: {_channels}"
)
if (interfaces.saveint(ssid.ng_is_guest) + interfaces.saveint(ssid.na_is_guest)) > 0:
if (_safe_int(ssid.ng_is_guest) + _safe_int(ssid.na_is_guest)) > 0:
yield Result(
state=State.OK,
summary="Guest"
)
_satisfaction = max(0,min(interfaces.saveint(ssid.ng_satisfaction),interfaces.saveint(ssid.na_satisfaction)))
_satisfaction = max(0,min(_safe_int(ssid.ng_satisfaction),_safe_int(ssid.na_satisfaction)))
yield Result(
state=State.OK,
summary=f"Satisfaction: {_satisfaction}"
)
_num_sta = interfaces.saveint(ssid.na_num_sta) + interfaces.saveint(ssid.ng_num_sta)
_num_sta = _safe_int(ssid.na_num_sta) + _safe_int(ssid.ng_num_sta)
if _num_sta > 0:
yield Result(
state=State.OK,
summary=f"User: {_num_sta}"
)
yield Metric("satisfaction",max(0,_satisfaction))
yield Metric("wlan_24Ghz_num_user",interfaces.saveint(ssid.ng_num_sta) )
yield Metric("wlan_5Ghz_num_user",interfaces.saveint(ssid.na_num_sta) )
yield Metric("wlan_24Ghz_num_user",_safe_int(ssid.ng_num_sta) )
yield Metric("wlan_5Ghz_num_user",_safe_int(ssid.na_num_sta) )
yield Metric("na_avg_client_signal",interfaces.saveint(ssid.na_avg_client_signal))
yield Metric("ng_avg_client_signal",interfaces.saveint(ssid.ng_avg_client_signal))
yield Metric("na_avg_client_signal",_safe_int(ssid.na_avg_client_signal))
yield Metric("ng_avg_client_signal",_safe_int(ssid.ng_avg_client_signal))
yield Metric("na_tcp_packet_loss",interfaces.saveint(ssid.na_tcp_packet_loss))
yield Metric("ng_tcp_packet_loss",interfaces.saveint(ssid.ng_tcp_packet_loss))
yield Metric("na_tcp_packet_loss",_safe_int(ssid.na_tcp_packet_loss))
yield Metric("ng_tcp_packet_loss",_safe_int(ssid.ng_tcp_packet_loss))
yield Metric("na_wifi_retries",interfaces.saveint(ssid.na_wifi_retries))
yield Metric("ng_wifi_retries",interfaces.saveint(ssid.ng_wifi_retries))
yield Metric("na_wifi_latency",interfaces.saveint(ssid.na_wifi_latency))
yield Metric("ng_wifi_latency",interfaces.saveint(ssid.ng_wifi_latency))
yield Metric("na_wifi_retries",_safe_int(ssid.na_wifi_retries))
yield Metric("ng_wifi_retries",_safe_int(ssid.ng_wifi_retries))
yield Metric("na_wifi_latency",_safe_int(ssid.na_wifi_latency))
yield Metric("ng_wifi_latency",_safe_int(ssid.ng_wifi_latency))
@ -503,19 +717,22 @@ def check_unifi_ssidlist(item,section):
state=State.OK,
summary=f"Channels: {ssid.channels}"
)
# if (interfaces.saveint(ssid.ng_is_guest) + interfaces.saveint(ssid.na_is_guest)) > 0:
# yield Result(
# state=State.OK,
# summary="Guest"
# )
# yield Result(
# state=State.OK,
# summary=f"Satisfaction: {_satisfaction}"
# )
yield Result(
state=State.OK,
summary=f"User: {ssid.num_sta}"
)
yield Metric("wlan_24Ghz_num_user",_safe_int(ssid.ng_num_sta) )
yield Metric("wlan_5Ghz_num_user",_safe_int(ssid.na_num_sta) )
yield Metric("na_avg_client_signal",_safe_int(ssid.na_avg_client_signal))
yield Metric("ng_avg_client_signal",_safe_int(ssid.ng_avg_client_signal))
yield Metric("na_tcp_packet_loss",_safe_int(ssid.na_tcp_packet_loss))
yield Metric("ng_tcp_packet_loss",_safe_int(ssid.ng_tcp_packet_loss))
yield Metric("na_wifi_retries",_safe_int(ssid.na_wifi_retries))
yield Metric("ng_wifi_retries",_safe_int(ssid.ng_wifi_retries))
yield Metric("na_wifi_latency",_safe_int(ssid.na_wifi_latency))
yield Metric("ng_wifi_latency",_safe_int(ssid.ng_wifi_latency))
register.agent_section(
name = 'unifi_ssid_list',
@ -530,3 +747,5 @@ register.check_plugin(
)