From 0bf0f67503520f04d684caa6448ad8d1a412ba03 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Thu, 14 Aug 2014 13:22:35 +0200 Subject: [PATCH] Add network bonding collector This collector exposes two metrics: - net_bonding_slaves: configured slaves per bonding interface - net_bonding_slaves_active: currently active slaves per bonding interface --- collector/bonding.go | 93 +++++++++++++++++++ collector/bonding_test.go | 23 +++++ .../fixtures/bonding/bond0/bonding/slaves | 0 collector/fixtures/bonding/bonding_masters | 1 + collector/fixtures/bonding/dmz/bonding/slaves | 1 + .../fixtures/bonding/dmz/slave_eth0/operstate | 1 + .../fixtures/bonding/dmz/slave_eth4/operstate | 1 + collector/fixtures/bonding/int/bonding/slaves | 1 + .../fixtures/bonding/int/slave_eth1/operstate | 1 + .../fixtures/bonding/int/slave_eth5/operstate | 1 + 10 files changed, 123 insertions(+) create mode 100644 collector/bonding.go create mode 100644 collector/bonding_test.go create mode 100644 collector/fixtures/bonding/bond0/bonding/slaves create mode 100644 collector/fixtures/bonding/bonding_masters create mode 100644 collector/fixtures/bonding/dmz/bonding/slaves create mode 100644 collector/fixtures/bonding/dmz/slave_eth0/operstate create mode 100644 collector/fixtures/bonding/dmz/slave_eth4/operstate create mode 100644 collector/fixtures/bonding/int/bonding/slaves create mode 100644 collector/fixtures/bonding/int/slave_eth1/operstate create mode 100644 collector/fixtures/bonding/int/slave_eth5/operstate diff --git a/collector/bonding.go b/collector/bonding.go new file mode 100644 index 00000000..4f3f1d1b --- /dev/null +++ b/collector/bonding.go @@ -0,0 +1,93 @@ +// +build !nobonding + +package collector + +import ( + "fmt" + "io/ioutil" + "path" + "strings" + + "github.com/prometheus/client_golang/prometheus" +) + +const ( + sysfsNet = "/sys/class/net" +) + +var ( + bondingSlaves = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "net_bonding_slaves", + Help: "Number of configured slaves per bonding interface.", + }, []string{"master"}) + bondingSlavesActive = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "net_bonding_slaves_active", + Help: "Number of active slaves per bonding interface.", + }, []string{"master"}) +) + +type bondingCollector struct{} + +func init() { + Factories["bonding"] = NewBondingCollector +} + +// NewBondingCollector returns a newly allocated bondingCollector. +// It exposes the number of configured and active slave of linux bonding interfaces. +func NewBondingCollector(config Config) (Collector, error) { + c := bondingCollector{} + if _, err := prometheus.RegisterOrGet(bondingSlaves); err != nil { + return nil, err + } + if _, err := prometheus.RegisterOrGet(bondingSlavesActive); err != nil { + return nil, err + } + return &c, nil +} + +// Update reads and exposes bonding states, implements Collector interface. Caution: This works only on linux. +func (c *bondingCollector) Update() (int, error) { + bondingStats, err := readBondingStats(sysfsNet) + if err != nil { + return 0, err + } + updates := 0 + for master, status := range bondingStats { + bondingSlaves.WithLabelValues(master).Set(float64(status[0])) + updates++ + bondingSlavesActive.WithLabelValues(master).Set(float64(status[1])) + updates++ + } + return updates, nil +} + +func readBondingStats(root string) (status map[string][2]int, err error) { + status = map[string][2]int{} + masters, err := ioutil.ReadFile(path.Join(root, "bonding_masters")) + if err != nil { + return nil, err + } + for _, master := range strings.Fields(string(masters)) { + slaves, err := ioutil.ReadFile(path.Join(root, master, "bonding", "slaves")) + if err != nil { + return nil, err + } + sstat := [2]int{0, 0} + for _, slave := range strings.Fields(string(slaves)) { + state, err := ioutil.ReadFile(path.Join(root, master, fmt.Sprintf("slave_%s", slave), "operstate")) + if err != nil { + return nil, err + } + sstat[0]++ + if strings.TrimSpace(string(state)) == "up" { + sstat[1]++ + } + } + status[master] = sstat + } + return status, err +} diff --git a/collector/bonding_test.go b/collector/bonding_test.go new file mode 100644 index 00000000..c68a41e7 --- /dev/null +++ b/collector/bonding_test.go @@ -0,0 +1,23 @@ +package collector + +import ( + "testing" +) + +func TestBonding(t *testing.T) { + bondingStats, err := readBondingStats("fixtures/bonding") + if err != nil { + t.Fatal(err) + } + if bondingStats["bond0"][0] != 0 || bondingStats["bond0"][1] != 0 { + t.Fatal("bond0 in unexpected state") + } + + t.Logf("int: %v", bondingStats["int"]) + if bondingStats["int"][0] != 2 || bondingStats["int"][1] != 1 { + t.Fatal("int in unexpected state") + } + if bondingStats["dmz"][0] != 2 || bondingStats["dmz"][1] != 2 { + t.Fatal("dmz in unexpected state") + } +} diff --git a/collector/fixtures/bonding/bond0/bonding/slaves b/collector/fixtures/bonding/bond0/bonding/slaves new file mode 100644 index 00000000..e69de29b diff --git a/collector/fixtures/bonding/bonding_masters b/collector/fixtures/bonding/bonding_masters new file mode 100644 index 00000000..b1cd24db --- /dev/null +++ b/collector/fixtures/bonding/bonding_masters @@ -0,0 +1 @@ +bond0 dmz int diff --git a/collector/fixtures/bonding/dmz/bonding/slaves b/collector/fixtures/bonding/dmz/bonding/slaves new file mode 100644 index 00000000..976743fc --- /dev/null +++ b/collector/fixtures/bonding/dmz/bonding/slaves @@ -0,0 +1 @@ +eth0 eth4 diff --git a/collector/fixtures/bonding/dmz/slave_eth0/operstate b/collector/fixtures/bonding/dmz/slave_eth0/operstate new file mode 100644 index 00000000..e31ee94e --- /dev/null +++ b/collector/fixtures/bonding/dmz/slave_eth0/operstate @@ -0,0 +1 @@ +up diff --git a/collector/fixtures/bonding/dmz/slave_eth4/operstate b/collector/fixtures/bonding/dmz/slave_eth4/operstate new file mode 100644 index 00000000..e31ee94e --- /dev/null +++ b/collector/fixtures/bonding/dmz/slave_eth4/operstate @@ -0,0 +1 @@ +up diff --git a/collector/fixtures/bonding/int/bonding/slaves b/collector/fixtures/bonding/int/bonding/slaves new file mode 100644 index 00000000..394b5a57 --- /dev/null +++ b/collector/fixtures/bonding/int/bonding/slaves @@ -0,0 +1 @@ +eth5 eth1 diff --git a/collector/fixtures/bonding/int/slave_eth1/operstate b/collector/fixtures/bonding/int/slave_eth1/operstate new file mode 100644 index 00000000..eb0e9043 --- /dev/null +++ b/collector/fixtures/bonding/int/slave_eth1/operstate @@ -0,0 +1 @@ +down diff --git a/collector/fixtures/bonding/int/slave_eth5/operstate b/collector/fixtures/bonding/int/slave_eth5/operstate new file mode 100644 index 00000000..e31ee94e --- /dev/null +++ b/collector/fixtures/bonding/int/slave_eth5/operstate @@ -0,0 +1 @@ +up