# HG changeset patch # User Franz Glasner # Date 1727618699 -7200 # Node ID 82a98db83a13d7485c0c74cd473025dc7fe80054 # Parent 25de0d27e4070e57374d4ceea82d95a84b1a5fbe ftjail: Implement a "-R" option for "ftjail freebsd-update" and "ftjail check-freebsd-update". This option creates/checks ZFS checkpoints that should be taken before really do some unmounts and calling freebsd-update for a thin jail. diff -r 25de0d27e407 -r 82a98db83a13 docs/man/man8/ftjail-check-freebsd-update.rst --- a/docs/man/man8/ftjail-check-freebsd-update.rst Sun Sep 29 12:18:02 2024 +0200 +++ b/docs/man/man8/ftjail-check-freebsd-update.rst Sun Sep 29 16:04:59 2024 +0200 @@ -9,7 +9,7 @@ Synopsis -------- -**ftjail check-freebsd-update** [**-k**] [**-o** `old-origin`] `directory` `new-origin` [`etcupdate-tarball`] +**ftjail check-freebsd-update** [**-k**] [**-o** `old-origin`] [[**-R** `dataset@snapname`]...] `directory` `new-origin` [`etcupdate-tarball`] Description @@ -29,6 +29,18 @@ Options ------- +.. option:: -R + + Check that the creation of ZFS snapshots for `dataset` and all its children + will succeed: + + The existence if `dataset` will be prooved. + + The snapshots may not exist already; this is prooved for `dataset` + and all its children. + + Can be given more than once. + .. option:: -k Does nothing. diff -r 25de0d27e407 -r 82a98db83a13 docs/man/man8/ftjail-freebsd-update.rst --- a/docs/man/man8/ftjail-freebsd-update.rst Sun Sep 29 12:18:02 2024 +0200 +++ b/docs/man/man8/ftjail-freebsd-update.rst Sun Sep 29 16:04:59 2024 +0200 @@ -3,10 +3,13 @@ ftjail-freebsd-update ===================== +.. program:: ftjail freebsd-update + + Synopsis -------- -**ftjail freebsd-update** [**-k**] [**-o** `old-origin`] `directory` `new-origin` [`etcupdate-tarball`] +**ftjail freebsd-update** [**-k**] [**-o** `old-origin`] [[**-R** `dataset@snapname`]...] `directory` `new-origin` [`etcupdate-tarball`] Description @@ -27,7 +30,14 @@ Options ------- -.. program:: ftjail freebsd-update +.. option:: -R + + Create ZFS snapshots for `dataset` and all its children before + updating. + + The snapshots may not exist already. + + Can be given more than once. .. option:: -k diff -r 25de0d27e407 -r 82a98db83a13 sbin/ftjail --- a/sbin/ftjail Sun Sep 29 12:18:02 2024 +0200 +++ b/sbin/ftjail Sun Sep 29 16:04:59 2024 +0200 @@ -45,7 +45,9 @@ build-etcupdate-current-tmpl DIRECTORY TARBALL - freebsd-update [-k] [-o OLD-ORIGIN] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] + check-freebsd-update [-k] [-o OLD-ORIGIN] [-R SNAPSHOT] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] + + freebsd-update [-k] [-o OLD-ORIGIN] [-R SNAPSHOT] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] ENVIRONMENT: @@ -901,30 +903,47 @@ #: command_check_freebsd_update() { local _directory _new_origin _etcupdate_tarball - local _opt_keep _opt_old_origin + local _opt_keep _opt_old_origin _opt_snapshots 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 + local _idx _sn_ds _sn_name _sn_ds_related _rc=0 _warnings='' - farray_create _warnings XXX + farray_create _warnings _errors='' farray_create _errors + _opt_snapshots='' + falist_create _opt_snapshots _opt_keep="no" _opt_old_origin="" - while getopts "ko:" _opt ; do + while getopts "R:ko:" _opt ; do case "${_opt}" in + R) + case "${OPTARG}" in + *?\@?*) + # + # Split in two parts: dataset hierarchy and the name of the + # snapshot + # + falist_set _opt_snapshots "${OPTARG%%@*}" "${OPTARG#*@}" + ;; + *) + farray_append _errors "argument \`${OPTARG}' is not a snapshot name" + ;; + esac + ;; k) _opt_keep="yes" ;; o) - _opt_old_origin="$OPTARG" + _opt_old_origin="${OPTARG}" ;; \?|:) return 2; @@ -952,6 +971,24 @@ [ -r "${_etcupdate_tarball}" ] || farray_append _errors "given etcupdate tarball does not exist and/or is not readable" fi + # Check snapshotting + _idx=1 + while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do + if zfs get -H -o value name "${_sn_ds}" >/dev/null 2>/dev/null; then + # yes dataset exists: check that snapshots do not exist + while IFS=$'\t' read -r _line; do + if zfs get -H -o value name "${_line}@${_sn_name}" >/dev/null 2>/dev/null; then + farray_append _errors "snapshot \`${_line}@${_sn_name}' already exists" + fi + done <&2; return 1; } fi + # Check snapshotting + _idx=1 + while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do + if zfs get -H -o value name "${_sn_ds}" >/dev/null 2>/dev/null; then + # yes dataset exists: check that snapshots do not exist + while IFS=$'\t' read -r _line; do + if zfs get -H -o value name "${_line}@${_sn_name}" >/dev/null 2>/dev/null; then + err "snapshot \`${_line}@${_sn_name}' already exists" + return 1 + fi + done </dev/null | LC_ALL=C /usr/bin/sort >>"${_dir_fn_tldir}" + _idx=1 + while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do + echo "Creating snapshot \`${_sn_ds}@${_sn_name}'" + zfs snapshot -r "${_sn_ds}@${_sn_name}" || { err "cannot snapshot \`${_sn_ds}@${_sn_name}'"; return 1; } + _idx=$((_idx + 1)) + done + # Unmount in reverse order: unmount can do it for us echo "Unmounting all datasets mounted at \`${_directory}'" /sbin/umount -a -F "${_dir_fn_fstab2}" -v @@ -1277,6 +1382,8 @@ [ -n "${_u_tmpdir}" ] && [ -d "${_u_tmpdir}" ] && rm -rvf "${_u_tmpdir}" fi echo "Done." + + falist_destroy _opt_snapshots } diff -r 25de0d27e407 -r 82a98db83a13 share/examples/local-bsdtools/freebsd-update-ftjail.sh --- a/share/examples/local-bsdtools/freebsd-update-ftjail.sh Sun Sep 29 12:18:02 2024 +0200 +++ b/share/examples/local-bsdtools/freebsd-update-ftjail.sh Sun Sep 29 16:04:59 2024 +0200 @@ -22,6 +22,8 @@ BASE_DIR="/jail/TROOT" +ftjail check-freebsd-update -R "${SNAPSHOT_ROOT}/${JAIL_NAME}@${SNAPSHOT_NAME}" -o "${OLD_BASE_RO}" "${BASE_DIR}/${JAIL_NAME}" "${NEW_BASE_RO}" "${NEW_ETCUPDATE}" || exit 1 + case "${JAIL_NAME}" in ftp) zfs umount dpool/data/ftp/home-data @@ -34,9 +36,10 @@ ;; esac -zfs snapshot -r "${SNAPSHOT_ROOT}/${JAIL_NAME}@${SNAPSHOT_NAME}" +# Is now requested with option -R +# zfs snapshot -r "${SNAPSHOT_ROOT}/${JAIL_NAME}@${SNAPSHOT_NAME}" -ftjail freebsd-update -o "${OLD_BASE_RO}" "${BASE_DIR}/${JAIL_NAME}" "${NEW_BASE_RO}" "${NEW_ETCUPDATE}" +ftjail freebsd-update -R "${SNAPSHOT_ROOT}/${JAIL_NAME}@${SNAPSHOT_NAME}" -o "${OLD_BASE_RO}" "${BASE_DIR}/${JAIL_NAME}" "${NEW_BASE_RO}" "${NEW_ETCUPDATE}" case "${JAIL_NAME}" in ftp)