Skip to content

Commit aa3ace3

Browse files
Hugo Blombluecmd
Hugo Blom
andauthored
feat(bgp): neighbour metrics (#106)
Co-authored-by: Christian Svensson <[email protected]>
1 parent 9994480 commit aa3ace3

File tree

6 files changed

+191
-0
lines changed

6 files changed

+191
-0
lines changed

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ Per-VDOM:
5757
* `fortigate_ipsec_tunnel_receive_bytes_total`
5858
* `fortigate_ipsec_tunnel_transmit_bytes_total`
5959
* `fortigate_ipsec_tunnel_up`
60+
* `fortigate_bgp_neighbor_ipv4_info`
61+
* `fortigate_bgp_neighbor_ipv6_info`
6062

6163
Per-HA-Member and VDOM:
6264
* `fortigate_ha_member_info`
@@ -171,6 +173,8 @@ config system accprofile
171173
# If you do not wish to grant this permission, the relevant
172174
# labels/metrics will be absent.
173175
set cfg read
176+
# If you wish to collect ipv6 bgp neighbours, add this:
177+
set route-cfg read
174178
end
175179
config fwgrp-permission
176180
set policy read

Diff for: pkg/probe/bgp_neighbors.go

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package probe
2+
3+
import (
4+
"log"
5+
"strconv"
6+
7+
"github.com/bluecmd/fortigate_exporter/internal/version"
8+
"github.com/bluecmd/fortigate_exporter/pkg/http"
9+
"github.com/prometheus/client_golang/prometheus"
10+
)
11+
12+
type BGPNeighbor struct {
13+
NeighborIP string `json:"neighbor_ip"`
14+
LocalIP string `json:"local_ip"`
15+
RemoteAS int `json:"remote_as"`
16+
AdminStatus bool `json:"admin_status"`
17+
State string `json:"state"`
18+
}
19+
20+
type BGPNeighborResponse struct {
21+
Results []BGPNeighbor `json:"results"`
22+
VDOM string `json:"vdom"`
23+
Version string `json:"version"`
24+
}
25+
26+
func probeBGPNeighborsIPv4(c http.FortiHTTP) ([]prometheus.Metric, bool) {
27+
28+
var (
29+
mBGPNeighbor = prometheus.NewDesc(
30+
"fortigate_bgp_neighbor_ipv4_info",
31+
"Confiured bgp neighbor over ipv4",
32+
[]string{"vdom", "remote_as", "state", "admin_status", "local_ip", "neighbor_ip"}, nil,
33+
)
34+
)
35+
36+
var rs []BGPNeighborResponse
37+
38+
if err := c.Get("api/v2/monitor/router/bgp/neighbors", "vdom=*", &rs); err != nil {
39+
log.Printf("Error: %v", err)
40+
return nil, false
41+
}
42+
43+
m := []prometheus.Metric{}
44+
45+
for _, r := range rs {
46+
major, _, ok := version.ParseVersion(r.Version)
47+
if !ok || major < 7 {
48+
// not supported version. Before 7.0.0 the requested endpoint doesn't exist
49+
return nil, false
50+
}
51+
for _, peer := range r.Results {
52+
m = append(m, prometheus.MustNewConstMetric(mBGPNeighbor, prometheus.GaugeValue, 1, r.VDOM, strconv.Itoa(peer.RemoteAS), peer.State, strconv.FormatBool(peer.AdminStatus), peer.LocalIP, peer.NeighborIP))
53+
}
54+
}
55+
56+
return m, true
57+
}
58+
59+
func probeBGPNeighborsIPv6(c http.FortiHTTP) ([]prometheus.Metric, bool) {
60+
61+
var (
62+
mBGPNeighbor = prometheus.NewDesc(
63+
"fortigate_bgp_neighbor_ipv6_info",
64+
"Confiured bgp neighbor over ipv6",
65+
[]string{"vdom", "remote_as", "state", "admin_status", "local_ip", "neighbor_ip"}, nil,
66+
)
67+
)
68+
69+
var rs []BGPNeighborResponse
70+
71+
if err := c.Get("api/v2/monitor/router/bgp/neighbors6", "vdom=*", &rs); err != nil {
72+
log.Printf("Error: %v", err)
73+
return nil, false
74+
}
75+
76+
m := []prometheus.Metric{}
77+
78+
for _, r := range rs {
79+
major, _, ok := version.ParseVersion(r.Version)
80+
if !ok || major < 7 {
81+
// not supported version. Before 7.0.0 the requested endpoint doesn't exist
82+
return nil, false
83+
}
84+
for _, peer := range r.Results {
85+
m = append(m, prometheus.MustNewConstMetric(mBGPNeighbor, prometheus.GaugeValue, 1, r.VDOM, strconv.Itoa(peer.RemoteAS), peer.State, strconv.FormatBool(peer.AdminStatus), peer.LocalIP, peer.NeighborIP))
86+
}
87+
}
88+
89+
return m, true
90+
}

Diff for: pkg/probe/bgp_neighbors_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package probe
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/prometheus/client_golang/prometheus"
8+
"github.com/prometheus/client_golang/prometheus/testutil"
9+
)
10+
11+
func TestBGPNeighborsIPv4(t *testing.T) {
12+
c := newFakeClient()
13+
c.prepare("api/v2/monitor/router/bgp/neighbors", "testdata/bpg-neighbors-v4.jsonnet")
14+
r := prometheus.NewPedanticRegistry()
15+
if !testProbe(probeBGPNeighborsIPv4, c, r) {
16+
t.Errorf("probeBGPNeighborsIPv4() returned non-success")
17+
}
18+
19+
em := `
20+
# HELP fortigate_bgp_neighbor_ipv4_info Confiured bgp neighbor over ipv4
21+
# TYPE fortigate_bgp_neighbor_ipv4_info gauge
22+
fortigate_bgp_neighbor_ipv4_info{admin_status="true",local_ip="10.0.0.0",neighbor_ip="10.0.0.1",remote_as="1337",state="Established",vdom="root"} 1
23+
`
24+
25+
if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
26+
t.Fatalf("metric compare: err %v", err)
27+
}
28+
}
29+
30+
func TestBGPNeighborsIPv6(t *testing.T) {
31+
c := newFakeClient()
32+
c.prepare("api/v2/monitor/router/bgp/neighbors6", "testdata/bpg-neighbors-v6.jsonnet")
33+
r := prometheus.NewPedanticRegistry()
34+
if !testProbe(probeBGPNeighborsIPv6, c, r) {
35+
t.Errorf("probeBGPNeighborsIPv6() returned non-success")
36+
}
37+
38+
em := `
39+
# HELP fortigate_bgp_neighbor_ipv6_info Confiured bgp neighbor over ipv6
40+
# TYPE fortigate_bgp_neighbor_ipv6_info gauge
41+
fortigate_bgp_neighbor_ipv6_info{admin_status="true",local_ip="fd00::1",neighbor_ip="fd00::2",remote_as="1337",state="Established",vdom="root"} 1
42+
`
43+
44+
if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
45+
t.Fatalf("metric compare: err %v", err)
46+
}
47+
}

