Skip to content
Snippets Groups Projects
Commit f63aed47 authored by godog's avatar godog
Browse files

smartmon: scan smartd.conf for additonal devices

Pick only -d from all disk options, if present
parent ee47500d
No related branches found
No related tags found
1 merge request!53smartmon support for nvme and hw raid
Pipeline #4319 passed
...@@ -4,6 +4,7 @@ import collections ...@@ -4,6 +4,7 @@ import collections
import csv import csv
import datetime import datetime
import decimal import decimal
import itertools
import re import re
import shlex import shlex
import subprocess import subprocess
...@@ -89,6 +90,23 @@ class Device(collections.namedtuple('DeviceBase', 'path opts')): ...@@ -89,6 +90,23 @@ class Device(collections.namedtuple('DeviceBase', 'path opts')):
def smartctl_select(self): def smartctl_select(self):
return ['--device', self.type, self.path] return ['--device', self.type, self.path]
@staticmethod
def from_string(string):
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--device', dest='type')
tokens = shlex.split(string, comments=True)
if not tokens:
return None
return Device(tokens[0], parser.parse_known_args(tokens[1:])[0])
def __hash__(self):
return hash((self.path, self.type))
def __eq__(self, other):
return ((self.path, self.type) == (other.path, other.type))
def metric_key(metric, prefix=''): def metric_key(metric, prefix=''):
return '{prefix}{metric.name}'.format(prefix=prefix, metric=metric) return '{prefix}{metric.name}'.format(prefix=prefix, metric=metric)
...@@ -128,33 +146,38 @@ def smart_ctl(*args, check=True): ...@@ -128,33 +146,38 @@ def smart_ctl(*args, check=True):
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
return e.output.decode('utf-8') return e.output.decode('utf-8')
def smart_ctl_version(): def smart_ctl_version():
return smart_ctl('-V').split('\n')[0].split()[1] return smart_ctl('-V').split('\n')[0].split()[1]
def find_devices(): def scan_devices():
"""Find SMART devices. """Find SMART devices by scanning.
Yields: Yields:
(Device) Single device found by smartctl. (Device) Single device found by smartctl --scan-open
""" """
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--device', dest='type')
devices = smart_ctl('--scan-open') devices = smart_ctl('--scan-open')
devices_nvme = smart_ctl('--scan-open', '-d', 'nvme') devices_nvme = smart_ctl('--scan-open', '-d', 'nvme')
for device in devices.split('\n') + \ for line in devices.split('\n') + \
devices_nvme.split('\n'): devices_nvme.split('\n'):
device = device.strip() device = Device.from_string(line.strip())
if not device: if device:
continue yield device
tokens = shlex.split(device, comments=True)
if not tokens:
continue
yield Device(tokens[0], parser.parse_args(tokens[1:])) def smartd_devices(config='/etc/smartd.conf'):
"""Find SMART devices by reading smartd configuration.
Yields:
(Device) Single device configured
"""
with open(config) as f:
for line in f:
if line.startswith('/dev/'):
yield Device.from_string(line.strip())
def device_is_active(device): def device_is_active(device):
...@@ -322,7 +345,12 @@ def collect_ata_error_count(device): ...@@ -322,7 +345,12 @@ def collect_ata_error_count(device):
def collect_disks_smart_metrics(): def collect_disks_smart_metrics():
now = int(datetime.datetime.utcnow().timestamp()) now = int(datetime.datetime.utcnow().timestamp())
for device in find_devices(): devices = set()
for device in itertools.chain(scan_devices(), smartd_devices()):
if device in devices:
continue
devices.add(device)
yield Metric('smartctl_run', device.base_labels, now) yield Metric('smartctl_run', device.base_labels, now)
is_active = device_is_active(device) is_active = device_is_active(device)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment