parent
f95ec898a9
commit
a85697efb5
|
@ -11,6 +11,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const alphanum string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
@ -122,6 +123,23 @@ func GetTLSConfig(
|
|||
return t, nil
|
||||
}
|
||||
|
||||
// SnakeCase converts the given string to snake case following the Golang format:
|
||||
// acronyms are converted to lower-case and preceded by an underscore.
|
||||
func SnakeCase(in string) string {
|
||||
runes := []rune(in)
|
||||
length := len(runes)
|
||||
|
||||
var out []rune
|
||||
for i := 0; i < length; i++ {
|
||||
if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
|
||||
out = append(out, '_')
|
||||
}
|
||||
out = append(out, unicode.ToLower(runes[i]))
|
||||
}
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// Glob will test a string pattern, potentially containing globs, against a
|
||||
// subject string. The result is a simple true/false, determining whether or
|
||||
// not the glob pattern matched the subject text.
|
||||
|
|
|
@ -42,3 +42,32 @@ func TestGlob(t *testing.T) {
|
|||
testGlobNoMatch(t, pattern, "this_is_a_test")
|
||||
}
|
||||
}
|
||||
|
||||
type SnakeTest struct {
|
||||
input string
|
||||
output string
|
||||
}
|
||||
|
||||
var tests = []SnakeTest{
|
||||
{"a", "a"},
|
||||
{"snake", "snake"},
|
||||
{"A", "a"},
|
||||
{"ID", "id"},
|
||||
{"MOTD", "motd"},
|
||||
{"Snake", "snake"},
|
||||
{"SnakeTest", "snake_test"},
|
||||
{"APIResponse", "api_response"},
|
||||
{"SnakeID", "snake_id"},
|
||||
{"SnakeIDGoogle", "snake_id_google"},
|
||||
{"LinuxMOTD", "linux_motd"},
|
||||
{"OMGWTFBBQ", "omgwtfbbq"},
|
||||
{"omg_wtf_bbq", "omg_wtf_bbq"},
|
||||
}
|
||||
|
||||
func TestSnakeCase(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if SnakeCase(test.input) != test.output {
|
||||
t.Errorf(`SnakeCase("%s"), wanted "%s", got \%s"`, test.input, test.output, SnakeCase(test.input))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
_ "github.com/influxdata/telegraf/plugins/inputs/haproxy"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/httpjson"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/influxdb"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/ipmi"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/ipmi_sensor"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/jolokia"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/kafka_consumer"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/leofs"
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# Telegraf ipmi plugin
|
||||
|
||||
Get bare metal metrics using the command line utility `ipmitool`
|
||||
|
||||
see ipmitool(https://sourceforge.net/projects/ipmitool/files/ipmitool/)
|
||||
|
||||
The plugin will use the following command to collect remote host sensor stats:
|
||||
|
||||
ipmitool -I lan -H 192.168.1.1 -U USERID -P PASSW0RD sdr
|
||||
|
||||
## Measurements
|
||||
|
||||
- ipmi_sensor:
|
||||
|
||||
* Tags: `server`,`host`
|
||||
* Fields:
|
||||
- status
|
||||
- value
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml
|
||||
[[inputs.ipmi]]
|
||||
## specify servers via a url matching:
|
||||
## [username[:password]@][protocol[(address)]]
|
||||
## e.g.
|
||||
## root:passwd@lan(127.0.0.1)
|
||||
##
|
||||
servers = ["USERID:PASSW0RD@lan(10.20.2.203)"]
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Ambient\ Temp status=1i,value=20 1458488465012559455
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Altitude status=1i,value=80 1458488465012688613
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Avg\ Power status=1i,value=220 1458488465012776511
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Planar\ 3.3V status=1i,value=3.28 1458488465012861875
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Planar\ 5V status=1i,value=4.9 1458488465012944188
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Planar\ 12V status=1i,value=12.04 1458488465013008485
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Planar\ VBAT status=1i,value=3.04 1458488465013072508
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 1A\ Tach status=1i,value=2610 1458488465013137932
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 1B\ Tach status=1i,value=1775 1458488465013279896
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 2A\ Tach status=1i,value=1972 1458488465013358177
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 2B\ Tach status=1i,value=1275 1458488465013434023
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 3A\ Tach status=1i,value=2929 1458488465013514567
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 3B\ Tach status=1i,value=2125 1458488465013582616
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 1 status=1i,value=0 1458488465013643746
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 2 status=1i,value=0 1458488465013714887
|
||||
> ipmi_sensor,host=10.20.2.203,inst=Fan\ 3 status=1i,value=0 1458488465013861854
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# Telegraf ipmi plugin
|
||||
|
||||
Get bare metal metrics using the command line utility `ipmitool`
|
||||
|
||||
see ipmitool(https://sourceforge.net/projects/ipmitool/files/ipmitool/)
|
||||
|
||||
The plugin will use the following command to collect remote host sensor stats:
|
||||
|
||||
ipmitool -I lan -H 192.168.1.1 -U USERID -P PASSW0RD sdr
|
||||
|
||||
## Measurements
|
||||
|
||||
- ipmi_sensor:
|
||||
|
||||
* Tags: `name`, `server`, `unit`
|
||||
* Fields:
|
||||
- status
|
||||
- value
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml
|
||||
[[inputs.ipmi]]
|
||||
## specify servers via a url matching:
|
||||
## [username[:password]@][protocol[(address)]]
|
||||
## e.g.
|
||||
## root:passwd@lan(127.0.0.1)
|
||||
##
|
||||
servers = ["USERID:PASSW0RD@lan(10.20.2.203)"]
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
```
|
||||
> ipmi_sensor,server=10.20.2.203,unit=degrees_c,name=ambient_temp status=1i,value=20 1458488465012559455
|
||||
> ipmi_sensor,server=10.20.2.203,unit=feet,name=altitude status=1i,value=80 1458488465012688613
|
||||
> ipmi_sensor,server=10.20.2.203,unit=watts,name=avg_power status=1i,value=220 1458488465012776511
|
||||
> ipmi_sensor,server=10.20.2.203,unit=volts,name=planar_3.3v status=1i,value=3.28 1458488465012861875
|
||||
> ipmi_sensor,server=10.20.2.203,unit=volts,name=planar_vbat status=1i,value=3.04 1458488465013072508
|
||||
> ipmi_sensor,server=10.20.2.203,unit=rpm,name=fan_1a_tach status=1i,value=2610 1458488465013137932
|
||||
> ipmi_sensor,server=10.20.2.203,unit=rpm,name=fan_1b_tach status=1i,value=1775 1458488465013279896
|
||||
```
|
|
@ -1,5 +1,4 @@
|
|||
// command
|
||||
package ipmi
|
||||
package ipmi_sensor
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -1,5 +1,4 @@
|
|||
// connection
|
||||
package ipmi
|
||||
package ipmi_sensor
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,5 +1,4 @@
|
|||
// ipmi
|
||||
package ipmi
|
||||
package ipmi_sensor
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
@ -60,30 +59,41 @@ func (m *Ipmi) gatherServer(serv string, acc telegraf.Accumulator) error {
|
|||
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 {
|
||||
tags := map[string]string{"server": conn.Hostname, "name": trim(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 {
|
||||
val := strings.Split(val1, " ")[0]
|
||||
fields["value"] = Atofloat(val)
|
||||
} else {
|
||||
fields["value"] = 0.0
|
||||
}
|
||||
|
||||
acc.AddFields("ipmi_sensor", fields, tags, time.Now())
|
||||
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
|
||||
|
@ -96,9 +106,9 @@ type Runner interface {
|
|||
func Atofloat(val string) float64 {
|
||||
f, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
return float64(0)
|
||||
return 0.0
|
||||
} else {
|
||||
return float64(f)
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,8 +116,14 @@ 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", func() telegraf.Input {
|
||||
inputs.Add("ipmi_sensor", func() telegraf.Input {
|
||||
return &Ipmi{}
|
||||
})
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
// ipmi_test
|
||||
package ipmi
|
||||
package ipmi_sensor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -179,6 +178,93 @@ func TestIpmi(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, acc.NFields(), 266, "non-numeric measurements should be ignored")
|
||||
|
||||
var tests = []struct {
|
||||
fields map[string]interface{}
|
||||
tags map[string]string
|
||||
}{
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(20),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "ambient_temp",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "degrees_c",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(80),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "altitude",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "feet",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(210),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "avg_power",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "watts",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(4.9),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "planar_5v",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "volts",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(3.05),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "planar_vbat",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "volts",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(2610),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "fan_1a_tach",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "rpm",
|
||||
},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"value": float64(1775),
|
||||
"status": int(1),
|
||||
},
|
||||
map[string]string{
|
||||
"name": "fan_1b_tach",
|
||||
"server": "192.168.1.1",
|
||||
"unit": "rpm",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
acc.AssertContainsTaggedFields(t, "ipmi_sensor", test.fields, test.tags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIpmiConnection(t *testing.T) {
|
Loading…
Reference in New Issue