Diff for: pkg/probe/probe.go

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ func (p *ProbeCollector) Probe(ctx context.Context, target string, hc *http.Clie
7070
probeVirtualWANHealthCheck,
7171
probeSystemAvailableCertificates,
7272
probeFirewallLoadBalance,
73+
probeBGPNeighborsIPv4,
74+
probeBGPNeighborsIPv6,
7375
} {
7476
m, ok := f(c)
7577
if !ok {

Diff for: pkg/probe/testdata/bpg-neighbors-v4.jsonnet

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# api/v2/monitor/router/bgp/neighbors?vdom=*
2+
[
3+
{
4+
"http_method":"GET",
5+
"results":[
6+
{
7+
"neighbor_ip":"10.0.0.1",
8+
"local_ip":"10.0.0.0",
9+
"remote_as":1337,
10+
"admin_status":true,
11+
"state":"Established",
12+
"type":"ipv4"
13+
}
14+
],
15+
"vdom":"root",
16+
"path":"router",
17+
"name":"bgp",
18+
"action":"neighbors",
19+
"status":"success",
20+
"serial":"FGT61FT000000000",
21+
"version":"v7.0.0",
22+
"build":66
23+
}
24+
]

Diff for: pkg/probe/testdata/bpg-neighbors-v6.jsonnet

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# api/v2/monitor/router/bgp/neighbors6?vdom=*
2+
[
3+
{
4+
"http_method":"GET",
5+
"results":[
6+
{
7+
"neighbor_ip":"fd00::2",
8+
"local_ip":"fd00::1",
9+
"remote_as":1337,
10+
"admin_status":true,
11+
"state":"Established",
12+
"type":"ipv6"
13+
}
14+
],
15+
"vdom":"root",
16+
"path":"router",
17+
"name":"bgp",
18+
"action":"neighbors6",
19+
"status":"success",
20+
"serial":"FGT61FT000000000",
21+
"version":"v7.0.0",
22+
"build":66
23+
}
24+
]

0 commit comments

Comments
 (0)