You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.3 KiB
114 lines
3.3 KiB
package detect
|
|
|
|
import (
|
|
"github.com/analogj/scrutiny/collector/pkg/common/shell"
|
|
"github.com/analogj/scrutiny/collector/pkg/models"
|
|
"github.com/jaypipes/ghw"
|
|
"strings"
|
|
)
|
|
|
|
func DevicePrefix() string {
|
|
return "/dev/"
|
|
}
|
|
|
|
func (d *Detect) Start() ([]models.Device, error) {
|
|
d.Shell = shell.Create()
|
|
// call the base/common functionality to get a list of devicess
|
|
detectedDevices, err := d.SmartctlScan()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//smartctl --scan doesn't seem to detect mac nvme drives, lets see if we can detect them manually.
|
|
missingDevices, err := d.findMissingDevices(detectedDevices) //we dont care about the error here, just continue retrieving device info.
|
|
if err == nil {
|
|
detectedDevices = append(detectedDevices, missingDevices...)
|
|
}
|
|
|
|
//inflate device info for detected devices.
|
|
for ndx, _ := range detectedDevices {
|
|
d.SmartCtlInfo(&detectedDevices[ndx]) //ignore errors.
|
|
}
|
|
|
|
return detectedDevices, nil
|
|
}
|
|
|
|
func (d *Detect) findMissingDevices(detectedDevices []models.Device) ([]models.Device, error) {
|
|
|
|
missingDevices := []models.Device{}
|
|
|
|
block, err := ghw.Block()
|
|
if err != nil {
|
|
d.Logger.Errorf("Error getting block storage info: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
for _, disk := range block.Disks {
|
|
|
|
// ignore optical drives and floppy disks
|
|
if disk.DriveType == ghw.DRIVE_TYPE_FDD || disk.DriveType == ghw.DRIVE_TYPE_ODD {
|
|
d.Logger.Debugf(" => Ignore: Optical or floppy disk - (found %s)\n", disk.DriveType.String())
|
|
continue
|
|
}
|
|
|
|
// ignore removable disks
|
|
if disk.IsRemovable {
|
|
d.Logger.Debugf(" => Ignore: Removable disk (%v)\n", disk.IsRemovable)
|
|
continue
|
|
}
|
|
|
|
// ignore virtual disks & mobile phone storage devices
|
|
if disk.StorageController == ghw.STORAGE_CONTROLLER_VIRTIO || disk.StorageController == ghw.STORAGE_CONTROLLER_MMC {
|
|
d.Logger.Debugf(" => Ignore: Virtual/multi-media storage controller - (found %s)\n", disk.StorageController.String())
|
|
continue
|
|
}
|
|
|
|
// Skip unknown storage controllers, not usually S.M.A.R.T compatible.
|
|
if disk.StorageController == ghw.STORAGE_CONTROLLER_UNKNOWN {
|
|
d.Logger.Debugf(" => Ignore: Unknown storage controller - (found %s)\n", disk.StorageController.String())
|
|
continue
|
|
}
|
|
|
|
//check if device is already detected.
|
|
alreadyDetected := false
|
|
diskName := strings.TrimPrefix(disk.Name, DevicePrefix())
|
|
for _, detectedDevice := range detectedDevices {
|
|
|
|
if detectedDevice.DeviceName == diskName {
|
|
alreadyDetected = true
|
|
break
|
|
}
|
|
}
|
|
if !alreadyDetected {
|
|
missingDevices = append(missingDevices, models.Device{
|
|
DeviceName: diskName,
|
|
DeviceType: "",
|
|
})
|
|
}
|
|
}
|
|
return missingDevices, nil
|
|
}
|
|
|
|
//WWN values NVMe and SCSI
|
|
func (d *Detect) wwnFallback(detectedDevice *models.Device) {
|
|
block, err := ghw.Block()
|
|
if err == nil {
|
|
for _, disk := range block.Disks {
|
|
if disk.Name == detectedDevice.DeviceName && strings.ToLower(disk.WWN) != "unknown" {
|
|
d.Logger.Debugf("Found matching block device. WWN: %s", disk.WWN)
|
|
detectedDevice.WWN = disk.WWN
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
//no WWN found, or could not open Block devices. Either way, fallback to serial number
|
|
if len(detectedDevice.WWN) == 0 {
|
|
d.Logger.Debugf("WWN is empty, falling back to serial number: %s", detectedDevice.SerialNumber)
|
|
detectedDevice.WWN = detectedDevice.SerialNumber
|
|
}
|
|
|
|
//wwn must always be lowercase.
|
|
detectedDevice.WWN = strings.ToLower(detectedDevice.WWN)
|
|
}
|