Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 2m27s
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
160 lines
6.3 KiB
Python
160 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Review and attend the fixed inactive backup-source installation or rollback."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import base64
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
OWNER = Path("/home/worsch/rapp-telemetry")
|
|
DELIVERY = ROOT / "docs/release/backup-operating-delivery-alerts-2026-10-31.json"
|
|
OBSERVATION = ROOT / "docs/release/backup-install-target-observation-2026-10-31.json"
|
|
ROUTE_DIGEST = "sha256:4d8481061dc9ce6835169defc96887945052332a0db8d4234ae84032d63cc328"
|
|
|
|
|
|
def module(name, path):
|
|
spec = importlib.util.spec_from_file_location(name, path)
|
|
loaded = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(loaded)
|
|
return loaded
|
|
|
|
|
|
def prepare():
|
|
if not __debug__:
|
|
raise ValueError("optimized_python_refused")
|
|
runtime = module("backup_install_runtime", ROOT / "scripts/backup_install_runtime.py")
|
|
installer = (ROOT / "scripts/backup_install.py").read_bytes()
|
|
implementation = module("backup_install", ROOT / "scripts/backup_install.py")
|
|
delivery = json.loads(DELIVERY.read_text())
|
|
archive = Path(delivery["private_archive"]).read_bytes()
|
|
implementation.read_bundle(archive, delivery["archive_sha256"], delivery["manifest_sha256"])
|
|
route = module("reviewed_backup_route", OWNER / "tools/deploy_coulomb_backup_route.py")
|
|
route_packet, route_source = route.prepare(route.DEFAULT)
|
|
if route_packet["execution_digest"] != ROUTE_DIGEST:
|
|
raise ValueError("reviewed_owner_route_changed")
|
|
# Verification needs no chart upload and does not perform an upgrade.
|
|
route_packet.pop("chart")
|
|
source = (ROOT / "scripts/backup_install_runtime.py").read_text()
|
|
plan = dict(
|
|
schema="coulomb.backup-source-installation-proposal.v1",
|
|
attempt_id="20261031bacc0001",
|
|
cluster_uid=runtime.CLUSTER_UID,
|
|
archive_sha256=delivery["archive_sha256"],
|
|
manifest_sha256=delivery["manifest_sha256"],
|
|
capacity_profile=runtime.PROFILE,
|
|
expected_before=json.loads(OBSERVATION.read_text())["targets"],
|
|
route_execution_digest=ROUTE_DIGEST,
|
|
route_packet=route_packet,
|
|
installer_sha256=hashlib.sha256(installer).hexdigest(),
|
|
route_verifier_sha256=hashlib.sha256(route_source.encode()).hexdigest(),
|
|
runtime_sha256=hashlib.sha256(source.encode()).hexdigest(),
|
|
launcher_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
|
|
)
|
|
packet = dict(
|
|
plan=plan,
|
|
proposal_digest="sha256:" + runtime.sha(runtime.canonical(plan)),
|
|
archive=base64.b64encode(archive).decode(),
|
|
installer=base64.b64encode(installer).decode(),
|
|
route_verifier=base64.b64encode(route_source.encode()).decode(),
|
|
)
|
|
return packet, source
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
actions = parser.add_mutually_exclusive_group()
|
|
actions.add_argument("--preflight", action="store_true")
|
|
actions.add_argument("--execute", action="store_true")
|
|
actions.add_argument("--rollback", action="store_true")
|
|
parser.add_argument("--expect-digest")
|
|
args = parser.parse_args(argv)
|
|
packet, source = prepare()
|
|
digest = packet["proposal_digest"]
|
|
if args.expect_digest and args.expect_digest != digest:
|
|
raise SystemExit("Reviewed source installation proposal changed; no action")
|
|
if not (args.preflight or args.execute or args.rollback):
|
|
print(
|
|
json.dumps(
|
|
dict(
|
|
status="prepared",
|
|
proposal_digest=digest,
|
|
capacity_profile=packet["plan"]["capacity_profile"],
|
|
targets=len(packet["plan"]["expected_before"]),
|
|
execution_requires_verified_route=True,
|
|
installed=False,
|
|
)
|
|
)
|
|
)
|
|
return 0
|
|
if args.execute or args.rollback:
|
|
if not args.expect_digest or not sys.stdin.isatty():
|
|
raise SystemExit("Founder terminal and reviewed digest required")
|
|
verb = "ROLLBACK" if args.rollback else "INSTALL"
|
|
print(
|
|
"Restore this installation only, with units inactive."
|
|
if args.rollback
|
|
else "Admit the displayed capacity profile and install the reviewed sources "
|
|
"with units inactive."
|
|
)
|
|
print(json.dumps(packet["plan"]["capacity_profile"], sort_keys=True))
|
|
if input("Type " + verb + " followed by the full digest: ").strip() != verb + " " + digest:
|
|
raise SystemExit("Not confirmed; no action")
|
|
packet["action"] = "rollback" if args.rollback else "install" if args.execute else "preflight"
|
|
bootstrap = (
|
|
source
|
|
+ """
|
|
import sys
|
|
packet=json.load(sys.stdin)
|
|
try:
|
|
result=run(packet,packet['action'])
|
|
except Exception as error:
|
|
status='preflight_refused' if packet['action']=='preflight' else 'installation_requires_inspection'
|
|
result=dict(status=status,
|
|
proposal_digest=packet['proposal_digest'],failure_type=type(error).__name__,retry_automatically=False)
|
|
if isinstance(error,Refused):result['reason']=str(error)
|
|
print(json.dumps(result))
|
|
sys.exit(0 if result['status'] in ('preflight_verified','sources_installed_units_inactive_verified',
|
|
'prior_files_restored_units_inactive_verified') else 1)
|
|
"""
|
|
)
|
|
try:
|
|
response = subprocess.run(
|
|
[
|
|
"ssh",
|
|
"-o",
|
|
"BatchMode=yes",
|
|
"-o",
|
|
"ConnectTimeout=10",
|
|
"railiance01",
|
|
"sudo -n python3 -c " + shlex.quote(bootstrap),
|
|
],
|
|
input=json.dumps(packet).encode(),
|
|
capture_output=True,
|
|
timeout=600,
|
|
)
|
|
result = json.loads(response.stdout)
|
|
except (subprocess.TimeoutExpired, ValueError):
|
|
print(
|
|
json.dumps(
|
|
dict(
|
|
status="remote_outcome_unconfirmed",
|
|
proposal_digest=digest,
|
|
retry_automatically=False,
|
|
)
|
|
)
|
|
)
|
|
return 1
|
|
print(json.dumps(result))
|
|
return int(response.returncode != 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|