more fixes

This commit is contained in:
timeshifter
2021-11-26 19:33:22 +01:00
parent 8bc1974fe6
commit 0900c85400
+28 -21
View File
@@ -3,18 +3,28 @@
from __future__ import annotations from __future__ import annotations
import os
import re
import subprocess
from functools import cache from functools import cache
from os import getuid
from pathlib import Path from pathlib import Path
from subprocess import PIPE, Popen, check_output from re import search
from subprocess import PIPE, Popen, call, check_output
from sys import exit from sys import exit
from typing import Optional from typing import Optional
from uuid import UUID from uuid import UUID
import config import config
ALREADY_DECRYPTED = "Cannot decrypt, already decrypted"
ALREADY_IMPORTED = "Cannot import, already imported"
CANNOT_FIND_BACKUP_DRIVE = "Could not find a backup drive"
DELETE_IN_LOCAL_POOL = "ALERT! Tried to delete in local pool!"
MAPPER_ENTRY_ALREADY_EXISTS = "mapper entry already exists"
NOT_DECRYPTED = "Cannot encrypt, not decrypted"
NOT_IMPORTED = "Cannot export, not imported"
NOT_VALID_ZFS_PATH = "Not a valid ZFSPath"
RUN_AS_ROOT = "Run as root."
SAME_DATASET = "Cannot send incremental snapshots if start and end snapshot are not based on the same dataset"
DISK_BY_UUID = Path("/dev/disk/by-uuid") DISK_BY_UUID = Path("/dev/disk/by-uuid")
MAPPER_PATH = Path("/dev/mapper") MAPPER_PATH = Path("/dev/mapper")
@@ -162,7 +172,7 @@ class ZFSPath:
def _sanity_check(self): def _sanity_check(self):
for item in self._elements: for item in self._elements:
if len(item) == 0: if len(item) == 0:
raise ValueError("Not a valid ZFSPath") raise ValueError(NOT_VALID_ZFS_PATH)
class ZFS: class ZFS:
@@ -220,8 +230,7 @@ class ZFS:
@staticmethod @staticmethod
def destroy(full_name, *, recursive=False): def destroy(full_name, *, recursive=False):
if config.local_pool_to_backup in full_name: if config.local_pool_to_backup in full_name:
msg = "ALERT! Tried to delete in local pool!" raise Exception(DELETE_IN_LOCAL_POOL)
raise Exception(msg)
cmdline = [config.ZFS, "destroy"] cmdline = [config.ZFS, "destroy"]
if recursive: if recursive:
cmdline.append("-r") cmdline.append("-r")
@@ -231,9 +240,7 @@ class ZFS:
@staticmethod @staticmethod
def send_incremental(old_snap: Snapshot, new_snap: Snapshot) -> Popen[str]: def send_incremental(old_snap: Snapshot, new_snap: Snapshot) -> Popen[str]:
if old_snap.dataset != new_snap.dataset: if old_snap.dataset != new_snap.dataset:
raise ValueError( raise ValueError(SAME_DATASET)
"Cannot send incremental snapshots if start and end snapshot are not based on the same dataset"
)
sender = Popen( sender = Popen(
[config.ZFS, "send", "-R", "-I", old_snap, new_snap], stdout=PIPE [config.ZFS, "send", "-R", "-I", old_snap, new_snap], stdout=PIPE
) )
@@ -264,7 +271,7 @@ class Disk:
def decrypt(self) -> None: def decrypt(self) -> None:
if self._decrypted: if self._decrypted:
raise ValueError(f"Already decrypted {self._name}") raise ValueError(ALREADY_DECRYPTED, self._name)
self._verify_mapper_entry_not_in_use() self._verify_mapper_entry_not_in_use()
self._decrypt_with_cryptsetup() self._decrypt_with_cryptsetup()
self._decrypted = True self._decrypted = True
@@ -275,7 +282,7 @@ class Disk:
def _verify_mapper_entry_not_in_use(self): def _verify_mapper_entry_not_in_use(self):
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(f"mapper entry {self._mapper_entry} already exists") print(MAPPER_ENTRY_ALREADY_EXISTS, self._mapper_entry)
exit(1) exit(1)
@property @property
@@ -288,7 +295,7 @@ class Disk:
def encrypt(self): def encrypt(self):
if not self._decrypted: if not self._decrypted:
raise ValueError(f"Not decrypted {self._name}") raise ValueError(NOT_DECRYPTED, self._name)
get_output_of_command([config.CRYPTSETUP, "close", self._name]) get_output_of_command([config.CRYPTSETUP, "close", self._name])
self._decrypted = False self._decrypted = False
@@ -319,14 +326,14 @@ class ExternalPool(Pool):
def import_(self) -> None: def import_(self) -> None:
if self._imported: if self._imported:
raise ValueError(f"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)
self._imported = True self._imported = True
def export(self) -> None: def export(self) -> None:
if not self._imported: if not self._imported:
raise ValueError(f"Not imported {self.name}") raise ValueError(NOT_IMPORTED, self.name)
self._export_pool() self._export_pool()
self._disk.encrypt() self._disk.encrypt()
self._imported = False self._imported = False
@@ -349,7 +356,7 @@ class ExternalPool(Pool):
print(f"Found disk {pool_name}, {disk_uuid}") print(f"Found disk {pool_name}, {disk_uuid}")
return cls(pool_name, disk) return cls(pool_name, disk)
else: else:
print("Could not find a backup drive") print(CANNOT_FIND_BACKUP_DRIVE)
exit(1) exit(1)
# def datasets_to_backup(self, do_not_backup: list[str]) -> list[Dataset]: # def datasets_to_backup(self, do_not_backup: list[str]) -> list[Dataset]:
@@ -425,7 +432,7 @@ class Snapshot:
return self._path.snapname return self._path.snapname
def matches_regex(self, regex: str) -> bool: def matches_regex(self, regex: str) -> bool:
return bool(re.search(regex, str(self._path))) return bool(search(regex, str(self._path)))
def destroy(self): def destroy(self):
ZFS.destroy(str(self)) ZFS.destroy(str(self))
@@ -440,18 +447,18 @@ class Snapshot:
def run_command(cmdline: list[str]): def run_command(cmdline: list[str]):
subprocess.call(cmdline) call(cmdline)
def get_output_of_command(cmdline: str | list[str]) -> str: def get_output_of_command(cmdline: str | list[str]) -> str:
if isinstance(cmdline, str): if isinstance(cmdline, str):
cmdline = [cmdline] cmdline = [cmdline]
return subprocess.check_output(cmdline).strip().decode() return check_output(cmdline).strip().decode()
def verify_running_as_root(): def verify_running_as_root():
if os.getuid() > 0: if getuid() > 0:
print("Run as root.") print(RUN_AS_ROOT)
exit(1) exit(1)