mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-12-27 07:39:05 +01:00
138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
|
package collectors
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
lp "github.com/influxdata/line-protocol"
|
||
|
"log"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"encoding/json"
|
||
|
)
|
||
|
|
||
|
const IPMITOOL_PATH = `/usr/bin/ipmitool`
|
||
|
const IPMISENSORS_PATH = `/usr/sbin/ipmi-sensors`
|
||
|
|
||
|
type IpmiCollectorConfig struct {
|
||
|
ExcludeDevices []string `json:"exclude_devices"`
|
||
|
IpmitoolPath string `json:"ipmitool_path"`
|
||
|
IpmisensorsPath string `json:"ipmisensors_path"`
|
||
|
}
|
||
|
|
||
|
type IpmiCollector struct {
|
||
|
MetricCollector
|
||
|
tags map[string]string
|
||
|
matches map[string]string
|
||
|
config IpmiCollectorConfig
|
||
|
}
|
||
|
|
||
|
func (m *IpmiCollector) Init(config []byte) error {
|
||
|
m.name = "IpmiCollector"
|
||
|
m.setup()
|
||
|
if len(config) > 0 {
|
||
|
err := json.Unmarshal(config, &m.config)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
_, err1 := os.Stat(m.config.IpmitoolPath)
|
||
|
_, err2 := os.Stat(m.config.IpmisensorsPath)
|
||
|
if err1 != nil {
|
||
|
m.config.IpmitoolPath = ""
|
||
|
}
|
||
|
if err2 != nil {
|
||
|
m.config.IpmisensorsPath = ""
|
||
|
}
|
||
|
if err1 != nil && err2 != nil {
|
||
|
return errors.New("No IPMI reader found")
|
||
|
}
|
||
|
m.init = true
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func ReadIpmiTool(cmd string, out *[]lp.MutableMetric) {
|
||
|
command := exec.Command(cmd, "sensor")
|
||
|
command.Wait()
|
||
|
stdout, err := command.Output()
|
||
|
if err != nil {
|
||
|
log.Print(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ll := strings.Split(string(stdout), "\n")
|
||
|
|
||
|
for _, line := range ll {
|
||
|
lv := strings.Split(line, "|")
|
||
|
if len(lv) < 3 {
|
||
|
continue
|
||
|
}
|
||
|
v, err := strconv.ParseFloat(strings.Trim(lv[1], " "), 64)
|
||
|
if err == nil {
|
||
|
name := strings.ToLower(strings.Replace(strings.Trim(lv[0], " "), " ", "_", -1))
|
||
|
unit := strings.Trim(lv[2], " ")
|
||
|
if unit == "Volts" {
|
||
|
unit = "V"
|
||
|
} else if unit == "degrees C" {
|
||
|
unit = "C"
|
||
|
} else if unit == "degrees F" {
|
||
|
unit = "F"
|
||
|
} else if unit == "Watts" {
|
||
|
unit = "W"
|
||
|
}
|
||
|
|
||
|
y, err := lp.New(name, map[string]string{"unit": unit, "type" : "node"}, map[string]interface{}{"value": v}, time.Now())
|
||
|
if err == nil {
|
||
|
*out = append(*out, y)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ReadIpmiSensors(cmd string, out *[]lp.MutableMetric) {
|
||
|
|
||
|
command := exec.Command(cmd, "--comma-separated-output", "--sdr-cache-recreate")
|
||
|
command.Wait()
|
||
|
stdout, err := command.Output()
|
||
|
if err != nil {
|
||
|
log.Print(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ll := strings.Split(string(stdout), "\n")
|
||
|
|
||
|
for _, line := range ll {
|
||
|
lv := strings.Split(line, ",")
|
||
|
if len(lv) > 3 {
|
||
|
v, err := strconv.ParseFloat(lv[3], 64)
|
||
|
if err == nil {
|
||
|
name := strings.ToLower(strings.Replace(lv[1], " ", "_", -1))
|
||
|
y, err := lp.New(name, map[string]string{"unit": lv[4], "type" : "node"}, map[string]interface{}{"value": v}, time.Now())
|
||
|
if err == nil {
|
||
|
*out = append(*out, y)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *IpmiCollector) Read(interval time.Duration, out *[]lp.MutableMetric) {
|
||
|
if len(m.config.IpmitoolPath) > 0 {
|
||
|
_, err := os.Stat(m.config.IpmitoolPath)
|
||
|
if err == nil {
|
||
|
ReadIpmiTool(m.config.IpmitoolPath, out)
|
||
|
}
|
||
|
} else if len(m.config.IpmisensorsPath) > 0 {
|
||
|
_, err := os.Stat(m.config.IpmisensorsPath)
|
||
|
if err == nil {
|
||
|
ReadIpmiSensors(m.config.IpmisensorsPath, out)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *IpmiCollector) Close() {
|
||
|
m.init = false
|
||
|
return
|
||
|
}
|