from __future__ import annotations from pathlib import Path from uuid import UUID from .commands.cryptsetup import Cryptsetup from .misc import DISK_BY_UUID class Disk: def __init__(self, uuid: UUID, name: str): self.uuid = uuid self._decrypted: bool = False self._was_already_decrypted: bool = False self._name = name def decrypt(self) -> None: """Open a LUKS-encrypted disk with `cryptsetup`. Silently pass if it was already decrypted.""" if self._decrypted: raise ValueError("Cannot decrypt, already decrypted", self._name) self._was_already_decrypted = Cryptsetup.decrypt(self._path, self._mapper_entry) self._decrypted = True @property def _path(self) -> Path: """Unique path of the disk using /dev/disk/by-uuid.""" return DISK_BY_UUID / str(self.uuid) @property def _mapper_entry(self) -> str: """Name under which the decrypted disk will appear in /dev/mapper.""" return f"crypt-{self._name}" def encrypt(self) -> None: """Close a LUKS-encrypted container with `cryptsetup`.""" if not self._decrypted: raise ValueError("Cannot encrypt, not decrypted", self._name) if self._was_already_decrypted: return Cryptsetup.encrypt(self._mapper_entry) self._decrypted = False