#!/usr/bin/env python3 """Continue a successfully prepared installed VM through faults/apply/cold boot. Run as one durable systemd service with CPUQuota=200%, MemoryMax=8G, MemorySwapMax=0. Each child takes the shared heavy lock inside that job. Faults operate on independent disk copies, never restore the active VM's financial data. """ import argparse import json from pathlib import Path import subprocess import sys import time def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--prepared-report', type=Path, required=True) parser.add_argument('--baseline-boot', type=Path, required=True) parser.add_argument('--output', type=Path, required=True) parser.add_argument('--wait-prepared', type=int, default=0) parser.add_argument('--preparation-faults-only', action='store_true', help='run offline/interrupted preparation only, even after failed prepare') parser.add_argument('--preparation-fault', action='append', choices=['offline','interrupted-before','bad-hash','space-prepare','partial-dpkg']) parser.add_argument('--fault',action='append',choices=['locked-apt','space','partial-dpkg','offline','missing-dependency','interrupted-before']) args = parser.parse_args() if args.preparation_fault and not args.preparation_faults_only: parser.error('--preparation-fault requires --preparation-faults-only') if args.fault and args.preparation_faults_only: parser.error('--fault is for the apply/coldboot matrix') deadline = time.monotonic()+args.wait_prepared while not (args.prepared_report/'result.json').exists() and time.monotonic()