-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck_stable.go
123 lines (110 loc) · 3.13 KB
/
check_stable.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"path/filepath"
"crypto/sha1"
"encoding/json"
"io/ioutil"
"syscall"
)
type Result struct {
// Dreck! Die Felder muessen mit Grossbuchstaben anfangen
// da sie sonst der feine Herr Golang nicht exportiert
Output string `json:"output"`
ExitCode int `json:"exitcode"`
Serial int `json:"serial"`
}
func match() {
}
func loadResult(resultFile string) Result {
var result Result;
raw, err := ioutil.ReadFile(resultFile)
if err != nil {
result = Result{"", 0, 0}
} else {
json.Unmarshal(raw, &result)
}
return result
}
func saveResult(resultFile string, result Result) {
json_result, err := json.Marshal(result)
if err != nil {
fmt.Println("json error:", err)
}
err = ioutil.WriteFile(resultFile, json_result, 0644)
if err != nil {
fmt.Printf("could not write resultFile %s\n", err)
}
}
func initResultFile(args string) string {
var resultDir string;
sha1_hash := fmt.Sprintf("%x", sha1.Sum([]byte(args)))
if (os.Getenv("OMD_ROOT") != "") {
resultDir = filepath.Join(os.Getenv("OMD_ROOT"),
"var", "tmp", "check_stable");
} else {
resultDir = filepath.Join("/", "var", "tmp", "check_stable");
}
os.MkdirAll(resultDir, 0755)
return filepath.Join(resultDir, sha1_hash)
}
func main() {
var params []string
args := os.Args
if len(args) == 1 {
fmt.Printf("usage: check_stable <command>\n")
os.Exit(3)
} else if len(args) >= 3 {
params = args[2:len(args)]
}
cmd := args[1]
exitCode := 0
resultFile := initResultFile(strings.Join(args, ""))
plugin := exec.Command(cmd, params...)
pluginOutput, err := plugin.CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
exitCode = exitError.Sys().(syscall.WaitStatus).ExitStatus()
}
} else {
exitCode = plugin.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
}
var errors = []string{
"Return code of 127 is out of bounds - plugin may be missing",
"Return code of 254 is out of bounds",
"Return code of 255 is out of bounds",
"Service Check Timed Out",
"could not start controlmaster",
"Could not open pipe: /usr/bin/ssh",
}
var error_found = false
for i:= 0; i < len(errors); i++ {
if strings.Index(string(pluginOutput), errors[i]) != -1 {
error_found = true
break
}
}
if error_found {
// plugin ended with one of these high-load side effects
lastResult := loadResult(resultFile)
if lastResult.Serial > 1 {
// the error did not go away, time to alert
fmt.Printf("%s\n", pluginOutput)
os.Exit(exitCode)
} else {
// output a fake result and increment the counter
saveResult(resultFile, Result{ lastResult.Output, lastResult.ExitCode, lastResult.Serial + 1 })
fmt.Printf("(stabilized #%d) %s\n", lastResult.Serial, lastResult.Output)
os.Exit(lastResult.ExitCode)
}
} else {
// save the output, plugin had no problems
saveResult(resultFile, Result{ string(pluginOutput), exitCode, 0 })
// exit with the original plugin result
fmt.Printf("%s\n", pluginOutput)
os.Exit(exitCode)
}
}