How to synchronize ZFS snapshots between CLI and GUI in SynetoOS 5

Written By Christian Castagna (Administrator)

Updated at July 17th, 2025

→ Applies to: SynetoOS 5.x

 

Step 1. Connect to SynetoOS appliance via SSH as admin  (replace <your_ip_address_or_hostname> with the correct ip/hostname)

ssh admin@<your_ip_address_or_hostname>

 

Step 2. Become Super User

sudo su

 

Step 3. Create sync_gui_snapshots.sh file

vi /tmp/sync_gui_snapshots.sh

IMPORTANT
Make sure to copy and paste the exact lines below.

#!/usr/bin/env bash

# This script deletes from chronos db recovery points that are not found on the system

# Exit on nonzero status
set -o errexit
# Fail pipeline if any commad in the pipeline returns nonzero
set -o pipefail

function on_exit() {
	# This function is invoked on script exit. Use this to perform cleanup operations.
	if [[ -n "$INFILE" ]]; then
		rm -f "$INFILE" &>/dev/null
	fi
	if [[ -n "$OUTFILE" ]]; then
		rm -f "$OUTFILE" &>/dev/null
	fi
	if [[ -n "$CHRONOS_OUTFILE" ]]; then
		kubectl exec pod/"$CHRONOS_POD_NAME" -- sh -c 'rm -f '"$CHRONOS_OUTFILE" &>/dev/null
	fi
}

# Stop all processes created by script when user presses Ctrl+C
trap "echo -e '\nCancelled' >&2 ; exit 130" SIGINT
trap on_exit EXIT

INFILE=$(mktemp)

echo
echo 'Before continuing, please ensure that:'
echo
echo '    1. no protection is running or about to run'
echo '    2. all desired pools are online'
echo
read -rp 'Do you want to continue? (y/n): ' choice
if [[ "$choice" != "y" ]]; then
	echo 'Cancelled'
	exit 1
fi

echo
echo 'Retrieving snapshot names from all pools'
zfs list -Hrt snap | grep syn-volumes | cut -f1 | grep -oP '(?<=@).*$' > "$INFILE"
echo

snapshot_count=$(wc -l < "$INFILE")
if [[ "$snapshot_count" -eq 0 ]]; then
	echo "No snapshots found. Are pools online?"
	exit 1
else
	echo "Found $snapshot_count snapshots in total"
fi

OUTFILE=$(mktemp)

echo 'SELECT snapshot_name FROM recovery_points WHERE snapshot_name NOT IN (' > "$OUTFILE"
while IFS= read -r snap_name; do
	echo "    '$snap_name'," >> "$OUTFILE"
done < "$INFILE"
unset snap_name
sed -i '$s/,$//' "$OUTFILE"
echo ');' >> "$OUTFILE"


CHRONOS_HOME=/home/syneto-chronos # Do not put trailing slash here
CHRONOS_OUTFILE=$CHRONOS_HOME/query.sql
CHRONOS_POD_NAME=$(kubectl get pods -o custom-columns=":metadata.name" | grep chronos)

kubectl cp "$OUTFILE" "$CHRONOS_POD_NAME":"$CHRONOS_OUTFILE"
SNAPSHOTS_TO_DELETE=$(kubectl exec pod/"$CHRONOS_POD_NAME" -- sh -c 'PGPASSWORD=$POSTGRES_PASSWORD psql -tA --host $POSTGRES_HOST --user postgres chronos -f '"$CHRONOS_OUTFILE")

snapshot_to_delete_count=$(grep -cP '\S' <<<"$SNAPSHOTS_TO_DELETE" || true)
echo
if [[ "$snapshot_to_delete_count" -eq 0 ]]; then
	echo "No recovery points to delete. Exiting."
	exit 0
else
	echo "$snapshot_to_delete_count recovery points are going to be deleted from chronos db:"
	echo
	echo "$SNAPSHOTS_TO_DELETE"
fi

echo
read -rp 'Do you want to continue? (y/n): ' choice
if [[ "$choice" != "y" ]]; then
	echo 'Cancelled'
	exit 1
fi
echo

# Replace SELECT with DELETE
sed -i 's/^SELECT snapshot_name/DELETE/' "$OUTFILE"
kubectl cp "$OUTFILE" "$CHRONOS_POD_NAME":"$CHRONOS_OUTFILE"

kubectl exec pod/"$CHRONOS_POD_NAME" -- sh -c 'PGPASSWORD=$POSTGRES_PASSWORD psql --host $POSTGRES_HOST --user postgres chronos -f '"$CHRONOS_OUTFILE"

echo
echo 'Done.'

 

Save and EXIT

:wq

 

Step 4. Give permissions to sync_gui_snapshots.sh file

chmod +x /tmp/sync_gui_snapshots.sh

 

Step 5. Sync the snapshots

./tmp/sync_gui_snapshots.sh

 

Step 6. Delete the sync_gui_snapshots.sh file after the snapshots have been synchronized

rm /tmp/sync_gui_snapshots.sh