telegraf/plugins/inputs/ipmi_sensor/ipmi.go

130 lines
2.3 KiB
Go

package ipmi_sensor
import (
"strconv"
"strings"
"time"
"github.com/influxdata/telegraf/plugins"
"github.com/influxdata/telegraf/plugins/inputs"
)
type Ipmi struct {
Servers []string
runner Runner
}
var sampleConfig = `
## specify servers via a url matching:
## [username[:password]@][protocol[(address)]]
## e.g.
## root:passwd@lan(127.0.0.1)
##
servers = ["USERID:PASSW0RD@lan(192.168.1.1)"]
`
func NewIpmi() *Ipmi {
return &Ipmi{
runner: CommandRunner{},
}
}
func (m *Ipmi) SampleConfig() string {
return sampleConfig
}
func (m *Ipmi) Description() string {
return "Read metrics from one or many bare metal servers"
}
func (m *Ipmi) Gather(acc plugins.Accumulator) error {
if m.runner == nil {
m.runner = CommandRunner{}
}
for _, serv := range m.Servers {
err := m.gatherServer(serv, acc)
if err != nil {
return err
}
}
return nil
}
func (m *Ipmi) gatherServer(serv string, acc plugins.Accumulator) error {
conn := NewConnection(serv)
res, err := m.runner.Run(conn, "sdr")
if err != nil {
return err
}
// each line will look something like
// Planar VBAT | 3.05 Volts | ok
lines := strings.Split(res, "\n")
for i := 0; i < len(lines); i++ {
vals := strings.Split(lines[i], "|")
if len(vals) != 3 {
continue
}
tags := map[string]string{
"server": conn.Hostname,
"name": transform(vals[0]),
}
fields := make(map[string]interface{})
if strings.EqualFold("ok", trim(vals[2])) {
fields["status"] = 1
} else {
fields["status"] = 0
}
val1 := trim(vals[1])
if strings.Index(val1, " ") > 0 {
// split middle column into value and unit
valunit := strings.SplitN(val1, " ", 2)
fields["value"] = Atofloat(valunit[0])
if len(valunit) > 1 {
tags["unit"] = transform(valunit[1])
}
} else {
fields["value"] = 0.0
}
acc.AddFields("ipmi_sensor", fields, tags, time.Now())
}
return nil
}
type Runner interface {
Run(conn *Connection, args ...string) (string, error)
}
func Atofloat(val string) float64 {
f, err := strconv.ParseFloat(val, 64)
if err != nil {
return 0.0
} else {
return f
}
}
func trim(s string) string {
return strings.TrimSpace(s)
}
func transform(s string) string {
s = trim(s)
s = strings.ToLower(s)
return strings.Replace(s, " ", "_", -1)
}
func init() {
inputs.Add("ipmi_sensor", func() plugins.Input {
return &Ipmi{}
})
}