fix(backup): make Host110 runtime receipt durable
This commit is contained in:
@@ -44,13 +44,19 @@ EXECUTOR_DIGEST=""
|
||||
VERIFIER_DIGEST=""
|
||||
STAGE_DIR=""
|
||||
ROLLBACK_DIR=""
|
||||
RECEIPT_PATH=""
|
||||
APPLY_STARTED=0
|
||||
APPLY_COMPLETE=0
|
||||
ROLLBACK_ATTEMPTED=0
|
||||
ROLLBACK_PERFORMED=0
|
||||
ROLLBACK_VERIFIED=0
|
||||
RUN_TEMP_RESIDUE_VERIFIED=0
|
||||
FAULT_INJECTION_ENABLED=0
|
||||
declare -A FILE_EXISTED=()
|
||||
declare -A PREVIOUS_DIGEST=()
|
||||
declare -A PREVIOUS_METADATA=()
|
||||
declare -A EXPECTED_DIGEST=()
|
||||
declare -A RUN_OWNED_TEMP_PATHS=()
|
||||
|
||||
usage() {
|
||||
printf '%s\n' \
|
||||
@@ -96,6 +102,11 @@ case "$MODE" in check|apply|verify) ;; *) fail "invalid_mode" ;; esac
|
||||
[[ "$RUN_ID" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,95}$ ]] || fail "invalid_run_id"
|
||||
expected_source_stage="/tmp/agent99-host110-backup-runtime-${RUN_ID}"
|
||||
[ "$SOURCE_STAGE" = "$expected_source_stage" ] || fail "invalid_source_stage"
|
||||
RECEIPT_PATH="$STATUS_ROOT/agent99-backup-runtime-deploy-${RUN_ID}.json"
|
||||
if [ "${HOST110_BACKUP_RUNTIME_ENABLE_TEST_FAULTS:-}" = "1" ] \
|
||||
&& [ "$DEST_ROOT" != "/backup/scripts" ]; then
|
||||
FAULT_INJECTION_ENABLED=1
|
||||
fi
|
||||
|
||||
for command_name in awk bash cp dirname flock grep hostname id install mv pgrep python3 readlink rm sha256sum stat timeout tr; do
|
||||
command -v "$command_name" >/dev/null 2>&1 || fail "required_command_missing_${command_name}"
|
||||
@@ -174,10 +185,10 @@ working_digest() {
|
||||
|| fail "verifier_identity_failed"
|
||||
|
||||
validate_file() {
|
||||
local path="$1"
|
||||
case "$path" in
|
||||
*.sh) bash -n "$path" ;;
|
||||
*.py) python3 -c 'import ast, pathlib, sys; ast.parse(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8"))' "$path" ;;
|
||||
local validation_path="$1"
|
||||
case "$validation_path" in
|
||||
*.sh) bash -n "$validation_path" ;;
|
||||
*.py) python3 -c 'import ast, pathlib, sys; ast.parse(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8"))' "$validation_path" ;;
|
||||
*) return 64 ;;
|
||||
esac
|
||||
}
|
||||
@@ -222,12 +233,75 @@ verify_destination() {
|
||||
done
|
||||
}
|
||||
|
||||
fsync_paths_and_parents() {
|
||||
python3 - "$@" <<'PY'
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
parents = set()
|
||||
for raw_path in sys.argv[1:]:
|
||||
path = Path(raw_path)
|
||||
parents.add(path.parent)
|
||||
if not os.path.lexists(path):
|
||||
continue
|
||||
if path.is_symlink() or not path.is_file():
|
||||
raise SystemExit(76)
|
||||
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
||||
descriptor = os.open(path, flags)
|
||||
try:
|
||||
if not stat.S_ISREG(os.fstat(descriptor).st_mode):
|
||||
raise SystemExit(76)
|
||||
os.fsync(descriptor)
|
||||
finally:
|
||||
os.close(descriptor)
|
||||
for parent in sorted(parents, key=str):
|
||||
if parent.is_symlink() or not parent.is_dir():
|
||||
raise SystemExit(76)
|
||||
flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_NOFOLLOW", 0)
|
||||
descriptor = os.open(parent, flags)
|
||||
try:
|
||||
os.fsync(descriptor)
|
||||
finally:
|
||||
os.close(descriptor)
|
||||
PY
|
||||
}
|
||||
|
||||
fsync_destination_state() {
|
||||
local name dest_path
|
||||
local -a fsync_targets=()
|
||||
for name in "${PAYLOAD_FILES[@]}"; do
|
||||
dest_path="$(destination_path "$name")"
|
||||
fsync_targets+=("$dest_path")
|
||||
done
|
||||
fsync_paths_and_parents "${fsync_targets[@]}"
|
||||
}
|
||||
|
||||
fsync_rollback_prestate() {
|
||||
local name
|
||||
local -a fsync_targets=("$ROLLBACK_DIR/prestate.tsv")
|
||||
for name in "${PAYLOAD_FILES[@]}"; do
|
||||
if [ "${FILE_EXISTED[$name]:-}" = "1" ]; then
|
||||
fsync_targets+=("$ROLLBACK_DIR/$name")
|
||||
fi
|
||||
done
|
||||
fsync_paths_and_parents "${fsync_targets[@]}"
|
||||
}
|
||||
|
||||
write_receipt() {
|
||||
local status="$1"
|
||||
local rollback_verified="$2"
|
||||
local receipt_path="$STATUS_ROOT/agent99-backup-runtime-deploy-${RUN_ID}.json"
|
||||
install -d -m 700 "$STATUS_ROOT"
|
||||
python3 - "$receipt_path" "$status" "$SOURCE_REVISION" "$SOURCE_HEAD" "$RUN_ID" "$rollback_verified" "$VERIFIER_DIGEST" <<'PY'
|
||||
local receipt_status="$1"
|
||||
local rollback_attempted="$2"
|
||||
local rollback_performed="$3"
|
||||
local rollback_verified="$4"
|
||||
local zero_residue_verified="$5"
|
||||
install -d -m 700 "$STATUS_ROOT" || return 1
|
||||
[ -d "$STATUS_ROOT" ] && [ ! -L "$STATUS_ROOT" ] || return 1
|
||||
[ "$(stat -c '%U:%G:%a' "$STATUS_ROOT")" = "wooo:wooo:700" ] || return 1
|
||||
if ! python3 - "$RECEIPT_PATH" "$receipt_status" "$SOURCE_REVISION" "$SOURCE_HEAD" "$RUN_ID" \
|
||||
"$rollback_attempted" "$rollback_performed" "$rollback_verified" \
|
||||
"$zero_residue_verified" "$VERIFIER_DIGEST" "$FAULT_INJECTION_ENABLED" <<'PY'
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@@ -235,64 +309,176 @@ import time
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
status = sys.argv[2]
|
||||
rollback_attempted = sys.argv[6] == "1"
|
||||
rollback_performed = sys.argv[7] == "1"
|
||||
rollback_verified = sys.argv[8] == "1"
|
||||
zero_residue_verified = sys.argv[9] == "1"
|
||||
if status not in {"verified", "failed_rolled_back", "rollback_unverified"}:
|
||||
raise SystemExit(78)
|
||||
if status == "verified" and (rollback_attempted or rollback_performed or rollback_verified or not zero_residue_verified):
|
||||
raise SystemExit(78)
|
||||
if status == "failed_rolled_back" and not (
|
||||
rollback_attempted and rollback_performed and rollback_verified and zero_residue_verified
|
||||
):
|
||||
raise SystemExit(78)
|
||||
if status == "rollback_unverified" and (not rollback_attempted or rollback_verified):
|
||||
raise SystemExit(78)
|
||||
document = {
|
||||
"schemaVersion": "agent99_host110_backup_runtime_deploy_receipt_v1",
|
||||
"status": sys.argv[2],
|
||||
"schemaVersion": "agent99_host110_backup_runtime_deploy_receipt_v2",
|
||||
"status": status,
|
||||
"sourceRevision": sys.argv[3],
|
||||
"sourceHead": sys.argv[4],
|
||||
"runId": sys.argv[5],
|
||||
"fileCount": 18,
|
||||
"backupScriptFileCount": 17,
|
||||
"backupHealthExporterIncluded": True,
|
||||
"rollbackPerformed": sys.argv[6] == "1",
|
||||
"rollbackVerified": sys.argv[6] == "1",
|
||||
"verifierSha256": sys.argv[7],
|
||||
"rollbackAttempted": rollback_attempted,
|
||||
"rollbackPerformed": rollback_performed,
|
||||
"rollbackVerified": rollback_verified,
|
||||
"zeroResidueVerified": zero_residue_verified,
|
||||
"verifierSha256": sys.argv[10],
|
||||
"executorHost": "192.168.0.110",
|
||||
"productionServiceRestarted": False,
|
||||
"secretValuesRead": False,
|
||||
"writtenAt": int(time.time()),
|
||||
}
|
||||
payload = (json.dumps(document, ensure_ascii=True, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8")
|
||||
expected_digest = hashlib.sha256(payload).hexdigest()
|
||||
temporary = path.with_name(f".{path.name}.tmp-{os.getpid()}")
|
||||
temporary.write_text(json.dumps(document, ensure_ascii=True, sort_keys=True) + "\n", encoding="utf-8")
|
||||
os.chmod(temporary, 0o600)
|
||||
fault_enabled = sys.argv[11] == "1"
|
||||
fault = (
|
||||
os.environ.get("HOST110_BACKUP_RUNTIME_TEST_RECEIPT_FAULT", "")
|
||||
if status == "verified" and fault_enabled
|
||||
else ""
|
||||
)
|
||||
if fault not in {"", "write", "link", "fsync", "readback"}:
|
||||
raise SystemExit(78)
|
||||
created_final = False
|
||||
directory_fd = None
|
||||
try:
|
||||
if os.path.lexists(path) or os.path.lexists(temporary):
|
||||
raise FileExistsError(path)
|
||||
if fault == "write":
|
||||
raise OSError("fault_injected_receipt_write")
|
||||
descriptor = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
with os.fdopen(descriptor, "wb") as handle:
|
||||
if handle.write(payload) != len(payload):
|
||||
raise OSError("receipt_short_write")
|
||||
handle.flush()
|
||||
if fault == "fsync":
|
||||
raise OSError("fault_injected_receipt_fsync")
|
||||
os.fsync(handle.fileno())
|
||||
os.chmod(temporary, 0o600)
|
||||
temporary_readback = temporary.read_bytes()
|
||||
if temporary_readback != payload or hashlib.sha256(temporary_readback).hexdigest() != expected_digest:
|
||||
raise OSError("receipt_temporary_readback_failed")
|
||||
if fault == "link":
|
||||
raise OSError("fault_injected_receipt_link")
|
||||
os.link(temporary, path)
|
||||
created_final = True
|
||||
directory_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
|
||||
directory_fd = os.open(path.parent, directory_flags)
|
||||
os.fsync(directory_fd)
|
||||
if fault == "readback":
|
||||
raise OSError("fault_injected_receipt_readback")
|
||||
readback = path.read_bytes()
|
||||
if readback != payload or hashlib.sha256(readback).hexdigest() != expected_digest:
|
||||
raise OSError("receipt_final_readback_failed")
|
||||
if json.loads(readback.decode("utf-8")) != document:
|
||||
raise OSError("receipt_document_readback_failed")
|
||||
temporary.unlink()
|
||||
os.fsync(directory_fd)
|
||||
except BaseException:
|
||||
try:
|
||||
if created_final:
|
||||
path.unlink(missing_ok=True)
|
||||
temporary.unlink(missing_ok=True)
|
||||
if directory_fd is None and path.parent.is_dir():
|
||||
directory_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
|
||||
directory_fd = os.open(path.parent, directory_flags)
|
||||
if directory_fd is not None:
|
||||
os.fsync(directory_fd)
|
||||
finally:
|
||||
raise
|
||||
finally:
|
||||
temporary.unlink(missing_ok=True)
|
||||
if directory_fd is not None:
|
||||
os.close(directory_fd)
|
||||
PY
|
||||
printf '%s' "$receipt_path"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
[ -f "$RECEIPT_PATH" ] && [ ! -L "$RECEIPT_PATH" ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
record_prestate() {
|
||||
local name dest_path digest metadata
|
||||
: > "$ROLLBACK_DIR/prestate.tsv"
|
||||
chmod 600 "$ROLLBACK_DIR/prestate.tsv"
|
||||
: > "$ROLLBACK_DIR/prestate.tsv" || return 74
|
||||
chmod 600 "$ROLLBACK_DIR/prestate.tsv" || return 74
|
||||
for name in "${PAYLOAD_FILES[@]}"; do
|
||||
dest_path="$(destination_path "$name")"
|
||||
if [ -f "$dest_path" ] && [ ! -L "$dest_path" ]; then
|
||||
[ "$(stat -c '%U:%G' "$dest_path")" = "wooo:wooo" ] || return 71
|
||||
FILE_EXISTED[$name]=1
|
||||
digest="$(working_digest "$dest_path")"
|
||||
metadata="$(stat -c '%u:%g:%a' "$dest_path")"
|
||||
digest="$(working_digest "$dest_path")" || return 72
|
||||
metadata="$(stat -c '%u:%g:%a' "$dest_path")" || return 72
|
||||
PREVIOUS_DIGEST[$name]="$digest"
|
||||
PREVIOUS_METADATA[$name]="$metadata"
|
||||
printf '%s\t1\t%s\t%s\n' "$name" "$digest" "$metadata" >> "$ROLLBACK_DIR/prestate.tsv"
|
||||
cp -p -- "$dest_path" "$ROLLBACK_DIR/$name"
|
||||
printf '%s\t1\t%s\t%s\n' "$name" "$digest" "$metadata" >> "$ROLLBACK_DIR/prestate.tsv" || return 72
|
||||
cp -p -- "$dest_path" "$ROLLBACK_DIR/$name" || return 72
|
||||
[ "$(working_digest "$ROLLBACK_DIR/$name")" = "$digest" ] || return 72
|
||||
elif [ ! -e "$dest_path" ]; then
|
||||
FILE_EXISTED[$name]=0
|
||||
PREVIOUS_DIGEST[$name]="-"
|
||||
PREVIOUS_METADATA[$name]="-"
|
||||
printf '%s\t0\t-\t-\n' "$name" >> "$ROLLBACK_DIR/prestate.tsv"
|
||||
printf '%s\t0\t-\t-\n' "$name" >> "$ROLLBACK_DIR/prestate.tsv" || return 72
|
||||
else
|
||||
return 73
|
||||
fi
|
||||
done
|
||||
fsync_rollback_prestate || return 75
|
||||
}
|
||||
|
||||
register_run_owned_temp() {
|
||||
RUN_OWNED_TEMP_PATHS["$1"]=1
|
||||
}
|
||||
|
||||
verify_run_owned_temp_absence() {
|
||||
local temporary
|
||||
for temporary in "${!RUN_OWNED_TEMP_PATHS[@]}"; do
|
||||
[ ! -e "$temporary" ] && [ ! -L "$temporary" ] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
cleanup_run_owned_temps() {
|
||||
local temporary failed=0 preserved=0
|
||||
local fault=""
|
||||
if [ "$FAULT_INJECTION_ENABLED" -eq 1 ]; then
|
||||
fault="${HOST110_BACKUP_RUNTIME_TEST_ROLLBACK_FAULT:-}"
|
||||
fi
|
||||
for temporary in "${!RUN_OWNED_TEMP_PATHS[@]}"; do
|
||||
if [ "$fault" = "preserve_first_temp" ] \
|
||||
&& [ "$preserved" -eq 0 ] \
|
||||
&& { [ -e "$temporary" ] || [ -L "$temporary" ]; }; then
|
||||
preserved=1
|
||||
failed=1
|
||||
continue
|
||||
fi
|
||||
rm -f -- "$temporary" || failed=1
|
||||
done
|
||||
verify_run_owned_temp_absence || failed=1
|
||||
[ "$failed" -eq 0 ]
|
||||
}
|
||||
|
||||
rollback_transaction() {
|
||||
local name dest_path destination_parent backup_path temporary failed=0
|
||||
ROLLBACK_ATTEMPTED=1
|
||||
ROLLBACK_PERFORMED=0
|
||||
ROLLBACK_VERIFIED=0
|
||||
RUN_TEMP_RESIDUE_VERIFIED=0
|
||||
set +e
|
||||
cleanup_run_owned_temps || failed=1
|
||||
for name in "${PAYLOAD_FILES[@]}"; do
|
||||
[ -n "${FILE_EXISTED[$name]+x}" ] || { failed=1; continue; }
|
||||
dest_path="$(destination_path "$name")"
|
||||
@@ -300,13 +486,22 @@ rollback_transaction() {
|
||||
backup_path="$ROLLBACK_DIR/$name"
|
||||
destination_parent="$(dirname "$dest_path")"
|
||||
temporary="$destination_parent/.${name}.agent99-rollback-${RUN_ID}"
|
||||
cp -p -- "$backup_path" "$temporary" \
|
||||
&& mv -f -- "$temporary" "$dest_path" \
|
||||
|| failed=1
|
||||
register_run_owned_temp "$temporary"
|
||||
if cp -p -- "$backup_path" "$temporary" && mv -f -- "$temporary" "$dest_path"; then
|
||||
ROLLBACK_PERFORMED=1
|
||||
else
|
||||
failed=1
|
||||
fi
|
||||
else
|
||||
rm -f -- "$dest_path" || failed=1
|
||||
if rm -f -- "$dest_path"; then
|
||||
ROLLBACK_PERFORMED=1
|
||||
else
|
||||
failed=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
cleanup_run_owned_temps || failed=1
|
||||
fsync_destination_state || failed=1
|
||||
for name in "${PAYLOAD_FILES[@]}"; do
|
||||
dest_path="$(destination_path "$name")"
|
||||
if [ "${FILE_EXISTED[$name]:-}" = "1" ]; then
|
||||
@@ -320,8 +515,14 @@ rollback_transaction() {
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
if verify_run_owned_temp_absence; then
|
||||
RUN_TEMP_RESIDUE_VERIFIED=1
|
||||
else
|
||||
failed=1
|
||||
RUN_TEMP_RESIDUE_VERIFIED=0
|
||||
fi
|
||||
set -e
|
||||
if [ "$failed" -eq 0 ]; then
|
||||
if [ "$failed" -eq 0 ] && [ "$ROLLBACK_PERFORMED" -eq 1 ] && [ "$RUN_TEMP_RESIDUE_VERIFIED" -eq 1 ]; then
|
||||
ROLLBACK_VERIFIED=1
|
||||
return 0
|
||||
fi
|
||||
@@ -330,20 +531,28 @@ rollback_transaction() {
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local status=$?
|
||||
local exit_status=$?
|
||||
local rollback_status="rollback_unverified"
|
||||
local failure_receipt_written=0
|
||||
trap - EXIT HUP INT TERM
|
||||
if [ "$APPLY_STARTED" -eq 1 ] && [ "$APPLY_COMPLETE" -ne 1 ]; then
|
||||
if rollback_transaction; then
|
||||
rollback_status="failed_rolled_back"
|
||||
fi
|
||||
write_receipt "$rollback_status" "$ROLLBACK_VERIFIED" >/dev/null || true
|
||||
if write_receipt "$rollback_status" "$ROLLBACK_ATTEMPTED" "$ROLLBACK_PERFORMED" \
|
||||
"$ROLLBACK_VERIFIED" "$RUN_TEMP_RESIDUE_VERIFIED"; then
|
||||
failure_receipt_written=1
|
||||
fi
|
||||
fi
|
||||
[ -z "$STAGE_DIR" ] || rm -rf -- "$STAGE_DIR"
|
||||
if [ "$ROLLBACK_VERIFIED" -eq 1 ]; then
|
||||
[ -z "$ROLLBACK_DIR" ] || rm -rf -- "$ROLLBACK_DIR"
|
||||
if [ -n "$STAGE_DIR" ]; then
|
||||
rm -rf -- "$STAGE_DIR" || true
|
||||
fi
|
||||
exit "$status"
|
||||
if [ "$ROLLBACK_VERIFIED" -eq 1 ] && [ "$failure_receipt_written" -eq 1 ]; then
|
||||
if [ -n "$ROLLBACK_DIR" ]; then
|
||||
rm -rf -- "$ROLLBACK_DIR" || true
|
||||
fi
|
||||
fi
|
||||
exit "$exit_status"
|
||||
}
|
||||
|
||||
validate_source || fail "source_validation_failed"
|
||||
@@ -359,7 +568,7 @@ if [ "$MODE" = "verify" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ ! -e "$STATUS_ROOT/agent99-backup-runtime-deploy-${RUN_ID}.json" ] || fail "run_identity_receipt_exists"
|
||||
[ ! -e "$RECEIPT_PATH" ] && [ ! -L "$RECEIPT_PATH" ] || fail "run_identity_receipt_exists"
|
||||
STAGE_DIR="$STAGE_ROOT/$RUN_ID"
|
||||
ROLLBACK_DIR="$ROLLBACK_ROOT/$RUN_ID"
|
||||
[ ! -e "$STAGE_DIR" ] || fail "run_identity_stage_exists"
|
||||
@@ -399,10 +608,17 @@ for name in "${PAYLOAD_FILES[@]}"; do
|
||||
dest_path="$(destination_path "$name")"
|
||||
destination_parent="$(dirname "$dest_path")"
|
||||
temporary="$destination_parent/.${name}.agent99-${RUN_ID}"
|
||||
register_run_owned_temp "$temporary"
|
||||
install -m 755 "$STAGE_DIR/$name" "$temporary"
|
||||
if [ "$FAULT_INJECTION_ENABLED" -eq 1 ] \
|
||||
&& [ "${HOST110_BACKUP_RUNTIME_TEST_APPLY_FAULT:-}" = "after_temp_install" ] \
|
||||
&& [ "$name" = "${PAYLOAD_FILES[0]}" ]; then
|
||||
fail "fault_injected_after_temp_install"
|
||||
fi
|
||||
mv -f -- "$temporary" "$dest_path"
|
||||
done
|
||||
|
||||
fsync_destination_state || fail "post_apply_durability_failed"
|
||||
verify_destination || fail "post_apply_verification_failed"
|
||||
verifier_result="$(BACKUP_RUNTIME_DEPLOY_CONTEXT=1 python3 "$SOURCE_STAGE/verify-host110-backup-runtime.py" \
|
||||
--manifest "$SOURCE_STAGE/manifest.json" \
|
||||
@@ -433,13 +649,26 @@ if not (
|
||||
raise SystemExit(1)
|
||||
PY
|
||||
|
||||
verify_run_owned_temp_absence || fail "post_apply_temp_residue_detected"
|
||||
RUN_TEMP_RESIDUE_VERIFIED=1
|
||||
if ! write_receipt "verified" 0 0 0 "$RUN_TEMP_RESIDUE_VERIFIED"; then
|
||||
fail "durable_receipt_failed"
|
||||
fi
|
||||
receipt_path="$RECEIPT_PATH"
|
||||
APPLY_COMPLETE=1
|
||||
receipt_path="$(write_receipt "verified" 0)"
|
||||
rm -rf -- "$STAGE_DIR" "$ROLLBACK_DIR"
|
||||
trap - EXIT HUP INT TERM
|
||||
stage_cleanup_verified=0
|
||||
rollback_prestate_cleanup_verified=0
|
||||
if rm -rf -- "$STAGE_DIR" && [ ! -e "$STAGE_DIR" ] && [ ! -L "$STAGE_DIR" ]; then
|
||||
stage_cleanup_verified=1
|
||||
fi
|
||||
if rm -rf -- "$ROLLBACK_DIR" && [ ! -e "$ROLLBACK_DIR" ] && [ ! -L "$ROLLBACK_DIR" ]; then
|
||||
rollback_prestate_cleanup_verified=1
|
||||
fi
|
||||
STAGE_DIR=""
|
||||
ROLLBACK_DIR=""
|
||||
trap - EXIT HUP INT TERM
|
||||
python3 - "$SOURCE_REVISION" "$SOURCE_HEAD" "$receipt_path" "$verifier_result" <<'PY'
|
||||
python3 - "$SOURCE_REVISION" "$SOURCE_HEAD" "$receipt_path" "$verifier_result" \
|
||||
"$stage_cleanup_verified" "$rollback_prestate_cleanup_verified" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
@@ -452,7 +681,12 @@ print(json.dumps({
|
||||
"fileCount": 18,
|
||||
"backupScriptFileCount": 17,
|
||||
"backupHealthExporterIncluded": True,
|
||||
"rollbackAttempted": False,
|
||||
"rollbackPerformed": False,
|
||||
"rollbackVerified": False,
|
||||
"zeroResidueVerified": True,
|
||||
"stageCleanupVerified": sys.argv[5] == "1",
|
||||
"rollbackPrestateCleanupVerified": sys.argv[6] == "1",
|
||||
"receipt": sys.argv[3],
|
||||
"verifier": json.loads(sys.argv[4]),
|
||||
}, ensure_ascii=True, sort_keys=True))
|
||||
|
||||
Reference in New Issue
Block a user