add todos

This commit is contained in:
timeshifter
2021-12-01 16:38:54 +01:00
parent d6ad4dba98
commit 21c04fb9e1
+19 -3
View File
@@ -9,7 +9,7 @@ from pathlib import Path
from re import search from re import search
from subprocess import PIPE, Popen, call, check_output from subprocess import PIPE, Popen, call, check_output
from sys import exit from sys import exit
from typing import Optional from typing import Optional # TODO replace with pipe notation
from uuid import UUID from uuid import UUID
import config import config
@@ -42,6 +42,10 @@ def main():
manager.backup() manager.backup()
# TODO tests
# TODO docstrings
# TODO first backup
class Manager: class Manager:
def __init__(self, local_pool: Pool, external_pool: ExternalPool): def __init__(self, local_pool: Pool, external_pool: ExternalPool):
self._local_pool = local_pool self._local_pool = local_pool
@@ -92,6 +96,7 @@ class Manager:
] ]
@staticmethod @staticmethod
# TODO make function
def _get_regex_matching_backup_tags(): def _get_regex_matching_backup_tags():
return "@" + ".*".join([config.snapshot_tag, config.snapshot_interval]) return "@" + ".*".join([config.snapshot_tag, config.snapshot_interval])
@@ -230,6 +235,8 @@ class ZFS:
@staticmethod @staticmethod
def destroy(full_name, *, recursive=False): def destroy(full_name, *, recursive=False):
# TODO condition must be "begins with"
# or better argument should be a ZFSPath
if config.local_pool_to_backup in full_name: if config.local_pool_to_backup in full_name:
raise Exception(DELETE_IN_LOCAL_POOL) raise Exception(DELETE_IN_LOCAL_POOL)
cmdline = [config.ZFS, "destroy"] cmdline = [config.ZFS, "destroy"]
@@ -260,8 +267,10 @@ class ZFS:
@staticmethod @staticmethod
def scrub(pool: str, *, wait_for_finish=True) -> None: def scrub(pool: str, *, wait_for_finish=True) -> None:
# TODO: check if scrub already in progress
run_command([config.ZPOOL, "scrub", pool]) run_command([config.ZPOOL, "scrub", pool])
if wait_for_finish: if wait_for_finish:
# TODO make Ctrl-c interrupt this
run_command([config.ZPOOL, "wait", "-t", "scrub", pool]) run_command([config.ZPOOL, "wait", "-t", "scrub", pool])
@@ -285,6 +294,7 @@ class Disk:
for item in MAPPER_PATH.iterdir(): for item in MAPPER_PATH.iterdir():
if self._mapper_entry == item.name: if self._mapper_entry == item.name:
print(MAPPER_ENTRY_ALREADY_EXISTS, self._mapper_entry) print(MAPPER_ENTRY_ALREADY_EXISTS, self._mapper_entry)
# TODO exit code constants
exit(1) exit(1)
@property @property
@@ -298,6 +308,7 @@ class Disk:
def encrypt(self): def encrypt(self):
if not self._decrypted: if not self._decrypted:
raise ValueError(NOT_DECRYPTED, self._name) raise ValueError(NOT_DECRYPTED, self._name)
# TODO use run instead?
get_output_of_command([config.CRYPTSETUP, "close", self._name]) get_output_of_command([config.CRYPTSETUP, "close", self._name])
self._decrypted = False self._decrypted = False
@@ -330,14 +341,14 @@ class ExternalPool(Pool):
if self._imported: if self._imported:
raise ValueError(ALREADY_IMPORTED, self.name) raise ValueError(ALREADY_IMPORTED, self.name)
self._disk.decrypt() self._disk.decrypt()
self._import_from_directory(MAPPER_PATH) self._import_from_directory(MAPPER_PATH) # TODO inline?
self._imported = True self._imported = True
def export(self) -> None: def export(self) -> None:
if not self._imported: if not self._imported:
raise ValueError(NOT_IMPORTED, self.name) raise ValueError(NOT_IMPORTED, self.name)
self._export_pool() self._export_pool()
self._disk.encrypt() self._disk.encrypt() # TODO inline?
self._imported = False self._imported = False
print(f"Exported {self.name}. Disk {self._disk.uuid} can be removed.") print(f"Exported {self.name}. Disk {self._disk.uuid} can be removed.")
@@ -345,6 +356,7 @@ class ExternalPool(Pool):
ZFS.import_pool_from_directory(self._name, directory) ZFS.import_pool_from_directory(self._name, directory)
def _export_pool(self) -> None: def _export_pool(self) -> None:
# TODO cancel scrub if necessary
ZFS.export_pool(self._name) ZFS.export_pool(self._name)
def scrub(self) -> None: def scrub(self) -> None:
@@ -371,6 +383,7 @@ class ExternalPool(Pool):
# return [d for d in self.datasets if d.qualified_name not in do_not_backup_correct_name] # return [d for d in self.datasets if d.qualified_name not in do_not_backup_correct_name]
def clean_old_snapshots(self): def clean_old_snapshots(self):
print("Cleaning old snapshots")
for dataset in self.datasets: for dataset in self.datasets:
dataset.clean_old_snapshots() dataset.clean_old_snapshots()
@@ -410,10 +423,12 @@ class Dataset:
self._clean_old_snapshots_for_interval(interval, number) self._clean_old_snapshots_for_interval(interval, number)
def _clean_old_snapshots_for_interval(self, interval: str, max_count: int): def _clean_old_snapshots_for_interval(self, interval: str, max_count: int):
# TODO this is somewhat similar to the regex method in Manager
regex = ".*".join(["", config.snapshot_tag, interval, ""]) regex = ".*".join(["", config.snapshot_tag, interval, ""])
snapshots = [ snapshots = [
snapshot for snapshot in self.snapshots if snapshot.matches_regex(regex) snapshot for snapshot in self.snapshots if snapshot.matches_regex(regex)
] ]
# TODO function _get_n_oldest_snapshots
if len(snapshots) > max_count: if len(snapshots) > max_count:
snapshots.sort() snapshots.sort()
for snap in snapshots[:-max_count]: for snap in snapshots[:-max_count]:
@@ -453,6 +468,7 @@ class Snapshot:
return Dataset(self._path.dataset) return Dataset(self._path.dataset)
# TODO class CommandRunner
def run_command(cmdline: list[str]): def run_command(cmdline: list[str]):
call(cmdline) call(cmdline)