rawfile-localpv/declarative.py
2021-07-04 23:15:50 +04:30

115 lines
2.9 KiB
Python

import os
import subprocess
import tempfile
from pathlib import Path
from util import run
def be_absent(path):
path = Path(path)
if path.is_symlink():
path.unlink()
elif path.is_file():
path.unlink()
elif path.is_dir():
path.rmdir()
# XXX: should we `shutil.rmtree(path)` instead?
elif not path.exists():
return
else:
raise Exception("Unknown file type")
def be_symlink(path, to):
path = Path(path)
to = Path(to)
if path.is_symlink():
if os.readlink(path) == str(to):
return
be_absent(path)
path.symlink_to(to)
def be_mounted(dev, mountpoint):
dev = Path(dev).resolve()
mountpoint = Path(mountpoint)
if mountpoint.is_mount():
if True: # TODO: verify that the right device is mounted
return
# noinspection PyUnreachableCode
be_unmounted(mountpoint)
fs = current_fs(dev)
if fs == "ext4":
run(f"mount -t ext4 {dev} {mountpoint}")
elif fs == "btrfs":
run(f"mount -t btrfs -o flushoncommit {dev} {mountpoint}")
elif fs == "xfs":
run(f"mount -t xfs {dev} {mountpoint}")
else:
raise Exception(f"Unsupported fs type: {fs}")
def be_unmounted(path):
path = Path(path)
while path.is_mount():
run(f"umount {path}")
def current_fs(device):
res = subprocess.run(
f"blkid -o value -s TYPE {device}", shell=True, capture_output=True
)
if res.returncode == 2: # specified token was not found
return None
return res.stdout.decode().strip()
def be_formatted(dev, fs):
def init_fs(device):
if fs == "ext4":
run(f"mkfs.ext4 -m 0 {device}")
elif fs == "btrfs":
run(f"mkfs.btrfs {device}")
tmp_mnt = tempfile.mkdtemp(prefix="mnt-")
default_subvol = f"{tmp_mnt}/default"
run(
f"""
set -ex
mkdir -p {tmp_mnt}
mount -t btrfs {device} {tmp_mnt}
btrfs subvolume create {default_subvol}
btrfs subvolume set-default {default_subvol}
umount {tmp_mnt}
rmdir {tmp_mnt}
"""
)
elif fs == "xfs":
run(f"mkfs.xfs {device}")
else:
raise Exception(f"Unsupported fs type: {fs}")
dev = Path(dev).resolve()
current = current_fs(dev)
if current is None:
init_fs(dev)
else:
if current != fs:
raise Exception(f"Existing filesystem does not match: {current}/{fs}")
def be_fs_expanded(dev, path):
dev = Path(dev).resolve()
fs = current_fs(dev)
path = Path(path).resolve()
if fs == "ext4":
run(f"resize2fs {dev}")
elif fs == "btrfs":
run(f"btrfs filesystem resize max {path}")
elif fs == "xfs":
run(f"xfs_growfs -d {dev}")
else:
raise Exception(f"Unsupported fsType: {fs}")