Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
diff sbin/ftjail @ 334:fdbb78c54ffb
Begin the "ftjail freebsd-update" command
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 02 Dec 2022 09:36:57 +0100 |
| parents | 8dbd11726ee5 |
| children | a423bc0e2a3f |
line wrap: on
line diff
--- a/sbin/ftjail Thu Dec 01 09:18:39 2022 +0100 +++ b/sbin/ftjail Fri Dec 02 09:36:57 2022 +0100 @@ -103,6 +103,90 @@ } +#: +#: Search for a running jail where it's "path" points to a given location +#: +#: Args: +#: $1: the location to search for +#: +#: Output (stdout): +#: The name if the jail with a "path" that is equal to the input param. +#: Nothing if a jail is not found. +#: +#: Return: +#: - 0: if a running jail is found +#: - 1: error +#: - 2: no running jail found +#: - 3: jail found but currently dying +#: +_get_jail_from_path() { + local _location + + local _name _path _dying + + _location="${1-}" + [ -z "${_location}" ] && { echo "ERROR: no mountpoint given" 1>&2; return 1; } + + + jls -d name path dying \ + | { + while IFS=' '$'\t' read -r _name _path _dying ; do + if [ "${_path}" = "${_location}" ]; then + if [ "${_dying}" != "false" ]; then + echo "Jail \`${_name}' is currently dying" 1>&2 + return 3 + fi + echo "${_name}" + return 0 + fi + done + return 2 + } +} + + +#: +#: Search for mounts and sub-mounts at a given directory. +#: +#: The output is sorted by the mountpoint. +#: +#: Args: +#: $1: the directory where to start for mounts and sub-mounts +#: +#: Output (stdout): +#: The sorted list (lines) of mounts in :manpage:`fstab(5)` format. +#: This list may be empty. +#: +#: Exit: +#: 1: on fatal errors (usage et al.) +#: +#: Important: +#: The input directory **must** be an absolute path. +#: +_get_mounts_at_directory() { + local _directory + + local _fstab + + _directory=${1-} + case "${_directory}" in + /*) + : + ;; + '') + echo "ERROR: no directory given" 1>&2; + exit 1; + ;; + *) + echo "ERROR: directory must be an absolute path" 1>&2; + exit 1; + ;; + esac + _fstab="$(mount -p | grep -E '\s'"${_directory}" | sort -k3)" + echo "${_fstab}" +} + + # # PARENT-BASE NAME DRY-RUN # @@ -787,6 +871,73 @@ } +#: +#: Implement the "freebsd-update" command for a thin jail +#: +command_freebsd_update() { + local _directory + + local _res _jailname _dir_mounts _dir_fn_fstab _dir_basename + local _root_dataset _root_mountpoint _root_type _root_options + local _dummy + local _root_readonly + + _directory="${1-}" + + [ -z "${_directory}" ] && { echo "ERROR: no directory given" 1>&2; return 2; } + [ -d "${_directory}" ] || { echo "ERROR: directory \`${_directory}' does not exist" 1>&2; exit 1; } + + _dir_basename="$(basename ${_directory})" + + set +e + _jailname=$(_get_jail_from_path "${_directory}")ยด + _res=$? + set -e + if [ ${_res} -ne 2 ] ; then + if [ ${_res} -ne 0 ] ; then + exit ${_res} + else + echo "ERROR: Please stop the \`${_jailname}' jail" >&2 + exit 1 + fi + fi + _dir_mounts="$(_get_mounts_at_directory "${_directory}")" + + # + # Check preconditions thoroughly! + # + # Check that the first item/line is a read-only ZFS mount directly + # at the given directory. + # Also check that it is a clone proper. + # + IFS=' '$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _dummy <<EOF4tHGCSS +${_dir_mounts} +EOF4tHGCSS + [ "${_root_mountpoint}" != "${_directory}" ] && { echo "ERROR: found root mountpoint does not match given directory" 1>&2; exit 1; } + [ "${_root_type}" != "zfs" ] && { echo "ERROR: root mountpoint is not from a ZFS dataset" 1>&2; exit 1; } + _root_readonly="$(zfs list -H -o readonly "${_root_dataset}")" + [ "${_root_readonly}" != "on" ] && { echo "ERROR: the root dataset is not mounted read-only" 1>&2; exit 1; } + # XXX TBD: Check that it is a proper clone + + # + # XXX FIXME: should we check that _root_options equals "ro" or + # start with "ro," + # + _dir_fn_fstab="$(env TMPDIR=/var/tmp mktemp -t ftjail-fstab.${_dir_basename})" + echo -n "${_dir_mounts}" >>"${_dir_fn_fstab}" + + # Unmount in reverse order: unmount can do it for us + umount -a -F "${_dir_fn_fstab}" -v || exit 1 + + # + # XXX TBD: Hooks to create some new top-level dirs (/srv /proc et + # al.) if needed: clone RW, mount, make the dirs, + # umount, make the clone RO and continue "normally" by + # completely mounting the stored fstab. + # +} + + # # Global option handling # @@ -851,6 +1002,9 @@ echo "ERROR: use \`fjail configure' instead" 1>&2; exit 2 ;; + freebsd-update) + command_freebsd_update "$@" + ;; *) echo "ERROR: unknown command \`${command}'" 1>&2 exit 2
