generated from sensu/check-plugin-template
/
ipmimon.go
104 lines (85 loc) · 2.14 KB
/
ipmimon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Package ipmimon provides interface to IPMI monitoing
package ipmimon
import (
"bytes"
"context"
"encoding/csv"
"fmt"
"os/exec"
"strings"
"syscall"
"github.com/gocarina/gocsv"
)
const (
TypePowerSupply = "Power Supply"
TypePowerUnit = "Power Unit"
)
const (
StateNominal = "Nominal"
StateWarning = "Warning"
StateCritical = "Critical"
)
// Item represents one line from the report
//
// ipmimonitoring --comma-separated-output | head -n1
// ID,Name,Type,State,Reading,Units,Event
type Item struct {
ID int `csv:"ID" json:"id"`
Name string `csv:"Name" json:"name"`
Type string `csv:"Type" json:"type"`
State string `csv:"State" json:"state"`
Reading string `csv:"Reading" json:"reading"`
Units string `csv:"Units" json:"units"`
Event string `csv:"Event" json:"event"`
}
// Report represent parsed report
type Report []Item
// ParseCSV parses report csv into Report
func ParseCSV(data []byte) (Report, error) {
items := make([]Item, 0)
// skip any messages before report table
idx := bytes.Index(data, []byte("ID,"))
if idx > 0 {
data = data[idx:]
}
err := gocsv.UnmarshalBytes(data, &items)
if err != nil {
return nil, fmt.Errorf("csv parse error: %w", err)
}
return Report(items), nil
}
// GetReport run ipmimonitoring and parse report
func GetReport(ctx context.Context) (Report, error) {
cmd := exec.CommandContext(ctx, "ipmimonitoring", "--comma-separated-output")
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
out, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("ipmimonitoring command failed: %w", err)
}
return ParseCSV(out)
}
func (report Report) Filter(testFunc func(*Item) bool) Report {
items := make([]Item, 0)
for _, it := range report {
if testFunc(&it) {
items = append(items, it)
}
}
return Report(items)
}
func (report Report) Type(typ string) Report {
return report.Filter(func(it *Item) bool {
return it.Type == typ
})
}
func (it *Item) Events() []string {
r := csv.NewReader(strings.NewReader(strings.ReplaceAll(it.Event, "'", "\"")))
r.Comma = ' '
fields, err := r.Read()
if err != nil {
panic(err)
}
return fields
}