Further improvments around compositions

This commit is contained in:
m8in
2026-06-27 01:36:14 +02:00
parent 8a4426961c
commit cb0a32ac0e
6 changed files with 85 additions and 55 deletions
@@ -38,10 +38,10 @@ function setup() {
&& echo
echo "Optionally you can create following file:"
echo " - rollback (e.g.: date +%F > rollback) : allows the removal of the newest @SYNC snapshots of this day,"
echo " as long as no normal snapshot is reached."
echo " - ssh-port (e.g.: echo 22 > ssh-port) : allows to use a custom port for the SSH connection."
echo ' - zfs-branch (e.g.: echo zpool1/persistent > zfs-branch) : allows to use a custom zfs prefix like: ${zfs-branch}/${composition}.'
echo " - rollback (e.g.: date +%F > rollback) : allows the removal of the newest @SYNC snapshots of this day,"
echo " as long as no normal snapshot is reached."
echo " - ssh-port (e.g.: echo 22 > ssh-port) : allows to use a custom port for the SSH connection."
echo ' - zfs (e.g.: echo zpool1/persistent/${composition} > zfs) : allows to use a custom zfs prefix like: ${zfs}.'
return 0
}
+15 -18
View File
@@ -96,15 +96,14 @@ function sendResume() {
}
function send() {
local _ZFS_BRANCH _COMPOSITION _RECEIVERHOST _RECEIVERS_SNAPSHOT _NOW _ZFS _NEW_SNAPSHOT
_ZFS_BRANCH="${1:?"send(): Missing first parameter ZFS_BRANCH"}"
_COMPOSITION="${2:?"send(): Missing first parameter COMPOSITION"}"
_RECEIVERHOST="${3:?"send(): Missing second parameter RECEIVERHOST"}"
_RECEIVERS_SNAPSHOT="${4}"
local _COMPOSITION _RECEIVERHOST _RECEIVERS_SNAPSHOT _NOW _ZFS _NEW_SNAPSHOT
_COMPOSITION="${1:?"send(): Missing first parameter COMPOSITION"}"
_RECEIVERHOST="${2:?"send(): Missing second parameter RECEIVERHOST"}"
_RECEIVERS_SNAPSHOT="${3}"
_NOW=$(date -u "+%Y-%m-%d_%H:%M:%SZ")
_ZFS="${_ZFS_BRANCH:?"Missing ZFS_BRANCH"}/${_COMPOSITION:?"Missing COMPOSITION"}"
_ZFS=$(composition.printZfsVerified "${_COMPOSITION}")
_NEW_SNAPSHOT="${_ZFS:?"Missing ZFS"}@SYNC_${_RECEIVERHOST:?"Missing RECEIVERHOST"}_${_NOW:?"Missing NOW"}"
readonly _ZFS_BRANCH _COMPOSITION _RECEIVERHOST _RECEIVERS_SNAPSHOT _NOW _ZFS _NEW_SNAPSHOT
readonly _COMPOSITION _RECEIVERHOST _RECEIVERS_SNAPSHOT _NOW _NEW_SNAPSHOT
# This common snapshot is the starting-point, if available.
! _COMMON_SNAPSHOT=$(printFoundCommonSnapshot "${_ZFS}" "${_RECEIVERHOST}" "${_RECEIVERS_SNAPSHOT}") \
@@ -127,30 +126,28 @@ function send() {
# Parameter 1: Only alphanumeric characters allowed and [._-] if not leading (due to: -oProxyCommand=...).
# Parameter 2: Only alphanumeric characters allowed and [/_-] if not leading (due to: -oProxyCommand=...).
# Parameter 3: Only alphanumeric characters allowed and [.-] if not leading (due to: -oProxyCommand=...).
# Parameter 1: Only alphanumeric characters allowed and [.-] if not leading (due to: -oProxyCommand=...).
# Parameter 2: Only alphanumeric characters allowed and [._-] if not leading (due to: -oProxyCommand=...).
# Parameter 3: Only alphanumeric characters allowed and [._:-] if not leading (due to: -oProxyCommand=...), but can be empty.
# Parameter 4: Only alphanumeric characters allowed and [._:-] if not leading (due to: -oProxyCommand=...), but can be empty.
# Parameter 5: Only alphanumeric characters allowed and [._:-] if not leading (due to: -oProxyCommand=...), but can be empty.
base.set RECEIVERHOST "${1}" "${REGEX[HOST]}"
base.set ZFS_BRANCH "${2}" "${REGEX[ZFS]}"
base.set COMPOSITION "${3}" "${REGEX[COMPOSITION]}"
base.set RECEIVERS_SNAPSHOT "${4}" "${REGEX[SNAPSHOT]}" optional
base.set RESUME_TOKEN "${5}" '^[a-zA-Z0-9][a-zA-Z0-9._:-]*$' optional
base.set COMPOSITION "${1}" "${REGEX[COMPOSITION]}"
base.set RECEIVERHOST "${2}" "${REGEX[HOST]}"
base.set RECEIVERS_SNAPSHOT "${3}" "${REGEX[SNAPSHOT]}" optional
base.set RESUME_TOKEN "${4}" '^[a-zA-Z0-9][a-zA-Z0-9._:-]*$' optional
! composition.shouldBeSyncedByGivenHost "${COMPOSITION}" "${RECEIVERHOST}" \
&& base.abort "no sync-host available" \
"Host '${RECEIVERHOST}' is no sync-host for composition: '${COMPOSITION}'"
# Resume mode
if [ "${RECEIVERS_SNAPSHOT}" == "@RESUME" ] && [ -n "${RESUME_TOKEN}" ]; then
if [ "${RECEIVERS_SNAPSHOT}" == '@RESUME' ] && [ -n "${RESUME_TOKEN}" ]; then
sendResume "${RESUME_TOKEN}"
# Exit preserving the code
exit $?
fi
send "${ZFS_BRANCH}" "${COMPOSITION}" "${RECEIVERHOST}" "${RECEIVERS_SNAPSHOT}" \
send "${COMPOSITION}" "${RECEIVERHOST}" "${RECEIVERS_SNAPSHOT}" \
&& exit 0
print.failure "Something unexpected happend."
+15 -17
View File
@@ -89,7 +89,7 @@ function tryRollbackToRepair() {
}
function receive() {
local _RECEIVERHOST _COMPOSITION _SOURCEHOST _SSH_PORT _SSH_COMMAND _SEND_SCRIPT _ZFS_BRANCH _ZFS
local _RECEIVERHOST _COMPOSITION _SOURCEHOST _SSH_PORT _SSH_COMMAND _SEND_SCRIPT _ZFS_BACKUP
_COMPOSITION="${1:?"receive(): Missing first parameter COMPOSITION"}"
_RECEIVERHOST="${CIS[HOST]:?"Missing CIS_HOST"}"
base.set _SOURCEHOST "$(composition.printRunningHost "${_COMPOSITION}")" '^[a-zA-Z0-9][a-zA-Z0-9.-]*$'
@@ -97,47 +97,45 @@ function receive() {
base.set _SSH_PORT "${_SSH_PORT:-22}" '^[1-9][0-9]{1,4}$'
_SSH_COMMAND="ssh -p ${_SSH_PORT} -o ConnectTimeout=20 -o ServerAliveInterval=15 -C composition-sync@${_SOURCEHOST}"
_SEND_SCRIPT="${CIS[SCRIPTSROOT]:?"Missing CIS_SCRIPTSROOT"}host/zfs/composition-sync/sync-send.sh"
_ZFS_BRANCH=$(head -n 1 "${CIS[DOMAINDEFINITIONS]:?"Missing CIS_DOMAINDEFINITIONS"}compositions/${_COMPOSITION}/zfs-branch" 2> /dev/null)
base.set _ZFS_BRANCH "${_ZFS_BRANCH:-zpool1/persistent}" '^[a-zA-Z][a-zA-Z0-9/_-]*[a-zA-Z0-9]$'
_ZFS="${_ZFS_BRANCH%/}/${_COMPOSITION}-BACKUP"
readonly _RECEIVERHOST _COMPOSITION _SSH_COMMAND _SEND_SCRIPT _ZFS_BRANCH _ZFS
_ZFS_BACKUP="$(composition.printZfs "${_COMPOSITION}")-BACKUP"
readonly _RECEIVERHOST _COMPOSITION _SSH_COMMAND _SEND_SCRIPT _ZFS_BACKUP
(
flock -n 9 || exit 1
_COMMON_SNAPSHOT=""
_RESUME_TOKEN=$(zfs get -H -o value receive_resume_token "${_ZFS}" 2> /dev/null)
_RESUME_TOKEN=$(zfs get -H -o value receive_resume_token "${_ZFS_BACKUP}" 2> /dev/null)
if [ -n "${_RESUME_TOKEN}" ] && [ "${_RESUME_TOKEN}" != "-" ]; then
print.important "Resume token present trying to resume at ${_RESUME_TOKEN}\n"
_COMMON_SNAPSHOT="@RESUME"
else
_RESUME_TOKEN=""
_COMMON_SNAPSHOT=$(zfs list -H -o name -S creation -t snapshot "${_ZFS}" 2> /dev/null | head -n 1)
! [ -z "${_COMMON_SNAPSHOT}" ] \
_COMMON_SNAPSHOT=$(zfs list -H -o name -S creation -t snapshot "${_ZFS_BACKUP}" 2> /dev/null | head -n 1)
[ -n "${_COMMON_SNAPSHOT}" ] \
&& print.data "Rolling back to newest snapshot: ${_COMMON_SNAPSHOT} ... " \
&& zfs rollback -r "${_COMMON_SNAPSHOT}" \
&& _COMMON_SNAPSHOT="@${_COMMON_SNAPSHOT#*@}" \
&& print.good "done\n"
fi
# Add "-s" for resumable streams in the next line at zfs receive. Not done yet because of: cannot receive resume stream: kernel modules must be upgraded to receive this stream.
${_SSH_COMMAND} "sudo ${_SEND_SCRIPT:?"Missing SEND_SCRIPT"} \"${_RECEIVERHOST}\" \"${_ZFS_BRANCH}\" \"${_COMPOSITION}\" \"@${_COMMON_SNAPSHOT#*@}\" \"${_RESUME_TOKEN}\"" | zfs receive -v "${_ZFS}"
${_SSH_COMMAND} "sudo ${_SEND_SCRIPT:?"Missing SEND_SCRIPT"} \"${_COMPOSITION}\" \"${_RECEIVERHOST}\" \"${_COMMON_SNAPSHOT}\" \"${_RESUME_TOKEN}\"" | zfs receive -v "${_ZFS_BACKUP}"
if [ $? -ne 0 ]; then
print.failure "Unable to receive stream" \
"These settings were used" \
"- Sending host: ${_SOURCEHOST}:${_SSH_PORT}" \
"- Receiving host: ${_RECEIVERHOST}" \
"- ZFS Branch: ${_ZFS_BRANCH}" \
"- Composition: ${_COMPOSITION}" \
"- Offered snapshot: @${_COMMON_SNAPSHOT#*@}" \
"- Receiving host: ${_RECEIVERHOST}" \
"- Offered snapshot: ${_COMMON_SNAPSHOT}" \
"- Resume token: ${_RESUME_TOKEN}"
print.highlight "Current state of snapshots:\n"
zfs list -t snapshot "${_ZFS}" 2> /dev/null | tail
tryRollbackToRepair "${_COMPOSITION}" "${_ZFS}" && return 0
zfs list -t snapshot "${_ZFS_BACKUP}" 2> /dev/null | tail
tryRollbackToRepair "${_COMPOSITION}" "${_ZFS_BACKUP}" && return 0
return 1
fi
protectZFS "${_ZFS}"
removeForeignSyncSnapshots "${_ZFS}"
removeOutdatedSyncSnapshots "${_ZFS}"
protectZFS "${_ZFS_BACKUP}"
removeForeignSyncSnapshots "${_ZFS_BACKUP}"
removeOutdatedSyncSnapshots "${_ZFS_BACKUP}"
) 9>>/tmp/synccomposition.${_COMPOSITION}.lock
+2 -2
View File
@@ -16,7 +16,7 @@ function cleanup() {
local _COMPOSITION _ZFS
composition.printAll | while read -r _COMPOSITION; do
_ZFS="$(composition.printZFS "${_COMPOSITION}")"
_ZFS="$(composition.printZfsVerified "${_COMPOSITION}")"
[ -n "${_ZFS}" ] \
&& printf -- "Cleaning snapshots of: '%b'\n" "${_ZFS}" \
&& local _LIST=( $(zfs list -t snap -H -o name -S creation "${_ZFS}" | grep -F '@SNAP' ) )
@@ -87,7 +87,7 @@ function snapshot() {
_MODE="${1:-"$(cat "${CIS[COMPOSITIONS]}${_COMPOSITION}/snapshot-mode" 2> /dev/null)"}"
_MODE="${_MODE:-"HOURLY"}"
_ZFS="$(composition.printZFS "${_COMPOSITION}")"
_ZFS="$(composition.printZfsVerified "${_COMPOSITION}")"
if [ -n "${_ZFS}" ]; then
(
flock -n 9 || return 1