package models import ( "github.com/analogj/scrutiny/webapp/backend/pkg" "github.com/analogj/scrutiny/webapp/backend/pkg/models/collector" "time" ) type DeviceWrapper struct { Success bool `json:"success"` Errors []error `json:"errors"` Data []Device `json:"data"` } type Device struct { //GORM attributes, see: http://gorm.io/docs/conventions.html CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time WWN string `json:"wwn" gorm:"primary_key"` DeviceName string `json:"device_name"` DeviceUUID string `json:"device_uuid"` DeviceSerialID string `json:"device_serial_id"` DeviceLabel string `json:"device_label"` Manufacturer string `json:"manufacturer"` ModelName string `json:"model_name"` InterfaceType string `json:"interface_type"` InterfaceSpeed string `json:"interface_speed"` SerialNumber string `json:"serial_number"` Firmware string `json:"firmware"` RotationSpeed int `json:"rotational_speed"` Capacity int64 `json:"capacity"` FormFactor string `json:"form_factor"` SmartSupport bool `json:"smart_support"` DeviceProtocol string `json:"device_protocol"` //protocol determines which smart attribute types are available (ATA, NVMe, SCSI) DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag, should only be used by collector. // User provided metadata Label string `json:"label"` HostId string `json:"host_id"` // Data set by Scrutiny DeviceStatus pkg.DeviceStatus `json:"device_status"` } func (dv *Device) IsAta() bool { return dv.DeviceProtocol == pkg.DeviceProtocolAta } func (dv *Device) IsScsi() bool { return dv.DeviceProtocol == pkg.DeviceProtocolScsi } func (dv *Device) IsNvme() bool { return dv.DeviceProtocol == pkg.DeviceProtocolNvme } // ////This method requires a device with an array of SmartResults. ////It will remove all SmartResults other than the first (the latest one) ////All removed SmartResults, will be processed, grouping SmartAtaAttribute by attribute_id //// and adding theme to an array called History. //func (dv *Device) SquashHistory() error { // if len(dv.SmartResults) <= 1 { // return nil //no ataHistory found. ignore // } // // latestSmartResultSlice := dv.SmartResults[0:1] // historicalSmartResultSlice := dv.SmartResults[1:] // // //re-assign the latest slice to the SmartResults field // dv.SmartResults = latestSmartResultSlice // // //process the historical slice for ATA data // if len(dv.SmartResults[0].AtaAttributes) > 0 { // ataHistory := map[int][]SmartAtaAttribute{} // for _, smartResult := range historicalSmartResultSlice { // for _, smartAttribute := range smartResult.AtaAttributes { // if _, ok := ataHistory[smartAttribute.AttributeId]; !ok { // ataHistory[smartAttribute.AttributeId] = []SmartAtaAttribute{} // } // ataHistory[smartAttribute.AttributeId] = append(ataHistory[smartAttribute.AttributeId], smartAttribute) // } // } // // //now assign the historical slices to the AtaAttributes in the latest SmartResults // for sandx, smartAttribute := range dv.SmartResults[0].AtaAttributes { // if attributeHistory, ok := ataHistory[smartAttribute.AttributeId]; ok { // dv.SmartResults[0].AtaAttributes[sandx].History = attributeHistory // } // } // } // // //process the historical slice for Nvme data // if len(dv.SmartResults[0].NvmeAttributes) > 0 { // nvmeHistory := map[string][]SmartNvmeAttribute{} // for _, smartResult := range historicalSmartResultSlice { // for _, smartAttribute := range smartResult.NvmeAttributes { // if _, ok := nvmeHistory[smartAttribute.AttributeId]; !ok { // nvmeHistory[smartAttribute.AttributeId] = []SmartNvmeAttribute{} // } // nvmeHistory[smartAttribute.AttributeId] = append(nvmeHistory[smartAttribute.AttributeId], smartAttribute) // } // } // // //now assign the historical slices to the AtaAttributes in the latest SmartResults // for sandx, smartAttribute := range dv.SmartResults[0].NvmeAttributes { // if attributeHistory, ok := nvmeHistory[smartAttribute.AttributeId]; ok { // dv.SmartResults[0].NvmeAttributes[sandx].History = attributeHistory // } // } // } // //process the historical slice for Scsi data // if len(dv.SmartResults[0].ScsiAttributes) > 0 { // scsiHistory := map[string][]SmartScsiAttribute{} // for _, smartResult := range historicalSmartResultSlice { // for _, smartAttribute := range smartResult.ScsiAttributes { // if _, ok := scsiHistory[smartAttribute.AttributeId]; !ok { // scsiHistory[smartAttribute.AttributeId] = []SmartScsiAttribute{} // } // scsiHistory[smartAttribute.AttributeId] = append(scsiHistory[smartAttribute.AttributeId], smartAttribute) // } // } // // //now assign the historical slices to the AtaAttributes in the latest SmartResults // for sandx, smartAttribute := range dv.SmartResults[0].ScsiAttributes { // if attributeHistory, ok := scsiHistory[smartAttribute.AttributeId]; ok { // dv.SmartResults[0].ScsiAttributes[sandx].History = attributeHistory // } // } // } // return nil //} // //func (dv *Device) ApplyMetadataRules() error { // // //embed metadata in the latest smart attributes object // if len(dv.SmartResults) > 0 { // for ndx, attr := range dv.SmartResults[0].AtaAttributes { // attr.PopulateAttributeStatus() // dv.SmartResults[0].AtaAttributes[ndx] = attr // } // // for ndx, attr := range dv.SmartResults[0].NvmeAttributes { // attr.PopulateAttributeStatus() // dv.SmartResults[0].NvmeAttributes[ndx] = attr // // } // // for ndx, attr := range dv.SmartResults[0].ScsiAttributes { // attr.PopulateAttributeStatus() // dv.SmartResults[0].ScsiAttributes[ndx] = attr // // } // } // return nil //} // This function is called every time the collector sends SMART data to the API. // It can be used to update device data that can change over time. func (dv *Device) UpdateFromCollectorSmartInfo(info collector.SmartInfo) error { dv.Firmware = info.FirmwareVersion dv.DeviceProtocol = info.Device.Protocol if !info.SmartStatus.Passed { dv.DeviceStatus = pkg.DeviceStatusSet(dv.DeviceStatus, pkg.DeviceStatusFailedSmart) } return nil }