This commit is contained in:
Daniel Langbein 2023-10-05 19:55:07 +02:00
parent a53639408e
commit f7a69b6121
Signed by: langfingaz
GPG Key ID: 6C47C753F0823002
3 changed files with 45 additions and 18 deletions

View File

@ -3,7 +3,7 @@
[metadata] [metadata]
name = de.p1st.monitor name = de.p1st.monitor
version = 0.10.3 version = 0.10.5
author = Daniel Langbein author = Daniel Langbein
author_email = daniel@systemli.org author_email = daniel@systemli.org
description = periodically monitor and warn description = periodically monitor and warn

View File

@ -58,7 +58,7 @@ warn_if_above = 0.75
; Either `uuid` or `mountpoint` must be given. ; Either `uuid` or `mountpoint` must be given.
; ;
; If both are given but the UUID of the disk mounted at `mountpoint` differs from `uuid`, then an exception is raised. ; If both are given but the UUID of the disk mounted at `mountpoint` differs from `uuid`, then an exception is raised.
uuid = 7fb12542-bd59-4727-9beb-7cf1f79f8293 uuid = 01f67928-9b35-48b2-aaa6-c58ff6c440a8
mountpoint = / mountpoint = /
; If `true` don't log or warn if the filesystem is not found. ; If `true` don't log or warn if the filesystem is not found.
@ -75,9 +75,9 @@ warn_if_above = 0.1
; `uuid` as in /dev/disk/by-uuid/* ; `uuid` as in /dev/disk/by-uuid/*
;uuid = ea7099e3-320d-4eb3-a4c3-9910a9af817b ;uuid = ea7099e3-320d-4eb3-a4c3-9910a9af817b
; `id` as in /dev/disk/by-id/* ; `id` as in /dev/disk/by-id/*
id = nvme-XPG_GAMMIX_S50_Lite_2K462L2JN9KG ; id = nvme-XPG_GAMMIX_S50_Lite_2K462L2JN9KG
; device as in /dev/* ; device as in /dev/*
;device = /dev/nvme0n1p2 device = /dev/nvme0n1
; Warn if temperature is above this value. ; Warn if temperature is above this value.
; Unit: °C ; Unit: °C

View File

@ -15,6 +15,14 @@ class BlkidException(Exception):
pass pass
class UUIDException(Exception):
pass
class IDException(Exception):
pass
class DriveLogger(Logger): class DriveLogger(Logger):
def __init__(self, def __init__(self,
uuid: str = None, uuid: str = None,
@ -39,21 +47,19 @@ class DriveLogger(Logger):
device = self.get_partition_from_uuid(uuid) device = self.get_partition_from_uuid(uuid)
if id_ is not None: if id_ is not None:
device = self.get_partition_from_id(id_) device = self.get_partition_from_id(id_)
# `device` is not `None`, `uuid` might be `None`. # `device` is not `None`.
if uuid is None: # `id_` might be `None`.
try: if id_ is None:
uuid = self.get_uuid_from_partition(device) id_ = self.get_id_from_device(device)
except BlkidException as e:
raise LoggerArgEx(getattr(e, 'message', e))
# Store as attributes. # Store as attributes.
self.uuid = uuid self.id_ = id_
self.device = device self.device = device
self.warn_if_above = warn_if_above self.warn_if_above = warn_if_above
def get_warn_data(self, data: list[any]) -> WarnData: def get_warn_data(self, data: list[any]) -> WarnData:
temp = data[1] temp = data[1]
message = f'Temperature of {self.uuid} ist at {temp}' message = f'Temperature of {self.id_} ist at {temp}'
return WarnData(data[0], temp, message) return WarnData(data[0], temp, message)
def read_data(self) -> list[any]: def read_data(self) -> list[any]:
@ -67,8 +73,8 @@ class DriveLogger(Logger):
def get_log_file(self) -> Path: def get_log_file(self) -> Path:
# self.device might change overtime. # self.device might change overtime.
# Thus, we use self.uuid to identify a partition. # Thus, we use self.id_ to identify a partition.
return self.get_log_dir() / f'drive_{self.uuid}.csv' return self.get_log_dir() / f'drive_{self.id_}.csv'
# #
# HELPERS # HELPERS
@ -79,14 +85,34 @@ class DriveLogger(Logger):
""" """
:return: Partition path, e.g. /dev/sda1 :return: Partition path, e.g. /dev/sda1
""" """
return Path(f'/dev/disk/by-uuid/{uuid}').resolve() device = Path(f'/dev/disk/by-uuid/{uuid}').resolve()
if not device.is_relative_to('/dev'):
raise UUIDException(f'Could not determine /dev/* path from UUID: {uuid}')
return device
@classmethod @classmethod
def get_partition_from_id(cls, id_: str) -> Path: def get_partition_from_id(cls, id_: str) -> Path:
""" """
:return: Partition path, e.g. /dev/sda1 :return: Partition path, e.g. /dev/sda1
""" """
return Path(f'/dev/disk/by-id/{id_}').resolve() device = Path(f'/dev/disk/by-id/{id_}').resolve()
if not device.is_relative_to('/dev'):
raise IDException(f'Could not determine /dev/* path from ID: {id_}')
return device
@classmethod
def get_id_from_device(cls, device: Path) -> str:
id_paths = Path('/dev/disk/by-id/').iterdir()
# Filter.
id_paths = [id_path for id_path in id_paths
if id_path.resolve() == device]
# We expect at least one result.
if len(id_paths) == 0:
raise IDException(f'Could not determine /dev/disk/by-id/* from device: {device}')
# Sort by path length => Sort by ID length.
id_paths = sorted(id_paths, key=lambda x: len(str(x)))
# Return shortest ID.
return id_paths[0].name
@classmethod @classmethod
def get_uuid_from_partition(cls, device: Path) -> str: def get_uuid_from_partition(cls, device: Path) -> str:
@ -97,11 +123,12 @@ class DriveLogger(Logger):
""" """
returncode, stdout, stderr = execute_capture(['blkid', '-s', 'UUID', '-o', 'value', f'{device}']) returncode, stdout, stderr = execute_capture(['blkid', '-s', 'UUID', '-o', 'value', f'{device}'])
if returncode != 0: if returncode != 0:
raise BlkidException(f'blkid failed with returncode {returncode}\nstdout: {stdout}\nstderr: {stderr}') raise BlkidException(f'blkid failed for device {device} with returncode {returncode}\nstdout: {stdout}\nstderr: {stderr}')
uuid = stdout.strip() uuid = stdout.strip()
if len(uuid) == 0: if len(uuid) == 0:
raise BlkidException('blkid had exit code zero, but the UUID is empty') raise BlkidException(f'blkid had exit code zero, but the UUID is empty.'
f' Did you maybe provide a device instead of a partition? {device}')
return uuid return uuid