1
1
#!/usr/bin/env python3
2
2
# -*- encoding: utf-8; py-indent-offset: 4 -*-
3
+ ## MIT License
4
+ ##
5
+ ## Copyright (c) 2021 Bash Club
6
+ ##
7
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ ## of this software and associated documentation files (the "Software"), to deal
9
+ ## in the Software without restriction, including without limitation the rights
10
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ ## copies of the Software, and to permit persons to whom the Software is
12
+ ## furnished to do so, subject to the following conditions:
13
+ ##
14
+ ## The above copyright notice and this permission notice shall be included in all
15
+ ## copies or substantial portions of the Software.
16
+ ##
17
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ ## SOFTWARE.
3
24
4
25
###
5
- __VERSION__ = 0.75
26
+ __VERSION__ = 0.79
6
27
7
28
import sys
8
29
import socket
@@ -14,7 +35,127 @@ from statistics import mean
14
35
from collections import defaultdict
15
36
16
37
from pprint import pprint
17
-
38
+ try :
39
+ import cmk .utils .paths
40
+ AGENT_TMP_PATH = cmk .utils .paths .Path (cmk .utils .paths .tmp_dir , "agents/agent_unifi" )
41
+ except ImportError :
42
+ AGENT_TMP_PATH = None
43
+
44
+ UNIFI_DEVICE_TABLE = {
45
+ 'BZ2' : 'UAP' ,
46
+ 'BZ2LR' : 'UAP-LR' ,
47
+ 'U2HSR' : 'UAP-Outdoor+' ,
48
+ 'U2IW' : 'UAP-IW' ,
49
+ 'U2L48' : 'UAP-AC-LR' ,
50
+ 'U2Lv2' : 'UAP-AC-LR' ,
51
+ 'U2M' : 'UAP-Mini' ,
52
+ 'U2O' : 'UAP-Outdoor' ,
53
+ 'U2S48' : 'UAP-AC' ,
54
+ 'U2Sv2' : 'UAP-AC' ,
55
+ 'U5O' : 'UAP-Outdoor5' ,
56
+ 'U7E' : 'UAP-AC' ,
57
+ 'U7EDU' : 'UAP-AC-EDU' ,
58
+ 'U7Ev2' : 'UAP-AC' ,
59
+ 'U7HD' : 'UAP-AC-HD' ,
60
+ 'U7SHD' : 'UAP-AC-SHD' ,
61
+ 'U7NHD' : 'UAP-nanoHD' ,
62
+ 'UFLHD' : 'UAP-FlexHD' ,
63
+ 'UHDIW' : 'UAP-IW-HD' ,
64
+ 'UAIW6' : 'U6-IW' ,
65
+ 'UAE6' : 'U6-Extender' ,
66
+ 'UAL6' : 'U6-Lite' ,
67
+ 'UAM6' : 'U6-Mesh' ,
68
+ 'UALR6' : 'U6-LR-EA' ,
69
+ 'UAP6' : 'U6-LR' ,
70
+ 'UALR6v2' : 'U6-LR' ,
71
+ 'UALR6v3' : 'U6-LR' ,
72
+ 'UCXG' : 'UAP-XG' ,
73
+ 'UXSDM' : 'UWB-XG' ,
74
+ 'UXBSDM' : 'UWB-XG-BK' ,
75
+ 'UCMSH' : 'UAP-XG-Mesh' ,
76
+ 'U7IW' : 'UAP-AC-IW' ,
77
+ 'U7IWP' : 'UAP-AC-IW-Pro' ,
78
+ 'U7MP' : 'UAP-AC-M-Pro' ,
79
+ 'U7LR' : 'UAP-AC-LR' ,
80
+ 'U7LT' : 'UAP-AC-Lite' ,
81
+ 'U7O' : 'UAP-AC-Outdoor' ,
82
+ 'U7P' : 'UAP-Pro' ,
83
+ 'U7MSH' : 'UAP-AC-M' ,
84
+ 'U7PG2' : 'UAP-AC-Pro' ,
85
+ 'p2N' : 'PICOM2HP' ,
86
+ 'UDMB' : 'UAP-BeaconHD' ,
87
+ 'USF5P' : 'USW-Flex' ,
88
+ 'US8' : 'US-8' ,
89
+ 'US8P60' : 'US-8-60W' ,
90
+ 'US8P150' : 'US-8-150W' ,
91
+ 'S28150' : 'US-8-150W' ,
92
+ 'USC8' : 'US-8' ,
93
+ 'USC8P60' : 'US-8-60W' ,
94
+ 'USC8P150' : 'US-8-150W' ,
95
+ 'US16P150' : 'US-16-150W' ,
96
+ 'S216150' : 'US-16-150W' ,
97
+ 'US24' : 'US-24-G1' ,
98
+ 'US24PRO' : 'USW-Pro-24-PoE' ,
99
+ 'US24PRO2' : 'USW-Pro-24' ,
100
+ 'US24P250' : 'US-24-250W' ,
101
+ 'US24PL2' : 'US-L2-24-PoE' ,
102
+ 'US24P500' : 'US-24-500W' ,
103
+ 'S224250' : 'US-24-250W' ,
104
+ 'S224500' : 'US-24-500W' ,
105
+ 'US48' : 'US-48-G1' ,
106
+ 'US48PRO' : 'USW-Pro-48-PoE' ,
107
+ 'US48PRO2' : 'USW-Pro-48' ,
108
+ 'US48P500' : 'US-48-500W' ,
109
+ 'US48PL2' : 'US-L2-48-PoE' ,
110
+ 'US48P750' : 'US-48-750W' ,
111
+ 'S248500' : 'US-48-500W' ,
112
+ 'S248750' : 'US-48-750W' ,
113
+ 'US6XG150' : 'US-XG-6PoE' ,
114
+ 'USMINI' : 'USW-Flex-Mini' ,
115
+ 'USXG' : 'US-16-XG' ,
116
+ 'USC8P450' : 'USW-Industrial' ,
117
+ 'UDC48X6' : 'USW-Leaf' ,
118
+ 'USL8A' : 'UniFi Switch Aggregation' ,
119
+ 'USAGGPRO' : 'UniFi Switch Aggregation Pro' ,
120
+ 'USL8LP' : 'USW-Lite-8-PoE' ,
121
+ 'USL8MP' : 'USW-Mission-Critical' ,
122
+ 'USL16P' : 'USW-16-PoE' ,
123
+ 'USL16LP' : 'USW-Lite-16-PoE' ,
124
+ 'USL24' : 'USW-24-G2' ,
125
+ 'USL48' : 'USW-48-G2' ,
126
+ 'USL24P' : 'USW-24-PoE' ,
127
+ 'USL48P' : 'USW-48-PoE' ,
128
+ 'UGW3' : 'USG-3P' ,
129
+ 'UGW4' : 'USG-Pro-4' ,
130
+ 'UGWHD4' : 'USG' ,
131
+ 'UGWXG' : 'USG-XG-8' ,
132
+ 'UDM' : 'UDM' ,
133
+ 'UDMSE' : 'UDM-SE' ,
134
+ 'UDMPRO' : 'UDM-Pro' ,
135
+ 'UP4' : 'UVP-X' ,
136
+ 'UP5' : 'UVP' ,
137
+ 'UP5t' : 'UVP-Pro' ,
138
+ 'UP7' : 'UVP-Executive' ,
139
+ 'UP5c' : 'UVP' ,
140
+ 'UP5tc' : 'UVP-Pro' ,
141
+ 'UP7c' : 'UVP-Executive' ,
142
+ 'UCK' : 'UCK' ,
143
+ 'UCK-v2' : 'UCK' ,
144
+ 'UCK-v3' : 'UCK' ,
145
+ 'UCKG2' : 'UCK-G2' ,
146
+ 'UCKP' : 'UCK-G2-Plus' ,
147
+ 'UASXG' : 'UAS-XG' ,
148
+ 'ULTE' : 'U-LTE' ,
149
+ 'ULTEPUS' : 'U-LTE-Pro' ,
150
+ 'ULTEPEU' : 'U-LTE-Pro' ,
151
+ 'UP1' : 'USP-Plug' ,
152
+ 'UP6' : 'USP-Strip' ,
153
+ 'USPPDUP' : 'USP - Power Distribution Unit Pro' ,
154
+ 'USPRPS' : 'USP-RPS' ,
155
+ 'US624P' : 'UniFi6 Switch 24' ,
156
+ 'UBB' : 'UBB' ,
157
+ 'UXGPRO' : 'UniFi NeXt-Gen Gateway PRO'
158
+ }
18
159
19
160
try :
20
161
from cmk .special_agents .utils .argument_parsing import create_default_argument_parser
@@ -40,6 +181,9 @@ class unifi_object(object):
40
181
if hasattr (self ,"_init" ):
41
182
self ._init ()
42
183
184
+ def __repr__ (self ):
185
+ return repr ([(_k ,_v ) for _k ,_v in self .__dict__ .items () if type (_v ) in (int ,str )])
186
+
43
187
########################################
44
188
######
45
189
###### S S I D
@@ -51,9 +195,17 @@ class unifi_network_ssid(unifi_object):
51
195
self ._UNIFI_SITE = self ._PARENT ._PARENT
52
196
for _k ,_v in getattr (self ,"reasons_bar_chart_now" ,{}).items ():
53
197
setattr (self ,_k ,_v )
198
+ setattr (self ,f"{ self .radio } _num_sta" ,self .num_sta )
199
+ setattr (self ,f"{ self .radio } _tcp_packet_loss" ,self .tcp_packet_loss )
200
+ setattr (self ,f"{ self .radio } _wifi_retries" ,self .wifi_retries )
201
+ setattr (self ,f"{ self .radio } _wifi_latency" ,self .wifi_latency )
202
+ setattr (self ,f"{ self .radio } _avg_client_signal" ,self .avg_client_signal )
54
203
def __str__ (self ):
55
204
_ret = []
56
- _unwanted = ["essid" ,"radio" ,"id" ,"t" ,"name" ,"radio_name" ,"wlanconf_id" ,"is_wep" ,"up" ,"site_id" ,"ap_mac" ,"state" ]
205
+ _unwanted = ["essid" ,"radio" ,"id" ,"t" ,"name" ,"radio_name" ,"wlanconf_id" ,"is_wep" ,"up" ,"site_id" ,"ap_mac" ,"state" ,
206
+ "na_num_sta" ,"ng_num_sta" ,"ng_tcp_packet_loss" ,"na_tcp_packet_loss" ,"na_wifi_retries" ,"ng_wifi_retries" ,
207
+ "na_wifi_latency" ,"ng_wifi_latency" ,"na_avg_client_signal" ,"ng_avg_client_signal"
208
+ ]
57
209
for _k ,_v in self .__dict__ .items ():
58
210
if _k .startswith ("_" ) or _k in _unwanted or type (_v ) not in (str ,int ,float ):
59
211
continue
@@ -101,6 +253,9 @@ class unifi_network_port(unifi_object):
101
253
self .name = self .ifname
102
254
if not hasattr (self ,"port_idx" ) and hasattr (self ,"ifname" ):
103
255
self .port_idx = int (self .ifname [- 1 ])+ 1 ## ethX
256
+
257
+ self .portconf = self ._PARENT ._PARENT ._PORTCONFIGS .get (getattr (self ,"portconf_id" ,None ))
258
+
104
259
105
260
def _get_state (self ,state ):
106
261
return {
@@ -135,6 +290,7 @@ class unifi_device(unifi_object):
135
290
for _k ,_v in getattr (self ,"sys_stats" ,{}).items ():
136
291
_k = _k .replace ("-" ,"_" )
137
292
setattr (self ,_k ,_v )
293
+ self .model_name = UNIFI_DEVICE_TABLE .get (self .model )
138
294
if self .type in ("ugw" ,"udm" ):
139
295
## change ip to local ip
140
296
self .wan_ip = self .ip
@@ -172,7 +328,7 @@ class unifi_device(unifi_object):
172
328
173
329
def _get_short_info (self ):
174
330
_ret = []
175
- _wanted = ["version" ,"ip" ,"mac" ,"serial" ,"model" ,"uptime" ,"upgradeable" ,"num_sta" ]
331
+ _wanted = ["version" ,"ip" ,"mac" ,"serial" ,"model" ,"model_name" , " uptime" ,"upgradeable" ,"num_sta" , "adopted" , "state " ]
176
332
for _k ,_v in self .__dict__ .items ():
177
333
if _k .startswith ("_" ) or _k not in _wanted or type (_v ) not in (str ,int ,float ):
178
334
continue
@@ -234,6 +390,8 @@ class unifi_site(unifi_object):
234
390
235
391
##pprint(_api.get_data("/stat/rogueap"))
236
392
self ._SITE_DEVICES = []
393
+ self ._PORTCONFIGS = {}
394
+ self ._get_portconfig ()
237
395
self ._get_devices ()
238
396
_satisfaction = list (filter (
239
397
lambda x : x != None ,map (
@@ -242,6 +400,10 @@ class unifi_site(unifi_object):
242
400
))
243
401
self .satisfaction = max (0 ,int (mean (_satisfaction )) if _satisfaction else 0 )
244
402
403
+ def _get_portconfig (self ):
404
+ _data = self ._API .get_portconfig (site = self .name )
405
+ for _config in _data :
406
+ self ._PORTCONFIGS [_config ["_id" ]] = _config .get ("name" )
245
407
246
408
def _get_devices (self ):
247
409
_data = self ._API .get_devices (site = self .name )
@@ -308,7 +470,11 @@ class unifi_controller(unifi_object):
308
470
309
471
_ret = []
310
472
for _ssid ,_obj in _dict .items ():
311
- _ret .append ("|" .join ([_ssid ,"num_sta" ,str (sum (map (lambda x : getattr (x ,"num_sta" ,0 ),_obj )))]))
473
+ pprint (_obj )
474
+ 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" ):
475
+ _ret .append ("|" .join ([_ssid ,_key ,str (sum (map (lambda x : getattr (x ,_key ,0 ),_obj )))]))
476
+ _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 ))))]))
477
+ _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 ))))]))
312
478
_ret .append ("|" .join ([_ssid ,"channels" ,"," .join (
313
479
sorted (
314
480
set (map (lambda x : str (getattr (x ,"channel" ,"0" )),_obj ))
@@ -338,7 +504,7 @@ class unifi_controller(unifi_object):
338
504
for _site in self ._UNIFI_SITES :
339
505
_ret .append (str (_site ))
340
506
341
- _ret .append ("<<<unifi_device_shortlist>>>" )
507
+ _ret .append ("<<<unifi_device_shortlist:sep(124) >>>" )
342
508
for _device in self ._UNIFI_DEVICES :
343
509
if _device ._piggy_back :
344
510
_ret .append (_device ._get_short_info ())
@@ -351,7 +517,7 @@ class unifi_controller(unifi_object):
351
517
if self ._API .PIGGYBACK_ATTRIBUT .lower () != "none" :
352
518
## PIGGYBACK DEVICES ##
353
519
for _device in self ._UNIFI_DEVICES :
354
- if _device ._piggy_back :
520
+ if _device ._piggy_back and _device . adopted :
355
521
_ret .append (str (_device ))
356
522
return "\n " .join (_ret )
357
523
@@ -388,6 +554,9 @@ class unifi_controller_api(object):
388
554
def get_sites (self ):
389
555
return self .get_data ("/stat/sites" ,site = None )
390
556
557
+ def get_portconfig (self ,site ):
558
+ return self .get_data ("/rest/portconf" ,site = site )
559
+
391
560
def get_devices (self ,site ):
392
561
return self .get_data ("/stat/device" ,site = site )
393
562
@@ -409,8 +578,8 @@ class unifi_controller_api(object):
409
578
return
410
579
raise unifi_api_exception ("Login failed" )
411
580
412
- def get_data (self ,path ,site = "default" ,method = "GET" ):
413
- _json = self .request (method = method ,path = path ,site = site ).json ()
581
+ def get_data (self ,path ,site = "default" ,method = "GET" , ** kwargs ):
582
+ _json = self .request (method = method ,path = path ,site = site , ** kwargs ).json ()
414
583
_meta = _json .get ("meta" ,{})
415
584
if _meta .get ("rc" ) == "ok" :
416
585
return _json .get ("data" ,[])
@@ -470,11 +639,10 @@ if __name__ == '__main__':
470
639
471
640
if _api .is_unifios :
472
641
print ("AgentOS: UnifiOS" )
473
- #pprint(_api.get_data("rest/portconf",site="default",method="GET"))
474
- ##pprint(_api.get_data("/stat/rogueap"))
642
+ ##pprint(_api.get_data("/stat/rogueap?within=4"))
475
643
##pprint(_api.get_data("/rest/user",site="default",method="GET"))
476
644
##pprint(_api.get_data("/stat/sta",site="default",method="GET"))
477
- #sys.exit(0)
645
+ ## sys.exit(0)
478
646
_controller = unifi_controller (_API = _api )
479
647
if args .rawapi == False :
480
648
print (_controller )
0 commit comments