Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
changeset 660:82a98db83a13
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.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sun, 29 Sep 2024 16:04:59 +0200 |
| parents | 25de0d27e407 |
| children | 1e6c86f0a850 |
| files | docs/man/man8/ftjail-check-freebsd-update.rst docs/man/man8/ftjail-freebsd-update.rst sbin/ftjail share/examples/local-bsdtools/freebsd-update-ftjail.sh |
| diffstat | 4 files changed, 146 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- 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 <dataset@snapname> + + 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.
--- 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 <dataset@snapname> + + 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
--- 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 <<EOF2988ee715b2d93fd93bdce23 +$(zfs list -H -r -o name "${_sn_ds}") +EOF2988ee715b2d93fd93bdce23 + else + farray_append _errors "dataset for snapshots \`${_sn_ds}' does not exist" + fi + _idx=$((_idx + 1)) + done + if [ -n "${_directory}" ]; then _dir_basename="$(basename "${_directory}")" @@ -1017,16 +1054,38 @@ [ "${_root_origin}" = '-' ] && farray_append _errors "the root dataset is not a ZFS clone" fi # - # Check for open files on all the mounted filesystems + # Check for open files on all the mounted filesystems. + # If snapshots are requested check that they are related somehow to + # mounted filesystems. # + _sn_ds_related='' 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 + _idx=1 + while falist_tryget_key_at_index _sn_ds _opt_snapshots ${_idx}; do + case "${_mnt_device}" in + "${_sn_ds}") + _sn_ds_related="yes" + ;; + "${_sn_ds}"/*) + _sn_ds_related="yes" + ;; + *) + ;; + esac + _idx=$((_idx + 1)) + done done <<EOF4tHGCAASL775f9f320205 ${_dir_mounts} EOF4tHGCAASL775f9f320205 fi + if falist_istrue _opt_snapshots; then + if ! checkyes _sn_ds_related; then + farray_append _warnings "snapshot datasets and mounted datasets are not related" + fi + fi if farray_istrue _errors; then _print_check_errors _errors @@ -1037,6 +1096,7 @@ farray_destroy _errors farray_destroy _warnings + falist_destroy _opt_snapshots return ${_rc} } @@ -1049,27 +1109,45 @@ #: command_freebsd_update() { local _directory _new_origin _etcupdate_tarball - local _opt_keep _opt_old_origin + local _opt_keep _opt_old_origin _opt_snapshots local _res _jailname _dir_mounts _dir_fn_fstab _dir_fn_fstab2 local _dir_basename _dir_fn_tldir local _root_dataset _root_mountpoint _root_type _root_options local _mnt_device _mnt_mountpoint _mnt_type _mnt_options + local _idx _sn_ds _sn_name local _clone_extra_props _canmount_prop local _line _opt local _root_readonly _root_origin local _u_tmpdir local _add_log_sock + _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#*@}" + ;; + *) + err "argument \`${OPTARG}' is not a snapshot name" + return 1 + ;; + esac + ;; k) _opt_keep="yes" ;; o) - _opt_old_origin="$OPTARG" + _opt_old_origin="${OPTARG}" ;; \?|:) return 2; @@ -1092,6 +1170,26 @@ [ -r "${_etcupdate_tarball}" ] || { echo "ERROR: given etcupdate tarball does not exist and/or is not readable" 1>&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 <<EOF2988ee715b2d93fd93bdce23 +$(zfs list -H -r -o name "${_sn_ds}") +EOF2988ee715b2d93fd93bdce23 + else + err "dataset for snapshots \`${_sn_ds}' does not exist" + return 1 + fi + _idx=$((_idx + 1)) + done + _dir_basename="$(basename "${_directory}")" set +e @@ -1191,6 +1289,13 @@ _dir_fn_tldir="${_u_tmpdir}/tldirs" LC_ALL=C /usr/bin/find "${_directory}" -depth 1 -type d 2>/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 }
--- 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)
