Check if device is online for statistics processing
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Stefan Hoffmann 2023-04-28 16:47:15 +02:00
parent 16dd56e320
commit 22c935ce2a
Signed by: stefan
GPG Key ID: 8EFC7042BF8D5CDD
6 changed files with 115 additions and 106 deletions

View File

@ -1,14 +1,14 @@
{ {
"unms": { "unms": {
"enabled": false, "enabled": false,
"unmsAPIUrl": "https://unifi.freifunk-troisdorf.de/v2.1", "unmsAPIUrl": "https://uisp.freifunk-troisdorf.de/v2.1",
"APItoken": "UNMS API TOKEN", "APItoken": "UNMS API TOKEN",
"devicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/example.devices.json" "devicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/example.devices.json"
}, },
"unifi": { "unifi": {
"enabled": false, "enabled": false,
"displayusers": true, "displayusers": true,
"APIUrl": "https://unifi.freifunk-troisdorf.de:8443", "APIUrl": "https://unifi.freifunk-troisdorf.de",
"user": "APIuser", "user": "APIuser",
"password": "PASSWORD", "password": "PASSWORD",
"ucDevicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/example.ucDevices.json" "ucDevicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/example.ucDevices.json"

10
go.mod
View File

@ -1,9 +1,17 @@
module git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api module git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api
go 1.16 go 1.20
require ( require (
git.nils.zone/nils/prettify v0.0.4 git.nils.zone/nils/prettify v0.0.4
github.com/fatih/structs v1.1.0 github.com/fatih/structs v1.1.0
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
) )
require (
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect
github.com/fatih/color v1.9.0 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.11 // indirect
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
)

33
main.go
View File

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io"
"log" "log"
"net/http" "net/http"
"net/http/cookiejar" "net/http/cookiejar"
@ -34,8 +34,19 @@ func main() {
if *configPath == "" { if *configPath == "" {
log.Fatalln("Please specify path to config.json flag '-configPath'") log.Fatalln("Please specify path to config.json flag '-configPath'")
} }
// start API processing (runs in a loop) // start API processing (runs in a loop)
go processAPIs() go func() {
if err := processAPIs(); err != nil {
log.Fatalln("API processing failed, error is", err)
}
tick := time.Tick(delay)
for range tick {
if err := processAPIs(); err != nil {
log.Fatalln("API processing failed, error is", err)
}
}
}()
//processUNMSAPIRouter() //processUNMSAPIRouter()
//createMetrics(influxDBClient()) //createMetrics(influxDBClient())
// start webserver on Port 3000 // start webserver on Port 3000
@ -55,22 +66,20 @@ func loadconfig(file string) config {
// int to bool converter // int to bool converter
func itob(i int) bool { func itob(i int) bool {
if i == 1 { return i == 1
return true
}
return false
} }
func processAPIs() { func processAPIs() error {
tick := time.Tick(delay)
for range tick {
var nodes []node var nodes []node
var links []link var links []link
if conf.Unms.Enabled { if conf.Unms.Enabled {
log.Println("Processing UNMS") log.Println("Processing UNMS")
unmsNodes, unmsLinks := processUNMSAPI() unmsNodes, unmsLinks := processUNMSAPI()
unmsRouters := processUNMSAPIRouter() unmsRouters, err := processUNMSAPIRouter()
if err != nil {
return err
}
nodes = append(nodes, unmsNodes...) nodes = append(nodes, unmsNodes...)
nodes = append(nodes, unmsRouters...) nodes = append(nodes, unmsRouters...)
links = append(links, unmsLinks...) links = append(links, unmsLinks...)
@ -107,7 +116,7 @@ func processAPIs() {
} }
// we're done here // we're done here
log.Println("...done") log.Println("...done")
} return nil
} }
// function to get file from meshviewer // function to get file from meshviewer
@ -117,7 +126,7 @@ func getFile(url string) []byte {
log.Println("Error getting file from:", url) log.Println("Error getting file from:", url)
} }
data := resp.Body data := resp.Body
byteValue, _ := ioutil.ReadAll(data) byteValue, _ := io.ReadAll(data)
return byteValue return byteValue
} }

View File

@ -314,40 +314,26 @@ type UNMSLogResponse struct {
} `json:"items"` } `json:"items"`
} }
type XY struct {
X int `json:"x"`
Y int `json:"y"`
}
type UNMSstatistics struct { type UNMSstatistics struct {
Period int `json:"period"` Period int `json:"period"`
Interval struct { Interval struct {
Start int `json:"start"` Start int `json:"start"`
End int `json:"end"` End int `json:"end"`
} `json:"interval"` } `json:"interval"`
CPU []struct { CPU []XY `json:"cpu"`
X int `json:"x"` RAM []XY `json:"ram"`
Y int `json:"y"` Errors []XY `json:"errors"`
} `json:"cpu"`
RAM []struct {
X int `json:"x"`
Y int `json:"y"`
} `json:"ram"`
Ping []struct {
X int `json:"x"`
Y int `json:"y"`
} `json:"ping"`
Errors []struct {
X int `json:"x"`
Y int `json:"y"`
} `json:"errors"`
Interfaces []struct { Interfaces []struct {
ID string `json:"id"` ID string `json:"id"`
Priority int `json:"priority"` Priority int `json:"priority"`
Name string `json:"name"` Name string `json:"name"`
Receive []struct { Receive []XY `json:"receive"`
X int `json:"x"` Transmit []XY `json:"transmit"`
Y int `json:"y"`
} `json:"receive"`
Transmit []struct {
X int `json:"x"`
Y int `json:"y"`
} `json:"transmit"`
} `json:"interfaces"` } `json:"interfaces"`
} }

View File

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io"
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
@ -126,10 +126,10 @@ func (u *UnifiAPIData) ucCallAPI(url string, method string, body *bytes.Buffer,
} }
defer response.Body.Close() defer response.Body.Close()
if response.StatusCode != 200 { if response.StatusCode != 200 {
return fmt.Errorf("Login failed %s", u.baseURL+url) return fmt.Errorf("login failed %s", u.baseURL+url)
} }
data, err := ioutil.ReadAll(response.Body) data, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
return err return err
} }

