Add a script to automatically mount datasets.

This commit is contained in:
Tom Alexander 2022-11-01 22:42:46 -04:00
parent d7a8dd4d67
commit 683c264650
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 176 additions and 2 deletions

View File

@ -9,7 +9,7 @@
# - zsh
# - network
# - sshd
# - base
- base
# - firewall
# - cpu
# - ntp
@ -27,4 +27,4 @@
# - fuse
# - autofs
# - exfat
- bhyve
# - bhyve

View File

@ -0,0 +1,126 @@
#!/usr/local/bin/bash
#
# Mount non-boot-environment datasets.
#
# We can't leave datasets outside the boot environment (for example,
# jails or bhyve VMs) as canmount=on because then every boot
# environment's external datasets would all attempt to mount every
# time. To work around this, we mark those datasets as canmount=noauto
# and run this script to mount datasets under the root of our boot
# environment. This script depends heavily on my zfs dataset structure
# so it needs to be improved to be robust enough for different
# layouts. An example of my layout is:
#
## NAME MOUNTPOINT CANMOUNT TA:BEMOUNT
## zroot none off -
## zroot/global /global on -
## zroot/freebsd none on -
## zroot/freebsd/13.1-RELEASE none on -
## zroot/freebsd/13.1-RELEASE/be none on -
## zroot/freebsd/13.1-RELEASE/be/main / noauto -
## zroot/freebsd/13.1-RELEASE/jails none on -
## zroot/freebsd/13.1-RELEASE/jails/foo /jail/foo noauto on
## zroot/freebsd/13.1-RELEASE/jails/bar /jail/bar noauto on
## zroot/freebsd/13.1-RELEASE/jails/baz /jail/baz noauto on
## zroot/freebsd/13.1-RELEASE/vm-bhyve /vm noauto on
## zroot/linux none on -
## zroot/linux/arch none on -
## zroot/linux/arch/be none on -
## zroot/linux/arch/be/main / noauto -
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function main {
local all_zfs_datasets=$(zfs list -Hp -o 'name,mountpoint,canmount,ta:bemount,mounted')
local root_dataset=$(find_root_dataset "$all_zfs_datasets")
local datasets_to_mount=$(find_datasets_to_mount_for_boot_environment "$all_zfs_datasets" "$root_dataset")
if [ -n "$datasets_to_mount" ]; then
mount_datasets "$datasets_to_mount"
fi
}
function reverse_lines {
sed '1!x;H;1h;$!d;g'
}
function find_dataset {
local all_zfs_datasets="$1"
local dataset_name="$2"
while read dataset; do
local ds_name=$(awk '{print $1}'<<<"$dataset")
if [ "$ds_name" = "$dataset_name" ]; then
echo "$dataset"
return
fi
done<<<"$all_zfs_datasets"
}
function find_root_dataset {
local all_zfs_datasets="$1"
while read dataset; do
local ds_name=$(awk '{print $1}'<<<"$dataset")
local ds_mountpoint=$(awk '{print $2}'<<<"$dataset")
# local ds_canmount=$(awk '{print $3}'<<<"$dataset")
# local ds_bemount=$(awk '{print $4}'<<<"$dataset")
local ds_mounted=$(awk '{print $5}'<<<"$dataset")
if [ "$ds_mounted" = "yes" ] && [ "$ds_mountpoint" = "/" ]; then
echo "$ds_name"
return
fi
done<<<"$all_zfs_datasets"
}
function find_datasets_to_mount_for_boot_environment {
local all_zfs_datasets="$1"
local root_dataset="$2"
# This is a consequence of my layout for zfs datasets. I should
# make this more robust. Perhaps a zfs property like search up
# from dataset mounted at / until you find a dataset with property
# ta:bemountroot="on"?
local be_root_name="${root_dataset%/*/*}"
local be_root_dataset=$(find_dataset "$all_zfs_datasets" "$be_root_name")
while read dataset; do
local ds_name=$(awk '{print $1}'<<<"$dataset")
# local ds_mountpoint=$(awk '{print $2}'<<<"$dataset")
local ds_canmount=$(awk '{print $3}'<<<"$dataset")
local ds_bemount=$(awk '{print $4}'<<<"$dataset")
local ds_mounted=$(awk '{print $5}'<<<"$dataset")
case "$ds_name" in
"${be_root_name}/"*) ;;
*) continue ;;
esac
if [ "$ds_bemount" != "on" ]; then
continue
fi
if [ "$ds_mounted" != "no" ]; then
continue
fi
if [ "$ds_canmount" != "noauto" ]; then
continue
fi
echo "$dataset"
done<<<"$all_zfs_datasets"
}
function mount_datasets {
local datasets_to_mount=$(reverse_lines<<<"$1")
while read dataset; do
local ds_name=$(awk '{print $1}'<<<"$dataset")
local ds_mountpoint=$(awk '{print $2}'<<<"$dataset")
local ds_canmount=$(awk '{print $3}'<<<"$dataset")
local ds_bemount=$(awk '{print $4}'<<<"$dataset")
local ds_mounted=$(awk '{print $5}'<<<"$dataset")
mount -v -t zfs "$ds_name" "$ds_mountpoint"
done<<<"$datasets_to_mount"
}
main

View File

@ -0,0 +1,20 @@
#!/bin/sh
#
# REQUIRE: FILESYSTEM kld
# PROVIDE: bemount
. /etc/rc.subr
name=bemount
rcvar=${name}_enable
start_cmd="${name}_start"
stop_cmd="${name}_stop"
load_rc_config $name
bemount_start() {
/usr/local/bin/bemount
}
bemount_stop() {
}
run_rc_command "$1"

View File

@ -94,3 +94,31 @@
src: tmpfs
fstype: tmpfs
opts: rw,mode=777
- name: Install scripts
copy:
src: "files/{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0755
owner: root
group: wheel
loop:
- src: bemount.bash
dest: /usr/local/bin/bemount
- name: Install rc script
copy:
src: "files/{{ item.src }}"
dest: "/usr/local/etc/rc.d/{{ item.dest|default(item.src) }}"
owner: root
group: wheel
mode: 0755
loop:
- src: bemount_rc.sh
dest: bemount
- name: Enable bemount
community.general.sysrc:
name: bemount_enable
value: "YES"
path: /etc/rc.conf.d/bemount