2016-03-23 15:40:38 +00:00
|
|
|
package ipmi_sensor
|
2016-03-17 15:45:29 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/influxdata/telegraf"
|
|
|
|
"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 telegraf.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 telegraf.Accumulator) error {
|
|
|
|
conn := NewConnection(serv)
|
|
|
|
|
|
|
|
res, err := m.runner.Run(conn, "sdr")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-23 15:40:38 +00:00
|
|
|
// each line will look something like
|
|
|
|
// Planar VBAT | 3.05 Volts | ok
|
2016-03-17 15:45:29 +00:00
|
|
|
lines := strings.Split(res, "\n")
|
|
|
|
for i := 0; i < len(lines); i++ {
|
|
|
|
vals := strings.Split(lines[i], "|")
|
2016-03-23 15:40:38 +00:00
|
|
|
if len(vals) != 3 {
|
|
|
|
continue
|
|
|
|
}
|
2016-03-17 15:45:29 +00:00
|
|
|
|
2016-03-23 15:40:38 +00:00
|
|
|
tags := map[string]string{
|
|
|
|
"server": conn.Hostname,
|
|
|
|
"name": transform(vals[0]),
|
|
|
|
}
|
2016-03-17 15:45:29 +00:00
|
|
|
|
2016-03-23 15:40:38 +00:00
|
|
|
fields := make(map[string]interface{})
|
|
|
|
if strings.EqualFold("ok", trim(vals[2])) {
|
|
|
|
fields["status"] = 1
|
|
|
|
} else {
|
|
|
|
fields["status"] = 0
|
|
|
|
}
|
2016-03-17 15:45:29 +00:00
|
|
|
|
2016-03-23 15:40:38 +00:00
|
|
|
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
|
2016-03-17 15:45:29 +00:00
|
|
|
}
|
2016-03-23 15:40:38 +00:00
|
|
|
|
|
|
|
acc.AddFields("ipmi_sensor", fields, tags, time.Now())
|
2016-03-17 15:45:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2016-03-23 15:40:38 +00:00
|
|
|
return 0.0
|
2016-03-17 15:45:29 +00:00
|
|
|
} else {
|
2016-03-23 15:40:38 +00:00
|
|
|
return f
|
2016-03-17 15:45:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func trim(s string) string {
|
|
|
|
return strings.TrimSpace(s)
|
|
|
|
}
|
|
|
|
|
2016-03-23 15:40:38 +00:00
|
|
|
func transform(s string) string {
|
|
|
|
s = trim(s)
|
|
|
|
s = strings.ToLower(s)
|
|
|
|
return strings.Replace(s, " ", "_", -1)
|
|
|
|
}
|
|
|
|
|
2016-03-17 15:45:29 +00:00
|
|
|
func init() {
|
2016-03-23 15:40:38 +00:00
|
|
|
inputs.Add("ipmi_sensor", func() telegraf.Input {
|
2016-03-17 15:45:29 +00:00
|
|
|
return &Ipmi{}
|
|
|
|
})
|
|
|
|
}
|