From ead267bcbfc73d15ee58819b0fba8b392333e9f3 Mon Sep 17 00:00:00 2001 From: M.Gergő Date: Sat, 15 Sep 2018 22:28:44 +0200 Subject: Munin monitoring plugin for Ubiquity unifi AP network, over SNMPv2. --- ubnt_unifi.php | 427 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 ubnt_unifi.php (limited to 'ubnt_unifi.php') diff --git a/ubnt_unifi.php b/ubnt_unifi.php new file mode 100644 index 0000000..aa4c315 --- /dev/null +++ b/ubnt_unifi.php @@ -0,0 +1,427 @@ +#!/usr/bin/php + $val){ + $cf .= "unifi_".$val['name'].".label ".$val['label']."\n"; + $cf .= "unifi_".$val['name'].".draw ".$val['draw']."\n"; + $cf .= "unifi_".$val['name'].".info ".$val['info']."\n"; + if(isset($val['type'])){ $cf .= "unifi_".$val['name'].".type ".$val['type']."\n"; } + if(isset($val['min'])) { $cf .= "unifi_".$val['name'].".min ".$val['min']."\n"; } + if(isset($val['cdef'])){ $cf .= "unifi_".$val['name'].".cdef ".$val['cdef']."\n"; } + if(isset($val['graph'])){ $cf .= "unifi_".$val['name'].".graph ".$val['graph']."\n"; } + if(isset($val['max'])){ $cf .= "unifi_".$val['name'].".max ".$val['max']."\n"; } + if(isset($val['negative'])){ $cf .= "unifi_".$val['name'].".negative ".$val['negative']."\n"; } + } + $cf .= "\n"; + echo iconv("UTF-8", "ISO-8859-2", $cf), PHP_EOL; +} + + +function print_data($inp) { + + $pf = "multigraph unifi_".$inp['g_multi']."\n"; + foreach($inp['data'] as $key => $val){ + $pf .= "unifi_".$val['name'].".value ".$val['value']."\n" ; + } + $pf .= "\n"; + + echo iconv("UTF-8", "ISO-8859-2", $pf), PHP_EOL; + +} + +function count_wl_networks($inp){ //Count wireless networks from interfade data + $num = -10; + foreach($inp as $key => $val){ // jump to the end of wl interface list + if(strpos($key, "iso.3.6.1.4.1.41112.1.6.1.2.1.1.") !== false){ + if(is_numeric(explode(": ", $val)[1]) and $num < explode(": ", $val)[1]){ + $num = explode(": ", $val)[1]; + } + } + } + $num = $num+1; //Because the snmp counts from 0 + + if($num > 0){ + return $num; + } else { + return -1; + } +} + + +function collect_radio_summary($inp,$host){ + global $controller, $replace_chars; + $ret = array(); + if(isset($host) and $host !== null and $host != "" ){ + $ret['g_multi'] = "radio_".str_replace( array(".", ":"), "_" ,$controller).".".str_replace( array(".", ":"), "_" ,$host); + $ret['g_controller'] = $controller; + $location = str_replace("\"", "", explode(": ", $inp[$host]["iso.3.6.1.2.1.1.6.0"])[1]); + if( $location != "Unknown" and $location != "" ){ $ret['g_title'] = "Unifi Clients on: ".$location ; } // if the Location is not filled in Controller settings, use the hostname or ip address + else { $ret['g_title'] = "Unifi Clients on: ".$host; }; + $ret['g_vlabel'] = "Users"; + $ret['g_category'] = "wl_clients_ap"; + $ret['g_info'] = "ubnt_wireless"; + } else { + $ret['g_multi'] = "radio_".str_replace( array(".", ":"), "_" ,$controller); + $ret['g_controller'] = $controller; + $ret['g_title'] = "Unifi Clients on: $controller (total)"; + $ret['g_vlabel'] = "Users"; + $ret['g_category'] = "Wl_clients_all"; + $ret['g_info'] = "ubnt_wireless"; + } + + $ret['head'][0]['name'] = "sum_clients"; + $ret['head'][0]['label'] = "Total clients"; + $ret['head'][0]['draw'] = "LINE1.2"; + $ret['head'][0]['info'] = "Total Clients"; + $ret['head'][0]['type'] = "GAUGE"; + $ret['head'][0]['min'] = "0"; + + $ret['head'][1]['name'] = "2g_clients"; + $ret['head'][1]['label'] = "2.4Ghz"; + $ret['head'][1]['draw'] = "LINE1.2"; + $ret['head'][1]['info'] = "2.4Ghz Clients"; + $ret['head'][1]['type'] = "GAUGE"; + $ret['head'][1]['min'] = "0"; + + $ret['head'][2]['name'] = "5g_clients"; + $ret['head'][2]['label'] = "5Ghz"; + $ret['head'][2]['draw'] = "LINE1.2"; + $ret['head'][2]['info'] = "2.4Ghz Clients"; + $ret['head'][2]['type'] = "GAUGE"; + $ret['head'][2]['min'] = "0"; + + + if(isset($host) and $host !== null and $host != "" ){ // trim raw data array to current device (in $host) or use the whole array when calculating controller's data + $temp = $inp; + unset($inp); + $inp = array($host => $temp[$host]); + unset($temp); + } + + foreach($inp as $key => $val){ + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect clients by band. + if( explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.4.".$i])[1] < 15 ){ //2.4Ghz client + $ret['data'][1]['name'] = "2g_clients"; + @$ret['data'][1]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + } else { // 5Ghz clients + $ret['data'][2]['name'] = "5g_clients"; + @$ret['data'][2]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + } + } + $ret['data'][0]['name'] = "sum_clients"; + $ret['data'][0]['value'] = $ret['data'][1]['value'] + $ret['data'][2]['value']; + + + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect clients by SSID. + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //found, update record + if($ret['data'][$key2]['name'] == str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + + } else { //not found, new record + $ret['data'][] = array( "name" => str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1] + ); + $ret['head'][] = array( "name" => str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] ), + "draw" => "LINE1.2", + "info" => explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "GAUGE", + "min" => "0", + ); + + } + } + } + + +return $ret; +} + + + + +function collect_netw_summary($inp,$host){ //network information + global $controller, $replace_chars; + $ret = array(); + + if(isset($host) and $host !== null and $host != "" ){ // When showing the Ap's summary. + $temp = $inp; + unset($inp); + $inp = array($host => $temp[$host]); + unset($temp); + $multiplier = 8; + $divider = 1; + } else { //because the normal INTEGER(32) would be overflowed + $multiplier = 8192; // When showing the controller's summary + $divider = 1024; + } + + + if(isset($host) and $host !== null and $host != "" ){ + $ret['g_multi'] = "netw_".str_replace( array(".", ":"), "_" ,$controller).".".str_replace( array(".", ":"), "_" ,$host); + $ret['g_controller'] = $controller; + $location = str_replace("\"", "", explode(": ", $inp[$host]["iso.3.6.1.2.1.1.6.0"])[1]); + if($location != "Unknown" and $location != ""){ $ret['g_title'] = "Network Usage on: ".$location; } + else{$ret['g_title'] = "Network Usage on: ".$host;} + $ret['g_vlabel'] = "bits in(-) / out(+) per second"; + $ret['g_category'] = "Wl_netw_ap"; + $ret['g_info'] = "ubnt_network"; + $ret['g_order'] = "rx_all tx_all rx_2g tx_2g rx_5g tx_5g"; + + } else { + $ret['g_multi'] = "netw_".str_replace( array(".", ":"), "_" ,$controller); + $ret['g_controller'] = $controller; + $ret['g_title'] = "Netwok Usage on: $controller (total)"; + $ret['g_vlabel'] = "bits in(-) / out(+) per second"; + $ret['g_category'] = "Wl_netw_all"; + $ret['g_info'] = "ubnt_network"; + $ret['g_order'] = "rx_all tx_all rx_2g tx_2g rx_5g tx_5g"; + } + + $ret['head'][0]['name'] = "rx_all"; + $ret['head'][0]['label'] = "RxTotal (bps)"; + $ret['head'][0]['draw'] = "LINE1.2"; + $ret['head'][0]['info'] = "Total Received"; + $ret['head'][0]['type'] = "DERIVE"; + $ret['head'][0]['min'] = "0"; + $ret['head'][0]['graph'] = "no"; + $ret['head'][0]['cdef'] = "unifi_rx_all,$multiplier,*"; + $ret['head'][0]['max'] = "1000000000"; + + $ret['head'][1]['name'] = "tx_all"; + $ret['head'][1]['label'] = "Total (bps)"; + $ret['head'][1]['draw'] = "LINE1.2"; + $ret['head'][1]['info'] = "Total Sent"; + $ret['head'][1]['type'] = "DERIVE"; + $ret['head'][1]['min'] = "0"; + $ret['head'][1]['cdef'] = "unifi_tx_all,$multiplier,*"; + $ret['head'][1]['max'] = "1000000000"; + $ret['head'][1]['negative'] = "unifi_rx_all"; + + $ret['head'][2]['name'] = "rx_2g"; + $ret['head'][2]['label'] = "2G (bps)"; + $ret['head'][2]['draw'] = "LINE1.2"; + $ret['head'][2]['info'] = "Total Received"; + $ret['head'][2]['type'] = "DERIVE"; + $ret['head'][2]['min'] = "0"; + $ret['head'][2]['graph'] = "no"; + $ret['head'][2]['cdef'] = "unifi_rx_2g,$multiplier,*"; + $ret['head'][2]['max'] = "1000000000"; + + $ret['head'][3]['name'] = "tx_2g"; + $ret['head'][3]['label'] = "2G (bps)"; + $ret['head'][3]['draw'] = "LINE1.2"; + $ret['head'][3]['info'] = "Total Sent"; + $ret['head'][3]['type'] = "DERIVE"; + $ret['head'][3]['min'] = "0"; + $ret['head'][3]['cdef'] = "unifi_tx_2g,$multiplier,*"; + $ret['head'][3]['max'] = "1000000000"; + $ret['head'][3]['negative'] = "unifi_rx_2g"; + + $ret['head'][4]['name'] = "rx_5g"; + $ret['head'][4]['label'] = "5G (bps)"; + $ret['head'][4]['draw'] = "LINE1.2"; + $ret['head'][4]['info'] = "Total Received"; + $ret['head'][4]['type'] = "DERIVE"; + $ret['head'][4]['min'] = "0"; + $ret['head'][4]['graph'] = "no"; + $ret['head'][4]['cdef'] = "unifi_rx_5g,$multiplier,*"; + $ret['head'][4]['max'] = "1000000000"; + + $ret['head'][5]['name'] = "tx_5g"; + $ret['head'][5]['label'] = "5G (bps)"; + $ret['head'][5]['draw'] = "LINE1.2"; + $ret['head'][5]['info'] = "Total Sent"; + $ret['head'][5]['type'] = "DERIVE"; + $ret['head'][5]['min'] = "0"; + $ret['head'][5]['cdef'] = "unifi_tx_5g,$multiplier,*"; + $ret['head'][5]['max'] = "1000000000"; + $ret['head'][5]['negative'] = "unifi_rx_5g"; + + + foreach($inp as $key => $val){ + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect netw_bytes by band and direction. + if( explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.4.".$i])[1] < 15 ){ //2.4Ghz client + $ret['data'][2]['name'] = "rx_2g"; + @$ret['data'][2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + $ret['data'][3]['name'] = "tx_2g"; + @$ret['data'][3]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + + } else { // 5Ghz clients + $ret['data'][4]['name'] = "rx_5g"; + @$ret['data'][4]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + $ret['data'][5]['name'] = "tx_5g"; + @$ret['data'][5]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + } + } + $ret['data'][0]['name'] = "rx_all"; + $ret['data'][0]['value'] = $ret['data'][2]['value'] + $ret['data'][4]['value']; + $ret['data'][1]['name'] = "tx_all"; + $ret['data'][1]['value'] = $ret['data'][3]['value'] + $ret['data'][5]['value']; + + + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect netw_bytes by SSID. + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //ssid found, update record + if($ret['data'][$key2]['name'] == "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + + } else { //ssid not found, new record + $ret['data'][] = array( "name" => "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider) , + ); + $ret['head'][] = array( "name" => "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => "RX_".str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] )."(bps)", + "draw" => "LINE1.2", + "info" => "Rx_".explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "DERIVE", + "min" => "0", + "graph" => "no", + "cdef" => "unifi_rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]).",$multiplier,*", + "max" => "1000000000", + ); + + } + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //ssid found, update record + if($ret['data'][$key2]['name'] == "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + + } else { //ssid not found, new record + $ret['data'][] = array( "name" => "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider) , + ); + $ret['head'][] = array( "name" => "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => "".str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] )." (bps)", + "draw" => "LINE1.2", + "info" => "Tx_".explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "DERIVE", + "min" => "0", + "cdef" => "unifi_tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]).",$multiplier,*", + "max" => "1000000000", + "negative" => "unifi_rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + ); + } + + + } + } + + +return $ret; +} + + +$hosts = explode(" ", $hosts); +$netw = @explode('/', $devnetw)[0]; +$mask = @explode('/', $devnetw)[1]; +$hosts2 = array(); + +if($mask != 0 ){ + for($i=1; $i<(1 << (32 - $mask)); $i++ ){ // fetch ip addresses from given network and mask + $hosts2[] = long2ip((ip2long($netw) & ~((1 << (32 - $mask)) -1)) +$i ) ; + } +} + + +foreach($hosts as $key => $val){ // delete addresses which are given by hostname + if(in_array(gethostbyname($val), $hosts2)){ + unset($hosts2[ array_keys($hosts2, gethostbyname($val))[0] ]); + } + +} +$hosts = array_merge($hosts, $hosts2); + +$raw=array(); +foreach($hosts as $key => $val){ // get raw snmp data from unifi devices + if($hosts[$key] == ""){ + unset($hosts[$key]); + } + if($val != "") { + $raw[$val] = @snmp2_real_walk($val, "public", ".1.3.6.1.4.1.41112.1.6.1.2.1", $timeout*1000, $retry ); // wl network info + $raw[$val]["iso.3.6.1.2.1.1.6.0"] = @snmp2_get($val, "public", ".1.3.6.1.2.1.1.6.0", $timeout*1000, $retry ) ; // location info + $raw[$val]["iso.3.6.1.2.1.1.1.0"] = @snmp2_get($val, "public", ".1.3.6.1.2.1.1.1.0", $timeout*1000, $retry ) ; // descr. info + } + if( !isset($raw[$val]["iso.3.6.1.4.1.41112.1.6.1.2.1.1.1"]) ){ + unset($raw[$val]); + unset($hosts[$key]); + } +} + + +//print_r($raw); +//print_r($hosts); +//$valami = collect_netw_summary($raw,"ap12.wireless.lan"); +//print_r($valami); + + +if (isset($argv[1]) and $argv[1] == "config"){ // munin config + print_header(collect_radio_summary($raw,null)); + foreach($hosts as $key => $val){ + print_header(collect_radio_summary($raw,$val)); + } + print_header(collect_netw_summary($raw,null)); + foreach($hosts as $key => $val){ + print_header(collect_netw_summary($raw,$val)); + } + + +} else { // munin data + print_data(collect_radio_summary($raw,null)); + foreach($hosts as $key => $val){ + print_data(collect_radio_summary($raw,$val)); + } + print_data(collect_netw_summary($raw,null)); + foreach($hosts as $key => $val){ + print_data(collect_netw_summary($raw,$val)); + } + +} + + +echo "\n"; + +?> -- cgit v1.2.3