Skip to content

Instantly share code, notes, and snippets.

@GRArmstrong
Created March 15, 2021 21:56
Show Gist options
  • Save GRArmstrong/8b8a0df0da6024d7d5beb1c12b7e023b to your computer and use it in GitHub Desktop.
Save GRArmstrong/8b8a0df0da6024d7d5beb1c12b7e023b to your computer and use it in GitHub Desktop.
Generates fstab entries for a FreeBSD/TrueNAS jail of all available ZFS datasets (excluding 'boot-pool', '.system', and live 'iocage') so that a backup program in a jail (e.g. duplicati) can access the data and back it all up.
#!/usr/local/bin/python
"""
make_backup_fstab.py
2021-03-15 by Graham R. Armstrong
Generates fstab entries for a FreeBSD/TrueNAS jail of all available ZFS
datasets (excluding 'boot-pool', '.system', and live 'iocage') so that
a backup program in a jail (e.g. duplicati) can access the data and back
it all up.
"""
import subprocess
OUTPUT_FILE = "fstab-append.txt"
PATH_TO_JAIL_ROOT = "/mnt/pool0/iocage/jails/duplicati-backup/root"
def include_dataset(dataset):
parts = dataset.split('/')
if len(parts) == 1:
return False
if parts[0] == "boot-pool":
return False
if parts[1] in ["iocage", ".system"]:
return False
return True
def main():
# Step 1: Get a list of datasets and mountpoints
pargs = ("zfs", "list", "-t", "filesystem", "-o", "name,mountpoint", "-rH")
process = subprocess.Popen(pargs,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
# Jump ship if stderr has errors
if stderr:
raise Exception(stderr.decode("utf-8"))
# Step 2: Parse output into a list of tuples
lines = stdout.decode("utf-8").strip().split('\n')
dataset_mounts = [line.split("\t") for line in lines]
# Step 3: Filter out datasets we don't need, store mounts for ones we do
mounts = []
for dataset, mount in dataset_mounts:
if mount in ["legacy", "/", "none"]:
continue
if include_dataset(dataset):
mounts.append(mount)
# Step 4: Prepend the jail prefix to create the mounts
fstab_lines = []
for mount in mounts:
mount_point = PATH_TO_JAIL_ROOT + mount
line = (mount, mount_point, "nullfs", "ro", "0", "0")
fstab_lines.append('\t'.join(line))
# Step 5: Write it to file
with open(OUTPUT_FILE, "w") as handle:
for line in fstab_lines:
handle.write(line + "\n")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment