add: docstrings in Manager

This commit is contained in:
timeshifter
2021-12-04 23:07:09 +01:00
parent be47ff5f68
commit d22108d20a
+39 -10
View File
@@ -48,6 +48,8 @@ def main():
class Manager:
"""Controls the overall backup process."""
_map_type: dict[Dataset, Dataset | None]
def __init__(self, local_pool: Pool, external_pool: ExternalPool):
@@ -55,6 +57,7 @@ class Manager:
self._external_pool = external_pool
def backup(self):
"""Backup workflow."""
self._external_pool.import_()
try:
self._external_pool.scrub(skip_if_recently_scrubbed=True)
@@ -65,18 +68,26 @@ class Manager:
self._external_pool.export()
def _backup_all_datasets(self):
"""Send snapshots of local datasets to the backup pool."""
print("Backing up datasets")
for local_dataset, remote_dataset in self._get_dataset_backup_map().items():
for (
local_dataset,
remote_dataset,
) in self._get_user_filtered_dataset_backup_map().items():
if remote_dataset is None:
stream = self._send_absolute(local_dataset)
else:
stream = self._send_incremental(local_dataset, remote_dataset)
ZFS.receive(stream, self._external_pool)
def _get_dataset_backup_map(self) -> _map_type:
def _get_user_filtered_dataset_backup_map(self) -> _map_type:
return self._user_confirm_new_datasets(self._get_raw_dataset_map())
def _user_confirm_new_datasets(self, dataset_map: _map_type) -> _map_type:
"""For datasets that exist only locally, ask the user if he wants to back it up.
If he doesn't, remove it from the dict.
"""
return {
local_dataset: remote_dataset
for local_dataset, remote_dataset in dataset_map.items()
@@ -84,6 +95,10 @@ class Manager:
}
def _get_raw_dataset_map(self) -> _map_type:
"""Return map from local to remote datasets.
If the local dataset has no remote match, set the remote dataset to None.
"""
return {
local_dataset: self._search_matching_dataset_in_remote_pool(
local_dataset, self._external_pool
@@ -94,23 +109,29 @@ class Manager:
def _send_incremental(
self, local_dataset: Dataset, remote_dataset: Dataset
) -> Popen:
start_snapshot = self._get_last_common_snapshot(local_dataset, remote_dataset)
end_snapshot = self._get_last_snapshot_with_backup_tag(local_dataset)
"""Send incremental stream between two datasets to remote."""
start_snapshot = self._get_newest_common_snapshot_with_backup_tags(
local_dataset, remote_dataset
)
end_snapshot = self._get_newest_snapshot_with_backup_tag(local_dataset)
stream = ZFS.send_incremental(start_snapshot, end_snapshot)
return stream
def _send_absolute(self, local_dataset: Dataset) -> Popen:
snapshot = self._get_last_snapshot_with_backup_tag(local_dataset)
"""Send absolute stream to remote."""
snapshot = self._get_newest_snapshot_with_backup_tag(local_dataset)
return ZFS.send_absolute(snapshot)
def _get_last_snapshot_with_backup_tag(self, local_dataset):
snapshots = self._find_snapshots_with_backup_tag(local_dataset)
def _get_newest_snapshot_with_backup_tag(self, dataset: Dataset) -> Snapshot:
"""From all snapshots in the dataset, get the newest one that matches the backup tags in the config."""
snapshots = self._find_snapshots_with_backup_tag(dataset)
snapshots.sort()
end_snapshot = snapshots[-1]
return end_snapshot
@property
def _datasets_to_backup(self) -> list[Dataset]:
"""Return local datasets to consider for a backup."""
return [
dataset
for dataset in self._local_pool.datasets
@@ -119,6 +140,7 @@ class Manager:
@staticmethod
def _find_snapshots_with_backup_tag(dataset: Dataset) -> list[Snapshot]:
"""Find snapshots of a dataset that carry the backup tags."""
regex = _get_regex_matching_snapshots_with_tags(
[config.snapshot_tag, config.snapshot_interval]
)
@@ -130,15 +152,22 @@ class Manager:
def _search_matching_dataset_in_remote_pool(
dataset: Dataset, pool: Pool
) -> Dataset | None:
"""For a dataset in the local pool, get the matching dataset in the remote pool.
If there is no match, return None.
"""
dataset_to_search = dataset.replace_pool(pool.name)
for dataset in pool.datasets:
if dataset == dataset_to_search:
return dataset
@classmethod
def _get_last_common_snapshot(
def _get_newest_common_snapshot_with_backup_tags(
cls, local_dataset: Dataset, remote_dataset: Dataset
) -> Snapshot:
"""In a local and a remote dataset, find the newest snapshot with backup tags which exists in both datasets.
Return the local snapshot."""
common_snapshots = [
local_snap
for local_snap in list(cls._find_snapshots_with_backup_tag(local_dataset))
@@ -287,7 +316,7 @@ class ZPool(CommandInterface):
cls._scrub_if_necessary(pool, skip_if_recently_scrubbed)
if wait_for_finish:
cls._run_command(*cls._Subcommands.wait, pool.name)
if not cls._healthy(pool):
if not cls._is_healthy(pool):
raise IOError(f"Pool {pool.name} is not healthy.")
@classmethod
@@ -312,7 +341,7 @@ class ZPool(CommandInterface):
return "scrub in progress" in cls._get_pool_status_output(pool)
@classmethod
def _healthy(cls, pool: Pool) -> bool:
def _is_healthy(cls, pool: Pool) -> bool:
return "ONLINE" in cls._get_pool_status_output(pool)
@classmethod