Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
changeset 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 | ebf6c8863d9b |
| children | ed0975c76386 |
| files | docs/conf.py docs/man/index8.rst docs/man/man8/ftjail-freebsd-update.rst docs/man/man8/ftjail.rst pkg-plist sbin/ftjail |
| diffstat | 6 files changed, 194 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/conf.py Thu Dec 01 09:18:39 2022 +0100 +++ b/docs/conf.py Fri Dec 02 09:36:57 2022 +0100 @@ -87,6 +87,7 @@ ("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-copy-skel", "ftjail-copy-skel", "Recursively copy skeleton contents", [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), ("man/man8/ftjail-interlink-tmpl", "ftjail-interlink-tmpl", "Create proper symlinks for \"skeleton\" style Thin Jails", [author], 8), ("man/man8/ftjail-mount-tmpl", "ftjail-mount-tmpl", "Canonically mount the RO base and the RW skeleton of a Thin Jail", [author], 8), ("man/man8/ftjail-populate-tmpl", "ftjail-populate-tmpl", "Populate a prepared directory structure with the contents of a FreeBSD base system", [author], 8),
--- a/docs/man/index8.rst Thu Dec 01 09:18:39 2022 +0100 +++ b/docs/man/index8.rst Fri Dec 02 09:36:57 2022 +0100 @@ -18,6 +18,7 @@ man8/ftjail-build-etcupdate-current-tmpl man8/ftjail-copy-skel man8/ftjail-datasets-tmpl + man8/ftjail-freebsd-update man8/ftjail-interlink-tmpl man8/ftjail-mount-tmpl man8/ftjail-populate-tmpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/man/man8/ftjail-freebsd-update.rst Fri Dec 02 09:36:57 2022 +0100 @@ -0,0 +1,33 @@ +.. -*- coding: utf-8; indent-tabs-mode: nil; -*- + +ftjail-freebsd-update +===================== + +Synopsis +-------- + +**ftjail freebsd-update** `directory` + + +Description +----------- + +A :manpage:`freebsd-update(8)` for a Thin Jail. + + +Options +------- + +.. program:: ftjail freebsd-update + + +Environment +----------- + +All environment variables that affect :command:`zfs` are effective also. + + +See Also +-------- + +:manpage:`ftjail(8)`, :manpage:`freebsd-update(8)`, :manpage:`etcupdate(8)`
--- a/docs/man/man8/ftjail.rst Thu Dec 01 09:18:39 2022 +0100 +++ b/docs/man/man8/ftjail.rst Fri Dec 02 09:36:57 2022 +0100 @@ -42,6 +42,10 @@ Create ZFS template datasets for new Thin Jails using base and skeleton +:manpage:`ftjail-freebsd-update(8)` + + A :manpage:`freebsd-update(8)` implementation for Thin Jails + :manpage:`ftjail-mount-tmpl(8)` Canonically mount the RO base and the RW skeleton of a Thin Jail
--- a/pkg-plist Thu Dec 01 09:18:39 2022 +0100 +++ b/pkg-plist Fri Dec 02 09:36:57 2022 +0100 @@ -16,6 +16,7 @@ %%DOCS%%man/man8/ftjail-build-etcupdate-current-tmpl.8.gz %%DOCS%%man/man8/ftjail-copy-skel.8.gz %%DOCS%%man/man8/ftjail-datasets-tmpl.8.gz +%%DOCS%%man/man8/ftjail-freebsd-update.8.gz %%DOCS%%man/man8/ftjail-interlink-tmpl.8.gz %%DOCS%%man/man8/ftjail-mount-tmpl.8.gz %%DOCS%%man/man8/ftjail-populate-tmpl.8.gz
--- 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
