Check chassis power state

Use ipmi-chassis to check power on /off
report via ipmi_chassis_power_state
enable via "chassis" module
This commit is contained in:
Michael Sherman 2019-10-14 15:43:30 -04:00
parent 41ce90557f
commit 25d1fd0ef8
5 changed files with 57 additions and 4 deletions

View File

@ -249,6 +249,13 @@ returned from the BMC. Example:
ipmi_bmc_info{firmware_revision="2.52",manufacturer_id="Dell Inc. (674)"} 1
### Chassis Power State
This metric is only provided if the `chassis` collector is enabled.
The metric `ipmi_chassis_power_state` shows the current chassis power state of the machine.
The value is 1 for poweron, and 0 otherwise.
### Power consumption
This metric is only provided if the `dcmi` collector is enabled.

View File

@ -28,6 +28,7 @@ const (
var (
ipmiDCMICurrentPowerRegex = regexp.MustCompile(`^Current Power\s*:\s*(?P<value>[0-9.]*)\s*Watts.*`)
ipmiChassisPowerRegex = regexp.MustCompile(`^System Power\s*:\s(?P<value>.*)`)
bmcInfoFirmwareRevisionRegex = regexp.MustCompile(`^Firmware Revision\s*:\s*(?P<value>[0-9.]*).*`)
bmcInfoManufacturerIDRegex = regexp.MustCompile(`^Manufacturer ID\s*:\s*(?P<value>.*)`)
)
@ -145,6 +146,13 @@ var (
nil,
)
chassisPowerState = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "chassis", "power_state"),
"Current power state (1=on, 0=off).",
[]string{},
nil,
)
bmcInfo = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "bmc", "info"),
"Constant metric with value '1' providing details about the BMC.",
@ -248,6 +256,10 @@ func bmcInfoOutput(target ipmiTarget) ([]byte, error) {
return freeipmiOutput("bmc-info", target, "--get-device-id")
}
func ipmiChassisOutput(target ipmiTarget) ([]byte, error) {
return freeipmiOutput("ipmi-chassis", target, "--get-chassis-status")
}
func splitMonitoringOutput(impiOutput []byte, excludeSensorIds []int64) ([]sensorData, error) {
var result []sensorData
@ -314,6 +326,17 @@ func getCurrentPowerConsumption(ipmiOutput []byte) (float64, error) {
return strconv.ParseFloat(value, 64)
}
func getChassisPowerState(ipmiOutput []byte) (float64, error) {
value, err := getValue(ipmiOutput, ipmiChassisPowerRegex)
if err != nil {
return -1, err
}
if value == "on" {
return 1, err
}
return 0, err
}
func getBMCInfoFirmwareRevision(ipmiOutput []byte) (string, error) {
return getValue(ipmiOutput, bmcInfoFirmwareRevisionRegex)
}
@ -438,6 +461,25 @@ func collectDCMI(ch chan<- prometheus.Metric, target ipmiTarget) (int, error) {
return 1, nil
}
func collectChassisState(ch chan<- prometheus.Metric, target ipmiTarget) (int, error) {
output, err := ipmiChassisOutput(target)
if err != nil {
log.Debugf("Failed to collect ipmi-chassis data from %s: %s", targetName(target.host), err)
return 0, err
}
currentChassisPowerState, err := getChassisPowerState(output)
if err != nil {
log.Errorf("Failed to parse ipmi-chassis data from %s: %s", targetName(target.host), err)
return 0, err
}
ch <- prometheus.MustNewConstMetric(
chassisPowerState,
prometheus.GaugeValue,
currentChassisPowerState,
)
return 1, nil
}
func collectBmcInfo(ch chan<- prometheus.Metric, target ipmiTarget) (int, error) {
output, err := bmcInfoOutput(target)
if err != nil {
@ -501,6 +543,8 @@ func (c collector) Collect(ch chan<- prometheus.Metric) {
up, _ = collectDCMI(ch, target)
case "bmc":
up, _ = collectBmcInfo(ch, target)
case "chassis":
up, _ = collectChassisState(ch, target)
}
markCollectorUp(ch, collector, up)
}

View File

@ -39,7 +39,7 @@ type IPMIConfig struct {
XXX map[string]interface{} `yaml:",inline"`
}
var emptyConfig = IPMIConfig{Collectors: []string{"ipmi", "dcmi", "bmc"}}
var emptyConfig = IPMIConfig{Collectors: []string{"ipmi", "dcmi", "bmc", "chassis"}}
// CollectorName is used for unmarshaling the list of collectors in the yaml config file
type CollectorName string
@ -78,7 +78,7 @@ func (s *IPMIConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err
}
for _, c := range s.Collectors {
if !(c == "ipmi" || c == "dcmi" || c == "bmc") {
if !(c == "ipmi" || c == "dcmi" || c == "bmc" || c == "chassis") {
return fmt.Errorf("unknown collector name: %s", c)
}
}

View File

@ -4,11 +4,12 @@
# In most cases, this should work without using a config file at all.
modules:
default:
# Available collectors are bmc, ipmi, and dcmi
# Available collectors are bmc, ipmi, chassis, and dcmi
collectors:
- bmc
- ipmi
- dcmi
- chassis
# Got any sensors you don't care about? Add them here.
exclude_sensor_ids:
- 2

View File

@ -21,11 +21,12 @@ modules:
# to (session-timeout * #-of-collectors) milliseconds, so set the scrape
# timeout in Prometheus accordingly.
timeout: 10000
# Available collectors are bmc, ipmi, and dcmi
# Available collectors are bmc, ipmi, chassis, and dcmi
# If not specified, all three are used
collectors:
- bmc
- ipmi
- chassis
# Got any sensors you don't care about? Add them here.
exclude_sensor_ids:
- 2