feat: add cleanup to autopromoter (#393)

- ensure the autopromoter removes hardlinks/replicas for repos older
  than the current promoted monthly
- this is to reduce MDS load for ceph, as hardlinks require memory

Reviewed-on: #393
This commit is contained in:
Ben Vincent 2025-09-13 20:08:32 +10:00
parent 98a433d366
commit 012e842d7d

View File

@ -1,33 +1,72 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DRY_RUN:=}" # set DRY_RUN=1 to preview deletions
log() { printf '[%(%F %T)T] %s\n' -1 "$*" >&2; }
# Function to create symlink for snapshots
create_symlink() {
local osname="$1"
local release="$2"
local repository="$3"
local basepath="$4"
local label="$5" # 'monthly', 'weekly', or 'daily'
local date_format="$6" # Date format for finding the snapshot
local osname="$1" # e.g. almalinux
local release="$2" # e.g. 9.6
local repository="$3" # e.g. appstream
local basepath="$4" # e.g. /shared/apps/packagerepo
local label="$5" # monthly|weekly|daily
local date_value="$6" # YYYYMMDD for the snapshot to promote
# The path where snapshots are stored
local snap_path="${basepath}/snap/${osname}/${release}/${repository}-${date_format}"
# The target path for the symlink
local snap_path="${basepath}/snap/${osname}/${release}/${repository}-${date_value}"
local symlink_target="${basepath}/snap/${osname}/${release}/${repository}-${label}"
# Check if the source directory exists
if [[ -d "$snap_path" ]]; then
# Create the symlink, overwrite if it already exists
ln -sfn "$snap_path" "$symlink_target"
echo "Symlink created for $snap_path -> $symlink_target"
log "Symlink set: ${symlink_target} -> ${snap_path}"
return 0
else
echo "Snapshot path does not exist: $snap_path"
log "Snapshot path does not exist: $snap_path"
return 1
fi
}
# Cleanup snapshot directories older than a cutoff date (YYYYMMDD)
cleanup_older_than_monthly() {
local osname="$1"
local release="$2"
local repository="$3"
local basepath="$4"
local cutoff_date="$5" # newly promoted monthly date, YYYYMMDD
local root="${basepath}/snap/${osname}/${release}"
local pattern="${repository}-"[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]
shopt -s nullglob
for dir in "${root}"/${pattern}; do
# Skip symlinks and non-directories
[[ -L "$dir" ]] && continue
[[ -d "$dir" ]] || continue
# Extract the date suffix
local name base datepart
name="$(basename -- "$dir")"
base="${name%-????????}" # remove last 8 chars
datepart="${name#${base}-}" # after "<repo>-"
# Only act on valid YYYYMMDD dates
if [[ "$datepart" =~ ^[0-9]{8}$ ]]; then
if [[ "$datepart" -lt "$cutoff_date" ]]; then
if [[ -n "${DRY_RUN}" ]]; then
log "[DRY_RUN] Would remove: $dir"
else
log "Removing: $dir"
rm -rf --one-file-system -- "$dir"
fi
fi
fi
done
shopt -u nullglob
}
# Determine which snapshot to promote based on the passed argument
case "$1" in
case "${1:-}" in
monthly)
promote_date=$(date --date="$(date +%Y%m01) -1 month" +%Y%m%d)
;;
@ -43,11 +82,26 @@ case "$1" in
;;
esac
# Call the function with appropriate arguments
# Iterate over the repositories to create symlinks for each
label="$1"
# Process each repo conf
for conf in /etc/reposync/conf.d/*.conf; do
# shellcheck disable=SC1090
source "$conf"
# Create symlink based on the provided argument
create_symlink "$OSNAME" "$RELEASE" "$REPOSITORY" "$BASEPATH" "$1" "$promote_date"
# Expecting these vars in the conf: OSNAME, RELEASE, REPOSITORY, BASEPATH
: "${OSNAME:?missing OSNAME in $conf}"
: "${RELEASE:?missing RELEASE in $conf}"
: "${REPOSITORY:?missing REPOSITORY in $conf}"
: "${BASEPATH:?missing BASEPATH in $conf}"
# 1) Promote the symlink for this label
if create_symlink "$OSNAME" "$RELEASE" "$REPOSITORY" "$BASEPATH" "$label" "$promote_date"; then
# 2) If monthly, clean up older snapshot dirs for this repo
if [[ "$label" == "monthly" ]]; then
cleanup_older_than_monthly "$OSNAME" "$RELEASE" "$REPOSITORY" "$BASEPATH" "$promote_date"
fi
else
log "Skipping cleanup for ${OSNAME}/${RELEASE}/${REPOSITORY} due to missing ${REPOSITORY}-${promote_date}"
fi
done