runtime: publish SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1
This commit is contained in:
+38
File diff suppressed because one or more lines are too long
+130
@@ -0,0 +1,130 @@
|
|||||||
|
CHAT_OUTPUT_BEGIN
|
||||||
|
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1
|
||||||
|
STATUS=FAIL
|
||||||
|
RC=2
|
||||||
|
HOST=pve01
|
||||||
|
MODE=read-only
|
||||||
|
COMPONENT=infra-dr-backupv2-control-backup-logic-focus
|
||||||
|
REFERENCE_REGISTER_CHECK=OK
|
||||||
|
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||||
|
ERROR_REGISTER_CHECK=OK
|
||||||
|
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||||
|
COMMAND_SHA256=9980bab4ad121c27772e38557dd65e4015aa4f3f718e5fcdc6e8dff43be4cd03
|
||||||
|
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
||||||
|
EXECUTION_STARTED=true
|
||||||
|
CHANGE_DECLARED=false
|
||||||
|
RESULT_CONTRACT_VALID=true
|
||||||
|
RESULT_CONTRACT_STATUS=NOT_APPLICABLE
|
||||||
|
RESULT_CONTRACT_ERROR=NONE
|
||||||
|
COMMAND_RC=2
|
||||||
|
CHANGES_MADE=false
|
||||||
|
ROLLBACK_STARTED=false
|
||||||
|
ROLLBACK_RESTORED=null
|
||||||
|
MUTATION_OUTCOME=NO_MUTATION
|
||||||
|
SANITIZED=yes
|
||||||
|
SECRETS_INCLUDED=no
|
||||||
|
PRIVATE_ADDRESSES_INCLUDED=no
|
||||||
|
RAW_EVIDENCE_SHA256=cb86b6a96cfd10465cf8955bc75edde6147f7b65633d31dd3f958e33501c2a82
|
||||||
|
SANITIZED_OUTPUT_SHA256=e987624faf1aaf226e4a886a8bc963d4096bd01e5f5a5f3d283c195d15db6c98
|
||||||
|
OUTPUT_BEGIN
|
||||||
|
FOCUS256_BEGIN
|
||||||
|
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1
|
||||||
|
MODE=READ_ONLY_LOCAL_SOURCE_LOGIC_FOCUS
|
||||||
|
CLOUD_CALLS_BY_256=0
|
||||||
|
RCLONE_COMMANDS_EXECUTED_BY_256=0
|
||||||
|
ERROR_REGISTER_CHECK=READ
|
||||||
|
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||||
|
REFERENCE_CHECK=READ
|
||||||
|
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||||
|
AUTHORITY_FRESH_READ=OK
|
||||||
|
TARGET_SHA256=0b3a0f685d4e67cb86250df89a4918aff2e6c67799b7d35b0e54b1bbc016ee57
|
||||||
|
TARGET_SHA_MATCH=YES
|
||||||
|
UNIT_SHA256=428d3e1f3042c3347b7c34b6f190e44fa35f7a97264eec3974239f581c9b9250
|
||||||
|
UNIT_SHA_MATCH=YES
|
||||||
|
TARGET_LINE_COUNT=150
|
||||||
|
FOCUS_FUNCTION=prepare_rclone
|
||||||
|
FOCUS_SPAN=66-69
|
||||||
|
FOCUS_BODY_BEGIN=prepare_rclone
|
||||||
|
L066=prepare_rclone(){
|
||||||
|
L067= local dst="$1"; [[ -f "$RCLONE_CONFIG_SOURCE" && ! -L "$RCLONE_CONFIG_SOURCE" ]] || die RCLONE_CONFIG_UNSAFE 66
|
||||||
|
L068= install -m 0600 "$RCLONE_CONFIG_SOURCE" "$dst"
|
||||||
|
L069=}
|
||||||
|
FOCUS_BODY_END=prepare_rclone
|
||||||
|
FOCUS_FUNCTION=run_backup
|
||||||
|
FOCUS_SPAN=109-150
|
||||||
|
FOCUS_BODY_BEGIN=run_backup
|
||||||
|
L109=run_backup(){
|
||||||
|
L110= local force="${1:-0}" decision line state gen payload outdir now
|
||||||
|
L111= mkdir -p "$STATE_DIR" "$EVIDENCE_ROOT" "$STAGE_ROOT" "$VERIFY_ROOT" /run/lock; chmod 0700 "$STATE_ROOT" "$STATE_DIR" "$EVIDENCE_ROOT" "$STAGE_ROOT" "$VERIFY_ROOT"
|
||||||
|
L112= exec 9>"$LOCK"; flock -n 9 || { printf 'CONTROL_BACKUP_DEFERRED=LOCK_BUSY\n'; return 0; }
|
||||||
|
L113= local incompletes
|
||||||
|
L114= incompletes="$(find "$STATE_DIR" -maxdepth 1 -type f -name 'control-bootstrap-v2-pve01-????????T??????Z.json' -print0 2>/dev/null | xargs -0 -r jq -r 'select(.status!="SEALED")|.generation' 2>/dev/null || true)"
|
||||||
|
L115= [[ "$(grep -c . <<<"$incompletes" || true)" -le 1 ]] || die MULTIPLE_INCOMPLETE_GENERATIONS 68
|
||||||
|
L116= line="$(scan)"; printf '%s\n' "$line"; decision="$(awk '{for(i=1;i<=NF;i++)if($i~/^DECISION=/){sub(/^DECISION=/,"",$i);print $i}}' <<<"$line")"
|
||||||
|
L117= gen="$(awk '{for(i=1;i<=NF;i++)if($i~/^GENERATION=/){sub(/^GENERATION=/,"",$i);print $i}}' <<<"$line")"
|
||||||
|
L118= if [[ "$decision" == SKIP_FRESH && "$force" != 1 ]]; then printf 'CONTROL_BACKUP_RESULT=SKIP_FRESH GENERATION=%s\n' "$gen"; return 0; fi
|
||||||
|
L119= if [[ "$decision" == BACKUP_REVERIFY ]]; then
|
||||||
|
L120= if [[ "$force" != 1 ]]; then verify_generation "$gen"; return 0; fi
|
||||||
|
L121= # Forced refresh deliberately creates a new generation instead of requiring
|
||||||
|
L122= # a legacy generation to satisfy the current bundle schema.
|
||||||
|
L123= decision=BACKUP_DUE
|
||||||
|
L124= fi
|
||||||
|
L125= if [[ "$decision" == BACKUP_RESUME ]]; then
|
||||||
|
L126= state="$STATE_DIR/$gen.json"; payload="$(jq -er '.payload_path' "$state")"; [[ -s "$payload" && ! -L "$payload" ]] || die INCOMPLETE_PAYLOAD_MISSING 68
|
||||||
|
L127= "$BUILDER" verify --archive "$payload" --expected-generation "$gen" >/dev/null || die <LONG_TOKEN_REDACTED> 68
|
||||||
|
L128= mark_cloud_write
|
||||||
|
L129= "$TRANSPORT" backup-delete "$LOGICAL_ID" "$gen" "$payload" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT"; verify_generation "$gen"; printf 'CONTROL_BACKUP_RESULT=SEALED_RESUMED GENERATION=%s\n' "$gen"; return 0
|
||||||
|
L130= fi
|
||||||
|
L131= case "$decision" in BACKUP_DUE|BACKUP_STALE|BACKUP_UNVERIFIED|SKIP_FRESH) ;; *) die "DECISION_INVALID_$decision" 65;; esac
|
||||||
|
L132= exec 8>"$HEAVY_LOCK"; flock -n 8 || { printf 'CONTROL_BACKUP_DEFERRED=HEAVY_LOCK_BUSY\n'; return 0; }
|
||||||
|
L133= now="$(date -u +%Y%m%dT%H%M%SZ)"; gen="control-bootstrap-v2-pve01-$now"; outdir="$STAGE_ROOT/$gen"
|
||||||
|
L134= "$BUILDER" build --generation "$gen" --output-dir "$outdir" >/dev/null
|
||||||
|
L135= payload="$outdir/$gen.tar.gz"; [[ -s "$payload" && ! -L "$payload" ]] || die BUILT_PAYLOAD_MISSING 68
|
||||||
|
L136= "$BUILDER" verify --archive "$payload" --expected-generation "$gen" >/dev/null || die <LONG_TOKEN_REDACTED> 68
|
||||||
|
L137= exec 8>&-
|
||||||
|
L138= mark_cloud_write
|
||||||
|
L139= "$TRANSPORT" backup-delete "$LOGICAL_ID" "$gen" "$payload" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT"
|
||||||
|
L140= rm -rf --one-file-system "$outdir" 2>/dev/null || true
|
||||||
|
L141= verify_generation "$gen"
|
||||||
|
L142= printf 'CONTROL_BACKUP_RESULT=SEALED_NEW GENERATION=%s\n' "$gen"
|
||||||
|
L143=}
|
||||||
|
L144=case "${1:-}" in
|
||||||
|
L145= scan) [[ "$#" == 1 ]] || die USAGE 64; scan;;
|
||||||
|
L146= run) [[ "$#" == 1 ]] || die USAGE 64; run_backup 0;;
|
||||||
|
L147= force) [[ "$#" == 1 ]] || die USAGE 64; run_backup 1;;
|
||||||
|
L148= verify) [[ "$#" == 2 ]] || die USAGE 64; verify_generation "$2";;
|
||||||
|
L149= *) die USAGE_scan_run_force_verify 64;;
|
||||||
|
L150=esac
|
||||||
|
FOCUS_BODY_END=run_backup
|
||||||
|
FOCUS_FUNCTION=verify_generation
|
||||||
|
FOCUS_SPAN=87-108
|
||||||
|
FOCUS_BODY_BEGIN=verify_generation
|
||||||
|
L087=verify_generation(){
|
||||||
|
L088= local gen state work cfg base_a base_b a b verify_json archive_sha tmp now
|
||||||
|
L089= gen="$1"
|
||||||
|
L090= state="$STATE_DIR/$gen.json"
|
||||||
|
L091= [[ -s "$state" && ! -L "$state" ]] || die VERIFY_STATE_UNSAFE 68
|
||||||
|
L092= "$TRANSPORT" verify-sealed "$LOGICAL_ID" "$gen" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT" >/dev/null
|
||||||
|
L093= mkdir -p "$VERIFY_ROOT"; chmod 0700 "$VERIFY_ROOT"
|
||||||
|
L094= work="$(mktemp -d "$VERIFY_ROOT/.verify.XXXXXX")"; cfg="$work/[SENSITIVE_FILE]"; prepare_rclone "$cfg"
|
||||||
|
L095= cleanup_verify(){ rm -rf --one-file-system "$work"; }; trap cleanup_verify EXIT
|
||||||
|
L096= base_a="$(jq -er '.remote_a_base' "$state")"; base_b="$(jq -er '.remote_b_base' "$state")"; a="$work/A.tar.gz"; b="$work/B.tar.gz"
|
||||||
|
L097= reconstruct "$base_a" "$a" "$cfg" "$state" A; reconstruct "$base_b" "$b" "$cfg" "$state" B
|
||||||
|
L098= cmp -s "$a" "$b" || die CLOUD_A_B_PAYLOAD_MISMATCH 68
|
||||||
|
L099= verify_json="$("$BUILDER" verify --archive "$a" --expected-generation "$gen")" || die <LONG_TOKEN_REDACTED> 68
|
||||||
|
L100=<REDACTED_SENSITIVE_LINE>
|
||||||
|
L101= archive_sha="$(jq -er '.archive_sha256' "$state")"; mkdir -p "$EVIDENCE_ROOT" /var/lib/homelab-health; chmod 0700 "$EVIDENCE_ROOT"
|
||||||
|
L102= tmp="$EVIDENCE_ROOT/.$gen.new.$$"; now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
L103=<REDACTED_SENSITIVE_LINE>
|
||||||
|
L104= chmod 0600 "$tmp"; mv -f "$tmp" "$EVIDENCE_ROOT/$gen.json"
|
||||||
|
L105= tmp="${HEALTH}.new.$$"; jq -n --arg gen "$gen" --arg state "$state" --arg evidence "$EVIDENCE_ROOT/$gen.json" --arg sha "$archive_sha" --arg now "$now" '{schema:"homelab-control-backup-health-v1",status:"OK",generation:$gen,state_file:$state,restore_evidence:$evidence,archive_sha256:$sha,cloud_quorum:2,control_freshness:"FRESH",full_site_dr_proven:false,updated_at_utc:$now}' >"$tmp"; chmod 0644 "$tmp"; mv -f "$tmp" "$HEALTH"
|
||||||
|
L106= trap - EXIT; cleanup_verify
|
||||||
|
L107= printf 'CONTROL_VERIFY=OK GENERATION=%s EVIDENCE=%s\n' "$gen" "$EVIDENCE_ROOT/$gen.json"
|
||||||
|
L108=}
|
||||||
|
FOCUS_BODY_END=verify_generation
|
||||||
|
FOCUS256_STOP=FOCUS_FUNCTION_MISSING
|
||||||
|
FOCUS256_DETAIL=cleanup_verify
|
||||||
|
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1","status":"FAIL","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
||||||
|
|
||||||
|
OUTPUT_END
|
||||||
|
CHAT_OUTPUT_END
|
||||||
+11
-11
File diff suppressed because one or more lines are too long
+96
-89
@@ -1,22 +1,22 @@
|
|||||||
CHAT_OUTPUT_BEGIN
|
CHAT_OUTPUT_BEGIN
|
||||||
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-255R1
|
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1
|
||||||
STATUS=OK
|
STATUS=FAIL
|
||||||
RC=0
|
RC=2
|
||||||
HOST=pve01
|
HOST=pve01
|
||||||
MODE=read-only
|
MODE=read-only
|
||||||
COMPONENT=infra-dr-backupv2-control-backup-logic
|
COMPONENT=infra-dr-backupv2-control-backup-logic-focus
|
||||||
REFERENCE_REGISTER_CHECK=OK
|
REFERENCE_REGISTER_CHECK=OK
|
||||||
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||||
ERROR_REGISTER_CHECK=OK
|
ERROR_REGISTER_CHECK=OK
|
||||||
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||||
COMMAND_SHA256=2c1d227e011446eb686ecf97218c70c89f651616f45b4bb3e68f32bba3533ace
|
COMMAND_SHA256=9980bab4ad121c27772e38557dd65e4015aa4f3f718e5fcdc6e8dff43be4cd03
|
||||||
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
||||||
EXECUTION_STARTED=true
|
EXECUTION_STARTED=true
|
||||||
CHANGE_DECLARED=false
|
CHANGE_DECLARED=false
|
||||||
RESULT_CONTRACT_VALID=true
|
RESULT_CONTRACT_VALID=true
|
||||||
RESULT_CONTRACT_STATUS=NOT_APPLICABLE
|
RESULT_CONTRACT_STATUS=NOT_APPLICABLE
|
||||||
RESULT_CONTRACT_ERROR=NONE
|
RESULT_CONTRACT_ERROR=NONE
|
||||||
COMMAND_RC=0
|
COMMAND_RC=2
|
||||||
CHANGES_MADE=false
|
CHANGES_MADE=false
|
||||||
ROLLBACK_STARTED=false
|
ROLLBACK_STARTED=false
|
||||||
ROLLBACK_RESTORED=null
|
ROLLBACK_RESTORED=null
|
||||||
@@ -24,100 +24,107 @@ MUTATION_OUTCOME=NO_MUTATION
|
|||||||
SANITIZED=yes
|
SANITIZED=yes
|
||||||
SECRETS_INCLUDED=no
|
SECRETS_INCLUDED=no
|
||||||
PRIVATE_ADDRESSES_INCLUDED=no
|
PRIVATE_ADDRESSES_INCLUDED=no
|
||||||
RAW_EVIDENCE_SHA256=4be463d9015eac40cac32a68aa1b48e571e45d59f953244a55f8eba2d6e159cb
|
RAW_EVIDENCE_SHA256=cb86b6a96cfd10465cf8955bc75edde6147f7b65633d31dd3f958e33501c2a82
|
||||||
SANITIZED_OUTPUT_SHA256=f367fb4787ad044b2e839dc8ca1d49f1687c27df5a650940aeacd85661a27130
|
SANITIZED_OUTPUT_SHA256=e987624faf1aaf226e4a886a8bc963d4096bd01e5f5a5f3d283c195d15db6c98
|
||||||
OUTPUT_BEGIN
|
OUTPUT_BEGIN
|
||||||
LOGIC255_BEGIN
|
FOCUS256_BEGIN
|
||||||
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-255R1
|
COMMAND_ID=SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1
|
||||||
MODE=READ_ONLY_LOCAL_SOURCE_LOGIC
|
MODE=READ_ONLY_LOCAL_SOURCE_LOGIC_FOCUS
|
||||||
CLOUD_CALLS_BY_255=0
|
CLOUD_CALLS_BY_256=0
|
||||||
RCLONE_COMMANDS_EXECUTED_BY_255=0
|
RCLONE_COMMANDS_EXECUTED_BY_256=0
|
||||||
ERROR_REGISTER_CHECK=READ
|
ERROR_REGISTER_CHECK=READ
|
||||||
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||||
REFERENCE_CHECK=READ
|
REFERENCE_CHECK=READ
|
||||||
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||||
AUTHORITY_FRESH_READ=OK
|
AUTHORITY_FRESH_READ=OK
|
||||||
TARGET_PATH=/usr/local/sbin/homelab-control-backup
|
|
||||||
TARGET_SHA256=0b3a0f685d4e67cb86250df89a4918aff2e6c67799b7d35b0e54b1bbc016ee57
|
TARGET_SHA256=0b3a0f685d4e67cb86250df89a4918aff2e6c67799b7d35b0e54b1bbc016ee57
|
||||||
TARGET_SHA_MATCH=YES
|
TARGET_SHA_MATCH=YES
|
||||||
UNIT_PATH=/etc/systemd/system/homelab-control-backup.service
|
|
||||||
UNIT_SHA256=428d3e1f3042c3347b7c34b6f190e44fa35f7a97264eec3974239f581c9b9250
|
UNIT_SHA256=428d3e1f3042c3347b7c34b6f190e44fa35f7a97264eec3974239f581c9b9250
|
||||||
UNIT_SHA_MATCH=YES
|
UNIT_SHA_MATCH=YES
|
||||||
TARGET_LINE_COUNT=150
|
TARGET_LINE_COUNT=150
|
||||||
FUNCTION_COUNT=0
|
FOCUS_FUNCTION=prepare_rclone
|
||||||
SOURCE_SKELETON_BEGIN
|
FOCUS_SPAN=66-69
|
||||||
SRC_LINE_001=#!/usr/bin/env bash
|
FOCUS_BODY_BEGIN=prepare_rclone
|
||||||
SRC_LINE_002=set -Eeuo pipefail
|
L066=prepare_rclone(){
|
||||||
SRC_LINE_003=umask 077
|
L067= local dst="$1"; [[ -f "$RCLONE_CONFIG_SOURCE" && ! -L "$RCLONE_CONFIG_SOURCE" ]] || die RCLONE_CONFIG_UNSAFE 66
|
||||||
SRC_LINE_004=LOGICAL_ID=control-bootstrap-v2
|
L068= install -m 0600 "$RCLONE_CONFIG_SOURCE" "$dst"
|
||||||
SRC_LINE_005=DUE_SECONDS=43200
|
L069=}
|
||||||
SRC_LINE_006=SLA_SECONDS=86400
|
FOCUS_BODY_END=prepare_rclone
|
||||||
SRC_LINE_007=STATE_ROOT=<LONG_TOKEN_REDACTED>
|
FOCUS_FUNCTION=run_backup
|
||||||
SRC_LINE_008=STATE_DIR=$STATE_ROOT/$LOGICAL_ID
|
FOCUS_SPAN=109-150
|
||||||
SRC_LINE_009=EVIDENCE_ROOT=<LONG_TOKEN_REDACTED>
|
FOCUS_BODY_BEGIN=run_backup
|
||||||
SRC_LINE_010=HEALTH=<LONG_TOKEN_REDACTED>.json
|
L109=run_backup(){
|
||||||
SRC_LINE_011=STAGE_ROOT=<LONG_TOKEN_REDACTED>
|
L110= local force="${1:-0}" decision line state gen payload outdir now
|
||||||
SRC_LINE_012=VERIFY_ROOT=<LONG_TOKEN_REDACTED>
|
L111= mkdir -p "$STATE_DIR" "$EVIDENCE_ROOT" "$STAGE_ROOT" "$VERIFY_ROOT" /run/lock; chmod 0700 "$STATE_ROOT" "$STATE_DIR" "$EVIDENCE_ROOT" "$STAGE_ROOT" "$VERIFY_ROOT"
|
||||||
SRC_LINE_013=LOCK=<LONG_TOKEN_REDACTED>.lock
|
L112= exec 9>"$LOCK"; flock -n 9 || { printf 'CONTROL_BACKUP_DEFERRED=LOCK_BUSY\n'; return 0; }
|
||||||
SRC_LINE_014=HEAVY_LOCK=/run/homelab-backup-heavy.lock
|
L113= local incompletes
|
||||||
SRC_LINE_015=RCLONE_CONFIG_SOURCE=${RCLONE_CONFIG:-/root/.config/rclone/[SENSITIVE_FILE]}
|
L114= incompletes="$(find "$STATE_DIR" -maxdepth 1 -type f -name 'control-bootstrap-v2-pve01-????????T??????Z.json' -print0 2>/dev/null | xargs -0 -r jq -r 'select(.status!="SEALED")|.generation' 2>/dev/null || true)"
|
||||||
SRC_LINE_016=TRANSPORT=<LONG_TOKEN_REDACTED>
|
L115= [[ "$(grep -c . <<<"$incompletes" || true)" -le 1 ]] || die MULTIPLE_INCOMPLETE_GENERATIONS 68
|
||||||
SRC_LINE_017=TRANSPORT_SHA=<LONG_TOKEN_REDACTED>
|
L116= line="$(scan)"; printf '%s\n' "$line"; decision="$(awk '{for(i=1;i<=NF;i++)if($i~/^DECISION=/){sub(/^DECISION=/,"",$i);print $i}}' <<<"$line")"
|
||||||
SRC_LINE_018=BUILDER=<LONG_TOKEN_REDACTED>
|
L117= gen="$(awk '{for(i=1;i<=NF;i++)if($i~/^GENERATION=/){sub(/^GENERATION=/,"",$i);print $i}}' <<<"$line")"
|
||||||
SRC_LINE_019=BUILDER_SHA=<LONG_TOKEN_REDACTED>
|
L118= if [[ "$decision" == SKIP_FRESH && "$force" != 1 ]]; then printf 'CONTROL_BACKUP_RESULT=SKIP_FRESH GENERATION=%s\n' "$gen"; return 0; fi
|
||||||
SRC_LINE_020=REMOTE_A=pve01-mail-01-crypt:homelab-backups
|
L119= if [[ "$decision" == BACKUP_REVERIFY ]]; then
|
||||||
SRC_LINE_021=REMOTE_B=pve01-mail-02-crypt:homelab-backups
|
L120= if [[ "$force" != 1 ]]; then verify_generation "$gen"; return 0; fi
|
||||||
SRC_LINE_022=CLOUD_WRITE_MARKER=${<LONG_TOKEN_REDACTED>:-}
|
L121= # Forced refresh deliberately creates a new generation instead of requiring
|
||||||
SRC_LINE_023=
|
L122= # a legacy generation to satisfy the current bundle schema.
|
||||||
SRC_LINE_024=die(){ printf 'CONTROL_BACKUP_ERROR=%s<LF>' "$1" >&2; exit "${2:-65}"; }
|
L123= decision=BACKUP_DUE
|
||||||
SRC_LINE_025=for c in jq date find sort tail cut sha256sum stat flock rclone mktemp cmp awk mkdir rm install xargs grep cat mv chmod; do command -v "$c" >/dev/null || die "TOOL_MISSING_$c" 69; done
|
L124= fi
|
||||||
SRC_LINE_026=[[ -x "$TRANSPORT" && ! -L "$TRANSPORT" ]] || die TRANSPORT_UNSAFE 69
|
L125= if [[ "$decision" == BACKUP_RESUME ]]; then
|
||||||
SRC_LINE_027=[[ "$(sha256sum "$TRANSPORT"|awk '{print $1}')" == "$TRANSPORT_SHA" ]] || die TRANSPORT_SHA_DRIFT 65
|
L126= state="$STATE_DIR/$gen.json"; payload="$(jq -er '.payload_path' "$state")"; [[ -s "$payload" && ! -L "$payload" ]] || die INCOMPLETE_PAYLOAD_MISSING 68
|
||||||
SRC_LINE_028=[[ -x "$BUILDER" && ! -L "$BUILDER" ]] || die BUILDER_UNSAFE 69
|
L127= "$BUILDER" verify --archive "$payload" --expected-generation "$gen" >/dev/null || die <LONG_TOKEN_REDACTED> 68
|
||||||
SRC_LINE_029=[[ "$(sha256sum "$BUILDER"|awk '{print $1}')" == "$BUILDER_SHA" ]] || die BUILDER_SHA_DRIFT 65
|
L128= mark_cloud_write
|
||||||
SRC_LINE_030=
|
L129= "$TRANSPORT" backup-delete "$LOGICAL_ID" "$gen" "$payload" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT"; verify_generation "$gen"; printf 'CONTROL_BACKUP_RESULT=SEALED_RESUMED GENERATION=%s\n' "$gen"; return 0
|
||||||
SOURCE_SKELETON_END
|
L130= fi
|
||||||
SOURCE_REDACTED_LINE_COUNT=0
|
L131= case "$decision" in BACKUP_DUE|BACKUP_STALE|BACKUP_UNVERIFIED|SKIP_FRESH) ;; *) die "DECISION_INVALID_$decision" 65;; esac
|
||||||
FIXED_REMOTE_PVE01_MAIL_01_CRYPT_LINES=20
|
L132= exec 8>"$HEAVY_LOCK"; flock -n 8 || { printf 'CONTROL_BACKUP_DEFERRED=HEAVY_LOCK_BUSY\n'; return 0; }
|
||||||
FIXED_REMOTE_PVE01_MAIL_02_CRYPT_LINES=21
|
L133= now="$(date -u +%Y%m%dT%H%M%SZ)"; gen="control-bootstrap-v2-pve01-$now"; outdir="$STAGE_ROOT/$gen"
|
||||||
MARKER_RCLONE_LINES=15,25,66,67,68,74,79,94
|
L134= "$BUILDER" build --generation "$gen" --output-dir "$outdir" >/dev/null
|
||||||
MARKER_SEALED_LINES=43,46,92,114,129,142
|
L135= payload="$outdir/$gen.tar.gz"; [[ -s "$payload" && ! -L "$payload" ]] || die BUILT_PAYLOAD_MISSING 68
|
||||||
MARKER_VERIFY_SEALED_LINES=92
|
L136= "$BUILDER" verify --archive "$payload" --expected-generation "$gen" >/dev/null || die <LONG_TOKEN_REDACTED> 68
|
||||||
MARKER_BACKUP_DELETE_LINES=129,139
|
L137= exec 8>&-
|
||||||
MARKER_LOCAL_CLEANUP_LINES=NONE
|
L138= mark_cloud_write
|
||||||
MARKER_RUN_BACKUP_LINES=109,146,147
|
L139= "$TRANSPORT" backup-delete "$LOGICAL_ID" "$gen" "$payload" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT"
|
||||||
MARKER_VERIFY_GENERATION_LINES=87,120,129,141,148
|
L140= rm -rf --one-file-system "$outdir" 2>/dev/null || true
|
||||||
MARKER_CLEANUP_VERIFY_LINES=95,106
|
L141= verify_generation "$gen"
|
||||||
MARKER_RECONSTRUCT_LINES=70,97,103
|
L142= printf 'CONTROL_BACKUP_RESULT=SEALED_NEW GENERATION=%s\n' "$gen"
|
||||||
MARKER_SPLIT_LINES=NONE
|
L143=}
|
||||||
MARKER_536870912_LINES=NONE
|
L144=case "${1:-}" in
|
||||||
MARKER_512M_LINES=NONE
|
L145= scan) [[ "$#" == 1 ]] || die USAGE 64; scan;;
|
||||||
MARKER_PART_LINES=71,72,73,74,78,79,80,81,82
|
L146= run) [[ "$#" == 1 ]] || die USAGE 64; run_backup 0;;
|
||||||
UNIT_LINE_COUNT=16
|
L147= force) [[ "$#" == 1 ]] || die USAGE 64; run_backup 1;;
|
||||||
UNIT_SKELETON_BEGIN
|
L148= verify) [[ "$#" == 2 ]] || die USAGE 64; verify_generation "$2";;
|
||||||
UNIT_LINE_001=[Unit]
|
L149= *) die USAGE_scan_run_force_verify 64;;
|
||||||
UNIT_LINE_002=Description=Homelab recurring CONTROL cloud quorum backup
|
L150=esac
|
||||||
UNIT_LINE_003=After=network-online.target
|
FOCUS_BODY_END=run_backup
|
||||||
UNIT_LINE_004=Wants=network-online.target
|
FOCUS_FUNCTION=verify_generation
|
||||||
UNIT_LINE_005=ConditionPathExists=<LONG_TOKEN_REDACTED>
|
FOCUS_SPAN=87-108
|
||||||
UNIT_LINE_006=ConditionPathExists=<LONG_TOKEN_REDACTED>
|
FOCUS_BODY_BEGIN=verify_generation
|
||||||
UNIT_LINE_007=
|
L087=verify_generation(){
|
||||||
UNIT_LINE_008=[Service]
|
L088= local gen state work cfg base_a base_b a b verify_json archive_sha tmp now
|
||||||
UNIT_LINE_009=Type=oneshot
|
L089= gen="$1"
|
||||||
UNIT_LINE_010=ExecStart=<LONG_TOKEN_REDACTED> run
|
L090= state="$STATE_DIR/$gen.json"
|
||||||
UNIT_LINE_011=User=root
|
L091= [[ -s "$state" && ! -L "$state" ]] || die VERIFY_STATE_UNSAFE 68
|
||||||
UNIT_LINE_012=Group=root
|
L092= "$TRANSPORT" verify-sealed "$LOGICAL_ID" "$gen" "$REMOTE_A" "$REMOTE_B" "$STATE_ROOT" >/dev/null
|
||||||
UNIT_LINE_013=UMask=0077
|
L093= mkdir -p "$VERIFY_ROOT"; chmod 0700 "$VERIFY_ROOT"
|
||||||
UNIT_LINE_014=Nice=10
|
L094= work="$(mktemp -d "$VERIFY_ROOT/.verify.XXXXXX")"; cfg="$work/[SENSITIVE_FILE]"; prepare_rclone "$cfg"
|
||||||
UNIT_LINE_015=IOSchedulingClass=best-effort
|
L095= cleanup_verify(){ rm -rf --one-file-system "$work"; }; trap cleanup_verify EXIT
|
||||||
UNIT_LINE_016=IOSchedulingPriority=7
|
L096= base_a="$(jq -er '.remote_a_base' "$state")"; base_b="$(jq -er '.remote_b_base' "$state")"; a="$work/A.tar.gz"; b="$work/B.tar.gz"
|
||||||
UNIT_SKELETON_END
|
L097= reconstruct "$base_a" "$a" "$cfg" "$state" A; reconstruct "$base_b" "$b" "$cfg" "$state" B
|
||||||
UNIT_REDACTED_LINE_COUNT=0
|
L098= cmp -s "$a" "$b" || die CLOUD_A_B_PAYLOAD_MISMATCH 68
|
||||||
FILES_WRITTEN_BY_PAYLOAD=0
|
L099= verify_json="$("$BUILDER" verify --archive "$a" --expected-generation "$gen")" || die <LONG_TOKEN_REDACTED> 68
|
||||||
SYSTEMD_MUTATIONS_BY_255=0
|
L100=<REDACTED_SENSITIVE_LINE>
|
||||||
LOGIC255_READY_FOR_MINIMAL_PATCH=YES
|
L101= archive_sha="$(jq -er '.archive_sha256' "$state")"; mkdir -p "$EVIDENCE_ROOT" /var/lib/homelab-health; chmod 0700 "$EVIDENCE_ROOT"
|
||||||
LOGIC255_END
|
L102= tmp="$EVIDENCE_ROOT/.$gen.new.$$"; now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-255R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
L103=<REDACTED_SENSITIVE_LINE>
|
||||||
|
L104= chmod 0600 "$tmp"; mv -f "$tmp" "$EVIDENCE_ROOT/$gen.json"
|
||||||
|
L105= tmp="${HEALTH}.new.$$"; jq -n --arg gen "$gen" --arg state "$state" --arg evidence "$EVIDENCE_ROOT/$gen.json" --arg sha "$archive_sha" --arg now "$now" '{schema:"homelab-control-backup-health-v1",status:"OK",generation:$gen,state_file:$state,restore_evidence:$evidence,archive_sha256:$sha,cloud_quorum:2,control_freshness:"FRESH",full_site_dr_proven:false,updated_at_utc:$now}' >"$tmp"; chmod 0644 "$tmp"; mv -f "$tmp" "$HEALTH"
|
||||||
|
L106= trap - EXIT; cleanup_verify
|
||||||
|
L107= printf 'CONTROL_VERIFY=OK GENERATION=%s EVIDENCE=%s\n' "$gen" "$EVIDENCE_ROOT/$gen.json"
|
||||||
|
L108=}
|
||||||
|
FOCUS_BODY_END=verify_generation
|
||||||
|
FOCUS256_STOP=FOCUS_FUNCTION_MISSING
|
||||||
|
FOCUS256_DETAIL=cleanup_verify
|
||||||
|
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260912-INFRA-DR-BACKUPV2-CONTROL-BACKUP-LOGIC-FOCUS-256R1","status":"FAIL","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
||||||
|
|
||||||
OUTPUT_END
|
OUTPUT_END
|
||||||
CHAT_OUTPUT_END
|
CHAT_OUTPUT_END
|
||||||
|
|||||||
Reference in New Issue
Block a user