fix(apt): snapshot recursive roots separately
This commit is contained in:
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
|
set -xv
|
||||||
|
|
||||||
declare -r config_file='/etc/apt-zfs-snapshot.conf'
|
declare -r config_file='/etc/apt-zfs-snapshot.conf'
|
||||||
declare -r zfs_property='space.quico:auto-snapshot'
|
declare -r zfs_property='space.quico:auto-snapshot'
|
||||||
declare -r zfs_property_value='true'
|
declare -r zfs_property_value='true'
|
||||||
declare -r zfs_max_name_length=255
|
declare -r zfs_max_name_length=255
|
||||||
|
|
||||||
set -xv
|
|
||||||
|
|
||||||
if [[ -r "${config_file}" ]]; then
|
if [[ -r "${config_file}" ]]; then
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${config_file}"
|
source "${config_file}"
|
||||||
@@ -34,7 +34,7 @@ downgrade_suffix="${downgrade_suffix:-down}"
|
|||||||
mixed_suffix="${mixed_suffix:-mixd}"
|
mixed_suffix="${mixed_suffix:-mixd}"
|
||||||
package_separator="${package_separator:-:}"
|
package_separator="${package_separator:-:}"
|
||||||
|
|
||||||
declare -a packages operations
|
declare -a packages operations successful_datasets
|
||||||
declare existing_snapshots
|
declare existing_snapshots
|
||||||
|
|
||||||
print_msg() {
|
print_msg() {
|
||||||
@@ -78,7 +78,7 @@ parse_apt_input() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -r package old_version _old_arch direction new_version _new_arch _multiarch action <<<"${line}"
|
read -r package old_version _old_arch _old_multiarch direction new_version _new_arch _new_multiarch action <<<"${line}"
|
||||||
[[ -n "${package}" ]] || continue
|
[[ -n "${package}" ]] || continue
|
||||||
if [[ "${action}" == '**CONFIGURE**' ]]; then
|
if [[ "${action}" == '**CONFIGURE**' ]]; then
|
||||||
continue
|
continue
|
||||||
@@ -95,18 +95,31 @@ parse_apt_input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_datasets() {
|
get_datasets() {
|
||||||
local dataset value
|
local dataset value candidate parent
|
||||||
|
local -a candidates
|
||||||
|
local mounted_datasets
|
||||||
if [[ -n "${snapshot_roots}" ]]; then
|
if [[ -n "${snapshot_roots}" ]]; then
|
||||||
read -r -a snappable_datasets <<<"${snapshot_roots}"
|
read -r -a candidates <<<"${snapshot_roots}"
|
||||||
|
snappable_datasets=("${candidates[@]}")
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mounted_datasets="$(findmnt -rn -t zfs -o SOURCE)"
|
||||||
while IFS=$'\t' read -r dataset value; do
|
while IFS=$'\t' read -r dataset value; do
|
||||||
[[ "${value}" == "${zfs_property_value}" && "${dataset}" != *@* ]] || continue
|
[[ "${value}" == "${zfs_property_value}" && "${dataset}" != *@* ]] || continue
|
||||||
if [[ "${snap_only_local_datasets}" != 'true' ]] || findmnt -rn -t zfs -o SOURCE | grep -Fxq -- "${dataset}"; then
|
if [[ "${snap_only_local_datasets}" != 'true' ]] || grep -Fxq -- "${dataset}" <<<"${mounted_datasets}"; then
|
||||||
snappable_datasets+=("${dataset}")
|
candidates+=("${dataset}")
|
||||||
fi
|
fi
|
||||||
done < <(zfs get -H -o name,value "${zfs_property}")
|
done < <(zfs get -H -t filesystem,volume -o name,value "${zfs_property}")
|
||||||
|
|
||||||
|
# An inherited property marks every descendant. Keep only the highest
|
||||||
|
# selected dataset because the snapshot operation is recursive.
|
||||||
|
for dataset in "${candidates[@]}"; do
|
||||||
|
for parent in "${candidates[@]}"; do
|
||||||
|
[[ "${dataset}" == "${parent}"/* ]] && continue 2
|
||||||
|
done
|
||||||
|
snappable_datasets+=("${dataset}")
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
operation_suffix() {
|
operation_suffix() {
|
||||||
@@ -181,7 +194,7 @@ prune_snapshots() {
|
|||||||
[[ "${dry_run}" == 'true' ]] && return 0
|
[[ "${dry_run}" == 'true' ]] && return 0
|
||||||
limit="${snapshots_trivial_keep}"
|
limit="${snapshots_trivial_keep}"
|
||||||
[[ "${severity}" == "${important_suffix}" ]] && limit="${snapshots_important_keep}"
|
[[ "${severity}" == "${important_suffix}" ]] && limit="${snapshots_important_keep}"
|
||||||
for dataset in "${snappable_datasets[@]}"; do
|
for dataset in "${successful_datasets[@]}"; do
|
||||||
# Query only the root dataset. Destroying its recursive snapshot also
|
# Query only the root dataset. Destroying its recursive snapshot also
|
||||||
# removes the matching descendant snapshots as one snapshot tree.
|
# removes the matching descendant snapshots as one snapshot tree.
|
||||||
mapfile -t snapshots < <(zfs list -H -t snapshot -o name -s creation "${dataset}" | grep -F "${dataset}@${snapshot_prefix}${field_separator}" | grep -F "${field_separator}sev:${severity}${field_separator}")
|
mapfile -t snapshots < <(zfs list -H -t snapshot -o name -s creation "${dataset}" | grep -F "${dataset}@${snapshot_prefix}${field_separator}" | grep -F "${field_separator}sev:${severity}${field_separator}")
|
||||||
@@ -220,10 +233,21 @@ main() {
|
|||||||
printf ' %s\n' "${names[@]}" >&2
|
printf ' %s\n' "${names[@]}" >&2
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
zfs snapshot -r "${names[@]}" || { print_msg WARN 'ZFS snapshot failed'; return 0; }
|
successful_datasets=()
|
||||||
printf '[INFO] Created ZFS snapshots:\n' >&2
|
local name dataset snapshot_failed='false'
|
||||||
printf ' %s\n' "${names[@]}" >&2
|
for name in "${names[@]}"; do
|
||||||
prune_snapshots
|
dataset="${name%%@*}"
|
||||||
|
if zfs snapshot -r "${name}"; then
|
||||||
|
successful_datasets+=("${dataset}")
|
||||||
|
printf '[INFO] Created ZFS snapshots for %s:\n' "${dataset}" >&2
|
||||||
|
printf ' %s\n' "${name}" >&2
|
||||||
|
else
|
||||||
|
snapshot_failed='true'
|
||||||
|
print_msg WARN "ZFS snapshot failed for ${dataset}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ "${snapshot_failed}" == 'false' ]] || print_msg WARN 'Snapshot set is incomplete'
|
||||||
|
((${#successful_datasets[@]} > 0)) && prune_snapshots
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|||||||
Reference in New Issue
Block a user