mirror of
				https://github.com/bashclub/check-unifi-controller.git
				synced 2025-11-03 22:32:26 +01:00 
			
		
		
		
	Added License, update to 0.79
This commit is contained in:
		@@ -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(
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,29 @@
 | 
			
		||||
#!/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.
 | 
			
		||||
 | 
			
		||||
### 
 | 
			
		||||
__VERSION__ = 0.75
 | 
			
		||||
__VERSION__ = 0.79
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import socket
 | 
			
		||||
@@ -14,7 +35,127 @@ from statistics import mean
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
 | 
			
		||||
from pprint import pprint
 | 
			
		||||
try:
 | 
			
		||||
    import cmk.utils.paths
 | 
			
		||||
    AGENT_TMP_PATH = cmk.utils.paths.Path(cmk.utils.paths.tmp_dir, "agents/agent_unifi")
 | 
			
		||||
except ImportError:
 | 
			
		||||
    AGENT_TMP_PATH = None
 | 
			
		||||
 | 
			
		||||
UNIFI_DEVICE_TABLE = {
 | 
			
		||||
    'BZ2'       : 'UAP',
 | 
			
		||||
    'BZ2LR'     : 'UAP-LR',
 | 
			
		||||
    'U2HSR'     : 'UAP-Outdoor+',
 | 
			
		||||
    'U2IW'      : 'UAP-IW',
 | 
			
		||||
    'U2L48'     : 'UAP-AC-LR',
 | 
			
		||||
    'U2Lv2'     : 'UAP-AC-LR',
 | 
			
		||||
    'U2M'       : 'UAP-Mini',
 | 
			
		||||
    'U2O'       : 'UAP-Outdoor',
 | 
			
		||||
    'U2S48'     : 'UAP-AC',
 | 
			
		||||
    'U2Sv2'     : 'UAP-AC',
 | 
			
		||||
    'U5O'       : 'UAP-Outdoor5',
 | 
			
		||||
    'U7E'       : 'UAP-AC',
 | 
			
		||||
    'U7EDU'     : 'UAP-AC-EDU',
 | 
			
		||||
    'U7Ev2'     : 'UAP-AC',
 | 
			
		||||
    'U7HD'      : 'UAP-AC-HD',
 | 
			
		||||
    'U7SHD'     : 'UAP-AC-SHD',
 | 
			
		||||
    'U7NHD'     : 'UAP-nanoHD',
 | 
			
		||||
    'UFLHD'     : 'UAP-FlexHD',
 | 
			
		||||
    'UHDIW'     : 'UAP-IW-HD',
 | 
			
		||||
    'UAIW6'     : 'U6-IW',
 | 
			
		||||
    'UAE6'      : 'U6-Extender',
 | 
			
		||||
    'UAL6'      : 'U6-Lite',
 | 
			
		||||
    'UAM6'      : 'U6-Mesh',
 | 
			
		||||
    'UALR6'     : 'U6-LR-EA',
 | 
			
		||||
    'UAP6'      : 'U6-LR',
 | 
			
		||||
    'UALR6v2'   : 'U6-LR',
 | 
			
		||||
    'UALR6v3'   : 'U6-LR',
 | 
			
		||||
    'UCXG'      : 'UAP-XG',
 | 
			
		||||
    'UXSDM'     : 'UWB-XG',
 | 
			
		||||
    'UXBSDM'    : 'UWB-XG-BK',
 | 
			
		||||
    'UCMSH'     : 'UAP-XG-Mesh',
 | 
			
		||||
    'U7IW'      : 'UAP-AC-IW',
 | 
			
		||||
    'U7IWP'     : 'UAP-AC-IW-Pro',
 | 
			
		||||
    'U7MP'      : 'UAP-AC-M-Pro',
 | 
			
		||||
    'U7LR'      : 'UAP-AC-LR',
 | 
			
		||||
    'U7LT'      : 'UAP-AC-Lite',
 | 
			
		||||
    'U7O'       : 'UAP-AC-Outdoor',
 | 
			
		||||
    'U7P'       : 'UAP-Pro',
 | 
			
		||||
    'U7MSH'     : 'UAP-AC-M',
 | 
			
		||||
    'U7PG2'     : 'UAP-AC-Pro',
 | 
			
		||||
    'p2N'       : 'PICOM2HP',
 | 
			
		||||
    'UDMB'      : 'UAP-BeaconHD',
 | 
			
		||||
    'USF5P'     : 'USW-Flex',
 | 
			
		||||
    'US8'       : 'US-8',
 | 
			
		||||
    'US8P60'    : 'US-8-60W',
 | 
			
		||||
    'US8P150'   : 'US-8-150W',
 | 
			
		||||
    'S28150'    : 'US-8-150W',
 | 
			
		||||
    'USC8'      : 'US-8',
 | 
			
		||||
    'USC8P60'   : 'US-8-60W',
 | 
			
		||||
    'USC8P150'  : 'US-8-150W',
 | 
			
		||||
    'US16P150'  : 'US-16-150W',
 | 
			
		||||
    'S216150'   : 'US-16-150W',
 | 
			
		||||
    'US24'      : 'US-24-G1',
 | 
			
		||||
    'US24PRO'   : 'USW-Pro-24-PoE',
 | 
			
		||||
    'US24PRO2'  : 'USW-Pro-24',
 | 
			
		||||
    'US24P250'  : 'US-24-250W',
 | 
			
		||||
    'US24PL2'   : 'US-L2-24-PoE',
 | 
			
		||||
    'US24P500'  : 'US-24-500W',
 | 
			
		||||
    'S224250'   : 'US-24-250W',
 | 
			
		||||
    'S224500'   : 'US-24-500W',
 | 
			
		||||
    'US48'      : 'US-48-G1',
 | 
			
		||||
    'US48PRO'   : 'USW-Pro-48-PoE',
 | 
			
		||||
    'US48PRO2'  : 'USW-Pro-48',
 | 
			
		||||
    'US48P500'  : 'US-48-500W',
 | 
			
		||||
    'US48PL2'   : 'US-L2-48-PoE',
 | 
			
		||||
    'US48P750'  : 'US-48-750W',
 | 
			
		||||
    'S248500'   : 'US-48-500W',
 | 
			
		||||
    'S248750'   : 'US-48-750W',
 | 
			
		||||
    'US6XG150'  : 'US-XG-6PoE',
 | 
			
		||||
    'USMINI'    : 'USW-Flex-Mini',
 | 
			
		||||
    'USXG'      : 'US-16-XG',
 | 
			
		||||
    'USC8P450'  : 'USW-Industrial',
 | 
			
		||||
    'UDC48X6'   : 'USW-Leaf',
 | 
			
		||||
    'USL8A'     : 'UniFi Switch Aggregation',
 | 
			
		||||
    'USAGGPRO'  : 'UniFi Switch Aggregation Pro',
 | 
			
		||||
    'USL8LP'    : 'USW-Lite-8-PoE',
 | 
			
		||||
    'USL8MP'    : 'USW-Mission-Critical',
 | 
			
		||||
    'USL16P'    : 'USW-16-PoE',
 | 
			
		||||
    'USL16LP'   : 'USW-Lite-16-PoE',
 | 
			
		||||
    'USL24'     : 'USW-24-G2',
 | 
			
		||||
    'USL48'     : 'USW-48-G2',
 | 
			
		||||
    'USL24P'    : 'USW-24-PoE',
 | 
			
		||||
    'USL48P'    : 'USW-48-PoE',
 | 
			
		||||
    'UGW3'      : 'USG-3P',
 | 
			
		||||
    'UGW4'      : 'USG-Pro-4',
 | 
			
		||||
    'UGWHD4'    : 'USG',
 | 
			
		||||
    'UGWXG'     : 'USG-XG-8',
 | 
			
		||||
    'UDM'       : 'UDM',
 | 
			
		||||
    'UDMSE'     : 'UDM-SE',
 | 
			
		||||
    'UDMPRO'    : 'UDM-Pro',
 | 
			
		||||
    'UP4'       : 'UVP-X',
 | 
			
		||||
    'UP5'       : 'UVP',
 | 
			
		||||
    'UP5t'      : 'UVP-Pro',
 | 
			
		||||
    'UP7'       : 'UVP-Executive',
 | 
			
		||||
    'UP5c'      : 'UVP',
 | 
			
		||||
    'UP5tc'     : 'UVP-Pro',
 | 
			
		||||
    'UP7c'      : 'UVP-Executive',
 | 
			
		||||
    'UCK'       : 'UCK',
 | 
			
		||||
    'UCK-v2'    : 'UCK',
 | 
			
		||||
    'UCK-v3'    : 'UCK',
 | 
			
		||||
    'UCKG2'     : 'UCK-G2',
 | 
			
		||||
    'UCKP'      : 'UCK-G2-Plus',
 | 
			
		||||
    'UASXG'     : 'UAS-XG',
 | 
			
		||||
    'ULTE'      : 'U-LTE',
 | 
			
		||||
    'ULTEPUS'   : 'U-LTE-Pro',
 | 
			
		||||
    'ULTEPEU'   : 'U-LTE-Pro',
 | 
			
		||||
    'UP1'       : 'USP-Plug',
 | 
			
		||||
    'UP6'       : 'USP-Strip',
 | 
			
		||||
    'USPPDUP'   : 'USP - Power Distribution Unit Pro',
 | 
			
		||||
    'USPRPS'    : 'USP-RPS',
 | 
			
		||||
    'US624P'    : 'UniFi6 Switch 24',
 | 
			
		||||
    'UBB'       : 'UBB',
 | 
			
		||||
    'UXGPRO'    : 'UniFi NeXt-Gen Gateway PRO'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from cmk.special_agents.utils.argument_parsing import create_default_argument_parser
 | 
			
		||||
@@ -40,6 +181,9 @@ class unifi_object(object):
 | 
			
		||||
        if hasattr(self,"_init"):
 | 
			
		||||
            self._init()
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return repr([(_k,_v) for _k,_v in self.__dict__.items() if type(_v) in (int,str)])
 | 
			
		||||
 | 
			
		||||
########################################
 | 
			
		||||
######
 | 
			
		||||
######      S S I D
 | 
			
		||||
@@ -51,9 +195,17 @@ class unifi_network_ssid(unifi_object):
 | 
			
		||||
        self._UNIFI_SITE = self._PARENT._PARENT
 | 
			
		||||
        for _k,_v in getattr(self,"reasons_bar_chart_now",{}).items():
 | 
			
		||||
            setattr(self,_k,_v)
 | 
			
		||||
        setattr(self,f"{self.radio}_num_sta",self.num_sta)
 | 
			
		||||
        setattr(self,f"{self.radio}_tcp_packet_loss",self.tcp_packet_loss)
 | 
			
		||||
        setattr(self,f"{self.radio}_wifi_retries",self.wifi_retries)
 | 
			
		||||
        setattr(self,f"{self.radio}_wifi_latency",self.wifi_latency)
 | 
			
		||||
        setattr(self,f"{self.radio}_avg_client_signal",self.avg_client_signal)
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        _ret = []
 | 
			
		||||
        _unwanted = ["essid","radio","id","t","name","radio_name","wlanconf_id","is_wep","up","site_id","ap_mac","state"]
 | 
			
		||||
        _unwanted = ["essid","radio","id","t","name","radio_name","wlanconf_id","is_wep","up","site_id","ap_mac","state",
 | 
			
		||||
            "na_num_sta","ng_num_sta","ng_tcp_packet_loss","na_tcp_packet_loss","na_wifi_retries","ng_wifi_retries",
 | 
			
		||||
            "na_wifi_latency","ng_wifi_latency","na_avg_client_signal","ng_avg_client_signal"
 | 
			
		||||
        ]
 | 
			
		||||
        for _k,_v in self.__dict__.items():
 | 
			
		||||
            if _k.startswith("_") or _k in _unwanted or type(_v) not in (str,int,float):
 | 
			
		||||
                continue
 | 
			
		||||
@@ -102,6 +254,9 @@ class unifi_network_port(unifi_object):
 | 
			
		||||
        if not hasattr(self,"port_idx") and hasattr(self,"ifname"):
 | 
			
		||||
            self.port_idx = int(self.ifname[-1])+1  ## ethX
 | 
			
		||||
        
 | 
			
		||||
        self.portconf = self._PARENT._PARENT._PORTCONFIGS.get(getattr(self,"portconf_id",None))
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    def _get_state(self,state):
 | 
			
		||||
        return {
 | 
			
		||||
            "1"     : 1, ## up
 | 
			
		||||
@@ -135,6 +290,7 @@ class unifi_device(unifi_object):
 | 
			
		||||
        for _k,_v in getattr(self,"sys_stats",{}).items():
 | 
			
		||||
            _k = _k.replace("-","_")
 | 
			
		||||
            setattr(self,_k,_v)
 | 
			
		||||
        self.model_name = UNIFI_DEVICE_TABLE.get(self.model)
 | 
			
		||||
        if self.type in ("ugw","udm"):
 | 
			
		||||
            ## change ip to local ip
 | 
			
		||||
            self.wan_ip = self.ip
 | 
			
		||||
@@ -172,7 +328,7 @@ class unifi_device(unifi_object):
 | 
			
		||||
 | 
			
		||||
    def _get_short_info(self):
 | 
			
		||||
        _ret = []
 | 
			
		||||
        _wanted = ["version","ip","mac","serial","model","uptime","upgradeable","num_sta"]
 | 
			
		||||
        _wanted = ["version","ip","mac","serial","model","model_name","uptime","upgradeable","num_sta","adopted","state"]
 | 
			
		||||
        for _k,_v in self.__dict__.items():
 | 
			
		||||
            if _k.startswith("_") or _k not in _wanted or type(_v) not in (str,int,float):
 | 
			
		||||
                continue
 | 
			
		||||
@@ -234,6 +390,8 @@ class unifi_site(unifi_object):
 | 
			
		||||
        
 | 
			
		||||
        ##pprint(_api.get_data("/stat/rogueap"))
 | 
			
		||||
        self._SITE_DEVICES = []
 | 
			
		||||
        self._PORTCONFIGS = {}
 | 
			
		||||
        self._get_portconfig()
 | 
			
		||||
        self._get_devices()
 | 
			
		||||
        _satisfaction = list(filter(
 | 
			
		||||
            lambda x: x != None,map(
 | 
			
		||||
@@ -242,6 +400,10 @@ class unifi_site(unifi_object):
 | 
			
		||||
        ))
 | 
			
		||||
        self.satisfaction = max(0,int(mean(_satisfaction)) if _satisfaction else 0)
 | 
			
		||||
 | 
			
		||||
    def _get_portconfig(self):
 | 
			
		||||
        _data = self._API.get_portconfig(site=self.name)
 | 
			
		||||
        for _config in _data:
 | 
			
		||||
            self._PORTCONFIGS[_config["_id"]] = _config.get("name")
 | 
			
		||||
 | 
			
		||||
    def _get_devices(self):
 | 
			
		||||
        _data = self._API.get_devices(site=self.name)
 | 
			
		||||
@@ -308,7 +470,11 @@ class unifi_controller(unifi_object):
 | 
			
		||||
        
 | 
			
		||||
        _ret = []
 | 
			
		||||
        for _ssid,_obj in _dict.items():
 | 
			
		||||
            _ret.append("|".join([_ssid,"num_sta",str(sum(map(lambda x: getattr(x,"num_sta",0),_obj)))]))
 | 
			
		||||
            pprint(_obj)
 | 
			
		||||
            for _key in ("num_sta","ng_num_sta","na_num_sta","ng_tcp_packet_loss","na_tcp_packet_loss","ng_wifi_retries","na_wifi_retries","ng_wifi_latency","na_wifi_latency"):
 | 
			
		||||
                _ret.append("|".join([_ssid,_key,str(sum(map(lambda x: getattr(x,_key,0),_obj)))]))
 | 
			
		||||
            _ret.append("|".join([_ssid,"ng_avg_client_signal",str(mean(map(lambda x: getattr(x,"ng_avg_client_signal",0),filter(lambda x: x.radio == "ng",_obj))))]))
 | 
			
		||||
            _ret.append("|".join([_ssid,"na_avg_client_signal",str(mean(map(lambda x: getattr(x,"na_avg_client_signal",0),filter(lambda x: x.radio == "na",_obj))))]))
 | 
			
		||||
            _ret.append("|".join([_ssid,"channels",",".join(
 | 
			
		||||
                sorted(
 | 
			
		||||
                    set(map(lambda x: str(getattr(x,"channel","0")),_obj))
 | 
			
		||||
@@ -338,7 +504,7 @@ class unifi_controller(unifi_object):
 | 
			
		||||
        for _site in self._UNIFI_SITES:
 | 
			
		||||
            _ret.append(str(_site))
 | 
			
		||||
 | 
			
		||||
        _ret.append("<<<unifi_device_shortlist>>>")
 | 
			
		||||
        _ret.append("<<<unifi_device_shortlist:sep(124)>>>")
 | 
			
		||||
        for _device in self._UNIFI_DEVICES:
 | 
			
		||||
            if _device._piggy_back:
 | 
			
		||||
                _ret.append(_device._get_short_info())
 | 
			
		||||
@@ -351,7 +517,7 @@ class unifi_controller(unifi_object):
 | 
			
		||||
        if self._API.PIGGYBACK_ATTRIBUT.lower() != "none":
 | 
			
		||||
            ## PIGGYBACK DEVICES ##
 | 
			
		||||
            for _device in self._UNIFI_DEVICES:
 | 
			
		||||
                if _device._piggy_back:
 | 
			
		||||
                if _device._piggy_back and _device.adopted:
 | 
			
		||||
                    _ret.append(str(_device))
 | 
			
		||||
        return "\n".join(_ret)
 | 
			
		||||
 | 
			
		||||
@@ -388,6 +554,9 @@ class unifi_controller_api(object):
 | 
			
		||||
    def get_sites(self):
 | 
			
		||||
        return self.get_data("/stat/sites",site=None)
 | 
			
		||||
 | 
			
		||||
    def get_portconfig(self,site):
 | 
			
		||||
        return self.get_data("/rest/portconf",site=site)
 | 
			
		||||
 | 
			
		||||
    def get_devices(self,site):
 | 
			
		||||
        return self.get_data("/stat/device",site=site)
 | 
			
		||||
 | 
			
		||||
@@ -409,8 +578,8 @@ class unifi_controller_api(object):
 | 
			
		||||
            return
 | 
			
		||||
        raise unifi_api_exception("Login failed")
 | 
			
		||||
 | 
			
		||||
    def get_data(self,path,site="default",method="GET"):
 | 
			
		||||
        _json = self.request(method=method,path=path,site=site).json()
 | 
			
		||||
    def get_data(self,path,site="default",method="GET",**kwargs):
 | 
			
		||||
        _json = self.request(method=method,path=path,site=site,**kwargs).json()
 | 
			
		||||
        _meta = _json.get("meta",{})
 | 
			
		||||
        if _meta.get("rc") == "ok":
 | 
			
		||||
            return _json.get("data",[])
 | 
			
		||||
@@ -470,11 +639,10 @@ if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    if _api.is_unifios:
 | 
			
		||||
        print("AgentOS: UnifiOS")
 | 
			
		||||
    #pprint(_api.get_data("rest/portconf",site="default",method="GET"))
 | 
			
		||||
    ##pprint(_api.get_data("/stat/rogueap"))
 | 
			
		||||
    ##pprint(_api.get_data("/stat/rogueap?within=4"))
 | 
			
		||||
    ##pprint(_api.get_data("/rest/user",site="default",method="GET"))
 | 
			
		||||
    ##pprint(_api.get_data("/stat/sta",site="default",method="GET"))
 | 
			
		||||
    #sys.exit(0)
 | 
			
		||||
    ##sys.exit(0)
 | 
			
		||||
    _controller = unifi_controller(_API=_api)
 | 
			
		||||
    if args.rawapi == False:
 | 
			
		||||
        print(_controller)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_controller
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_controller
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Controller
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the device
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each device
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_device
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_device
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Device
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the device
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each device
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_device_shortlist
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_device_shortlist
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Devicelist
 | 
			
		||||
catalog: networking
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the device
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each device
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_network_ports_if
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_network_ports_if
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Network Port
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the Port
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each Port
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_network_radios
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_network_radios
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi WLAN Radio
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the Radio
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each Radio
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_network_ssids
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_network_ssids
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi SSID
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the SSID
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each SSID
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_sites
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_sites
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Site
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
catalog: networking
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the Site
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each Site
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								share/check_mk/checkman/unifi_ssid_list
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								share/check_mk/checkman/unifi_ssid_list
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
title: Unifi Devicelist
 | 
			
		||||
catalog: networking
 | 
			
		||||
agents: unifi_controller
 | 
			
		||||
licence: MIT
 | 
			
		||||
description:
 | 
			
		||||
 plz fill me
 | 
			
		||||
 | 
			
		||||
item:
 | 
			
		||||
 The name of the device
 | 
			
		||||
 | 
			
		||||
inventory:
 | 
			
		||||
 One Service for each device
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,26 @@
 | 
			
		||||
#!/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.
 | 
			
		||||
 | 
			
		||||
#Function get params (in this case is port, passed via WATO agent rule cunfiguration, hostname and ip addres of host, 
 | 
			
		||||
#for which agent will be invoked 
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,27 @@
 | 
			
		||||
#!/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 cmk.gui.plugins.metrics import (
 | 
			
		||||
    metric_info,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,27 @@
 | 
			
		||||
# -*- 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.plugins.metrics import perfometer_info
 | 
			
		||||
 | 
			
		||||
perfometer_info.append({
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,26 @@
 | 
			
		||||
#!/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 cmk.gui.plugins.wato import (
 | 
			
		||||
@@ -50,3 +71,4 @@ rulespec_registry.register(
 | 
			
		||||
        name='special_agents:unifi_controller',
 | 
			
		||||
        valuespec=_valuespec_special_agent_unifi_controller,
 | 
			
		||||
    ))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user