opnsense-exporter/opnsense/gateways.go

95 lines
2.8 KiB
Go
Raw Permalink Normal View History

package opnsense
import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
)
// gatewaysStatusResponse is the response from the OPNsense API that contains the gateways status details
// The data is constucted in this script:
// ---> https://github.com/opnsense/core/blob/master/src/opnsense/scripts/routes/gateway_status.php
// Following the reverse engineering of the call:
// ---> https://github.com/opnsense/core/blob/master/src/etc/inc/plugins.inc.d/dpinger.inc#L368
// From this file we know that Loss and Delay always have the same format of '%0.1f ms'
type gatewaysStatusResponse struct {
Items []struct {
Name string `json:"name"`
Address string `json:"address"`
Status string `json:"status"`
Loss string `json:"loss"`
Delay string `json:"delay"`
Stddev string `json:"stddev"`
StatusTranslated string `json:"status_translated"`
} `json:"items"`
Status string `json:"status"`
}
// GatewayStatus is the custom type that represents the status of a gateway
type GatewayStatus int
const (
GatewayStatusOffline GatewayStatus = iota
GatewayStatusOnline
GatewayStatusUnknown
)
type Gateway struct {
Name string
Address string
Status GatewayStatus
RTTMilliseconds float64
RTTDMilliseconds float64
LossPercentage float64
}
type Gateways struct {
Gateways []Gateway
}
// parseGatewayStatus parses a string status to a GatewayStatus type.
func parseGatewayStatus(statusTranslated string, logger log.Logger, originalStatus string) GatewayStatus {
switch statusTranslated {
case "Online":
return GatewayStatusOnline
case "Offline":
return GatewayStatusOffline
default:
level.Warn(logger).
Log("msg", "unknown gateway status detected", "status", originalStatus)
return GatewayStatusUnknown
}
}
// FetchGateways fetches the gateways status details from the OPNsense API
// and returns a safe wrapper Gateways struct.
func (c *Client) FetchGateways() (Gateways, *APICallError) {
var resp gatewaysStatusResponse
var data Gateways
url, ok := c.endpoints["gatewaysStatus"]
if !ok {
return data, &APICallError{
Endpoint: "gatewaysStatus",
Message: "endpoint not found in client endpoints",
StatusCode: 0,
}
}
err := c.do("GET", url, nil, &resp)
if err != nil {
return data, err
}
for _, v := range resp.Items {
data.Gateways = append(data.Gateways, Gateway{
Name: v.Name,
Address: v.Address,
Status: parseGatewayStatus(v.StatusTranslated, c.log, v.Status),
RTTMilliseconds: parseStringToFloatWithReplace(v.Delay, c.gatewayRTTRegex, " ms", "rtt", c.log),
RTTDMilliseconds: parseStringToFloatWithReplace(v.Stddev, c.gatewayRTTRegex, " ms", "rttd", c.log),
LossPercentage: parseStringToFloatWithReplace(v.Loss, c.gatewayLossRegex, " %", "loss", c.log),
})
}
return data, nil
}