bumblebee-status/bumblebee_status/modules/contrib/smartstatus.py

132 lines
4.2 KiB
Python
Raw Normal View History

2020-04-26 10:01:51 +02:00
# -*- coding: UTF-8 -*-
# smart function inspired by py-SMART https://github.com/freenas/py-SMART
# under Copyright (C) 2015 Marc Herndon and GPL2
"""Displays HDD smart status of different drives or all drives
2020-07-18 08:23:28 +02:00
Requires the following executables:
* sudo
* smartctl
2020-04-26 10:01:51 +02:00
Parameters:
2020-04-26 10:02:05 +02:00
* smartstatus.display: how to display (defaults to 'combined', other choices: 'seperate' or 'singles')
2020-05-07 06:18:17 +02:00
* smartstatus.drives: in the case of singles which drives to display, separated comma list value, multiple accepted (defaults to 'sda', example:'sda,sdc')
* smartstatus.show_names: boolean in the form of "True" or "False" to show the name of the drives in the form of sda, sbd, combined or none at all.
2020-04-26 10:01:51 +02:00
"""
import os
import shutil
2020-04-26 10:01:51 +02:00
import core.module
import core.decorators
2020-04-26 10:01:51 +02:00
import util.cli
import util.format
class Module(core.module.Module):
@core.decorators.every(minutes=5)
def __init__(self, config, theme):
super().__init__(config, theme, [])
2020-04-26 10:01:51 +02:00
self.devices = self.list_devices()
self.display = self.parameter("display", "combined")
self.drives = self.parameter("drives", "sda")
self.show_names = util.format.asbool(self.parameter("show_names", True))
self.create_widgets()
2020-04-26 10:01:51 +02:00
def create_widgets(self):
if self.display == "combined":
widget = self.add_widget()
widget.set("device", "combined")
widget.set("assessment", self.combined())
2020-04-26 10:01:51 +02:00
self.output(widget)
else:
for device in self.devices:
if self.display == "singles" and device not in self.drives:
2020-04-26 10:01:51 +02:00
continue
widget = self.add_widget()
widget.set("device", device)
widget.set("assessment", self.smart(device))
2020-04-26 10:01:51 +02:00
self.output(widget)
def update(self):
for widget in self.widgets():
device = widget.get("device")
if device == "combined":
widget.set("assessment", self.combined())
2020-04-26 10:01:51 +02:00
self.output(widget)
else:
widget.set("assessment", self.smart(device))
2020-04-26 10:01:51 +02:00
self.output(widget)
def output(self, widget):
device = widget.get("device")
assessment = widget.get("assessment")
if self.show_names:
2020-05-07 06:18:17 +02:00
widget.full_text("{}: {}".format(device, assessment))
else:
widget.full_text("{}".format(assessment))
2020-04-26 10:01:51 +02:00
def state(self, widget):
states = []
assessment = widget.get("assessment")
if assessment == "Pre-fail":
states.append("warning")
if assessment == "Fail":
states.append("critical")
2020-04-26 10:01:51 +02:00
return states
def combined(self):
for device in self.devices:
result = self.smart(device)
if result == "Fail":
return "Fail"
if result == "Pre-fail":
return "Pre-fail"
return "OK"
2020-04-26 10:01:51 +02:00
def list_devices(self):
for (root, folders, files) in os.walk("/dev"):
if root == "/dev":
devices = {
"".join(filter(lambda i: i.isdigit() == False, file))
for file in files
if "sd" in file
}
nvme = {
file for file in files if ("nvme0n" in file and "p" not in file)
}
2020-04-26 10:01:51 +02:00
devices.update(nvme)
return devices
def smart(self, disk_name):
smartctl = shutil.which("smartctl")
2020-04-26 10:01:51 +02:00
assessment = None
output = util.cli.execute(
"sudo {} --health {}".format(smartctl, os.path.join("/dev/", disk_name))
)
output = output.split("\n")
line = output[4]
if "SMART" in line:
if any([i in line for i in ["PASSED", "OK"]]):
assessment = "OK"
2020-04-26 10:01:51 +02:00
else:
assessment = "Fail"
2020-04-26 10:01:51 +02:00
if assessment == "OK":
output = util.cli.execute(
"sudo {} -A {}".format(smartctl, os.path.join("/dev/", disk_name))
)
output = output.split("\n")
for line in output:
if "Pre-fail" in line:
assessment = "Pre-fail"
2020-04-26 10:01:51 +02:00
return assessment
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4