make sure that the device host id is provided in notifications (if available).
fixes #337
This commit is contained in:
@@ -21,5 +21,6 @@ SCRUTINY_DEVICE_NAME - eg. /dev/sda
|
|||||||
SCRUTINY_DEVICE_TYPE - ATA/SCSI/NVMe
|
SCRUTINY_DEVICE_TYPE - ATA/SCSI/NVMe
|
||||||
SCRUTINY_DEVICE_SERIAL - eg. WDDJ324KSO
|
SCRUTINY_DEVICE_SERIAL - eg. WDDJ324KSO
|
||||||
SCRUTINY_MESSAGE - eg. "Scrutiny SMART error notification for device: %s\nFailure Type: %s\nDevice Name: %s\nDevice Serial: %s\nDevice Type: %s\nDate: %s"
|
SCRUTINY_MESSAGE - eg. "Scrutiny SMART error notification for device: %s\nFailure Type: %s\nDevice Name: %s\nDevice Serial: %s\nDevice Type: %s\nDate: %s"
|
||||||
|
SCRUTINY_HOST_ID - (optional) eg. "my-custom-host-id"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,9 @@ func ShouldNotify(device models.Device, smartAttrs measurements.Smart, statusThr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: include host and/or user label for device.
|
// TODO: include user label for device.
|
||||||
type Payload struct {
|
type Payload struct {
|
||||||
|
HostId string `json:"host_id,omitempty"` //host id (optional)
|
||||||
DeviceType string `json:"device_type"` //ATA/SCSI/NVMe
|
DeviceType string `json:"device_type"` //ATA/SCSI/NVMe
|
||||||
DeviceName string `json:"device_name"` //dev/sda
|
DeviceName string `json:"device_name"` //dev/sda
|
||||||
DeviceSerial string `json:"device_serial"` //WDDJ324KSO
|
DeviceSerial string `json:"device_serial"` //WDDJ324KSO
|
||||||
@@ -115,8 +116,9 @@ type Payload struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPayload(device models.Device, test bool) Payload {
|
func NewPayload(device models.Device, test bool, currentTime ...time.Time) Payload {
|
||||||
payload := Payload{
|
payload := Payload{
|
||||||
|
HostId: strings.TrimSpace(device.HostId),
|
||||||
DeviceType: device.DeviceType,
|
DeviceType: device.DeviceType,
|
||||||
DeviceName: device.DeviceName,
|
DeviceName: device.DeviceName,
|
||||||
DeviceSerial: device.SerialNumber,
|
DeviceSerial: device.SerialNumber,
|
||||||
@@ -124,7 +126,13 @@ func NewPayload(device models.Device, test bool) Payload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//validate that the Payload is populated
|
//validate that the Payload is populated
|
||||||
sendDate := time.Now()
|
var sendDate time.Time
|
||||||
|
if currentTime != nil && len(currentTime) > 0 {
|
||||||
|
sendDate = currentTime[0]
|
||||||
|
} else {
|
||||||
|
sendDate = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
payload.Date = sendDate.Format(time.RFC3339)
|
payload.Date = sendDate.Format(time.RFC3339)
|
||||||
payload.FailureType = payload.GenerateFailureType(device.DeviceStatus)
|
payload.FailureType = payload.GenerateFailureType(device.DeviceStatus)
|
||||||
payload.Subject = payload.GenerateSubject()
|
payload.Subject = payload.GenerateSubject()
|
||||||
@@ -148,25 +156,39 @@ func (p *Payload) GenerateFailureType(deviceStatus pkg.DeviceStatus) string {
|
|||||||
|
|
||||||
func (p *Payload) GenerateSubject() string {
|
func (p *Payload) GenerateSubject() string {
|
||||||
//generate a detailed failure message
|
//generate a detailed failure message
|
||||||
return fmt.Sprintf("Scrutiny SMART error (%s) detected on device: %s", p.FailureType, p.DeviceName)
|
var subject string
|
||||||
|
if len(p.HostId) > 0 {
|
||||||
|
subject = fmt.Sprintf("Scrutiny SMART error (%s) detected on [host]device: [%s]%s", p.FailureType, p.HostId, p.DeviceName)
|
||||||
|
} else {
|
||||||
|
subject = fmt.Sprintf("Scrutiny SMART error (%s) detected on device: %s", p.FailureType, p.DeviceName)
|
||||||
|
}
|
||||||
|
return subject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Payload) GenerateMessage() string {
|
func (p *Payload) GenerateMessage() string {
|
||||||
//generate a detailed failure message
|
//generate a detailed failure message
|
||||||
message := fmt.Sprintf(
|
|
||||||
`Scrutiny SMART error notification for device: %s
|
|
||||||
Failure Type: %s
|
|
||||||
Device Name: %s
|
|
||||||
Device Serial: %s
|
|
||||||
Device Type: %s
|
|
||||||
|
|
||||||
Date: %s`, p.DeviceName, p.FailureType, p.DeviceName, p.DeviceSerial, p.DeviceType, p.Date)
|
messageParts := []string{}
|
||||||
|
|
||||||
if p.Test {
|
messageParts = append(messageParts, fmt.Sprintf("Scrutiny SMART error notification for device: %s", p.DeviceName))
|
||||||
message = "TEST NOTIFICATION:\n" + message
|
if len(p.HostId) > 0 {
|
||||||
|
messageParts = append(messageParts, fmt.Sprintf("Host Id: %s", p.HostId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return message
|
messageParts = append(messageParts,
|
||||||
|
fmt.Sprintf("Failure Type: %s", p.FailureType),
|
||||||
|
fmt.Sprintf("Device Name: %s", p.DeviceName),
|
||||||
|
fmt.Sprintf("Device Serial: %s", p.DeviceSerial),
|
||||||
|
fmt.Sprintf("Device Type: %s", p.DeviceType),
|
||||||
|
"",
|
||||||
|
fmt.Sprintf("Date: %s", p.Date),
|
||||||
|
)
|
||||||
|
|
||||||
|
if p.Test {
|
||||||
|
messageParts = append([]string{"TEST NOTIFICATION:"}, messageParts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(messageParts, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(logger logrus.FieldLogger, appconfig config.Interface, device models.Device, test bool) Notify {
|
func New(logger logrus.FieldLogger, appconfig config.Interface, device models.Device, test bool) Notify {
|
||||||
@@ -287,6 +309,9 @@ func (n *Notify) SendScriptNotification(scriptUrl string) error {
|
|||||||
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_DEVICE_TYPE=%s", n.Payload.DeviceType))
|
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_DEVICE_TYPE=%s", n.Payload.DeviceType))
|
||||||
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_DEVICE_SERIAL=%s", n.Payload.DeviceSerial))
|
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_DEVICE_SERIAL=%s", n.Payload.DeviceSerial))
|
||||||
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_MESSAGE=%s", n.Payload.Message))
|
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_MESSAGE=%s", n.Payload.Message))
|
||||||
|
if len(n.Payload.HostId) > 0 {
|
||||||
|
copyEnv = append(copyEnv, fmt.Sprintf("SCRUTINY_HOST_ID=%s", n.Payload.HostId))
|
||||||
|
}
|
||||||
err := utils.CmdExec(scriptPath, []string{}, "", copyEnv, "")
|
err := utils.CmdExec(scriptPath, []string{}, "", copyEnv, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.Logger.Errorf("An error occurred while executing script %s: %v", scriptPath, err)
|
n.Logger.Errorf("An error occurred while executing script %s: %v", scriptPath, err)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/analogj/scrutiny/webapp/backend/pkg"
|
"github.com/analogj/scrutiny/webapp/backend/pkg"
|
||||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models"
|
"github.com/analogj/scrutiny/webapp/backend/pkg/models"
|
||||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models/measurements"
|
"github.com/analogj/scrutiny/webapp/backend/pkg/models/measurements"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShouldNotify_MustSkipPassingDevices(t *testing.T) {
|
func TestShouldNotify_MustSkipPassingDevices(t *testing.T) {
|
||||||
@@ -159,3 +161,84 @@ func TestShouldNotify_MetricsStatusFilterAttributesCritical_MetricsStatusThresho
|
|||||||
//assert
|
//assert
|
||||||
require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
|
require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewPayload(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
//setup
|
||||||
|
device := models.Device{
|
||||||
|
SerialNumber: "FAKEWDDJ324KSO",
|
||||||
|
DeviceType: pkg.DeviceProtocolAta,
|
||||||
|
DeviceName: "/dev/sda",
|
||||||
|
DeviceStatus: pkg.DeviceStatusFailedScrutiny,
|
||||||
|
}
|
||||||
|
currentTime := time.Now()
|
||||||
|
//test
|
||||||
|
|
||||||
|
payload := NewPayload(device, false, currentTime)
|
||||||
|
|
||||||
|
//assert
|
||||||
|
require.Equal(t, "Scrutiny SMART error (ScrutinyFailure) detected on device: /dev/sda", payload.Subject)
|
||||||
|
require.Equal(t, fmt.Sprintf(`Scrutiny SMART error notification for device: /dev/sda
|
||||||
|
Failure Type: ScrutinyFailure
|
||||||
|
Device Name: /dev/sda
|
||||||
|
Device Serial: FAKEWDDJ324KSO
|
||||||
|
Device Type: ATA
|
||||||
|
|
||||||
|
Date: %s`, currentTime.Format(time.RFC3339)), payload.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewPayload_TestMode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
//setup
|
||||||
|
device := models.Device{
|
||||||
|
SerialNumber: "FAKEWDDJ324KSO",
|
||||||
|
DeviceType: pkg.DeviceProtocolAta,
|
||||||
|
DeviceName: "/dev/sda",
|
||||||
|
DeviceStatus: pkg.DeviceStatusFailedScrutiny,
|
||||||
|
}
|
||||||
|
currentTime := time.Now()
|
||||||
|
//test
|
||||||
|
|
||||||
|
payload := NewPayload(device, true, currentTime)
|
||||||
|
|
||||||
|
//assert
|
||||||
|
require.Equal(t, "Scrutiny SMART error (EmailTest) detected on device: /dev/sda", payload.Subject)
|
||||||
|
require.Equal(t, fmt.Sprintf(`TEST NOTIFICATION:
|
||||||
|
Scrutiny SMART error notification for device: /dev/sda
|
||||||
|
Failure Type: EmailTest
|
||||||
|
Device Name: /dev/sda
|
||||||
|
Device Serial: FAKEWDDJ324KSO
|
||||||
|
Device Type: ATA
|
||||||
|
|
||||||
|
Date: %s`, currentTime.Format(time.RFC3339)), payload.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewPayload_WithHostId(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
//setup
|
||||||
|
device := models.Device{
|
||||||
|
SerialNumber: "FAKEWDDJ324KSO",
|
||||||
|
DeviceType: pkg.DeviceProtocolAta,
|
||||||
|
DeviceName: "/dev/sda",
|
||||||
|
DeviceStatus: pkg.DeviceStatusFailedScrutiny,
|
||||||
|
HostId: "custom-host",
|
||||||
|
}
|
||||||
|
currentTime := time.Now()
|
||||||
|
//test
|
||||||
|
|
||||||
|
payload := NewPayload(device, false, currentTime)
|
||||||
|
|
||||||
|
//assert
|
||||||
|
require.Equal(t, "Scrutiny SMART error (ScrutinyFailure) detected on [host]device: [custom-host]/dev/sda", payload.Subject)
|
||||||
|
require.Equal(t, fmt.Sprintf(`Scrutiny SMART error notification for device: /dev/sda
|
||||||
|
Host Id: custom-host
|
||||||
|
Failure Type: ScrutinyFailure
|
||||||
|
Device Name: /dev/sda
|
||||||
|
Device Serial: FAKEWDDJ324KSO
|
||||||
|
Device Type: ATA
|
||||||
|
|
||||||
|
Date: %s`, currentTime.Format(time.RFC3339)), payload.Message)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user