Recover disk space safely and complete metadata-only backup updates

This commit is contained in:
admin committed 2026-09-21 16:30:38 +02:00
1 parent 04283a607c
commit a5a7e38853
17 files changed
+827 -209

No files matched your search

+40 -8
View File
@@ -4,34 +4,66 @@ clean_backup_scratch() {
python3 "$LIB_DIR/space.py" clean "$WORKDIR" "$STAGING_ROOT" "$ARCHIVE_DIR" "$ARCHIVE_PREFIX" "$RESTORE_ROOT"
}
available_space() {
local value
value=$(df -PB1 -- "$1" | awk 'END{print $4}') || return 1
[[ $value =~ ^(0|[1-9][0-9]{0,17})$ ]] || die "Cannot determine available space on $1"
printf '%s\n' "$value"
}
ensure_space() {
local path=$1 additional=${2:-0} avail name dir candidates
local path=$1 additional=${2:-0} avail name dir candidates code protected
[[ $additional =~ ^(0|[1-9][0-9]{0,15})$ ]] || die 'Invalid or excessive space request'
local required=$((MIN_FREE_GB * 1024 * 1024 * 1024 + additional))
avail=$(df -PB1 -- "$path" | awk 'END{print $4}')
avail=$(available_space "$path")
(( avail < required )) || return 0
echo "-- Space recovery: need $required bytes, available $avail on $path"
echo "-- Space policy: keep $SPACE_KEEP_LOCAL uploaded local set(s) under pressure; normal retention keeps $RETENTION_KEEP_LAST"
if [[ $ENABLE_UPLOAD == true && $(stat -c %d "$path") == "$(stat -c %d "$ARCHIVE_DIR")" ]]; then
check_remote
candidates=$(python3 "$LIB_DIR/space.py" eligible "$ARCHIVE_DIR" "$ARCHIVE_PREFIX" "$RETENTION_KEEP_LAST")
candidates=$(python3 "$LIB_DIR/space.py" eligible "$ARCHIVE_DIR" "$ARCHIVE_PREFIX" "$SPACE_KEEP_LOCAL")
if [[ -n $candidates ]]; then
protected=$(python3 "$LIB_DIR/space.py" protected "$ARCHIVE_DIR" "$ARCHIVE_PREFIX" "$SPACE_KEEP_LOCAL")
[[ -n $protected ]] || die 'No protected local backup; refusing space recovery'
while IFS= read -r name; do
echo "-- Space recovery: validating protected local copy: $name"
if helper verify "$ARCHIVE_DIR/$name" >/dev/null; then continue; else code=$?; fi
(( code < 128 )) || return "$code"
echo "WARNING: Protected local copy is damaged; keeping all candidates: $name"
candidates=''
break
done <<< "$protected"
fi
while IFS= read -r name; do
[[ -n $name ]] || continue
avail=$(available_space "$path")
(( avail < required )) || return 0
dir="$ARCHIVE_DIR/$name"
# A manually selected local restore source is never a cleanup candidate.
[[ -z ${LOCAL_RUN:-} || $(realpath -m "$LOCAL_RUN") != "$dir" ]] || continue
echo "-- Space recovery: verifying offsite copy before local removal: $name"
if helper verify "$dir" >/dev/null &&
remote_readback "$dir" "${RCLONE_REMOTE_BASE%/}/$name" --exclude /UPLOADED; then
remote_metadata_check "$dir" "${RCLONE_REMOTE_BASE%/}/$name" --exclude /UPLOADED &&
remote_identity_check "$dir" "${RCLONE_REMOTE_BASE%/}/$name"; then
python3 "$LIB_DIR/space.py" remove "$dir"
echo "-- Space recovery: removed local copy $name; verified offsite copy retained"
echo "-- Space recovery: removed local copy $name; offsite copy with matching file sizes retained"
else
code=$?
(( code < 128 )) || return "$code"
echo "WARNING: Keeping $name: local/offsite verification failed"
fi
avail=$(df -PB1 -- "$path" | awk 'END{print $4}')
(( avail < required )) || return 0
avail=$(available_space "$path")
if (( avail >= required )); then
echo "-- Space recovery complete: available $avail bytes, required $required"
return 0
fi
done <<< "$candidates"
fi
die "Insufficient space after safe cleanup on $path: need $required bytes, available $avail; protected backups/recovery data retained"
avail=$(available_space "$path")
(( avail < required )) || return 0
python3 "$LIB_DIR/space.py" inventory "$ARCHIVE_DIR" "$ARCHIVE_PREFIX" "$SPACE_KEEP_LOCAL" ||
echo 'WARNING: Local archive inventory incomplete; no further cleanup attempted'
die "Insufficient space after safe cleanup on $path: need $required bytes, available $avail, deficit $((required - avail)) bytes; protected backups/recovery data retained. See SPEICHER.md: resolve pending uploads or move backup workspace to a larger filesystem."
}
prepare_backup_space() {