This commit is contained in:
timeshifter
2022-12-06 15:10:36 +01:00
parent 695c4fc924
commit 28963c3e64
11 changed files with 58 additions and 41 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ def main():
verify_running_as_root()
local_pool = Pool(config.local_pool_to_backup)
external_pool = ExternalPool.find_from_dict(config.backup_pools)
manager = Manager(local_pool, external_pool)
manager = Manager(local_pool, external_pool, config.recent_scrub_timedelta)
manager.backup()
View File
@@ -3,7 +3,7 @@ from __future__ import annotations
from pathlib import Path
from subprocess import Popen, call, check_output, PIPE
from misc import assert_type
from zfs_backup.misc import assert_type
class CommandInterface:
@@ -2,9 +2,9 @@ from __future__ import annotations
from pathlib import Path
from .messages import MAPPER_ENTRY_ALREADY_EXISTS, CANNOT_FIND_DEVICE_PATH
from .commands import CommandInterface
from .misc import DISK_BY_UUID, MAPPER_PATH
from ._core import CommandInterface
from ..messages import MAPPER_ENTRY_ALREADY_EXISTS, CANNOT_FIND_DEVICE_PATH
from ..misc import MAPPER_PATH, DISK_BY_UUID
class Cryptsetup(CommandInterface):
@@ -3,14 +3,13 @@ from __future__ import annotations
from pathlib import Path
from subprocess import Popen
import config
from .messages import DELETE_IN_LOCAL_POOL, SAME_DATASET
from .misc import assert_type
from .commands import CommandInterface
from .snapshot import Snapshot
from .dataset import Dataset
from .pool import Pool
from .zfs_path import ZFSPath
from .. import Pool
from ._core import CommandInterface
from ..dataset import Dataset
from ..messages import SAME_DATASET
from ..misc import assert_type
from ..snapshot import Snapshot
from ..zfs_path import ZFSPath
class ZFS(CommandInterface):
@@ -65,8 +64,6 @@ class ZFS(CommandInterface):
def destroy_snapshot(cls, snapshot: Snapshot) -> None:
"""Non-recursively destroy a snapshot."""
assert_type(snapshot, Snapshot, "Can only destroy snapshots.")
if config.local_pool_to_backup == snapshot.pool:
raise Exception(DELETE_IN_LOCAL_POOL)
cls._run_command(*cls._Subcommands.destroy, str(snapshot))
@classmethod
@@ -1,12 +1,12 @@
from __future__ import annotations
from datetime import datetime, timedelta
from datetime import timedelta, datetime
from pathlib import Path
from .misc import assert_type
from .commands import CommandInterface
from .pool import Pool
from .time import Time
from ._core import CommandInterface
from ..pool import Pool
from ..misc import assert_type
from ..time import Time
class ZPool(CommandInterface):
@@ -33,8 +33,9 @@ class ZPool(CommandInterface):
assert_type(pool, Pool, "Can only export Pool objects")
cls._run_command(*cls._Subcommands.export, pool.name)
@classmethod
def scrub(
self,
cls,
pool: Pool,
*,
skip_if_recently_scrubbed: bool,
@@ -45,16 +46,15 @@ class ZPool(CommandInterface):
Waits for the scrub to finish. Raise an IOError if the pool reports as not healthy after the scrub."""
assert_type(pool, Pool, "Can only scrub pools.")
self._scrub_if_necessary(
pool, skip_if_recently_scrubbed, recent_scrub_timedelta
)
cls._scrub_if_necessary(pool, skip_if_recently_scrubbed, recent_scrub_timedelta)
if wait_for_finish:
self._run_command(*self._Subcommands.wait, pool.name)
if not self._is_healthy(pool):
cls._run_command(*cls._Subcommands.wait, pool.name)
if not cls._is_healthy(pool):
raise IOError(f"Pool {pool.name} is not healthy.")
@classmethod
def _scrub_if_necessary(
self,
cls,
pool: Pool,
skip_if_recently_scrubbed: bool,
recent_scrub_timedelta: timedelta,
@@ -62,14 +62,14 @@ class ZPool(CommandInterface):
"""Scrub the pool. If"""
def do_scrub():
self._run_command(*self._Subcommands.scrub, pool.name)
cls._run_command(*cls._Subcommands.scrub, pool.name)
if self._scrub_in_progress(pool):
if cls._scrub_in_progress(pool):
return
if not skip_if_recently_scrubbed:
do_scrub()
else:
if not self._recently_scrubbed(pool, recent_scrub_timedelta):
if not cls._recently_scrubbed(pool, recent_scrub_timedelta):
do_scrub()
@classmethod
+17 -4
View File
@@ -1,18 +1,25 @@
from __future__ import annotations
from datetime import timedelta
from subprocess import Popen
import config
from dataset import Dataset
from pool import Pool, ExternalPool
from snapshot import Snapshot
from zfs import ZFS
from zfs_backup.commands.zfs import ZFS
class Manager:
"""Controls the overall backup process."""
def __init__(self, local_pool: Pool, external_pool: ExternalPool):
def __init__(
self,
local_pool: Pool,
external_pool: ExternalPool,
recent_scrub_timedelta: timedelta,
):
self._recent_scrub_timedelta = recent_scrub_timedelta
self._local_pool = local_pool
self._external_pool = external_pool
@@ -20,10 +27,16 @@ class Manager:
"""Backup workflow."""
self._external_pool.import_()
try:
self._external_pool.scrub(skip_if_recently_scrubbed=True)
self._external_pool.scrub(
skip_if_recently_scrubbed=True,
recent_scrub_timedelta=self._recent_scrub_timedelta,
)
self._backup_all_datasets()
self._external_pool.clean_old_snapshots()
self._external_pool.scrub(skip_if_recently_scrubbed=False)
self._external_pool.scrub(
skip_if_recently_scrubbed=False,
recent_scrub_timedelta=self._recent_scrub_timedelta,
)
finally:
self._external_pool.export()
+1 -1
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import config
from zfs import ZFS
from zfs_backup.commands.zfs import ZFS
from zfs_backup.core import _get_regex_matching_snapshots_with_tags
from snapshot import Snapshot
from zfs_path import ZFSPath
+1 -1
View File
@@ -4,7 +4,7 @@ from pathlib import Path
from uuid import UUID
from .messages import ALREADY_DECRYPTED, NOT_DECRYPTED
from .cryptsetup import Cryptsetup
from .commands.cryptsetup import Cryptsetup
from .misc import DISK_BY_UUID
+11 -4
View File
@@ -1,14 +1,15 @@
from __future__ import annotations
from datetime import timedelta
from uuid import UUID
from .disk import Disk
from .messages import CANNOT_FIND_BACKUP_DRIVE, ALREADY_IMPORTED, NOT_IMPORTED
from .misc import MAPPER_PATH, DISK_BY_UUID
from .zfs import ZFS
from .commands.zfs import ZFS
from .dataset import Dataset
from .zfs_path import ZFSPath
from .zpool import ZPool
from .commands.zpool import ZPool
class Pool:
@@ -52,9 +53,15 @@ class ExternalPool(Pool):
self._imported = False
print(f"Exported {self.name}. Disk {self._disk.uuid} can be removed.")
def scrub(self, skip_if_recently_scrubbed: bool) -> None:
def scrub(
self, skip_if_recently_scrubbed: bool, recent_scrub_timedelta: timedelta
) -> None:
print(f"Scrubbing {self._name}")
ZPool.scrub(self, skip_if_recently_scrubbed=skip_if_recently_scrubbed)
ZPool.scrub(
self,
skip_if_recently_scrubbed=skip_if_recently_scrubbed,
recent_scrub_timedelta=recent_scrub_timedelta,
)
@classmethod
def find_from_dict(cls, backup_pools: dict[str, UUID]) -> ExternalPool:
+1 -1
View File
@@ -3,7 +3,7 @@ from __future__ import annotations
from re import search
from dataset import Dataset
from zfs import ZFS
from zfs_backup.commands.zfs import ZFS
from zfs_path import ZFSPath