diff --git a/CHANGELOG b/CHANGELOG index 1042c6a..33e4979 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- [SNAPSHOT] Snapshot/restore now handle the absence of some datasets +### Fixed +- [SNAPSHOT] Use /var/db jail datasets for jail snapshots ## [1.0.2] - 2025-03-28 diff --git a/usr/local/share/vulture-utils/common.sh b/usr/local/share/vulture-utils/common.sh index 516e749..cc6f879 100644 --- a/usr/local/share/vulture-utils/common.sh +++ b/usr/local/share/vulture-utils/common.sh @@ -11,7 +11,7 @@ SNAPSHOT_PREFIX="VLT_" JAILS_LIST="apache haproxy mongodb portal redis rsyslog" AVAILABLE_DATASET_TYPES="JAIL DB HOMES TMPVAR" -JAIL_DATASETS="apache apache/var apache/usr portal portal/var portal/usr haproxy haproxy/var haproxy/usr mongodb mongodb/var mongodb/usr redis redis/var redis/usr rsyslog rsyslog/var rsyslog/usr" +JAIL_DATASETS="apache apache/var apache/var/db apache/usr portal portal/var portal/var/db portal/usr haproxy haproxy/var haproxy/var/db haproxy/usr mongodb mongodb/var mongodb/usr redis redis/var redis/var/db redis/usr rsyslog rsyslog/var rsyslog/var/db rsyslog/usr" DB_DATASETS="mongodb/var/db" HOMES_DATASETS="usr/home" TMPVAR_DATASETS="apache/var/log portal/var/log haproxy/var/log mongodb/var/log redis/var/log rsyslog/var/log tmp var/audit var/cache var/crash var/log var/tmp" @@ -90,6 +90,25 @@ has_upgraded_kernel() { fi } +get_root_zpool_name() { + /sbin/mount -l | /usr/bin/grep "on / " | /usr/bin/cut -d / -f 1 +} + +zfs_dataset_exists() { + _dataset="$1" + _zpool="$(get_root_zpool_name)" + + if [ -z "${_dataset}" ]; then + return 1 + fi + + if /sbin/zfs list -oname | grep -q "^${_zpool}/${_dataset}\$"; then + return 0 + else + return 1 + fi +} + ################### ## Miscellaneous ## ################### @@ -209,10 +228,6 @@ clean_old_BEs() { ############################ ## Snapshotting functions ## ############################ -get_root_zpool_name() { - /sbin/mount -l | /usr/bin/grep "on / " | /usr/bin/cut -d / -f 1 -} - snapshot_datasets() { _datasets="$1" _snapshot_name="$2" @@ -223,7 +238,9 @@ snapshot_datasets() { fi for dataset in ${_datasets}; do - /sbin/zfs snap "${_zpool}/${dataset}@${_snapshot_name}" + if zfs_dataset_exists "${dataset}"; then + /sbin/zfs snap "${_zpool}/${dataset}@${_snapshot_name}" + fi done } @@ -235,14 +252,16 @@ list_snapshots() { return 1 fi - # List snapshot names only, ordering by descending order (most recent first) - /sbin/zfs list -H -tsnap -oname -Screation "${_zpool}/${_dataset}" |\ - # Get snapshot name part (remove dataset part) - /usr/bin/cut -d '@' -f 2 |\ - # filter out snapshot not created by scripts - /usr/bin/grep -E "^${SNAPSHOT_PREFIX}.*" |\ - # remove leading/trailing whitespaces and return a single string with elements separated by a space - /usr/bin/xargs + if zfs_dataset_exists "${_dataset}"; then + # List snapshot names only, ordering by descending order (most recent first) + /sbin/zfs list -H -tsnap -oname -Screation "${_zpool}/${_dataset}" |\ + # Get snapshot name part (remove dataset part) + /usr/bin/cut -d '@' -f 2 |\ + # filter out snapshot not created by scripts + /usr/bin/grep -E "^${SNAPSHOT_PREFIX}.*" |\ + # remove leading/trailing whitespaces and return a single string with elements separated by a space + /usr/bin/xargs + fi } clean_previous_snapshots() { @@ -260,15 +279,17 @@ clean_previous_snapshots() { fi for _dataset in ${_datasets}; do - # most recent are first in list - _ordered_snapshots="$(list_snapshots "${_dataset}")" - - # List index begins at 1, so remove from the next element to the last - _snaps_to_remove="$(sublist "${_ordered_snapshots}" "$((_number_to_keep+1))")" - for _snap in $_snaps_to_remove; do - /bin/echo "removing snapshot '${_zpool}/${_dataset}@${_snap}'" - /sbin/zfs destroy "${_zpool}/${_dataset}@${_snap}" - done + if zfs_dataset_exists "${_dataset}"; then + # most recent are first in list + _ordered_snapshots="$(list_snapshots "${_dataset}")" + + # List index begins at 1, so remove from the next element to the last + _snaps_to_remove="$(sublist "${_ordered_snapshots}" "$((_number_to_keep+1))")" + for _snap in $_snaps_to_remove; do + /bin/echo "removing snapshot '${_zpool}/${_dataset}@${_snap}'" + /sbin/zfs destroy "${_zpool}/${_dataset}@${_snap}" + done + fi done } @@ -286,8 +307,10 @@ tag_snapshots_for_rollback() { return 1 fi for _dataset in ${_datasets}; do - echo "will rollback to ${_zpool}/${_dataset}@${_snapshot}" - /sbin/zfs set snapshot:restore=YES "${_zpool}/${_dataset}@${_snapshot}" + if zfs_dataset_exists "${_dataset}"; then + echo "will rollback to ${_zpool}/${_dataset}@${_snapshot}" + /sbin/zfs set snapshot:restore=YES "${_zpool}/${_dataset}@${_snapshot}" + fi done } @@ -301,13 +324,15 @@ list_pending_rollbacks() { return 1 fi - zfs list -tsnap -o name,snapshot:restore "${_zpool}/${_dataset}" 2>/dev/null |\ - while read -r _name _status; do - if [ "${_status}" = "YES" ]; then - _snap_name=$(echo "${_name}" | cut -d @ -f 2) - /usr/bin/printf "%s " "${_snap_name}" - fi - done + if zfs_dataset_exists "${_dataset}"; then + zfs list -tsnap -o name,snapshot:restore "${_zpool}/${_dataset}" 2>/dev/null |\ + while read -r _name _status; do + if [ "${_status}" = "YES" ]; then + _snap_name=$(echo "${_name}" | cut -d @ -f 2) + /usr/bin/printf "%s " "${_snap_name}" + fi + done + fi } clean_rollback_state_on_datasets() { @@ -320,10 +345,12 @@ clean_rollback_state_on_datasets() { fi for _dataset in ${_datasets}; do - _snapshot_list="$(list_pending_rollbacks "${_dataset}")" - for _snapshot in ${_snapshot_list}; do - echo "Resetting rollback state for ${_dataset}" - /sbin/zfs inherit snapshot:restore "${_zpool}/${_dataset}@${_snapshot}" - done + if zfs_dataset_exists "${_dataset}"; then + _snapshot_list="$(list_pending_rollbacks "${_dataset}")" + for _snapshot in ${_snapshot_list}; do + echo "Resetting rollback state for ${_dataset}" + /sbin/zfs inherit snapshot:restore "${_zpool}/${_dataset}@${_snapshot}" + done + fi done }