Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison sbin/ftjail @ 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 | 260a81d769a6 |
| children | 83ec66c64f47 |
comparison
equal
deleted
inserted
replaced
| 659:25de0d27e407 | 660:82a98db83a13 |
|---|---|
| 43 | 43 |
| 44 copy-skel [-A] [-D] [-L] [-M MOUNTPOINT] [-P] [-u] SOURCE-DS SNAPSHOT-NAME TARGET-DS | 44 copy-skel [-A] [-D] [-L] [-M MOUNTPOINT] [-P] [-u] SOURCE-DS SNAPSHOT-NAME TARGET-DS |
| 45 | 45 |
| 46 build-etcupdate-current-tmpl DIRECTORY TARBALL | 46 build-etcupdate-current-tmpl DIRECTORY TARBALL |
| 47 | 47 |
| 48 freebsd-update [-k] [-o OLD-ORIGIN] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] | 48 check-freebsd-update [-k] [-o OLD-ORIGIN] [-R SNAPSHOT] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] |
| 49 | |
| 50 freebsd-update [-k] [-o OLD-ORIGIN] [-R SNAPSHOT] DIRECTORY NEW-ORIGIN [ETCUPDATE-TARBALL] | |
| 49 | 51 |
| 50 ENVIRONMENT: | 52 ENVIRONMENT: |
| 51 | 53 |
| 52 All environment variables that affect "zfs" are effective also. | 54 All environment variables that affect "zfs" are effective also. |
| 53 | 55 |
| 899 #: | 901 #: |
| 900 #: Implement the "check-freebsd-update" command for a thin jail | 902 #: Implement the "check-freebsd-update" command for a thin jail |
| 901 #: | 903 #: |
| 902 command_check_freebsd_update() { | 904 command_check_freebsd_update() { |
| 903 local _directory _new_origin _etcupdate_tarball | 905 local _directory _new_origin _etcupdate_tarball |
| 904 local _opt_keep _opt_old_origin | 906 local _opt_keep _opt_old_origin _opt_snapshots |
| 905 | 907 |
| 906 local _errors _warnings _rc | 908 local _errors _warnings _rc |
| 907 local _directory _new_origin _etcupdate_tarball | 909 local _directory _new_origin _etcupdate_tarball |
| 908 local _dir_basename _dir_mounts _jailname _tmp _line _log_sock | 910 local _dir_basename _dir_mounts _jailname _tmp _line _log_sock |
| 909 local _root_dataset _root_mountpoint _root_type _root_options | 911 local _root_dataset _root_mountpoint _root_type _root_options |
| 910 local _mnt_device _mnt_mountpoint _mnt_type _mnt_options | 912 local _mnt_device _mnt_mountpoint _mnt_type _mnt_options |
| 913 local _idx _sn_ds _sn_name _sn_ds_related | |
| 911 | 914 |
| 912 _rc=0 | 915 _rc=0 |
| 913 | 916 |
| 914 _warnings='' | 917 _warnings='' |
| 915 farray_create _warnings XXX | 918 farray_create _warnings |
| 916 _errors='' | 919 _errors='' |
| 917 farray_create _errors | 920 farray_create _errors |
| 918 | 921 |
| 922 _opt_snapshots='' | |
| 923 falist_create _opt_snapshots | |
| 919 _opt_keep="no" | 924 _opt_keep="no" |
| 920 _opt_old_origin="" | 925 _opt_old_origin="" |
| 921 while getopts "ko:" _opt ; do | 926 while getopts "R:ko:" _opt ; do |
| 922 case "${_opt}" in | 927 case "${_opt}" in |
| 928 R) | |
| 929 case "${OPTARG}" in | |
| 930 *?\@?*) | |
| 931 # | |
| 932 # Split in two parts: dataset hierarchy and the name of the | |
| 933 # snapshot | |
| 934 # | |
| 935 falist_set _opt_snapshots "${OPTARG%%@*}" "${OPTARG#*@}" | |
| 936 ;; | |
| 937 *) | |
| 938 farray_append _errors "argument \`${OPTARG}' is not a snapshot name" | |
| 939 ;; | |
| 940 esac | |
| 941 ;; | |
| 923 k) | 942 k) |
| 924 _opt_keep="yes" | 943 _opt_keep="yes" |
| 925 ;; | 944 ;; |
| 926 o) | 945 o) |
| 927 _opt_old_origin="$OPTARG" | 946 _opt_old_origin="${OPTARG}" |
| 928 ;; | 947 ;; |
| 929 \?|:) | 948 \?|:) |
| 930 return 2; | 949 return 2; |
| 931 ;; | 950 ;; |
| 932 esac | 951 esac |
| 949 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" | 968 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" |
| 950 fi | 969 fi |
| 951 if [ -n "${_etcupdate_tarball}" ]; then | 970 if [ -n "${_etcupdate_tarball}" ]; then |
| 952 [ -r "${_etcupdate_tarball}" ] || farray_append _errors "given etcupdate tarball does not exist and/or is not readable" | 971 [ -r "${_etcupdate_tarball}" ] || farray_append _errors "given etcupdate tarball does not exist and/or is not readable" |
| 953 fi | 972 fi |
| 973 | |
| 974 # Check snapshotting | |
| 975 _idx=1 | |
| 976 while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do | |
| 977 if zfs get -H -o value name "${_sn_ds}" >/dev/null 2>/dev/null; then | |
| 978 # yes dataset exists: check that snapshots do not exist | |
| 979 while IFS=$'\t' read -r _line; do | |
| 980 if zfs get -H -o value name "${_line}@${_sn_name}" >/dev/null 2>/dev/null; then | |
| 981 farray_append _errors "snapshot \`${_line}@${_sn_name}' already exists" | |
| 982 fi | |
| 983 done <<EOF2988ee715b2d93fd93bdce23 | |
| 984 $(zfs list -H -r -o name "${_sn_ds}") | |
| 985 EOF2988ee715b2d93fd93bdce23 | |
| 986 else | |
| 987 farray_append _errors "dataset for snapshots \`${_sn_ds}' does not exist" | |
| 988 fi | |
| 989 _idx=$((_idx + 1)) | |
| 990 done | |
| 954 | 991 |
| 955 if [ -n "${_directory}" ]; then | 992 if [ -n "${_directory}" ]; then |
| 956 | 993 |
| 957 _dir_basename="$(basename "${_directory}")" | 994 _dir_basename="$(basename "${_directory}")" |
| 958 | 995 |
| 1015 [ "${_opt_old_origin}" != "${_root_origin}" ] && farray_append _errors "origin mismatch" | 1052 [ "${_opt_old_origin}" != "${_root_origin}" ] && farray_append _errors "origin mismatch" |
| 1016 else | 1053 else |
| 1017 [ "${_root_origin}" = '-' ] && farray_append _errors "the root dataset is not a ZFS clone" | 1054 [ "${_root_origin}" = '-' ] && farray_append _errors "the root dataset is not a ZFS clone" |
| 1018 fi | 1055 fi |
| 1019 # | 1056 # |
| 1020 # Check for open files on all the mounted filesystems | 1057 # Check for open files on all the mounted filesystems. |
| 1058 # If snapshots are requested check that they are related somehow to | |
| 1059 # mounted filesystems. | |
| 1021 # | 1060 # |
| 1061 _sn_ds_related='' | |
| 1022 while IFS=$'\t' read -r _mnt_device _mnt_mountpoint _mnt_type _mnt_options _line; do | 1062 while IFS=$'\t' read -r _mnt_device _mnt_mountpoint _mnt_type _mnt_options _line; do |
| 1023 if ! _check_no_open_files_on_filesystem "${_mnt_mountpoint}" ; then | 1063 if ! _check_no_open_files_on_filesystem "${_mnt_mountpoint}" ; then |
| 1024 farray_append _errors "There are open files or memory mapping on file system \`${_mnt_mountpoint}'" | 1064 farray_append _errors "There are open files or memory mapping on file system \`${_mnt_mountpoint}'" |
| 1025 fi | 1065 fi |
| 1066 _idx=1 | |
| 1067 while falist_tryget_key_at_index _sn_ds _opt_snapshots ${_idx}; do | |
| 1068 case "${_mnt_device}" in | |
| 1069 "${_sn_ds}") | |
| 1070 _sn_ds_related="yes" | |
| 1071 ;; | |
| 1072 "${_sn_ds}"/*) | |
| 1073 _sn_ds_related="yes" | |
| 1074 ;; | |
| 1075 *) | |
| 1076 ;; | |
| 1077 esac | |
| 1078 _idx=$((_idx + 1)) | |
| 1079 done | |
| 1026 done <<EOF4tHGCAASL775f9f320205 | 1080 done <<EOF4tHGCAASL775f9f320205 |
| 1027 ${_dir_mounts} | 1081 ${_dir_mounts} |
| 1028 EOF4tHGCAASL775f9f320205 | 1082 EOF4tHGCAASL775f9f320205 |
| 1029 fi | 1083 fi |
| 1084 if falist_istrue _opt_snapshots; then | |
| 1085 if ! checkyes _sn_ds_related; then | |
| 1086 farray_append _warnings "snapshot datasets and mounted datasets are not related" | |
| 1087 fi | |
| 1088 fi | |
| 1030 | 1089 |
| 1031 if farray_istrue _errors; then | 1090 if farray_istrue _errors; then |
| 1032 _print_check_errors _errors | 1091 _print_check_errors _errors |
| 1033 _rc=1 | 1092 _rc=1 |
| 1034 fi | 1093 fi |
| 1035 # Warnings do not influence the return code | 1094 # Warnings do not influence the return code |
| 1036 _print_check_warnings _warnings | 1095 _print_check_warnings _warnings |
| 1037 | 1096 |
| 1038 farray_destroy _errors | 1097 farray_destroy _errors |
| 1039 farray_destroy _warnings | 1098 farray_destroy _warnings |
| 1099 falist_destroy _opt_snapshots | |
| 1040 return ${_rc} | 1100 return ${_rc} |
| 1041 } | 1101 } |
| 1042 | 1102 |
| 1043 | 1103 |
| 1044 #: | 1104 #: |
| 1047 #: .. note:: FreeBSD's :command:`etcupdate` also executes | 1107 #: .. note:: FreeBSD's :command:`etcupdate` also executes |
| 1048 #: :command:`certctl rehash` if certs are to be added or removed! | 1108 #: :command:`certctl rehash` if certs are to be added or removed! |
| 1049 #: | 1109 #: |
| 1050 command_freebsd_update() { | 1110 command_freebsd_update() { |
| 1051 local _directory _new_origin _etcupdate_tarball | 1111 local _directory _new_origin _etcupdate_tarball |
| 1052 local _opt_keep _opt_old_origin | 1112 local _opt_keep _opt_old_origin _opt_snapshots |
| 1053 | 1113 |
| 1054 local _res _jailname _dir_mounts _dir_fn_fstab _dir_fn_fstab2 | 1114 local _res _jailname _dir_mounts _dir_fn_fstab _dir_fn_fstab2 |
| 1055 local _dir_basename _dir_fn_tldir | 1115 local _dir_basename _dir_fn_tldir |
| 1056 local _root_dataset _root_mountpoint _root_type _root_options | 1116 local _root_dataset _root_mountpoint _root_type _root_options |
| 1057 local _mnt_device _mnt_mountpoint _mnt_type _mnt_options | 1117 local _mnt_device _mnt_mountpoint _mnt_type _mnt_options |
| 1118 local _idx _sn_ds _sn_name | |
| 1058 local _clone_extra_props _canmount_prop | 1119 local _clone_extra_props _canmount_prop |
| 1059 local _line _opt | 1120 local _line _opt |
| 1060 local _root_readonly _root_origin | 1121 local _root_readonly _root_origin |
| 1061 local _u_tmpdir | 1122 local _u_tmpdir |
| 1062 local _add_log_sock | 1123 local _add_log_sock |
| 1063 | 1124 |
| 1125 _opt_snapshots='' | |
| 1126 falist_create _opt_snapshots | |
| 1064 _opt_keep="no" | 1127 _opt_keep="no" |
| 1065 _opt_old_origin="" | 1128 _opt_old_origin="" |
| 1066 while getopts "ko:" _opt ; do | 1129 while getopts "R:ko:" _opt ; do |
| 1067 case "${_opt}" in | 1130 case "${_opt}" in |
| 1131 R) | |
| 1132 case "${OPTARG}" in | |
| 1133 *?\@?*) | |
| 1134 # | |
| 1135 # Split in two parts: dataset hierarchy and the name of the | |
| 1136 # snapshot | |
| 1137 # | |
| 1138 falist_set _opt_snapshots "${OPTARG%%@*}" "${OPTARG#*@}" | |
| 1139 ;; | |
| 1140 *) | |
| 1141 err "argument \`${OPTARG}' is not a snapshot name" | |
| 1142 return 1 | |
| 1143 ;; | |
| 1144 esac | |
| 1145 ;; | |
| 1068 k) | 1146 k) |
| 1069 _opt_keep="yes" | 1147 _opt_keep="yes" |
| 1070 ;; | 1148 ;; |
| 1071 o) | 1149 o) |
| 1072 _opt_old_origin="$OPTARG" | 1150 _opt_old_origin="${OPTARG}" |
| 1073 ;; | 1151 ;; |
| 1074 \?|:) | 1152 \?|:) |
| 1075 return 2; | 1153 return 2; |
| 1076 ;; | 1154 ;; |
| 1077 esac | 1155 esac |
| 1089 [ -z "${_new_origin}" ] && { echo "ERROR: no new origin given" 1>&2; return 2; } | 1167 [ -z "${_new_origin}" ] && { echo "ERROR: no new origin given" 1>&2; return 2; } |
| 1090 zfs list -H -o name -t snapshot "${_new_origin}" >/dev/null 2>/dev/null || { echo "ERROR: ZFS dataset snapshot for the new origin \`${_new_origin}' does not exist" 1>&2; return 1; } | 1168 zfs list -H -o name -t snapshot "${_new_origin}" >/dev/null 2>/dev/null || { echo "ERROR: ZFS dataset snapshot for the new origin \`${_new_origin}' does not exist" 1>&2; return 1; } |
| 1091 if [ -n "${_etcupdate_tarball}" ]; then | 1169 if [ -n "${_etcupdate_tarball}" ]; then |
| 1092 [ -r "${_etcupdate_tarball}" ] || { echo "ERROR: given etcupdate tarball does not exist and/or is not readable" 1>&2; return 1; } | 1170 [ -r "${_etcupdate_tarball}" ] || { echo "ERROR: given etcupdate tarball does not exist and/or is not readable" 1>&2; return 1; } |
| 1093 fi | 1171 fi |
| 1172 | |
| 1173 # Check snapshotting | |
| 1174 _idx=1 | |
| 1175 while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do | |
| 1176 if zfs get -H -o value name "${_sn_ds}" >/dev/null 2>/dev/null; then | |
| 1177 # yes dataset exists: check that snapshots do not exist | |
| 1178 while IFS=$'\t' read -r _line; do | |
| 1179 if zfs get -H -o value name "${_line}@${_sn_name}" >/dev/null 2>/dev/null; then | |
| 1180 err "snapshot \`${_line}@${_sn_name}' already exists" | |
| 1181 return 1 | |
| 1182 fi | |
| 1183 done <<EOF2988ee715b2d93fd93bdce23 | |
| 1184 $(zfs list -H -r -o name "${_sn_ds}") | |
| 1185 EOF2988ee715b2d93fd93bdce23 | |
| 1186 else | |
| 1187 err "dataset for snapshots \`${_sn_ds}' does not exist" | |
| 1188 return 1 | |
| 1189 fi | |
| 1190 _idx=$((_idx + 1)) | |
| 1191 done | |
| 1094 | 1192 |
| 1095 _dir_basename="$(basename "${_directory}")" | 1193 _dir_basename="$(basename "${_directory}")" |
| 1096 | 1194 |
| 1097 set +e | 1195 set +e |
| 1098 _jailname="$(_get_jail_from_path "${_directory}")" | 1196 _jailname="$(_get_jail_from_path "${_directory}")" |
| 1189 # Replace all spaces with a sequence that is understood by mount | 1287 # Replace all spaces with a sequence that is understood by mount |
| 1190 LC_ALL=C /usr/bin/sed -e 's/ /\\040/g' <"${_dir_fn_fstab}" >"${_dir_fn_fstab2}" | 1288 LC_ALL=C /usr/bin/sed -e 's/ /\\040/g' <"${_dir_fn_fstab}" >"${_dir_fn_fstab2}" |
| 1191 _dir_fn_tldir="${_u_tmpdir}/tldirs" | 1289 _dir_fn_tldir="${_u_tmpdir}/tldirs" |
| 1192 LC_ALL=C /usr/bin/find "${_directory}" -depth 1 -type d 2>/dev/null | LC_ALL=C /usr/bin/sort >>"${_dir_fn_tldir}" | 1290 LC_ALL=C /usr/bin/find "${_directory}" -depth 1 -type d 2>/dev/null | LC_ALL=C /usr/bin/sort >>"${_dir_fn_tldir}" |
| 1193 | 1291 |
| 1292 _idx=1 | |
| 1293 while falist_tryget_item_at_index _sn_ds _sn_name _opt_snapshots ${_idx}; do | |
| 1294 echo "Creating snapshot \`${_sn_ds}@${_sn_name}'" | |
| 1295 zfs snapshot -r "${_sn_ds}@${_sn_name}" || { err "cannot snapshot \`${_sn_ds}@${_sn_name}'"; return 1; } | |
| 1296 _idx=$((_idx + 1)) | |
| 1297 done | |
| 1298 | |
| 1194 # Unmount in reverse order: unmount can do it for us | 1299 # Unmount in reverse order: unmount can do it for us |
| 1195 echo "Unmounting all datasets mounted at \`${_directory}'" | 1300 echo "Unmounting all datasets mounted at \`${_directory}'" |
| 1196 /sbin/umount -a -F "${_dir_fn_fstab2}" -v | 1301 /sbin/umount -a -F "${_dir_fn_fstab2}" -v |
| 1197 | 1302 |
| 1198 # | 1303 # |
| 1275 if [ "${_opt_keep}" != "yes" ]; then | 1380 if [ "${_opt_keep}" != "yes" ]; then |
| 1276 echo "Cleaning up...""" | 1381 echo "Cleaning up...""" |
| 1277 [ -n "${_u_tmpdir}" ] && [ -d "${_u_tmpdir}" ] && rm -rvf "${_u_tmpdir}" | 1382 [ -n "${_u_tmpdir}" ] && [ -d "${_u_tmpdir}" ] && rm -rvf "${_u_tmpdir}" |
| 1278 fi | 1383 fi |
| 1279 echo "Done." | 1384 echo "Done." |
| 1385 | |
| 1386 falist_destroy _opt_snapshots | |
| 1280 } | 1387 } |
| 1281 | 1388 |
| 1282 | 1389 |
| 1283 # | 1390 # |
| 1284 # Global option handling | 1391 # Global option handling |