48
unms.go
View File

@ -42,10 +42,7 @@ func processUNMSAPI() ([]node, []link) {
} }
} }
var isOnline bool = false isOnline := dev.Overview.Status == "active"
if dev.Overview.Status == "active" {
isOnline = true
}
// END OF API CALL 1 // END OF API CALL 1
// API CALL 2 // API CALL 2
@ -104,7 +101,7 @@ func processUNMSAPI() ([]node, []link) {
return nodes, links return nodes, links
} }
func processUNMSAPIRouter() []node { func processUNMSAPIRouter() ([]node, error) {
// Variables for runtime // Variables for runtime
var nodes []node var nodes []node
@ -115,7 +112,7 @@ func processUNMSAPIRouter() []node {
var u []unifiAPIResponse var u []unifiAPIResponse
err := UnmsCallAPI("/devices", &u) err := UnmsCallAPI("/devices", &u)
if err != nil { if err != nil {
log.Fatalln(err) return nil, err
} }
// END OF API CALL 1 // END OF API CALL 1
@ -130,26 +127,29 @@ func processUNMSAPIRouter() []node {
} }
} }
var isOnline bool = false isOnline := dev.Overview.Status == "active"
if dev.Overview.Status == "active" {
isOnline = true
}
// API CALL FOR ROUTER DETAILS (Interface RX/TX) // API CALL FOR ROUTER DETAILS (Interface RX/TX)
log.Println("Getting details of ", d.Devices[i].Name, "from UNMS API") log.Println("Getting details of ", d.Devices[i].Name, "from UNMS API")
var details unifiAPIDetails var details unifiAPIDetails
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details) if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
return nil, err
}
// API CALL FOR DEVICE STATISTICS (CPU, RAM) // API CALL FOR DEVICE STATISTICS (CPU, RAM)
log.Println("Getting statistics of ", d.Devices[i].Name, "from UNMS API") log.Println("Getting statistics of ", d.Devices[i].Name, "from UNMS API")
var statistics UNMSstatistics var statistics UNMSstatistics
UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics) if err := UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics); err != nil {
return nil, err
}
// API CALL FOR DHCP LEASES // API CALL FOR DHCP LEASES
log.Println("Getting DHCP Leases of ", d.Devices[i].Name, "from UNMS API") log.Println("Getting DHCP Leases of ", d.Devices[i].Name, "from UNMS API")
var dhcpleases UNMSdhcp var dhcpleases UNMSdhcp
if isOnline { if isOnline {
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID+"/dhcp/leases", &dhcpleases) if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID+"/dhcp/leases", &dhcpleases); err != nil {
return nil, err
}
} else { } else {
log.Println("Router ist offline, skipping DHCP Leases") log.Println("Router ist offline, skipping DHCP Leases")
} }
@ -164,7 +164,8 @@ func processUNMSAPIRouter() []node {
} }
// //
fields := map[string]interface{}{} // fields := map[string]interface{}{}
fields := make(map[string]any)
tags := map[string]string{ tags := map[string]string{
"hostname": strings.ReplaceAll(d.Devices[i].Name, " ", "-"), "hostname": strings.ReplaceAll(d.Devices[i].Name, " ", "-"),
"nodeid": strings.ReplaceAll(dev.Identification.MAC, ":", ""), "nodeid": strings.ReplaceAll(dev.Identification.MAC, ":", ""),
@ -177,15 +178,21 @@ func processUNMSAPIRouter() []node {
fields[interface_name_tx] = details.Interfaces[eth].Statistics.Txrate fields[interface_name_tx] = details.Interfaces[eth].Statistics.Txrate
} }
// set default values if we can't get statistics
fields["cpu"] = 0
fields["load"] = float64(0)
fields["ram"] = 0
if isOnline {
// Generate fields for all Statistics // Generate fields for all Statistics
load := (float64(statistics.CPU[0].Y) / float64(100)) load := (float64(statistics.CPU[0].Y) / float64(100))
fields["cpu"] = statistics.CPU[0].Y fields["cpu"] = statistics.CPU[0].Y
fields["load"] = load fields["load"] = load
fields["ram"] = statistics.RAM[0].Y fields["ram"] = statistics.RAM[0].Y
}
// Generate field for DHCP Leases // Generate field for DHCP Leases
leases := len(dhcpleases) fields["clients.total"] = len(dhcpleases)
fields["clients.total"] = leases
// Generate Dataponts // Generate Dataponts
point, err := client.NewPoint( point, err := client.NewPoint(
@ -240,7 +247,7 @@ func processUNMSAPIRouter() []node {
Model: details.Identification.Model, Model: details.Identification.Model,
}) })
} }
return nodes return nodes, nil
} }
func influxDBClient() client.Client { func influxDBClient() client.Client {
@ -253,7 +260,7 @@ func influxDBClient() client.Client {
return c return c
} }
func UnmsCallAPI(url string, i interface{}) error { func UnmsCallAPI(url string, i any) error {
request, err := http.NewRequest(http.MethodGet, conf.Unms.UnmsAPIURL+url, nil) request, err := http.NewRequest(http.MethodGet, conf.Unms.UnmsAPIURL+url, nil)
if err != nil { if err != nil {
return errors.New(fmt.Sprint("can't set request", conf.Unms.UnmsAPIURL+url)) return errors.New(fmt.Sprint("can't set request", conf.Unms.UnmsAPIURL+url))
@ -265,7 +272,7 @@ func UnmsCallAPI(url string, i interface{}) error {
return fmt.Errorf("can't get request %s with x-auth-token %s", conf.Unms.UnmsAPIURL+url, conf.Unms.APItoken) return fmt.Errorf("can't get request %s with x-auth-token %s", conf.Unms.UnmsAPIURL+url, conf.Unms.APItoken)
} }
if response.StatusCode != 200 { if response.StatusCode != 200 {
log.Fatalln("Can´t call UNMS API, check token and URL. HTTP Status: ", response.StatusCode) log.Fatalln("Can't call UNMS API, check token and URL. HTTP Status: ", response.StatusCode)
} }
data, err := ioutil.ReadAll(response.Body) data, err := ioutil.ReadAll(response.Body)
defer response.Body.Close() defer response.Body.Close()
@ -273,8 +280,7 @@ func UnmsCallAPI(url string, i interface{}) error {
return fmt.Errorf("can't read response body: %+v", response.Body) return fmt.Errorf("can't read response body: %+v", response.Body)
} }
// no error occurred, unmarshal to struct // no error occurred, unmarshal to struct
json.Unmarshal(data, &i) return json.Unmarshal(data, &i)
return nil
} }
func UnmsGetAddresses(ip string) []string { func UnmsGetAddresses(ip string) []string {