diff --git a/README.md b/README.md index 628a446..22a3e81 100755 --- a/README.md +++ b/README.md @@ -162,6 +162,10 @@ Per-VDOM: * `fortigate_bgp_neighbor_ipv6_paths` * `fortigate_bgp_neighbor_ipv6_best_paths` + Per-OSPF-Neighbor and VDOM: + * _OSPF/Neighbors_ + * `fortigate_ospf_neighbor_info` + Per-VirtualServer and VDOM: * _Firewall/LoadBalance_ * `fortigate_lb_virtual_server_info` diff --git a/go.sum b/go.sum index 9ce5471..2ca21d0 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,7 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= diff --git a/pkg/probe/ospf_neighbors.go b/pkg/probe/ospf_neighbors.go new file mode 100644 index 0000000..e539cb0 --- /dev/null +++ b/pkg/probe/ospf_neighbors.go @@ -0,0 +1,74 @@ +package probe + +import ( + "log" + "strconv" + + "github.com/bluecmd/fortigate_exporter/pkg/http" + "github.com/prometheus/client_golang/prometheus" +) + +type OSPFNeighbor struct { + NeighborIP string `json:"neighbor_ip"` + RouterID string `json:"router_id"` + State string `json:"state"` + Priority int `json:"priority"` +} + +type OSPFNeighborResponse struct { + Results []OSPFNeighbor `json:"results"` + VDOM string `json:"vdom"` + Version string `json:"version"` +} + +func probeOSPFNeighbors(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) { + if meta.VersionMajor < 7 { + // not supported version. Before 7.0.0 the requested endpoint doesn't exist + return nil, true + } + var ( + mOSPFNeighbor = prometheus.NewDesc( + "fortigate_ospf_neighbor_info", + "List all discovered OSPF neighbors, return state as value (1 - Down, 2 - Attempt, 3 - Init, 4 - Two way, 5 - Exchange start, 6 - Exchange, 7 - Loading, 8 - Full)", + []string{"vdom", "state", "priority", "router_id", "neighbor_ip"}, nil, + ) + ) + + var rs []OSPFNeighborResponse + + if err := c.Get("api/v2/monitor/router/ospf/neighbors", "vdom=*", &rs); err != nil { + log.Printf("Error: %v", err) + return nil, false + } + + m := []prometheus.Metric{} + + for _, r := range rs { + for _, peer := range r.Results { + m = append(m, prometheus.MustNewConstMetric(mOSPFNeighbor, prometheus.GaugeValue, ospfStateToNumber(peer.State), r.VDOM, peer.State, strconv.Itoa(peer.Priority), peer.RouterID, peer.NeighborIP)) + } + } + + return m, true +} + +func ospfStateToNumber(ospfState string) float64 { + switch ospfState { + case "Attempt": + return 1 + case "Init": + return 2 + case "Two way": + return 3 + case "Exchange start": + return 4 + case "Exchange": + return 5 + case "Loading": + return 6 + case "Full": + return 7 + default: // Down + return 0 + } +} diff --git a/pkg/probe/ospf_neighbors_test.go b/pkg/probe/ospf_neighbors_test.go new file mode 100644 index 0000000..246a44d --- /dev/null +++ b/pkg/probe/ospf_neighbors_test.go @@ -0,0 +1,28 @@ +package probe + +import ( + "strings" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" +) + +func TestOSPFNeighborsIPv4(t *testing.T) { + c := newFakeClient() + c.prepare("api/v2/monitor/router/ospf/neighbors", "testdata/router-ospf-neighbors.jsonnet") + r := prometheus.NewPedanticRegistry() + if !testProbe(probeOSPFNeighbors, c, r) { + t.Errorf("probeOSPFNeighbors() returned non-success") + } + + em := ` + # HELP fortigate_ospf_neighbor_info List all discovered OSPF neighbors, return state as value (1 - Down, 2 - Attempt, 3 - Init, 4 - Two way, 5 - Exchange start, 6 - Exchange, 7 - Loading, 8 - Full) + # TYPE fortigate_ospf_neighbor_info gauge + fortigate_ospf_neighbor_info{neighbor_ip="10.0.0.1",priority="3",router_id="12345",state="Full",vdom="root"} 7 + ` + + if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil { + t.Fatalf("metric compare: err %v", err) + } +} diff --git a/pkg/probe/probe.go b/pkg/probe/probe.go index 7104283..c79a7f6 100644 --- a/pkg/probe/probe.go +++ b/pkg/probe/probe.go @@ -148,6 +148,7 @@ func (p *ProbeCollector) Probe(ctx context.Context, target map[string]string, hc {"Wifi/Clients", probeWifiClients}, {"Wifi/ManagedAP", probeWifiManagedAP}, {"Switch/ManagedSwitch", probeManagedSwitch}, + {"OSPF/Neighbors", probeOSPFNeighbors}, } { wanted := false diff --git a/pkg/probe/testdata/router-ospf-neighbors.jsonnet b/pkg/probe/testdata/router-ospf-neighbors.jsonnet new file mode 100644 index 0000000..80b26cd --- /dev/null +++ b/pkg/probe/testdata/router-ospf-neighbors.jsonnet @@ -0,0 +1,22 @@ +# api/v2/monitor/router/ospf/neighbors?vdom=* +[ + { + "http_method":"GET", + "results":[ + { + "neighbor_ip":"10.0.0.1", + "priority":3, + "state":"Full", + "router_id":"12345" + } + ], + "vdom":"root", + "path":"router", + "name":"ospf", + "action":"neighbors", + "status":"success", + "serial":"FGT61FT000000000", + "version":"v7.0.0", + "build":66 + } +] \ No newline at end of file