mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-21 08:57:48 +02:00
fix(agent): warn on critical ATA SMART attributes (#2275)
This commit is contained in:
@@ -931,6 +931,9 @@ func (sm *SmartManager) parseSmartForSata(output []byte, deviceType string) (boo
|
|||||||
if parsed, ok := smart.ParseSmartRawValueString(attr.Raw.String); ok {
|
if parsed, ok := smart.ParseSmartRawValueString(attr.Raw.String); ok {
|
||||||
rawValue = parsed
|
rawValue = parsed
|
||||||
}
|
}
|
||||||
|
if smartData.SmartStatus == "PASSED" && rawValue > 0 && (attr.ID == 5 || attr.ID == 197 || attr.ID == 198) {
|
||||||
|
smartData.SmartStatus = "WARNING"
|
||||||
|
}
|
||||||
smartAttr := &smart.SmartAttribute{
|
smartAttr := &smart.SmartAttribute{
|
||||||
ID: attr.ID,
|
ID: attr.ID,
|
||||||
Name: attr.Name,
|
Name: attr.Name,
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ package agent
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/henrygd/beszel/internal/entities/smart"
|
"github.com/henrygd/beszel/internal/entities/smart"
|
||||||
@@ -88,6 +90,52 @@ func TestParseSmartForSata(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseSmartForSataWarnsForCriticalAttributes(t *testing.T) {
|
||||||
|
for _, attrID := range []int{5, 197, 198} {
|
||||||
|
t.Run("attribute "+strconv.Itoa(attrID), func(t *testing.T) {
|
||||||
|
jsonPayload := []byte(fmt.Sprintf(`{
|
||||||
|
"smartctl": {"exit_status": 0},
|
||||||
|
"device": {"name": "/dev/sda", "type": "sat"},
|
||||||
|
"model_name": "Example",
|
||||||
|
"serial_number": "WARNING%d",
|
||||||
|
"smart_status": {"passed": true},
|
||||||
|
"temperature": {"current": 30},
|
||||||
|
"ata_smart_attributes": {"table": [{"id": %d, "raw": {"value": 1, "string": "1"}}]}
|
||||||
|
}`, attrID, attrID))
|
||||||
|
|
||||||
|
sm := &SmartManager{SmartDataMap: make(map[string]*smart.SmartData)}
|
||||||
|
hasData, _ := sm.parseSmartForSata(jsonPayload, "")
|
||||||
|
require.True(t, hasData)
|
||||||
|
assert.Equal(t, "WARNING", sm.SmartDataMap[fmt.Sprintf("WARNING%d", attrID)].SmartStatus)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseSmartForSataPreservesFailedAndUnknownStatus(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
name string
|
||||||
|
temperature int
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{name: "failed", temperature: 30, want: "FAILED"},
|
||||||
|
{name: "unknown", want: "UNKNOWN"},
|
||||||
|
} {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
jsonPayload := []byte(fmt.Sprintf(`{
|
||||||
|
"device": {"name": "/dev/sda", "type": "sat"},
|
||||||
|
"serial_number": "PRESERVE%s",
|
||||||
|
"temperature": {"current": %d},
|
||||||
|
"ata_smart_attributes": {"table": [{"id": 197, "raw": {"value": 1, "string": "1"}}]}
|
||||||
|
}`, test.name, test.temperature))
|
||||||
|
|
||||||
|
sm := &SmartManager{SmartDataMap: make(map[string]*smart.SmartData)}
|
||||||
|
hasData, _ := sm.parseSmartForSata(jsonPayload, "")
|
||||||
|
require.True(t, hasData)
|
||||||
|
assert.Equal(t, test.want, sm.SmartDataMap["PRESERVE"+test.name].SmartStatus)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseSmartForSataDeviceStatisticsTemperature(t *testing.T) {
|
func TestParseSmartForSataDeviceStatisticsTemperature(t *testing.T) {
|
||||||
jsonPayload := []byte(`{
|
jsonPayload := []byte(`{
|
||||||
"smartctl": {"exit_status": 0},
|
"smartctl": {"exit_status": 0},
|
||||||
|
|||||||
Reference in New Issue
Block a user