from __future__ import annotations import config from zfs import ZFS from zfs_backup.core import _get_regex_matching_snapshots_with_tags from snapshot import Snapshot from zfs_path import ZFSPath class Dataset: def __init__(self, zfs_path: ZFSPath): self._path = zfs_path def __repr__(self): return self.qualified_name def __eq__(self, other: Dataset): return self._path == other._path def __hash__(self): return self._path.__hash__() @classmethod def from_string(cls, qualified_name: str) -> Dataset: return cls(ZFSPath.from_string(qualified_name)) @property def qualified_name(self) -> str: return str(self._path) @property def name_without_pool(self) -> str: return self._path.name_without_pool @property def snapshots(self) -> list[Snapshot]: """get qualified snapshots that are direct children of the dataset""" return ZFS.get_snapshots(self) def replace_pool(self, name: str) -> Dataset: return Dataset(self._path.replace_pool(name)) def clean_old_snapshots(self) -> None: for interval, number in config.keep_snapshots_per_interval.items(): self._clean_old_snapshots_for_interval(interval, number) def _clean_old_snapshots_for_interval(self, interval: str, max_count: int) -> None: regex = _get_regex_matching_snapshots_with_tags([config.snapshot_tag, interval]) snapshots = [ snapshot for snapshot in self.snapshots if snapshot.matches_regex(regex) ] old_snapshots = self._get_oldest_snapshots_exceeding_max_count( snapshots, max_count ) for snapshot in old_snapshots: snapshot.destroy() @staticmethod def _get_oldest_snapshots_exceeding_max_count( snapshots: list[Snapshot], max_count: int ) -> list[Snapshot]: snapshots.sort() count = len(snapshots) - max_count if count < 0: count = 0 return snapshots[:count]