Files
fs-scripts/zfs/zfs-media-drive.sh

192 lines
5.1 KiB
Bash

#!/bin/bash
set -euo pipefail
SCRIPT_ROOT=$(dirname "$0")
# @TODO: Implement more soft-coding and interactivity to this script
ZFS_POOL_NAME="medialib"
ZFS_COMPAT="openzfs-2.1-linux"
ZFS_KEY_LOC="file:///etc/zfs/keys/zroot.key"
ZFS_KEY_FORMAT="passphrase"
ZFS_COMPRESSION="zstd-3"
create_zpool () {
sudo zpool create \
-o ashift=12 \
-o autotrim=on \
-o compatibility="$3" \
-O encryption=on \
-O keylocation="$4" \
-O keyformat="$5" \
-O acltype=posixacl \
-O xattr=sa \
-O dnodesize=auto \
-O compression="$6" \
-O normalization=formD \
-O relatime=on \
-O canmount=off \
-O mountpoint=none \
"$2" \
/dev/disk/by-id/"${1}"
}
mkdataset () {
mkdir -p "$1"
sudo zfs create -v -o mountpoint="$1" "$2"
}
create_datasets () {
read -r -p "Provide custom datasets? (y/n): " CUSTOMIZE_DATASETS
if [[ "$CUSTOMIZE_DATASETS" =~ [Nn]* ]]; then
DATASET=("${HOME}/Documents/.calibre" "${1}/LITERATURE")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
DATASET=("${HOME}/Videos" "${1}/FILM")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
DATASET=("${HOME}/.var/app/com.valvesoftware.Steam" "${1}/STEAMGAMES")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
DATASET=("${HOME}/.var/app/org.libretro.RetroArch" "${1}/RARCHGAMES")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
DATASET=("${HOME}/Games" "${1}/GAMES")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
ln -s "${HOME}/.var/app/com.valvesoftware.Steam" "${DATASET[0]}/Steam"
ln -s "${HOME}/.var/app/org.libretro.RetroArch" "${DATASET[0]}/libRetro"
DATASET=("${HOME}/.var/app/org.libretro.RetroArch" "${1}/RARCHGAMES")
mkdataset "${DATASET[0]}" "${DATASET[1]}"
DATASET=("${HOME}/.XXX" "${1}/XXX")
mkdir -p "${DATASET[0]}"
sudo zfs create -o keylocation=prompt -o keyformat=passphrase -o mountpoint="${DATASET[0]}" "${DATASET[1]}"
elif [[ "$CUSTOMIZE_DATASETS" =~ [Yy]* ]]; then
while true; do
read -r -a DATASET -p "Define a mount path and its corresponding dataset name or route, in that order: "
if [ ${#DATASET[@]} -eq 2 ]; then
mkdataset "${DATASET[0]}" "${1}"/"${DATASET[1]}"
read -r -p "Create another ZFS dataset? (y/n): " ANOTHER_DATASET
if [[ "$ANOTHER_DATASET" =~ [Yy]* ]]; then
continue
elif [[ "$ANOTHER_DATASET" =~ [Nn]* ]]; then
break
fi
else
printf "Error: must provide 2 arguments (i.e., mount path and dataset name or route)."
read -r -p "Try again? (y/n): " RETRY_PROMPT
if [[ "$RETRY_PROMPT" =~ [Yy]* ]]; then
continue
elif [[ "$RETRY_PROMPT" =~ [Nn]* ]]; then
break
fi
fi
done
else
exit 1
fi
}
print_menu () {
printf "%s" "$(<"${SCRIPT_ROOT}"/zfs-media-drive.help)"
}
if [ -z "$1" ]; then
printf "Subcommand must be provided"
exit 1
fi
if [ -n "$1" ] && [ "$1" == "init" ]; then
shift
while getopts "d:p:k:f:c:v:" opt; do
case $opt in
k) ZFS_KEY_LOC="${OPTARG}";;
f) ZFS_KEY_FORMAT="${OPTARG}";;
c) ZFS_COMPRESSION="${OPTARG}";;
v) ZFS_COMPAT="${OPTARG}";;
p) ZFS_POOL_NAME="${OPTARG}";;
d) ZFS_TARGET_DRIVE="${OPTARG}";;
*) exit 1;
esac
done
if [ -z "$ZFS_TARGET_DRIVE" ]; then
printf "Error: It is necessary to argue a -d option."
exit 1
fi
export ZFS_POOL_NAME
create_zpool "$ZFS_TARGET_DRIVE" "$ZFS_POOL_NAME" "$ZFS_COMPAT" "$ZFS_KEY_LOC" "$ZFS_KEY_FORMAT" "$ZFS_COMPRESSION"
printf "Following pool has been created: \n"
zpool list -v | grep "$ZFS_POOL_NAME"
create_datasets "$ZFS_POOL_NAME"
printf "Following datasets have been created: \n"
zfs list | grep "$ZFS_POOL_NAME"
elif [ -n "$1" ] && [ "$1" == "enc" ]; then
while true; do
read -r -a DATASET -p "Define a mount path and its corresponding dataset name or route, in that order: "
if [ ${#DATASET[@]} -eq 2 ]; then
mkdir -p "${DATASET[0]}"
sudo zfs create -v -o keylocation=prompt -o keyformat=passphrase -o mountpoint="${DATASET[0]}" "${ZFS_POOL_NAME}"/"${DATASET[1]}"
read -r -p "Create another ZFS dataset? (y/n): " ANOTHER_DATASET
if [[ "$ANOTHER_DATASET" =~ [Yy]* ]]; then
continue
elif [[ "$ANOTHER_DATASET" =~ [Nn]* ]]; then
break
fi
else
printf "Error: must provide 2 arguments (i.e., mount path and dataset name or route)."
read -r -p "Try again? (y/n): " RETRY_PROMPT
if [[ "$RETRY_PROMPT" =~ [Yy]* ]]; then
continue
elif [[ "$RETRY_PROMPT" =~ [Nn]* ]]; then
break
fi
fi
done
elif [ -n "$1" ] && [ "$1" == "link" ]; then
while true; do
read -r -a LINKAGE -p "Define a symbolic link source path and destination dataset: "
if [ ${#LINKAGE[@]} -eq 2 ]; then
if ! [ -d "${LINKAGE[0]}" ]; then
mkdir -p "${LINKAGE[0]}"
fi
ln -s "${LINKAGE[0]}" "${ZFS_POOL_NAME}"/"${LINKAGE[1]}"
read -r -p "Create another symbolic link? (y/n): " ANOTHER_LINKAGE
if [[ "$ANOTHER_LINKAGE" =~ [Yy]* ]]; then
continue
elif [[ "$ANOTHER_LINKAGE" =~ [Nn]* ]]; then
break
fi
else
printf "Error: must provide 2 arguments (i.e., source path and destination path)."
read -r -p "Try again? (y/n): " RETRY_PROMPT
if [[ "$RETRY_PROMPT" =~ [Yy]* ]]; then
continue
elif [[ "$RETRY_PROMPT" =~ [Nn]* ]]; then
break
fi
fi
done
else
while getopts "h" flag; do
case "$flag" in
h) print_menu;;
*) exit 1;;
esac
done
fi