Skip to content
1 change: 1 addition & 0 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ To improve security, limit permissions to required ones only (least privilege pr
|System/Central-management/Status | sysgrp.cfg |api/v2/monitor/system/central-management/status|
|System/Fortimanager/Status | sysgrp.cfg |api/v2/monitor/system/fortimanager/status |
|System/HAStatistics | sysgrp.cfg |api/v2/monitor/system/ha-statistics<br>api/v2/cmdb/system/ha |
|System/Ha-peer | sysgrp.cfg |api/v2/monitor/system/ha-peer |
|System/Interface | netgrp.cfg |api/v2/monitor/system/interface/select |
|System/Interface/Transceivers| *any* |api/v2/monitor/system/interface/transceivers |
|System/LinkMonitor | sysgrp.cfg |api/v2/monitor/system/link-monitor |
Expand Down
3 changes: 3 additions & 0 deletions metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Global:
* `fortigate_system_performance_status_mem_used_bytes`
* _System/HAChecksums_
* `fortigate_ha_member_has_role`
* _System/HAPeer_
* `fortigate_ha_peer_info`
* `fortigate_ha_peer_primary`
* _System/Ntp/Status_
* `fortigate_system_ntp_delay_seconds`
* `fortigate_system_ntp_dispersion_seconds`
Expand Down
1 change: 1 addition & 0 deletions pkg/probe/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func (p *Collector) Probe(ctx context.Context, target map[string]string, hc *htt
{"System/Central-Management/Status", probeSystemCentralManagementStatus},
{"System/Fortimanager/Status", probeSystemFortimanagerStatus},
{"System/HAStatistics", probeSystemHAStatistics},
{"System/Ha-peer", probeSystemHaPeer},
{"System/Interface", probeSystemInterface},
{"System/Interface/Transceivers", probeSystemInterfaceTransceivers},
{"System/LinkMonitor", probeSystemLinkMonitor},
Expand Down
84 changes: 84 additions & 0 deletions pkg/probe/system_ha_peer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package probe

import (
"log"
"strconv"

"github.com/prometheus/client_golang/prometheus"

"github.com/prometheus-community/fortigate_exporter/pkg/http"
)

func probeSystemHaPeer(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) {
info := prometheus.NewDesc(
"fortigate_ha_peer_info",
"Information about the ha peer.",
[]string{"serial", "vcluster", "hostname", "priority"}, nil,
)

primary := prometheus.NewDesc(
"fortigate_ha_peer_primary",
"True when the peer device is the HA primary.",
[]string{"vcluster", "hostname"}, nil,
)

master := prometheus.NewDesc(
"fortigate_ha_peer_master",
"True when the peer device is the HA master.",
[]string{"vcluster", "hostname"}, nil,
)

type SystemHaPeer struct {
Serial string `json:"serial_no"`
Vcluster int64 `json:"vcluster_id"`
Priority float64 `json:"priority"`
Hostname string `json:"hostname"`
Master bool `json:"master"`
Primary bool `json:"primary"`
}

type SystemHaPeerResult struct {
Result []SystemHaPeer `json:"results"`
}

var res SystemHaPeerResult
if err := c.Get("api/v2/monitor/system/ha-peer", "", &res); err != nil {
log.Printf("Warning: %v", err)
return nil, false
}
m := []prometheus.Metric{}
for _, r := range res.Result {
if meta.VersionMajor >= 7 && meta.VersionMinor >= 4 {
m = append(m, prometheus.MustNewConstMetric(info, prometheus.GaugeValue, 1, r.Serial, strconv.FormatInt(r.Vcluster, 10), r.Hostname, strconv.FormatFloat(r.Priority, 'f', -1, 64)))
if r.Primary {
m = append(m, prometheus.MustNewConstMetric(primary, prometheus.GaugeValue, 1, strconv.FormatInt(r.Vcluster, 10), r.Hostname))
} else {
m = append(m, prometheus.MustNewConstMetric(primary, prometheus.GaugeValue, 0, strconv.FormatInt(r.Vcluster, 10), r.Hostname))
}
if meta.VersionMinor == 4 {
if r.Master {
m = append(m, prometheus.MustNewConstMetric(master, prometheus.GaugeValue, 1, strconv.FormatInt(r.Vcluster, 10), r.Hostname))
} else {
m = append(m, prometheus.MustNewConstMetric(master, prometheus.GaugeValue, 0, strconv.FormatInt(r.Vcluster, 10), r.Hostname))
}
}
} else {
m = append(m, prometheus.MustNewConstMetric(info, prometheus.GaugeValue, -1, "None", "0", "None", "false"))
break
}
}
return m, true
}
77 changes: 77 additions & 0 deletions pkg/probe/system_ha_peer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package probe

import (
"strings"
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
)

func TestSystemHaPeerOld(t *testing.T) {
c := newFakeClient()
c.prepare("api/v2/monitor/system/ha-peer", "testdata/system-ha-peer.jsonnet")
r := prometheus.NewPedanticRegistry()
meta := &TargetMetadata{
VersionMajor: 7,
VersionMinor: 0,
}
if !testProbeWithMetadata(probeSystemHaPeer, c, meta, r) {
t.Errorf("probeSystemHaPeer() returned non-success")
}

em := `
# HELP fortigate_ha_peer_info Information about the ha peer.
# TYPE fortigate_ha_peer_info gauge
fortigate_ha_peer_info{hostname="None",priority="false",serial="None",vcluster="0"} -1
`

if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
t.Fatalf("metric compare: err %v", err)
}
}

func TestSystemHaPeerAfter74(t *testing.T) {
c := newFakeClient()
c.prepare("api/v2/monitor/system/ha-peer", "testdata/system-ha-peer.jsonnet")
r := prometheus.NewPedanticRegistry()
meta := &TargetMetadata{
VersionMajor: 7,
VersionMinor: 4,
}
if !testProbeWithMetadata(probeSystemHaPeer, c, meta, r) {
t.Errorf("probeSystemHaPeer() returned non-success")
}

em := `
# HELP fortigate_ha_peer_info Information about the ha peer.
# TYPE fortigate_ha_peer_info gauge
fortigate_ha_peer_info{hostname="member-name-1",priority="200",serial="FGT61E4QXXXXXXXX1",vcluster="0"} 1
fortigate_ha_peer_info{hostname="member-name-2",priority="100",serial="FGT61E4QXXXXXXXX2",vcluster="0"} 1
# HELP fortigate_ha_peer_master True when the peer device is the HA master.
# TYPE fortigate_ha_peer_master gauge
fortigate_ha_peer_master{hostname="member-name-1",vcluster="0"} 0
fortigate_ha_peer_master{hostname="member-name-2",vcluster="0"} 1
# HELP fortigate_ha_peer_primary True when the peer device is the HA primary.
# TYPE fortigate_ha_peer_primary gauge
fortigate_ha_peer_primary{hostname="member-name-1",vcluster="0"} 1
fortigate_ha_peer_primary{hostname="member-name-2",vcluster="0"} 0
`

if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
t.Fatalf("metric compare: err %v", err)
}
}
28 changes: 28 additions & 0 deletions pkg/probe/testdata/system-ha-peer.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# api/v2/monitor/system/ha-peer
{
"http_method":"GET",
"results":[
{
"serial_no":"FGT61E4QXXXXXXXX1",
"vcluster_id":0,
"priority":200,
"hostname":"member-name-1",
"primary":true
},
{
"serial_no":"FGT61E4QXXXXXXXX2",
"vcluster_id":0,
"priority":100,
"hostname":"member-name-2",
"master": true
}
],
"vdom":"root",
"path":"system",
"name":"ha-peer",
"action":"",
"status":"success",
"serial":"FGT61E4QXXXXXXXX1",
"version":"v7.4.0",
"build":700
}
Loading