diff --git a/setup.cfg b/setup.cfg index 68cd0de..c839c9f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ [metadata] name = de.p1st.monitor -version = 0.10.3 +version = 0.10.5 author = Daniel Langbein author_email = daniel@systemli.org description = periodically monitor and warn diff --git a/src/de/p1st/monitor/data/yodaTux.ini b/src/de/p1st/monitor/data/yodaTux.ini index 4754838..a6a525b 100644 --- a/src/de/p1st/monitor/data/yodaTux.ini +++ b/src/de/p1st/monitor/data/yodaTux.ini @@ -58,7 +58,7 @@ warn_if_above = 0.75 ; 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. -uuid = 7fb12542-bd59-4727-9beb-7cf1f79f8293 +uuid = 01f67928-9b35-48b2-aaa6-c58ff6c440a8 mountpoint = / ; 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 = ea7099e3-320d-4eb3-a4c3-9910a9af817b ; `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 = /dev/nvme0n1p2 +device = /dev/nvme0n1 ; Warn if temperature is above this value. ; Unit: °C diff --git a/src/de/p1st/monitor/loggers/drive.py b/src/de/p1st/monitor/loggers/drive.py index f51c60c..93721c2 100644 --- a/src/de/p1st/monitor/loggers/drive.py +++ b/src/de/p1st/monitor/loggers/drive.py @@ -15,6 +15,14 @@ class BlkidException(Exception): pass +class UUIDException(Exception): + pass + + +class IDException(Exception): + pass + + class DriveLogger(Logger): def __init__(self, uuid: str = None, @@ -39,21 +47,19 @@ class DriveLogger(Logger): device = self.get_partition_from_uuid(uuid) if id_ is not None: device = self.get_partition_from_id(id_) - # `device` is not `None`, `uuid` might be `None`. - if uuid is None: - try: - uuid = self.get_uuid_from_partition(device) - except BlkidException as e: - raise LoggerArgEx(getattr(e, 'message', e)) + # `device` is not `None`. + # `id_` might be `None`. + if id_ is None: + id_ = self.get_id_from_device(device) # Store as attributes. - self.uuid = uuid + self.id_ = id_ self.device = device self.warn_if_above = warn_if_above def get_warn_data(self, data: list[any]) -> WarnData: 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) def read_data(self) -> list[any]: @@ -67,8 +73,8 @@ class DriveLogger(Logger): def get_log_file(self) -> Path: # self.device might change overtime. - # Thus, we use self.uuid to identify a partition. - return self.get_log_dir() / f'drive_{self.uuid}.csv' + # Thus, we use self.id_ to identify a partition. + return self.get_log_dir() / f'drive_{self.id_}.csv' # # HELPERS @@ -79,14 +85,34 @@ class DriveLogger(Logger): """ :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 def get_partition_from_id(cls, id_: str) -> Path: """ :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 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}']) 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() 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