Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
changeset 658:260a81d769a6
Implemented "ftjail check-freebsd-update": thorough check for preconditions to a successful run of "ftjail freebsd-update".
All checks that "ftjail freebsd-update" does are replicated in
"ftjail check-freebsd-update".
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 28 Sep 2024 19:12:05 +0200 |
| parents | db22766df6a4 |
| children | 25de0d27e407 |
| files | docs/conf.py docs/man/index.rst docs/man/man8/ftjail-check-freebsd-update.rst docs/man/man8/ftjail-freebsd-update.rst docs/man/man8/ftjail.rst docs/man/man8/local-bsdtools.rst pkg-plist sbin/ftjail |
| diffstat | 8 files changed, 265 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/conf.py Sat Sep 28 14:55:57 2024 +0200 +++ b/docs/conf.py Sat Sep 28 19:12:05 2024 +0200 @@ -94,6 +94,7 @@ ("man/man8/fpkg", "fpkg", "A frontend for some pkg(8) commands that also operate on running jails", [author], 8), ("man/man8/ftjail", "ftjail", "Management of Thin Jails", [author], 8), ("man/man8/ftjail-build-etcupdate-current-tmpl", "ftjail-build-etcupdate-current-tmpl", "Build a \"current\" tree suitable for the default and extract mode of \"etcupdate\"", [author], 8), + ("man/man8/ftjail-check-freebsd-update", "ftjail-check-freebsd-update", "Check preconditions to run freebsd-update for a Thin Jail successfully", [author], 8), ("man/man8/ftjail-copy-skel", "ftjail-copy-skel", "Recursively copy skeleton contents from the template tree into a jail-specific ZFS datasets", [author], 8), ("man/man8/ftjail-datasets-tmpl", "ftjail-datasets-tmpl", "Create ZFS datasets for new Thin Jails using base and skeleton", [author], 8), ("man/man8/ftjail-freebsd-update", "ftjail-freebsd-update", "A freebsd-update implementation for a Thin Jail", [author], 8),
--- a/docs/man/index.rst Sat Sep 28 14:55:57 2024 +0200 +++ b/docs/man/index.rst Sat Sep 28 19:12:05 2024 +0200 @@ -20,6 +20,7 @@ man8/fwireguard man8/ftjail man8/ftjail-build-etcupdate-current-tmpl + man8/ftjail-check-freebsd-update man8/ftjail-copy-skel man8/ftjail-datasets-tmpl man8/ftjail-freebsd-update
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/man/man8/ftjail-check-freebsd-update.rst Sat Sep 28 19:12:05 2024 +0200 @@ -0,0 +1,63 @@ +.. -*- coding: utf-8; indent-tabs-mode: nil; -*- + +ftjail-check-freebsd-update +=========================== + +.. program:: ftjail freebsd-update + + +Synopsis +-------- + +**ftjail check-freebsd-update** [**-k**] [**-o** `old-origin`] `directory` `new-origin` [`etcupdate-tarball`] + + +Description +----------- + +A thorough check for preconditions to run :manpage:`ftjail-freebsd-update(8)` +for a Thin Jail successfully. + +It does all checks that :manpage:`ftjail-freebsd-update(8)` does but +tries to collect all errors. + +It is intended that a successful run of :command:`ftjail check-freebsd-update` +implies a successful run of :command:`ftjail freebsd-update` if the same +arguments are given. + + +Options +------- + +.. option:: -k + + Does nothing. + Implemented for compatibility to :manpage:`ftjail-freebsd-update(8)`. + +.. option:: -o <old-origin> + + In addition to check that `directory` is a ZFS clone also check that + its origin is equal to `old-origin`. + + Note that a check that `directory` is a ZFS clone with some origin + is done by default. + + +Environment +----------- + +All environment variables that affect :command:`zfs` are effective also. + + +Files +----- + +A unique temporary directory is created within :file:`/var/tmp`. All +temporary files are created within this directory. + + +See Also +-------- + +:manpage:`ftjail(8)`, :manpage:`ftjail-freebsd-update(8)`, +:manpage:`freebsd-update(8)`, :manpage:`etcupdate(8)`
--- a/docs/man/man8/ftjail-freebsd-update.rst Sat Sep 28 14:55:57 2024 +0200 +++ b/docs/man/man8/ftjail-freebsd-update.rst Sat Sep 28 19:12:05 2024 +0200 @@ -20,6 +20,9 @@ the fully re-mounted directory tree that is rooted at `directory` using `etcupdate-tarball` as the new "current". +See also :manpage:`ftjail-check-freebsd-update(8)` for a tool that +tries to thoroughly check the preconditions to run this tool successfully. + Options ------- @@ -57,4 +60,5 @@ See Also -------- -:manpage:`ftjail(8)`, :manpage:`freebsd-update(8)`, :manpage:`etcupdate(8)` +:manpage:`ftjail(8)`, :manpage:`ftjail-check-freebsd-update(8)`, +:manpage:`freebsd-update(8)`, :manpage:`etcupdate(8)`
--- a/docs/man/man8/ftjail.rst Sat Sep 28 14:55:57 2024 +0200 +++ b/docs/man/man8/ftjail.rst Sat Sep 28 19:12:05 2024 +0200 @@ -38,6 +38,11 @@ Build a "current" tree suitable for the default and extract mode of \"etcupdate\" +:manpage:`ftjail-check-freebsd-update(8)` + + Check for preconditions to run :manpage:`ftjail-freebsd-update(8)` + for a Thin Jail successfully + :manpage:`ftjail-copy-skel(8)` Recursively copy template skeleton contents into jail-specific datasets
--- a/docs/man/man8/local-bsdtools.rst Sat Sep 28 14:55:57 2024 +0200 +++ b/docs/man/man8/local-bsdtools.rst Sat Sep 28 19:12:05 2024 +0200 @@ -55,6 +55,7 @@ - :manpage:`ftjail(8)` * :manpage:`ftjail-build-etcupdate-current-tmpl(8)` + * :manpage:`ftjail-check-freebsd-update(8)` * :manpage:`ftjail-copy-skel(8)` * :manpage:`ftjail-datasets-tmpl(8)` * :manpage:`ftjail-freebsd-update(8)`
--- a/pkg-plist Sat Sep 28 14:55:57 2024 +0200 +++ b/pkg-plist Sat Sep 28 19:12:05 2024 +0200 @@ -27,6 +27,7 @@ %%DOCS%%share/man/man8/fpkg.8.gz %%DOCS%%share/man/man8/ftjail.8.gz %%DOCS%%share/man/man8/ftjail-build-etcupdate-current-tmpl.8.gz +%%DOCS%%share/man/man8/ftjail-check-freebsd-update.8.gz %%DOCS%%share/man/man8/ftjail-copy-skel.8.gz %%DOCS%%share/man/man8/ftjail-datasets-tmpl.8.gz %%DOCS%%share/man/man8/ftjail-freebsd-update.8.gz
--- a/sbin/ftjail Sat Sep 28 14:55:57 2024 +0200 +++ b/sbin/ftjail Sat Sep 28 19:12:05 2024 +0200 @@ -61,6 +61,7 @@ _p_datadir='@@DATADIR@@' [ "${_p_datadir#@@DATADIR}" = '@@' ] && _p_datadir="$(dirname "$0")"/../share/local-bsdtools . "${_p_datadir}/common.subr" +. "${_p_datadir}/farray.sh" # Reset to standard umask @@ -858,6 +859,189 @@ #: +#: Callback for _print_check_errors +#: +_print_check_error() { + printf '%s CHECK: %s\n' '-' "$3" 1>&2 + return 0 +} + + +#: +#: Print all the errors to stderr +#: +_print_check_errors() { + farray_istrue "$1" || return 0 + echo "There are ERRORs to be resolved before \`freebsd-update' can be run:" 1>&2 + farray_for_each "$1" _print_check_error +} + + +#: +#: Callback for _print_check_warnings +#: +_print_check_warning() { + printf '%s WARNING: %s\n' '-' "$3" 1>&2 + return 0 +} + + +#: +#: Print all the warnings to stderr +#: +_print_check_warnings() { + farray_istrue "$1" || return 0 + echo "There are WARNINGs to be considered before \`freebsd-update' should be run:" 1>&2 + farray_for_each "$1" _print_check_warning +} + + +#: +#: Implement the "check-freebsd-update" command for a thin jail +#: +command_check_freebsd_update() { + local _directory _new_origin _etcupdate_tarball + local _opt_keep _opt_old_origin + + local _errors _warnings _rc + local _directory _new_origin _etcupdate_tarball + local _dir_basename _dir_mounts _jailname _tmp _line _log_sock + local _root_dataset _root_mountpoint _root_type _root_options + local _mnt_device _mnt_mountpoint _mnt_type _mnt_options + + _rc=0 + + _warnings='' + farray_create _warnings XXX + _errors='' + farray_create _errors + + _opt_keep="no" + _opt_old_origin="" + while getopts "ko:" _opt ; do + case "${_opt}" in + k) + _opt_keep="yes" + ;; + o) + _opt_old_origin="$OPTARG" + ;; + \?|:) + return 2; + ;; + esac + done + shift $((OPTIND-1)) + OPTIND=1 + + _directory="${1-}" + _new_origin="${2-}" + _etcupdate_tarball="${3-}" + + if [ -z "${_directory}" ]; then + farray_append _errors "no directory given" + else + [ -d "${_directory}" ] || farray_append _errors "directory \`${_directory}' does not exist" + fi + if [ -z "${_new_origin}" ]; then + farray_append _errors "no new origin given" + else + zfs list -H -o name -t snapshot "${_new_origin}" >/dev/null 2>/dev/null || farray_append _errors "ZFS dataset snapshot for the new origin \`${_new_origin}' does not exist" + fi + if [ -n "${_etcupdate_tarball}" ]; then + [ -r "${_etcupdate_tarball}" ] || farray_append _errors "given etcupdate tarball does not exist and/or is not readable" + fi + + if [ -n "${_directory}" ]; then + + _dir_basename="$(basename "${_directory}")" + + set +e + _jailname="$(_get_jail_from_path "${_directory}")" + _tmp=$? + set -e + case ${_tmp} in + 0) + farray_append _errors "Jail \`${_jailname}' is running. Please stop it." + ;; + 1) + farray_append _errors "Cannot determine jail name" + ;; + 3) + true + ;; + 2) + farray_append _errors "Jail \`${_jailname}' is currently yet dying. Please wait." + ;; + *) + farray_append _errors "UNHANDLED RETURN VALUE from _get_jail_from_path()" + ;; + esac + + # + # Check whether additional log sockets are opened at their default + # locations. Because they hinder proper unmounting of filesystems. + # + for _log_sock in /var/run/log /var/run/logpriv ; do + if [ -S "${_directory}${_log_sock}" ]; then + farray_append _errors "log socket is open at \`${_directory}${_log_sock}'" + fi + done + + # Check whether there are any open files or VM mappings within the jail. + if ! _check_no_open_files_from_all_proc "${_directory}" ; then + farray_append _errors "There are open files or memory mappings within the jail" + 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. This must also be its configured + # mountpoint in ZFS. + # Also check that it is a clone proper. + # + IFS=$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _line <<EOF4tHGCSSf5d7d9cf +${_dir_mounts} +EOF4tHGCSSf5d7d9cf + [ "${_root_mountpoint}" != "${_directory}" ] && farray_append _errors "found root mountpoint does not match given directory" + [ "${_root_type}" != "zfs" ] && farray_append _errors "root mountpoint is not from a ZFS dataset" + _root_readonly="$(zfs get -H -o value readonly "${_root_dataset}")" + [ "${_root_readonly}" != "on" ] && farray_append _errors "the root dataset is not mounted read-only" + _root_origin="$(zfs get -H -o value origin "${_root_dataset}")" + if [ -n "${_opt_old_origin}" ]; then + [ "${_opt_old_origin}" != "${_root_origin}" ] && farray_append _errors "origin mismatch" + else + [ "${_root_origin}" = '-' ] && farray_append _errors "the root dataset is not a ZFS clone" + fi + # + # Check for open files on all the mounted filesystems + # + while IFS=$'\t' read -r _mnt_device _mnt_mountpoint _mnt_type _mnt_options _line; do + if ! _check_no_open_files_on_filesystem "${_mnt_mountpoint}" ; then + farray_append _errors "There are open files or memory mapping on file system \`${_mnt_mountpoint}'" + fi + done <<EOF4tHGCAASL775f9f320205 +${_dir_mounts} +EOF4tHGCAASL775f9f320205 + fi + + if farray_istrue _errors; then + _print_check_errors _errors + _rc=1 + fi + # Warnings do not influence the return code + _print_check_warnings _warnings + + farray_destroy _errors + farray_destroy _warnings + return ${_rc} +} + + +#: #: Implement the "freebsd-update" command for a thin jail #: #: .. note:: FreeBSD's :command:`etcupdate` also executes @@ -1160,11 +1344,13 @@ echo "ERROR: use \`fjail configure' instead" 1>&2; exit 2 ;; + check-freebsd-update) + command_check_freebsd_update "$@" + ;; freebsd-update) command_freebsd_update "$@" ;; *) - echo "ERROR: unknown command \`${command}'" 1>&2 - exit 2 + fatal 2 "unknown command \`${command}'" ;; esac
