2019-08-14 22:34:49 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
2019-08-15 23:01:16 +02:00
|
|
|
"time"
|
2019-08-14 22:34:49 +02:00
|
|
|
|
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
)
|
|
|
|
|
2019-08-15 23:01:16 +02:00
|
|
|
// JSONCache caching json
|
|
|
|
type JSONCache struct {
|
|
|
|
JSON gjson.Result
|
|
|
|
LastCollect time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
jsonCache map[string]JSONCache
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
jsonCache = make(map[string]JSONCache)
|
|
|
|
}
|
|
|
|
|
2019-08-14 22:34:49 +02:00
|
|
|
// Parse json to gjson object
|
2019-08-15 23:01:16 +02:00
|
|
|
func parseJSON(data string) gjson.Result {
|
2019-08-14 22:34:49 +02:00
|
|
|
if !gjson.Valid(data) {
|
2019-08-15 23:01:16 +02:00
|
|
|
return gjson.Parse("{}")
|
2019-08-14 22:34:49 +02:00
|
|
|
}
|
2019-08-15 23:01:16 +02:00
|
|
|
return gjson.Parse(data)
|
2019-08-14 22:34:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reading fake smartctl json
|
2019-08-15 23:01:16 +02:00
|
|
|
func readFakeSMARTctl(device string) gjson.Result {
|
2019-08-14 22:34:49 +02:00
|
|
|
splitted := strings.Split(device, "/")
|
|
|
|
filename := fmt.Sprintf("%s.json", splitted[len(splitted)-1])
|
|
|
|
logger.Verbose("Read fake S.M.A.R.T. data from json: %s", filename)
|
|
|
|
jsonFile, err := ioutil.ReadFile(filename)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error("Fake S.M.A.R.T. data reading error: %s", err)
|
|
|
|
return parseJSON("{}")
|
|
|
|
}
|
|
|
|
return parseJSON(string(jsonFile))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get json from smartctl and parse it
|
2019-08-15 23:01:16 +02:00
|
|
|
func readSMARTctl(device string) gjson.Result {
|
|
|
|
logger.Debug("Collecting S.M.A.R.T. counters, device: %s", device)
|
2019-08-14 22:34:49 +02:00
|
|
|
out, err := exec.Command(options.SMARTctl.SMARTctlLocation, "--json", "--xall", device).Output()
|
|
|
|
if err != nil {
|
2019-08-15 23:01:16 +02:00
|
|
|
logger.Warning("S.M.A.R.T. output reading error: %s", err)
|
2019-08-14 22:34:49 +02:00
|
|
|
}
|
|
|
|
return parseJSON(string(out))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select json source and parse
|
2019-08-15 23:01:16 +02:00
|
|
|
func readData(device string) gjson.Result {
|
2019-08-14 22:34:49 +02:00
|
|
|
if options.SMARTctl.FakeJSON {
|
|
|
|
return readFakeSMARTctl(device)
|
|
|
|
}
|
2019-08-15 23:01:16 +02:00
|
|
|
|
|
|
|
if value, ok := jsonCache[device]; ok {
|
|
|
|
// logger.Debug("Cache exists")
|
|
|
|
if time.Now().After(value.LastCollect.Add(options.SMARTctl.CollectPeriodDuration)) {
|
|
|
|
// logger.Debug("Cache update")
|
|
|
|
jsonCache[device] = JSONCache{JSON: readSMARTctl(device), LastCollect: time.Now()}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// logger.Debug("Cache not exists")
|
|
|
|
jsonCache[device] = JSONCache{JSON: readSMARTctl(device), LastCollect: time.Now()}
|
|
|
|
}
|
|
|
|
return jsonCache[device].JSON
|
2019-08-14 22:34:49 +02:00
|
|
|
}
|