CHAT_OUTPUT_BEGIN
COMMAND_ID=SUPPORT-260921-HOMELAB-BACKUP-NODEWORKER-CONTRACT-RCA-READONLY-1104R1
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=homelab-backup-nodeworker-contract-rca
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=476f69ce1ba9062cf703c5b1de5f81404fc50b1b31240c36e2e6ecdcd7aebecc
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=0
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=6889fdc8e9ed9a2a2d17d6033311e611ad2a4fc46893776f10806c0b194ff052
SANITIZED_OUTPUT_SHA256=6889fdc8e9ed9a2a2d17d6033311e611ad2a4fc46893776f10806c0b194ff052
OUTPUT_BEGIN
WORKERS2_NODEWORKER_CONTRACT_RCA_BEGIN=1
COMMAND_ID=SUPPORT-260921-HOMELAB-BACKUP-NODEWORKER-CONTRACT-RCA-READONLY-1104R1
MODE=read-only
COMPONENT=homelab-backup-nodeworker-contract-rca
MUTATION_BOUNDARY=READ_ONLY_NO_EXECUTION_OF_BACKUP_WORKERS_NO_SERVICE_START_NO_TIMER_CHANGE_NO_LOCK_BREAK_NO_GIT_WRITE
WRAPPER_INFO={"logic":[{"line":4,"text":"ACCEPTED=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b')"},{"line":5,"text":"EXPECTED={'fresh_lxc_helper.py': 'dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011', 'producer_exec_helper.py': 'b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3', 'lxc_adapter.py': '3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d', 'qemu_adapter.py': '1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b', 'scheduler_adapter.py': 'a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96', 'entry504.py': 'ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793'}"}],"path":"/usr/local/sbin/homelab-backup-v2","sha256":"5077444065c732451cb84898680f62361b21a24ef9eb4f191253e82ead524ea2","size":1656}
HASH_MATCHED_HELPERS={"entry504.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","sha256":"ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793","size":10566},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","sha256":"ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793","size":10566}],"fresh_lxc_helper.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-501r1-e55e5c8c446a/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-501r1-e55e5c8c446a/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py","sha256":"dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011","size":2320}],"lxc_adapter.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","sha256":"3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d","size":13825}],"producer_exec_helper.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","sha256":"b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3","size":3449}],"qemu_adapter.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","sha256":"1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b","size":4627},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","sha256":"1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b","size":4627},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","sha256":"1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b","size":4627},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","sha256":"1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b","size":4627}],"scheduler_adapter.py":[{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","sha256":"a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96","size":4097},{"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","sha256":"a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96","size":4097}]}
HELPER_LOGIC_HITS={"entry504.py":[{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE):"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',"},{"line":64,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"'choose_due_target','write_state','epoch')"},{"line":78,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])"},{"line":79,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:"},{"line":80,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')"},{"line":81,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced."},{"line":89,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper.selftest()"},{"line":93,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"scheduler_adapter=importlib.import_module('scheduler_adapter')"},{"line":96,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)"},{"line":97,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired"},{"line":99,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def _target(wrapper,lid):"},{"line":100,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]"},{"line":101,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')"},{"line":104,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def selftest():"},{"line":105,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()"},{"line":108,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:"},{"line":109,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_CHOOSE_BINDING')"},{"line":110,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:"},{"line":111,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_WRITE_BINDING')"},{"line":112,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:"},{"line":113,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')"},{"line":114,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):"},{"line":116,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SELFTEST_OVERLAY504=PASS',flush=True)"},{"line":120,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"argv=list(sys.argv[1:] if argv is None else argv)"},{"line":121,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['selftest']:"},{"line":122,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return selftest()"},{"line":123,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()"},{"line":125,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['scheduler-proof']:"},{"line":129,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')"},{"line":132,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"with tempfile.TemporaryDirectory(prefix='homelab-scheduler-proof-',dir='/run') as td:"},{"line":141,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"targets=[{'logical_id':'proof-a','enabled':True,'due_seconds':100},{'logical_id':'proof-b','enabled':True,'due_seconds':100}]"},{"line":142,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"first=legacy.choose_due_target(targets,state,now[0])"},{"line":143,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not isinstance(first,dict) or first.get('logical_id')!='proof-b': raise RuntimeError('SCHEDULER_PROOF_PEER_NOT_SELECTED')"},{"line":146,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_PROOF_FAILURE_STATE')"},{"line":148,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"second=legacy.choose_due_target(targets,legacy.load_state_all(),now[0])"},{"line":149,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not isinstance(second,dict) or second.get('logical_id')!='proof-a': raise RuntimeError('SCHEDULER_PROOF_RETRY_NOT_REELIGIBLE')"},{"line":153,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_PROOF_SUCCESS_RESET')"},{"line":154,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"proof={'failed_target':'proof-a','peer_selected_during_backoff':first['logical_id'],'retry_after_epoch':retry,'last_success_preserved':preserved==1000,'retry_target_after_backoff':second['logical_id'],'success_resets_failures':True,'production_state_root_used':False}"},{"line":155,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_FAILURE_ISOLATION_PROOF='+json.dumps(proof,separators=(',',':'),sort_keys=True),flush=True)"},{"line":159,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['scheduler-select-live']:"},{"line":160,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"state=legacy.load_state_all(); targets=wrapper.load_targets()"},{"line":161,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"chosen=legacy.choose_due_target(targets,state)"},{"line":163,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_LIVE_SELECTION=DEFER_NO_DUE_TARGET',flush=True)"},{"line":165,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_LIVE_SELECTION='+json.dumps({'logical_id':chosen.get('logical_id'),'due_seconds':chosen.get('due_seconds'),'enabled':chosen.get('enabled') is True},separators=(',',':'),sort_keys=True),flush=True)"},{"line":167,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(argv)==2 and argv[0]=='plan-lxc':"},{"line":168,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"t=_target(wrapper,argv[1])"},{"line":169,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if t.get('guest_type')!='lxc' or t.get('logical_id')=='guest-pve01-lxc-112':"},{"line":170,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('PLAN_TARGET_NOT_LEGACY_LXC')"},{"line":172,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('PLAN_LXC_RESULT='+json.dumps({'logical_id':t['logical_id'],'vmid':int(t['vmid']),'node':out['job']['node'],'job':out['job']},separators=(',',':'),sort_keys=True),flush=True)"},{"line":174,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(argv)==2 and argv[0]=='verify-target':"},{"line":175,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"t=_target(wrapper,argv[1])"},{"line":176,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if t.get('logical_id')=='guest-pve01-lxc-112':"},{"line":179,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"out=wrapper.backup_target(t,True)"},{"line":180,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"except legacy.BackupError as e:"},{"line":181,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_RESULT=FAIL',flush=True)"},{"line":182,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_REASON='+str(e.code),flush=True)"},{"line":184,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_RESULT='+json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)"},{"line":186,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return wrapper.main([sys.argv[0],*argv])"},{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE):"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',"},{"line":64,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"'choose_due_target','write_state','epoch')"},{"line":78,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])"},{"line":79,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:"},{"line":80,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')"},{"line":81,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced."},{"line":89,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper.selftest()"},{"line":93,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"scheduler_adapter=importlib.import_module('scheduler_adapter')"},{"line":96,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)"},{"line":97,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired"},{"line":99,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def _target(wrapper,lid):"},{"line":100,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]"},{"line":101,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')"},{"line":104,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"def selftest():"},{"line":105,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()"},{"line":108,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:"},{"line":109,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_CHOOSE_BINDING')"},{"line":110,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:"},{"line":111,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_WRITE_BINDING')"},{"line":112,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:"},{"line":113,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')"},{"line":114,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):"},{"line":116,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SELFTEST_OVERLAY504=PASS',flush=True)"},{"line":120,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"argv=list(sys.argv[1:] if argv is None else argv)"},{"line":121,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['selftest']:"},{"line":122,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return selftest()"},{"line":123,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()"},{"line":125,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['scheduler-proof']:"},{"line":129,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')"},{"line":132,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"with tempfile.TemporaryDirectory(prefix='homelab-scheduler-proof-',dir='/run') as td:"},{"line":141,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"targets=[{'logical_id':'proof-a','enabled':True,'due_seconds':100},{'logical_id':'proof-b','enabled':True,'due_seconds':100}]"},{"line":142,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"first=legacy.choose_due_target(targets,state,now[0])"},{"line":143,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not isinstance(first,dict) or first.get('logical_id')!='proof-b': raise RuntimeError('SCHEDULER_PROOF_PEER_NOT_SELECTED')"},{"line":146,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_PROOF_FAILURE_STATE')"},{"line":148,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"second=legacy.choose_due_target(targets,legacy.load_state_all(),now[0])"},{"line":149,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if not isinstance(second,dict) or second.get('logical_id')!='proof-a': raise RuntimeError('SCHEDULER_PROOF_RETRY_NOT_REELIGIBLE')"},{"line":153,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('SCHEDULER_PROOF_SUCCESS_RESET')"},{"line":154,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"proof={'failed_target':'proof-a','peer_selected_during_backoff':first['logical_id'],'retry_after_epoch':retry,'last_success_preserved':preserved==1000,'retry_target_after_backoff':second['logical_id'],'success_resets_failures':True,'production_state_root_used':False}"},{"line":155,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_FAILURE_ISOLATION_PROOF='+json.dumps(proof,separators=(',',':'),sort_keys=True),flush=True)"},{"line":159,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if argv==['scheduler-select-live']:"},{"line":160,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"state=legacy.load_state_all(); targets=wrapper.load_targets()"},{"line":161,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"chosen=legacy.choose_due_target(targets,state)"},{"line":163,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_LIVE_SELECTION=DEFER_NO_DUE_TARGET',flush=True)"},{"line":165,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('SCHEDULER_LIVE_SELECTION='+json.dumps({'logical_id':chosen.get('logical_id'),'due_seconds':chosen.get('due_seconds'),'enabled':chosen.get('enabled') is True},separators=(',',':'),sort_keys=True),flush=True)"},{"line":167,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(argv)==2 and argv[0]=='plan-lxc':"},{"line":168,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"t=_target(wrapper,argv[1])"},{"line":169,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if t.get('guest_type')!='lxc' or t.get('logical_id')=='guest-pve01-lxc-112':"},{"line":170,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"raise RuntimeError('PLAN_TARGET_NOT_LEGACY_LXC')"},{"line":172,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('PLAN_LXC_RESULT='+json.dumps({'logical_id':t['logical_id'],'vmid':int(t['vmid']),'node':out['job']['node'],'job':out['job']},separators=(',',':'),sort_keys=True),flush=True)"},{"line":174,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if len(argv)==2 and argv[0]=='verify-target':"},{"line":175,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"t=_target(wrapper,argv[1])"},{"line":176,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"if t.get('logical_id')=='guest-pve01-lxc-112':"},{"line":179,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"out=wrapper.backup_target(t,True)"},{"line":180,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"except legacy.BackupError as e:"},{"line":181,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_RESULT=FAIL',flush=True)"},{"line":182,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_REASON='+str(e.code),flush=True)"},{"line":184,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"print('VERIFY_TARGET_RESULT='+json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)"},{"line":186,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py","text":"return wrapper.main([sys.argv[0],*argv])"}],"fresh_lxc_helper.py":[{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')"},{"line":15,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"if len(sys.argv)!=1: fail('HELPER_ARGC')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"node=raw.get('node'); vmid=raw.get('vmid'); scratch=raw.get('scratch'); now=raw.get('now')"},{"line":27,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"if type(node) is not str or type(vmid) is not int or type(scratch) is not str or type(now) is not int: fail('INPUT_FIELDS')"},{"line":30,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"plan=pve265.make_plan(raw.get('rows'),configs,raw.get('storage_rows'),defaults,int(raw.get('staging_free')),now,node=node)"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"jobs=[j for j in plan['jobs'] if j.get('vmid')==vmid]"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"if job.get('type')!='lxc' or job.get('node')!=node: fail('JOB_IDENTITY')"},{"line":37,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"guest266.no_active_tasks(raw.get('tasks'),vmid)"},{"line":39,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-500r1-a3964599e60c/fresh_lxc_helper.py","text":"keep=('vmid','type','node','status','template','config_sha256','disks','configured_disk_bytes','configured_archive_bound_bytes','archive_cap_bytes','global_defaults_sha256','blockers','coverage_eligible')"},{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')"},{"line":15,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"if len(sys.argv)!=1: fail('HELPER_ARGC')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"node=raw.get('node'); vmid=raw.get('vmid'); scratch=raw.get('scratch'); now=raw.get('now')"},{"line":27,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"if type(node) is not str or type(vmid) is not int or type(scratch) is not str or type(now) is not int: fail('INPUT_FIELDS')"},{"line":30,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"plan=pve265.make_plan(raw.get('rows'),configs,raw.get('storage_rows'),defaults,int(raw.get('staging_free')),now,node=node)"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"jobs=[j for j in plan['jobs'] if j.get('vmid')==vmid]"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"if job.get('type')!='lxc' or job.get('node')!=node: fail('JOB_IDENTITY')"},{"line":37,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"guest266.no_active_tasks(raw.get('tasks'),vmid)"},{"line":39,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/fresh_lxc_helper.py","text":"keep=('vmid','type','node','status','template','config_sha256','disks','configured_disk_bytes','configured_archive_bound_bytes','archive_cap_bytes','global_defaults_sha256','blockers','coverage_eligible')"},{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')"},{"line":15,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"if len(sys.argv)!=1: fail('HELPER_ARGC')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"node=raw.get('node'); vmid=raw.get('vmid'); scratch=raw.get('scratch'); now=raw.get('now')"},{"line":27,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"if type(node) is not str or type(vmid) is not int or type(scratch) is not str or type(now) is not int: fail('INPUT_FIELDS')"},{"line":30,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"plan=pve265.make_plan(raw.get('rows'),configs,raw.get('storage_rows'),defaults,int(raw.get('staging_free')),now,node=node)"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"jobs=[j for j in plan['jobs'] if j.get('vmid')==vmid]"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"if job.get('type')!='lxc' or job.get('node')!=node: fail('JOB_IDENTITY')"},{"line":37,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"guest266.no_active_tasks(raw.get('tasks'),vmid)"},{"line":39,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/fresh_lxc_helper.py","text":"keep=('vmid','type','node','status','template','config_sha256','disks','configured_disk_bytes','configured_archive_bound_bytes','archive_cap_bytes','global_defaults_sha256','blockers','coverage_eligible')"}],"lxc_adapter.py":[{"line":2,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time"},{"line":6,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py'"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"def _live_inputs(legacy,node,vmid,scratch):"},{"line":42,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue"},{"line":50,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"try: rid=int(r.get('vmid'))"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"except Exception: raise AdapterError('RESOURCE_VMID')"},{"line":52,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r[\"type\"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')"},{"line":57,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)"},{"line":59,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(0<len(data)<=4_000_000,'FRESH_HELPER_INPUT_BOUND')"},{"line":68,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(p.returncode==0 and not p.stderr and 0<len(p.stdout)<=262144,'FRESH_HELPER_FAILED')"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"except Exception as e: raise AdapterError('FRESH_HELPER_JSON') from e"},{"line":72,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(type(out) is dict and out.get('schema')==1 and type(out.get('argv')) is list and type(out.get('job')) is dict,'FRESH_HELPER_SCHEMA')"},{"line":80,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":82,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":84,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":85,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"a=_helper(_live_inputs(legacy,node,vmid,scratch)); b=_helper(_live_inputs(legacy,node,vmid,scratch))"},{"line":86,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_stable_job(a['job'])==_stable_job(b['job']),'FRESH_PLAN_UNSTABLE')"},{"line":87,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(a['argv']==b['argv'],'FRESH_ARGV_UNSTABLE')"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_POST')"},{"line":91,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"def _execute_local(legacy,node,argv,dest,cap,timeout):"},{"line":92,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(node=='pve01','LOCAL_NODE')"},{"line":95,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)"},{"line":112,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"except subprocess.TimeoutExpired:"},{"line":117,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"def _execute_remote(legacy,node,argv,dest,cap,timeout):"},{"line":118,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')"},{"line":120,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')"},{"line":122,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_PRE')"},{"line":130,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]"},{"line":133,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)"},{"line":156,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')"},{"line":183,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"def _emit_diag(node,summary):"},{"line":184,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"safe={'node':node}"},{"line":193,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":195,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":197,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":199,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)"},{"line":200,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)"},{"line":203,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"legacy.mapped_scratch_probe(node,scratch)"},{"line":206,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)"},{"line":208,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_emit_diag(node,e.summary|{'failure_code':e.code})"},{"line":209,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"raise legacy.BackupError('LXC_PRODUCER_FAILED') from None"},{"line":211,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"_emit_diag(node,result)"},{"line":213,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise"},{"line":214,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':scratch}"},{"line":215,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),"},{"line":216,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/lxc_adapter.py","text":"'producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}"},{"line":2,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time"},{"line":6,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py'"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"def _live_inputs(legacy,node,vmid,scratch):"},{"line":42,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue"},{"line":50,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"try: rid=int(r.get('vmid'))"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"except Exception: raise AdapterError('RESOURCE_VMID')"},{"line":52,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r[\"type\"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')"},{"line":57,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)"},{"line":59,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(0<len(data)<=4_000_000,'FRESH_HELPER_INPUT_BOUND')"},{"line":68,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(p.returncode==0 and not p.stderr and 0<len(p.stdout)<=262144,'FRESH_HELPER_FAILED')"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"except Exception as e: raise AdapterError('FRESH_HELPER_JSON') from e"},{"line":72,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(type(out) is dict and out.get('schema')==1 and type(out.get('argv')) is list and type(out.get('job')) is dict,'FRESH_HELPER_SCHEMA')"},{"line":80,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":82,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":84,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":85,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"a=_helper(_live_inputs(legacy,node,vmid,scratch)); b=_helper(_live_inputs(legacy,node,vmid,scratch))"},{"line":86,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_stable_job(a['job'])==_stable_job(b['job']),'FRESH_PLAN_UNSTABLE')"},{"line":87,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(a['argv']==b['argv'],'FRESH_ARGV_UNSTABLE')"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_POST')"},{"line":91,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"def _execute_local(legacy,node,argv,dest,cap,timeout):"},{"line":92,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(node=='pve01','LOCAL_NODE')"},{"line":95,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)"},{"line":112,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"except subprocess.TimeoutExpired:"},{"line":117,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"def _execute_remote(legacy,node,argv,dest,cap,timeout):"},{"line":118,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')"},{"line":120,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')"},{"line":122,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_PRE')"},{"line":130,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]"},{"line":133,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)"},{"line":156,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')"},{"line":183,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"def _emit_diag(node,summary):"},{"line":184,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"safe={'node':node}"},{"line":193,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":195,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":197,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":199,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)"},{"line":200,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)"},{"line":203,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"legacy.mapped_scratch_probe(node,scratch)"},{"line":206,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)"},{"line":208,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_emit_diag(node,e.summary|{'failure_code':e.code})"},{"line":209,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"raise legacy.BackupError('LXC_PRODUCER_FAILED') from None"},{"line":211,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"_emit_diag(node,result)"},{"line":213,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise"},{"line":214,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':scratch}"},{"line":215,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),"},{"line":216,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/lxc_adapter.py","text":"'producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}"},{"line":2,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time"},{"line":6,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py'"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"def _live_inputs(legacy,node,vmid,scratch):"},{"line":42,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue"},{"line":50,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"try: rid=int(r.get('vmid'))"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"except Exception: raise AdapterError('RESOURCE_VMID')"},{"line":52,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r[\"type\"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')"},{"line":57,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)"},{"line":59,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(0<len(data)<=4_000_000,'FRESH_HELPER_INPUT_BOUND')"},{"line":68,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(p.returncode==0 and not p.stderr and 0<len(p.stdout)<=262144,'FRESH_HELPER_FAILED')"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"except Exception as e: raise AdapterError('FRESH_HELPER_JSON') from e"},{"line":72,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(type(out) is dict and out.get('schema')==1 and type(out.get('argv')) is list and type(out.get('job')) is dict,'FRESH_HELPER_SCHEMA')"},{"line":80,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":82,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":84,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":85,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"a=_helper(_live_inputs(legacy,node,vmid,scratch)); b=_helper(_live_inputs(legacy,node,vmid,scratch))"},{"line":86,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_stable_job(a['job'])==_stable_job(b['job']),'FRESH_PLAN_UNSTABLE')"},{"line":87,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(a['argv']==b['argv'],'FRESH_ARGV_UNSTABLE')"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_POST')"},{"line":91,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"def _execute_local(legacy,node,argv,dest,cap,timeout):"},{"line":92,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(node=='pve01','LOCAL_NODE')"},{"line":95,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)"},{"line":112,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"except subprocess.TimeoutExpired:"},{"line":117,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"def _execute_remote(legacy,node,argv,dest,cap,timeout):"},{"line":118,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')"},{"line":120,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')"},{"line":122,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_PRE')"},{"line":130,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]"},{"line":133,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)"},{"line":156,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')"},{"line":183,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"def _emit_diag(node,summary):"},{"line":184,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"safe={'node':node}"},{"line":193,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":195,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":197,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"legacy._default_unprivileged_lxc(node,vmid)"},{"line":199,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)"},{"line":200,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)"},{"line":203,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"legacy.mapped_scratch_probe(node,scratch)"},{"line":206,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)"},{"line":208,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_emit_diag(node,e.summary|{'failure_code':e.code})"},{"line":209,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"raise legacy.BackupError('LXC_PRODUCER_FAILED') from None"},{"line":211,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"_emit_diag(node,result)"},{"line":213,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise"},{"line":214,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':scratch}"},{"line":215,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),"},{"line":216,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py","text":"'producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}"}],"producer_exec_helper.py":[{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"def selftest()->int:"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"if sys.argv[1:]==['selftest']: return selftest()"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"if sys.argv[1:]: fail('ARGC')"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"if type(x) is not dict or set(x)!={'argv','dest','cap','seconds'}: fail('INPUT_SCHEMA')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"if not (type(argv) is list and argv and all(type(v) is str and '\\x00' not in v for v in argv)): fail('ARGV')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-502r1-9d13ea486935/producer_exec_helper.py","text":"if argv[0]!='/usr/bin/vzdump': fail('VZDUMP_PATH')"},{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"def selftest()->int:"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"if sys.argv[1:]==['selftest']: return selftest()"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"if sys.argv[1:]: fail('ARGC')"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"if type(x) is not dict or set(x)!={'argv','dest','cap','seconds'}: fail('INPUT_SCHEMA')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"if not (type(argv) is list and argv and all(type(v) is str and '\\x00' not in v for v in argv)): fail('ARGV')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/producer_exec_helper.py","text":"if argv[0]!='/usr/bin/vzdump': fail('VZDUMP_PATH')"},{"line":4,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411')"},{"line":26,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"def selftest()->int:"},{"line":31,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)"},{"line":35,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"if sys.argv[1:]==['selftest']: return selftest()"},{"line":36,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"if sys.argv[1:]: fail('ARGC')"},{"line":41,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"if type(x) is not dict or set(x)!={'argv','dest','cap','seconds'}: fail('INPUT_SCHEMA')"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"if not (type(argv) is list and argv and all(type(v) is str and '\\x00' not in v for v in argv)): fail('ARGV')"},{"line":44,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py","text":"if argv[0]!='/usr/bin/vzdump': fail('VZDUMP_PATH')"}],"qemu_adapter.py":[{"line":11,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":12,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":17,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"def _select_qemu_outputs(vmid,files):"},{"line":18,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(type(vmid) is int and vmid>0,'QEMU_VMID')"},{"line":21,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"pat=re.compile(r'^vzdump-qemu-'+re.escape(str(vmid))+r'-(\\d{4}_\\d{2}_\\d{2}-\\d{2}_\\d{2}_\\d{2})\\.vma\\.zst$')"},{"line":29,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"expected_log=parent/f'vzdump-qemu-{vmid}-{stamp}.log'"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":47,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)"},{"line":53,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=vp.returncode,stderr_bytes=len(vp.stderr),stderr_sha256=hashlib.sha256(vp.stderr).hexdigest(),archive_selected=False)"},{"line":54,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"raise legacy.BackupError('QEMU_VZDUMP_FAILED')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')"},{"line":56,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)"},{"line":58,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"try: src,log=_select_qemu_outputs(vmid,files)"},{"line":60,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))"},{"line":61,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"raise legacy.BackupError(str(e)) from None"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"if node=='pve01': local=pathlib.Path(src)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),sidecar_count=1 if log else 0,archive_bytes=size,archive_selected=True)"},{"line":73,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise"},{"line":74,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}"},{"line":75,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),"},{"line":11,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":12,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":17,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"def _select_qemu_outputs(vmid,files):"},{"line":18,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_need(type(vmid) is int and vmid>0,'QEMU_VMID')"},{"line":21,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"pat=re.compile(r'^vzdump-qemu-'+re.escape(str(vmid))+r'-(\\d{4}_\\d{2}_\\d{2}-\\d{2}_\\d{2}_\\d{2})\\.vma\\.zst$')"},{"line":29,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"expected_log=parent/f'vzdump-qemu-{vmid}-{stamp}.log'"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":47,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)"},{"line":53,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=vp.returncode,stderr_bytes=len(vp.stderr),stderr_sha256=hashlib.sha256(vp.stderr).hexdigest(),archive_selected=False)"},{"line":54,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"raise legacy.BackupError('QEMU_VZDUMP_FAILED')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')"},{"line":56,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)"},{"line":58,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"try: src,log=_select_qemu_outputs(vmid,files)"},{"line":60,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))"},{"line":61,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"raise legacy.BackupError(str(e)) from None"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"if node=='pve01': local=pathlib.Path(src)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),sidecar_count=1 if log else 0,archive_bytes=size,archive_selected=True)"},{"line":73,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise"},{"line":74,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}"},{"line":75,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),"},{"line":11,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"def _remote_sha(legacy,node,path):"},{"line":12,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)"},{"line":17,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"def _select_qemu_outputs(vmid,files):"},{"line":18,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(type(vmid) is int and vmid>0,'QEMU_VMID')"},{"line":21,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"pat=re.compile(r'^vzdump-qemu-'+re.escape(str(vmid))+r'-(\\d{4}_\\d{2}_\\d{2}-\\d{2}_\\d{2}_\\d{2})\\.vma\\.zst$')"},{"line":29,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"expected_log=parent/f'vzdump-qemu-{vmid}-{stamp}.log'"},{"line":43,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"vmid=int(t['vmid']); rows=[r for r in legacy.cluster_inventory() if int(r.get('vmid',-1))==vmid]"},{"line":45,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"row=rows[0]; node=row.get('node'); typ=row.get('type')"},{"line":47,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')"},{"line":49,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)"},{"line":51,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)"},{"line":53,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=vp.returncode,stderr_bytes=len(vp.stderr),stderr_sha256=hashlib.sha256(vp.stderr).hexdigest(),archive_selected=False)"},{"line":54,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"raise legacy.BackupError('QEMU_VZDUMP_FAILED')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')"},{"line":56,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)"},{"line":58,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"try: src,log=_select_qemu_outputs(vmid,files)"},{"line":60,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))"},{"line":61,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"raise legacy.BackupError(str(e)) from None"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)"},{"line":67,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"if node=='pve01': local=pathlib.Path(src)"},{"line":69,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),sidecar_count=1 if log else 0,archive_bytes=size,archive_selected=True)"},{"line":73,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise"},{"line":74,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}"},{"line":75,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-503r1-ac51fd96ec13/qemu_adapter.py","text":"meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),"}],"scheduler_adapter.py":[{"line":7,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"class SchedulerAdapterError(RuntimeError): pass"},{"line":10,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"if not ok: raise SchedulerAdapterError(code)"},{"line":23,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def _read_prior(legacy,logical_id):"},{"line":25,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"p=root/(str(logical_id)+'.json')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def choose_due_target(targets,state,now=None):"},{"line":57,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"_need(isinstance(targets,list) and isinstance(state,dict),'SCHEDULER_INPUT_SCHEMA')"},{"line":58,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"due=[]"},{"line":59,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"for order,t in enumerate(targets):"},{"line":61,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"lid=t.get('logical_id'); seconds=_as_nonneg_int(t.get('due_seconds'),0)"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"_need(isinstance(lid,str) and lid and seconds>0,'SCHEDULER_TARGET_SCHEMA')"},{"line":70,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"overdue=age-seconds"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"due.append((overdue,-order,t))"},{"line":72,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"if not due: return None"},{"line":73,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return max(due,key=lambda x:(x[0],x[1]))[2]"},{"line":75,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def write_state(logical_id,result,**kw):"},{"line":77,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"prior=_read_prior(legacy,logical_id)"},{"line":81,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return original_write(logical_id,result,**clean)"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return original_write(logical_id,result,**clean)"},{"line":90,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"legacy.choose_due_target=choose_due_target"},{"line":92,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return {'choose_due_target':choose_due_target,'write_state':write_state,"},{"line":7,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"class SchedulerAdapterError(RuntimeError): pass"},{"line":10,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"if not ok: raise SchedulerAdapterError(code)"},{"line":23,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def _read_prior(legacy,logical_id):"},{"line":25,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"p=root/(str(logical_id)+'.json')"},{"line":55,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def choose_due_target(targets,state,now=None):"},{"line":57,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"_need(isinstance(targets,list) and isinstance(state,dict),'SCHEDULER_INPUT_SCHEMA')"},{"line":58,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"due=[]"},{"line":59,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"for order,t in enumerate(targets):"},{"line":61,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"lid=t.get('logical_id'); seconds=_as_nonneg_int(t.get('due_seconds'),0)"},{"line":62,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"_need(isinstance(lid,str) and lid and seconds>0,'SCHEDULER_TARGET_SCHEMA')"},{"line":70,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"overdue=age-seconds"},{"line":71,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"due.append((overdue,-order,t))"},{"line":72,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"if not due: return None"},{"line":73,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return max(due,key=lambda x:(x[0],x[1]))[2]"},{"line":75,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"def write_state(logical_id,result,**kw):"},{"line":77,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"prior=_read_prior(legacy,logical_id)"},{"line":81,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return original_write(logical_id,result,**clean)"},{"line":88,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return original_write(logical_id,result,**clean)"},{"line":90,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"legacy.choose_due_target=choose_due_target"},{"line":92,"path":"/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py","text":"return {'choose_due_target':choose_due_target,'write_state':write_state,"}]}
NODEWORKER_INFO={"path":"/usr/local/libexec/homelab-vm-cloud-quorum-node-worker","sha256":"91bdd116be865560a38105dffbd1a66d687232035e2359e4a5be4d225e9c61d1","size":17702}
NODEWORKER_LOGIC_HITS=[{"line":6,"text":"STATE_ROOT=/var/lib/homelab-backup/cloud-quorum"},{"line":8,"text":"RESTORE_STATE_ROOT=/var/lib/homelab-backup/vm-restore-validation"},{"line":9,"text":"RESTORE_WORK_ROOT=/mnt/staging/homelab-vm-restore-validation"},{"line":11,"text":"REMOTE_A='pve01-mail-01-crypt:homelab-backups'"},{"line":12,"text":"REMOTE_B='pve01-mail-02-crypt:homelab-backups'"},{"line":18,"text":"ACTIVE_RESTORE_STAGE=\"\""},{"line":19,"text":"cleanup_restore_stage(){ if [[ -n \"$ACTIVE_RESTORE_STAGE\" && \"$ACTIVE_RESTORE_STAGE\" == \"$RESTORE_WORK_ROOT\"/* && -d \"$ACTIVE_RESTORE_STAGE\" ]]; then rm -rf --one-file-system \"$ACTIVE_RESTORE_STAGE\"; fi; }"},{"line":20,"text":"trap cleanup_restore_stage EXIT"},{"line":21,"text":"active_backup_restore(){ local rc; if pgrep -af '(^|/)(vzdump|qmrestore|pctrestore|vma|zstd|rclone)([[:space:]]|$)'; then return 0; else rc=$?; [[ \"$rc\" == 1 ]] && return 0; die \"PGREP_FAILED_$rc\" 69; fi; }"},{"line":24,"text":"expected_owner(){"},{"line":25,"text":"case \"$1\" in"},{"line":29,"text":"*) die \"VMID_NOT_ALLOWED_$1\" 64 ;;"},{"line":33,"text":"case \"$1\" in"},{"line":36,"text":"*) die \"VMID_NOT_ALLOWED_$1\" 64 ;;"},{"line":43,"text":"local vmid=\"$1\" type=\"$2\""},{"line":44,"text":"if [[ \"$type\" == \"qemu\" ]]; then qm status \"$vmid\" | awk '{print $2}'; else pct status \"$vmid\" | awk '{print $2}'; fi"},{"line":47,"text":"local vmid=\"$1\" owner type status expect_status"},{"line":48,"text":"owner=\"$(expected_owner \"$vmid\")\""},{"line":49,"text":"type=\"$(expected_type \"$vmid\")\""},{"line":50,"text":"[[ \"$HOST\" == \"$owner\" ]] || die \"OWNER_MISMATCH_${vmid}_${HOST}_EXPECTED_${owner}\" 65"},{"line":52,"text":"[[ -s \"/etc/pve/qemu-server/${vmid}.conf\" ]] || die \"QEMU_CONFIG_MISSING_$vmid\" 66"},{"line":54,"text":"[[ -s \"/etc/pve/lxc/${vmid}.conf\" ]] || die \"LXC_CONFIG_MISSING_$vmid\" 66"},{"line":56,"text":"status=\"$(current_status \"$vmid\" \"$type\")\""},{"line":57,"text":"expect_status=\"$(expected_status \"$vmid\")\""},{"line":58,"text":"[[ \"$status\" == \"$expect_status\" ]] || die \"STATUS_MISMATCH_${vmid}_${status}_EXPECTED_${expect_status}\" 66"},{"line":59,"text":"if [[ \"$vmid\" == \"160\" ]]; then [[ \"$(snapshot_count_160)\" == \"0\" ]] || die \"VM160_SNAPSHOT_COUNT_CHANGED\" 66; fi"},{"line":60,"text":"if [[ \"$vmid\" == \"9130\" ]]; then [[ \"$(vm_lock 9130)\" == \"none\" ]] || die \"VM9130_LOCK_PRESENT\" 66; fi"},{"line":65,"text":"local vmid=\"$1\" type=\"$2\" status expect_status"},{"line":66,"text":"status=\"$(current_status \"$vmid\" \"$type\")\""},{"line":67,"text":"expect_status=\"$(expected_status \"$vmid\")\""},{"line":68,"text":"[[ \"$status\" == \"$expect_status\" ]] || die \"POST_STATUS_MISMATCH_${vmid}_${status}_EXPECTED_${expect_status}\" 66"},{"line":69,"text":"if [[ \"$vmid\" == \"160\" ]]; then [[ \"$(snapshot_count_160)\" == \"0\" ]] || die \"VM160_SNAPSHOT_COUNT_CHANGED_POST\" 66; fi"},{"line":70,"text":"if [[ \"$vmid\" == \"9130\" ]]; then [[ \"$(vm_lock 9130)\" == \"none\" ]] || die \"VM9130_LOCK_PRESENT_POST\" 66; fi"},{"line":73,"text":"local vmid=\"$1\" dir=\"$STATE_ROOT/vm${vmid}\" f"},{"line":79,"text":"restore_dir(){ printf '%s\\n' \"$RESTORE_STATE_ROOT/vm$1\"; }"},{"line":80,"text":"restore_ok(){"},{"line":81,"text":"local vmid=\"$1\" gen=\"$2\" f state sha"},{"line":82,"text":"f=\"$(restore_dir \"$vmid\")/$gen.json\"; state=\"$STATE_ROOT/vm${vmid}/$gen.json\""},{"line":85,"text":"jq -e --arg l \"vm${vmid}\" --arg g \"$gen\" --arg s \"$state\" --arg sha \"$sha\" '.schema==\"homelab-vm-restore-validation-v1\" and .logical_id==$l and .generation==$g and .transport_state==\"SEALED\" and .transport_state_file==$s and .restore_source==\"Cloud A\" and .parts_manifest_verified==true and .payload_sha256==$sha and .payload_sha256_verified==true and .payload_decompression_verified==true and .proxmox_config_extract_verified==true and .archive_recovery_readback_verified==true and .bounded_staging==true and .full_local_payload_written==false and .full_restore_proven==false and .result==\"OK\"' \"$f\" >/dev/null"},{"line":88,"text":"local vmid=\"$1\" gen=\"$2\" state=\"$3\" work=\"$4\" base manifest expected_msha got_msha expected_count expected_size idx name size psha count total"},{"line":90,"text":"[[ \"$base\" == \"${REMOTE_A%/}/vm${vmid}/$gen\" ]] || die \"RESTORE_A_BASE_MISMATCH_$vmid\" 70"},{"line":92,"text":"got_msha=\"$(sha256sum \"$manifest\"|awk '{print $1}')\"; [[ \"$got_msha\" == \"$expected_msha\" ]] || die \"RESTORE_A_MANIFEST_SHA_MISMATCH_$vmid\" 70"},{"line":95,"text":"[[ \"$idx\" =~ ^[0-9]{8}$ && \"$name\" == part-????????.bin && \"$size\" =~ ^[1-9][0-9]*$ && \"$psha\" =~ ^[0-9a-f]{64}$ ]] || die \"RESTORE_A_MANIFEST_ROW_INVALID_$vmid\" 70"},{"line":96,"text":"(( size <= 536870912 )) || die \"RESTORE_A_PART_EXCEEDS_BOUND_$vmid\" 70"},{"line":97,"text":"[[ \"$idx\" == \"$(printf '%08d' \"$count\")\" ]] || die \"RESTORE_A_MANIFEST_INDEX_INVALID_$vmid\" 70"},{"line":100,"text":"[[ \"$count\" == \"$expected_count\" ]] || die \"RESTORE_A_PART_COUNT_MISMATCH_$vmid\" 70"},{"line":101,"text":"[[ \"$total\" == \"$expected_size\" ]] || die \"RESTORE_A_MANIFEST_TOTAL_SIZE_MISMATCH_$vmid\" 70"},{"line":105,"text":"local vmid=\"$1\" base=\"$2\" manifest=\"$3\" work=\"$4\" idx name size psha part actual count"},{"line":109,"text":"[[ -s \"$part\" && ! -L \"$part\" && \"$(stat -c %s \"$part\")\" == \"$size\" ]] || die \"RESTORE_A_PART_SIZE_MISMATCH_$vmid\" 70"},{"line":110,"text":"actual=\"$(sha256sum \"$part\"|awk '{print $1}')\"; [[ \"$actual\" == \"$psha\" ]] || die \"RESTORE_A_PART_SHA_MISMATCH_$vmid\" 70"},{"line":114,"text":"restore_validate(){"},{"line":115,"text":"local vmid=\"$1\" gen=\"$2\" logical state work payload_name expected_sha expected_size base manifest fifo sha_out sha_pid pipe_rc sha_rc actual_sha config config_sha members member_count cfg_member level out tmp"},{"line":116,"text":"assert_local_identity \"$vmid\"; logical=\"vm${vmid}\"; state=\"$STATE_ROOT/$logical/$gen.json\""},{"line":117,"text":"[[ -s \"$state\" && ! -L \"$state\" ]] || die \"RESTORE_STATE_MISSING_$vmid\" 65"},{"line":118,"text":"jq -e '.schema==\"homelab-cloud-quorum-payload-v1\" and .status==\"SEALED\" and .cloud_quorum==2 and .cloud_a_verified==true and .cloud_b_verified==true and .part_hashes_verified==true and .seal_written==true and .cloud_a_seal_verified==true and .cloud_b_seal_verified==true and .local_payload_present==false and .local_cleanup==\"OK\"' \"$state\" >/dev/null || die \"RESTORE_REQUIRES_STRICT_SEALED_$vmid\" 65"},{"line":119,"text":"if restore_ok \"$vmid\" \"$gen\"; then printf 'RESTORE_VALIDATION_STATUS=OK\\nVMID=%s\\nGENERATION=%s\\nRESULT=ALREADY_VALIDATED\\nRESTORE_EVIDENCE=%s\\n' \"$vmid\" \"$gen\" \"$(restore_dir \"$vmid\")/$gen.json\"; return 0; fi"},{"line":120,"text":"[[ -z \"$(active_backup_restore)\" ]] || die ACTIVE_BACKUP_RESTORE_PRESENT 75"},{"line":122,"text":"[[ \"$payload_name\" == \"vzdump-lxc-${vmid}-\"*.tar.zst || \"$payload_name\" == \"vzdump-qemu-${vmid}-\"*.vma.zst ]] || die \"RESTORE_PAYLOAD_NAME_INVALID_$vmid\" 70"},{"line":123,"text":"work=\"$RESTORE_WORK_ROOT/$logical/$gen\"; if [[ -e \"$work\" ]]; then [[ -d \"$work\" && ! -L \"$work\" ]] || die \"RESTORE_WORK_UNSAFE_$vmid\" 70; rm -rf --one-file-system \"$work\"; fi; mkdir -p \"$work\"; chmod 0700 \"$RESTORE_WORK_ROOT\" \"$RESTORE_WORK_ROOT/$logical\" \"$work\"; ACTIVE_RESTORE_STAGE=\"$work\""},{"line":124,"text":"base=\"$(prepare_cloud_a_manifest \"$vmid\" \"$gen\" \"$state\" \"$work\")\"; manifest=\"$work/PARTS.tsv\"; fifo=\"$work/archive.sha.fifo\"; sha_out=\"$work/archive.sha256\"; mkfifo -m 0600 \"$fifo\""},{"line":127,"text":"members=\"$work/members.txt\"; if stream_cloud_a \"$vmid\" \"$base\" \"$manifest\" \"$work\" | tee \"$fifo\" | zstd -dc | tar -tf - >\"$members\"; then pipe_rc=0; else pipe_rc=$?; fi"},{"line":129,"text":"if stream_cloud_a \"$vmid\" \"$base\" \"$manifest\" \"$work\" | tee \"$fifo\" | zstd -t - >/dev/null; then pipe_rc=0; else pipe_rc=$?; fi"},{"line":132,"text":"(( pipe_rc == 0 && sha_rc == 0 )) || die \"RESTORE_A_STREAM_VALIDATION_FAILED_${vmid}_${pipe_rc}_${sha_rc}\" 70"},{"line":133,"text":"actual_sha=\"$(awk 'NR==1{print $1}' \"$sha_out\")\"; [[ \"$actual_sha\" == \"$expected_sha\" ]] || die \"RESTORE_A_PAYLOAD_SHA_MISMATCH_$vmid\" 70"},{"line":136,"text":"[[ -s \"$members\" ]] || die \"RESTORE_LXC_ARCHIVE_EMPTY_$vmid\" 70"},{"line":137,"text":"awk '$0 ~ /^\\// || $0 ~ /(^|\\/)\\.\\.(\\/|$)/ {bad=1} END{exit bad}' \"$members\" || die \"RESTORE_LXC_MEMBER_UNSAFE_$vmid\" 70"},{"line":138,"text":"member_count=\"$(wc -l <\"$members\")\"; [[ \"$member_count\" =~ ^[1-9][0-9]*$ ]] || die \"RESTORE_LXC_MEMBER_COUNT_INVALID_$vmid\" 70"},{"line":139,"text":"cfg_member=\"$(awk '$0==\"./etc/vzdump/pct.conf\" || $0==\"etc/vzdump/pct.conf\" {print; exit}' \"$members\")\"; [[ -n \"$cfg_member\" ]] || die \"RESTORE_LXC_CONFIG_MEMBER_MISSING_$vmid\" 70"},{"line":140,"text":"if ( set +o pipefail; stream_cloud_a \"$vmid\" \"$base\" \"$manifest\" \"$work\" | zstd -dc | tar -xOf - \"$cfg_member\" >\"$config\" ); then :; else die \"RESTORE_LXC_CONFIG_EXTRACT_FAILED_$vmid\" 70; fi"},{"line":143,"text":"if ( set +o pipefail; stream_cloud_a \"$vmid\" \"$base\" \"$manifest\" \"$work\" | zstd -dc | vma config - >\"$config\" ); then :; else die \"RESTORE_QEMU_CONFIG_EXTRACT_FAILED_$vmid\" 70; fi"},{"line":146,"text":"[[ -s \"$config\" && ! -L \"$config\" ]] || die \"RESTORE_CONFIG_EMPTY_$vmid\" 70; config_sha=\"$(sha256sum \"$config\"|awk '{print $1}')\""},{"line":147,"text":"out=\"$(restore_dir \"$vmid\")/$gen.json\"; mkdir -p \"$(dirname \"$out\")\"; chmod 0700 \"$RESTORE_STATE_ROOT\" \"$(dirname \"$out\")\"; tmp=\"${out}.new.$$\""},{"line":148,"text":"jq -n --arg logical \"$logical\" --arg generation \"$gen\" --argjson vmid \"$vmid\" --arg vm_type \"$VM_TYPE\" --arg state \"$state\" --arg sha \"$expected_sha\" --arg config_sha \"$config_sha\" --arg level \"$level\" --argjson member_count \"$member_count\" --arg at \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" '{schema:\"homelab-vm-restore-validation-v1\",logical_id:$logical,generation:$generation,vmid:$vmid,vm_type:$vm_type,transport_state:\"SEALED\",transport_state_file:$state,restore_source:\"Cloud A\",parts_manifest_verified:true,payload_sha256:$sha,payload_sha256_verified:true,payload_decompression_verified:true,proxmox_config_extract_verified:true,proxmox_config_sha256:$config_sha,lxc_member_count:$member_count,archive_recovery_readback_verified:true,bounded_staging:true,max_staged_part_bytes:536870912,full_local_payload_written:false,full_restore_proven:false,validation_level:$level,result:\"OK\",validated_at_utc:$at}' >\"$tmp\""},{"line":149,"text":"chmod 0600 \"$tmp\"; mv -f -- \"$tmp\" \"$out\"; rm -rf --one-file-system \"$work\"; ACTIVE_RESTORE_STAGE=\"\""},{"line":150,"text":"restore_ok \"$vmid\" \"$gen\" || die \"RESTORE_EVIDENCE_POSTWRITE_INVALID_$vmid\" 70"},{"line":151,"text":"printf 'RESTORE_VALIDATION_STATUS=OK\\nVMID=%s\\nGENERATION=%s\\nRESTORE_EVIDENCE=%s\\n' \"$vmid\" \"$gen\" \"$out\""},{"line":154,"text":"local vmid=\"$1\" owner type status"},{"line":155,"text":"assert_local_identity \"$vmid\""},{"line":156,"text":"owner=\"$(expected_owner \"$vmid\")\""},{"line":157,"text":"type=\"$(expected_type \"$vmid\")\""},{"line":158,"text":"status=\"$(expected_status \"$vmid\")\""},{"line":159,"text":"printf 'PLAN_STATUS=OK\\nVMID=%s\\nOWNER=%s\\nTYPE=%s\\nEXPECTED_STATUS=%s\\n' \"$vmid\" \"$owner\" \"$type\" \"$status\""},{"line":162,"text":"local vmid=\"$1\" generation=\"$2\""},{"line":163,"text":"assert_local_identity \"$vmid\""},{"line":164,"text":"restore_validate \"$vmid\" \"$generation\""},{"line":165,"text":"assert_post_identity \"$vmid\" \"$VM_TYPE\""},{"line":166,"text":"printf 'VERIFY_STATUS=OK\\nVMID=%s\\nGENERATION=%s\\nRESTORE_EVIDENCE=%s\\n' \"$vmid\" \"$generation\" \"$(restore_dir \"$vmid\")/$generation.json\""},{"line":168,"text":"backup_one(){"},{"line":169,"text":"local vmid=\"$1\" pending_count pending state generation payload gen_dir archive_count archive log_file before_status"},{"line":171,"text":"assert_local_identity \"$vmid\""},{"line":176,"text":"[[ -z \"$(active_backup_restore)\" ]] || die \"ACTIVE_BACKUP_RESTORE_PRESENT\" 75"},{"line":179,"text":"mapfile -t pending < <(latest_incomplete_state \"$vmid\")"},{"line":181,"text":"(( pending_count <= 1 )) || die \"MULTIPLE_INCOMPLETE_GENERATIONS_$vmid\" 65"},{"line":186,"text":"printf 'RESUME=YES\\nVMID=%s\\nGENERATION=%s\\nSTATE=%s\\n' \"$vmid\" \"$generation\" \"$state\""},{"line":187,"text":"\"$TRANSPORT\" backup-delete \"vm${vmid}\" \"$generation\" \"$payload\" \"$REMOTE_A\" \"$REMOTE_B\" \"$STATE_ROOT\""},{"line":189,"text":"generation=\"vm${vmid}-${HOST}-$(date -u +%Y%m%dT%H%M%SZ)\""},{"line":190,"text":"gen_dir=\"$STAGE_ROOT/vm${vmid}/$generation\""},{"line":195,"text":"printf 'RESUME=NO\\nVMID=%s\\nGENERATION=%s\\n' \"$vmid\" \"$generation\""},{"line":202,"text":"if ! ( umask 0022; exec vzdump \"$vmid\" \"${vzdump_args[@]}\" ) >\"$log_file\" 2>&1; then"},{"line":204,"text":"die \"VZDUMP_FAILED_$vmid\" 70"},{"line":206,"text":"mapfile -t archives < <(find \"$gen_dir\" -maxdepth 1 -type f -name \"vzdump-*-${vmid}-*.zst\" -print)"},{"line":208,"text":"[[ \"$archive_count\" == \"1\" ]] || { rm -rf -- \"$gen_dir\"; die \"VZDUMP_ARCHIVE_COUNT_${vmid}_${archive_count}\" 70; }"},{"line":210,"text":"[[ -s \"$archive\" && ! -L \"$archive\" ]] || die \"VZDUMP_ARCHIVE_UNSAFE_$vmid\" 70"},{"line":212,"text":"\"$TRANSPORT\" backup-delete \"vm${vmid}\" \"$generation\" \"$archive\" \"$REMOTE_A\" \"$REMOTE_B\" \"$STATE_ROOT\""},{"line":215,"text":"rmdir -- \"$STAGE_ROOT/vm${vmid}\" 2>/dev/null || true"},{"line":217,"text":"assert_post_identity \"$vmid\" \"$VM_TYPE\""},{"line":218,"text":"state=\"$STATE_ROOT/vm${vmid}/$generation.json\""},{"line":220,"text":"restore_validate \"$vmid\" \"$generation\""},{"line":221,"text":"printf 'BACKUP_STATUS=SEALED\\nVMID=%s\\nGENERATION=%s\\nOWNER=%s\\nTYPE=%s\\nPOST_STATUS=%s\\nRESTORE_EVIDENCE=%s\\n' \"$vmid\" \"$generation\" \"$HOST\" \"$VM_TYPE\" \"$(expected_status \"$vmid\")\" \"$(restore_dir \"$vmid\")/$generation.json\""},{"line":226,"text":"[[ -z \"$(active_backup_restore)\" ]] || die \"ACTIVE_BACKUP_RESTORE_PRESENT\" 75"},{"line":231,"text":"printf 'HOST_PREFLIGHT_STATUS=OK\\nHOST=%s\\nSTAGING_FREE_BYTES=%s\\nREMOTE_A_FREE_BYTES=%s\\nREMOTE_B_FREE_BYTES=%s\\nACTIVE_BACKUP_RESTORE=0\\n' \"$HOST\" \"$free\" \"$a_free\" \"$b_free\""},{"line":234,"text":"local vmid=\"$1\" dir latest gen"},{"line":235,"text":"assert_local_identity \"$vmid\"; dir=\"$STATE_ROOT/vm${vmid}\""},{"line":236,"text":"[[ -d \"$dir\" ]] || die \"STATE_DIR_MISSING_$vmid\" 65"},{"line":238,"text":"[[ -n \"$latest\" && -s \"$latest\" && ! -L \"$latest\" ]] || die \"LATEST_STATE_MISSING_$vmid\" 65"},{"line":239,"text":"jq -e '.status==\"SEALED\" and .cloud_quorum==2 and .local_payload_present==false and .local_cleanup==\"OK\" and .seal_written==true' \"$latest\" >/dev/null || die \"LATEST_STATE_NOT_SEALED_$vmid\" 65"},{"line":240,"text":"gen=\"$(jq -er '.generation' \"$latest\")\"; restore_ok \"$vmid\" \"$gen\" || die \"LATEST_RESTORE_NOT_OK_$vmid\" 65"},{"line":241,"text":"printf 'LATEST_SEALED_STATUS=OK\\nVMID=%s\\nGENERATION=%s\\nSTATE_FILE=%s\\nRESTORE_EVIDENCE=%s\\n' \"$vmid\" \"$gen\" \"$latest\" \"$(restore_dir \"$vmid\")/$gen.json\""},{"line":244,"text":"case \"$ACTION\" in"},{"line":246,"text":"[[ \"$#\" == 1 ]] || die \"USAGE_HOST_PREFLIGHT\" 64"},{"line":249,"text":"latest-sealed)"},{"line":250,"text":"[[ \"$#\" == 2 ]] || die \"USAGE_LATEST_SEALED\" 64"},{"line":254,"text":"[[ \"$#\" == 2 ]] || die \"USAGE_PLAN\" 64"},{"line":257,"text":"backup)"},{"line":258,"text":"[[ \"$#\" == 2 ]] || die \"USAGE_BACKUP\" 64"},{"line":259,"text":"backup_one \"$2\""},{"line":261,"text":"restore-validate)"},{"line":262,"text":"[[ \"$#\" == 3 ]] || die \"USAGE_RESTORE_VALIDATE\" 64"},{"line":263,"text":"restore_validate \"$2\" \"$3\""},{"line":266,"text":"[[ \"$#\" == 3 ]] || die \"USAGE_VERIFY\" 64"}]
NODEWORKER_CLI_CANDIDATES=[{"kind":"dispatch","text":"case \"$1\" in"},{"kind":"subcommand-token","text":"backup"},{"kind":"subcommand-token","text":"restore"},{"kind":"subcommand-token","text":"latest-sealed"}]
DECISION=DIRECT_NODEWORKER_TARGETED_BACKUP_CLI_DISCOVERED
NO_MUTATION=true
TASK_RESULT=PASS_HOMELAB_BACKUP_NODEWORKER_CONTRACT_RCA_READONLY
HOMELAB_RESULT_CONTRACT={"changes_made":false,"command_id":"SUPPORT-260921-HOMELAB-BACKUP-NODEWORKER-CONTRACT-RCA-READONLY-1104R1","rollback_restored":null,"rollback_started":false,"status":"OK","version":1}
WORKERS2_NODEWORKER_CONTRACT_RCA_END=1

OUTPUT_END
CHAT_OUTPUT_END
