snap-sync: apply snapper description variables
- destinguish three states (running, synced, finished) - adapt handling where needed
This commit is contained in:
141
bin/snap-sync
141
bin/snap-sync
@@ -86,18 +86,23 @@ check_prerequisites () {
|
||||
}
|
||||
|
||||
check_snapper_failed_ids () {
|
||||
local noconfirm=${1:-$false}
|
||||
|
||||
# active, non finished snapshot backups are marked with following string
|
||||
# "$progname backup in progress" (snapper description field)
|
||||
snapper_failed_ids=$(eval snapper -c $selected_config list -t single | awk '/'"$progname"' backup in progress/ {cnt++} END {print cnt}')
|
||||
if [ -n "$snapper_failed_ids" ]; then
|
||||
if [ noconfirm ]; then
|
||||
snapper -c $selected_config delete $(snapper -c $selected_config list | awk '/'"$progname"' backup in progress/ {print $3}')
|
||||
snapper_failed_ids=$(eval snapper --config $selected_config list --type single | awk '/'"$snap_description_running"'/ {cnt++} END {print cnt}')
|
||||
if [ ${#snapper_failed_ids} -gt 0 ]; then
|
||||
#if [ -n "$snapper_failed_ids" ]; then
|
||||
if [ "$noconfirm" ]; then
|
||||
answer="yes"
|
||||
else
|
||||
printf "\nNOTE: Previous failed %s backup snapshots found for '%s'.\n" "$progname" "$selected_config" | tee $PIPE
|
||||
printf "\nNOTE: Found %s previous failed sync runs for '%s'.\n" "${snapper_failed_ids}" "$selected_config" | tee $PIPE
|
||||
get_answer_yes_no "Delete failed backup snapshots [y/N]? " "no"
|
||||
if [ "$answer" = "yes" ]; then
|
||||
snapper -c $selected_config delete $(snapper -c $selected_config list | awk '/'"$progname"' backup in progress/ {print $3}')
|
||||
fi
|
||||
fi
|
||||
if [ "$answer" = "yes" ]; then
|
||||
cmd2="snapper --config \"$selected_config\" list | awk '/'\"$snap_description_running\"'/ {print \$3}'"
|
||||
cmd="snapper --config \"$selected_config\" delete "
|
||||
$(eval $cmd $(eval $cmd2))
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -227,9 +232,7 @@ notify_error() {
|
||||
}
|
||||
|
||||
parse_params () {
|
||||
###
|
||||
# Evaluate given call parameters
|
||||
###
|
||||
while [ $# -gt 0 ]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
@@ -243,13 +246,21 @@ parse_params () {
|
||||
;;
|
||||
-c|--config)
|
||||
if [ ${#selected_config} -gt 0 ]; then
|
||||
selected_config="${selected_config} ${2}"
|
||||
selected_configs="${selected_configs} ${2}"
|
||||
else
|
||||
selected_config="$2"
|
||||
selected_configs="$2"
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
-d|--description)
|
||||
-d|--description|--description-finished)
|
||||
description="$2"
|
||||
shift 2
|
||||
;;
|
||||
--description-running)
|
||||
description="$2"
|
||||
shift 2
|
||||
;;
|
||||
--description-synced)
|
||||
description="$2"
|
||||
shift 2
|
||||
;;
|
||||
@@ -329,7 +340,10 @@ parse_params () {
|
||||
. $SNAPPER_CONFIG
|
||||
selected_configs=${selected_configs:-$SNAPPER_CONFIGS}
|
||||
|
||||
description=${description:-"latest incremental backup"}
|
||||
snap_description_synced=${description_lastsync:-"snap-sync last incremental"}
|
||||
snap_description_finished=${description_finished:-"snap-sync backup"}
|
||||
snap_description_running=${description_running:-"snap-sync in progress"}
|
||||
|
||||
uuid_cmdline=${uuid_cmdline:-"none"}
|
||||
target_cmdline=${target_cmdline:-"none"}
|
||||
subvolid_cmdline=${subvolid_cmdline:-"none"}
|
||||
@@ -350,6 +364,11 @@ parse_params () {
|
||||
printf "Snap Config: '%s'\n" "$selected_config"
|
||||
printf "Snap Remote: '%s'\n" "$ssh"
|
||||
|
||||
printf "Snapper Descriptions"
|
||||
printf " backup finished: '%s'\n" "$snap_description_finished"
|
||||
printf " backup synced: '%s'\n" "$snap_description_synced"
|
||||
printf " backup running: '%s'\n" "$snap_description_running"
|
||||
|
||||
if [ "$verbose" ]; then snap_sync_options="verbose=true"; fi
|
||||
if [ "$dryrun" ]; then snap_sync_options="${snap_sync_options} dry-run=true"; fi
|
||||
if [ "$noconfirm" ]; then snap_sync_options="${snap_sync_options} noconfirm=true"; fi
|
||||
@@ -359,29 +378,28 @@ parse_params () {
|
||||
|
||||
run_config () {
|
||||
|
||||
printf "\nVerify configuration...\n" | tee $PIPE
|
||||
|
||||
# commandline selection takes precedence
|
||||
if [ -n "$selected_config" ]; then
|
||||
selected_configs=$selected_config
|
||||
fi
|
||||
printf "\nVerify configuration...\n"
|
||||
|
||||
# loop though selected snapper configurations
|
||||
# Pseudo Arrays $i -> store associated elements of selected_config
|
||||
i=0
|
||||
for selected_config in $selected_configs; do
|
||||
count=$(eval snapper -c $selected_config list -t single | awk '/subvolid='"$selected_subvol"'/, /uuid='"$selected_uuid"'/ {cnt++} END {print cnt}')
|
||||
#count=$(eval snapper -c $selected_config list -t single | grep -c -e "subvolid=$selected_subvol" -e 'uuid=$selected_uuid')
|
||||
count=$(eval snapper --config $selected_config list --type single | \
|
||||
awk '/'"$snap_description_synced"'/' | \
|
||||
awk '/subvolid='"$selected_subvol"'/, /uuid='"$selected_uuid"'/ {cnt++} END {print cnt}')
|
||||
if [ -n "$count" ] && [ "$count" -gt 1 ]; then
|
||||
error "More than one snapper entry found with UUID $selected_uuid and SUBVOLID $selected_subvol for configuration '$selected_config'. Skipping configuration '$selected_config'."
|
||||
printf "%s entries are marked as '%s' for snapper config '%s'\n" \
|
||||
"$count" "$snap_description_synced" "$selected_config" | tee PIPE
|
||||
printf "Pointing to target with UUID '%s' and SUBVOLID '%s'. Skipping configuration '%s'.\n" \
|
||||
"$selected_uuid" "$selected_subvol" "$selected_config"
|
||||
printf "Please cleanup for further processing.\n" | tee PIPE
|
||||
error "Skipping configuration $selected_config."
|
||||
selected_configs=$(echo $selected_configs | sed -e "s/\($selected_config*\)//")
|
||||
if [ "$verbose" ]; then
|
||||
printf "Counter=%s" "$count"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
# cleanup failed former runs
|
||||
check_snapper_failed_ids cleanup
|
||||
check_snapper_failed_ids $noconfirm
|
||||
|
||||
SNAP_SYNC_EXCLUDE=no
|
||||
if [ -f "/etc/snapper/configs/$selected_config" ]; then
|
||||
@@ -399,9 +417,11 @@ run_config () {
|
||||
|
||||
printf "\n"
|
||||
|
||||
# processed snapshot backup is marked with userdata key/value pairs
|
||||
# backupdir, uuid
|
||||
snapper_sync_id=$(eval snapper --config "$selected_config" list --type single | awk '/subvolid='"$selected_subvol"'/, /uuid='"$selected_uuid"'/ {print $1}')
|
||||
# get latest successfully finished snapshot
|
||||
# (tagged with userdata key/value pairs)
|
||||
snapper_sync_id=$(eval snapper --config "$selected_config" list --type single | \
|
||||
awk '/'"$snap_description_synced"'/' | \
|
||||
awk '/subvolid='"$selected_subvol"'/, /uuid='"$selected_uuid"'/ {print $1}')
|
||||
if [ ${#snapper_sync_id} -gt 0 ]; then
|
||||
snapper_sync_snapshot=$SUBVOLUME/.snapshots/$snapper_sync_id/snapshot
|
||||
fi
|
||||
@@ -688,29 +708,66 @@ run_finalize () {
|
||||
src_uuid=$(eval findmnt --noheadings --output UUID $SUBVOLUME)
|
||||
src_subvolid=$(eval findmnt --noheadings --output OPTIONS $SUBVOLUME | sed -e 's/.*subvolid=\([0-9]*\).*/\1/')
|
||||
userdata="backupdir=$backup_dir, subvolid=$selected_subvol, uuid=$selected_uuid, host=$remote"
|
||||
target_description="snap-sync backup"
|
||||
target_userdata="subvolid=$src_subvolid, uuid=$src_uuid, host=$src_host"
|
||||
|
||||
# Tag new snapshots key/value parameter
|
||||
printf "Tagging snapper metadata for configuration '%s' ...\n" "$selected_config" | tee $PIPE
|
||||
if [ ! "$dryrun" ]; then
|
||||
$(eval snapper --verbose --config "$selected_config" modify --description \"$description\" --userdata \"$userdata\" "$snapper_new_id")
|
||||
# source snapshot
|
||||
if [ "$verbose" ]; then
|
||||
printf "Tagging snapper metadata on source for configuration '%s' ...\n" "$selected_config" | tee $PIPE
|
||||
fi
|
||||
cmd="snapper --verbose --config \"$selected_config\" modify --description \"$snap_description_synced\" --userdata \"$userdata\" \"$snapper_new_id\""
|
||||
ret=$(eval $cmd)
|
||||
#printf "return: '%s'\n" "$ret"
|
||||
sync
|
||||
#TODO: wait for btrfs-receive to be completed!
|
||||
$ssh "snapper --verbose --config $snapper_target_config modify --description \"$target_description\" --userdata \"$target_userdata\" $snapper_new_id"
|
||||
$ssh sync
|
||||
|
||||
# target snapshot
|
||||
if [ "$verbose" ]; then
|
||||
printf "Tagging snapper metadata on target for configuration '%s' ...\n" "$selected_config" | tee $PIPE
|
||||
fi
|
||||
i=1
|
||||
cmd="snapper --verbose --config \"$snapper_target_config\" list --type single | awk '/'\"$snap_description_running\"'/' | awk -F '|' '\$1 == "$snapper_new_id" {print \$1}'"
|
||||
# !!! ugly hack !!!: wait for snapper to list target snapshot in database. how to trigger database resync?
|
||||
# it is not deterministic, when the entry in the listing will show up .... for now, wait max 10 min ...
|
||||
while [ "$i" -le 20 ]; do
|
||||
if [ -n "$ssh" ]; then
|
||||
ret=$($ssh $cmd)
|
||||
else
|
||||
ret=$(eval $cmd)
|
||||
fi
|
||||
#printf "return: '%s'\n" "$ret"
|
||||
if [ -n "$ret" ]; then
|
||||
if [ "$ret" -eq "$snapper_new_id" ]; then
|
||||
cmd="snapper --verbose --config \"$snapper_target_config\" modify --description \"$snap_description_finished\" --userdata \"$target_userdata\" \"$snapper_new_id\""
|
||||
if [ -n "$ssh" ]; then
|
||||
ret=$($ssh "$cmd")
|
||||
else
|
||||
ret=$(eval $cmd)
|
||||
fi
|
||||
#printf "return: '%s'\n" "$ret"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
if [ "$verbose" ]; then
|
||||
printf "Waiting for snappers database update on target ...\n"
|
||||
fi
|
||||
sleep 30
|
||||
i=$(($i + 1))
|
||||
done
|
||||
else
|
||||
cmd="snapper --verbose --config $selected_config modify --description $snap_description_lastsync --userdata $userdata $snapper_new_id"
|
||||
cmd="snapper --verbose --config $selected_config modify --description $snap_description_synced --userdata $userdata $snapper_new_id"
|
||||
printf "dryrun: %s\n" "$cmd"
|
||||
cmd="$ssh snapper --verbose --config $snapper_target_config modify -description $snap_description_finished --userdata $target_userdata $snapper_new_id"
|
||||
printf "dryrun: %s\n" "$cmd"
|
||||
fi
|
||||
|
||||
# Cleanup old source snapshots
|
||||
source_description="snap-sync backup"
|
||||
$(eval snapper --verbose --config "$selected_config" modify --description \"$source_description\" --cleanup timeline "$snapper_sync_id")
|
||||
#snapper -c "$selected_config" delete "$snapper_sync_id"
|
||||
sync
|
||||
# Cleanup synced source snapshots
|
||||
if [ -n "$snapper_sync_id" ]; then
|
||||
cmd="snapper --verbose --config \"$snapper_config\" modify --description \"$snap_description_finished\" --cleanup timeline \"$snapper_sync_id\""
|
||||
ret=$(eval $cmd)
|
||||
#printf "return: '%s'\n" "$ret"
|
||||
sync
|
||||
fi
|
||||
|
||||
printf "Backup complete for snapper configuration '%s'.\n" "$selected_config" > $PIPE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user