1
0
Files
homelab-public-context/runtime/latest.txt
T
2026-09-20 02:01:22 +00:00

780 lines
46 KiB
Plaintext

CHAT_OUTPUT_BEGIN
COMMAND_ID=NEWFI-260920-NEWFDOM-MESSENGERS214-PRODUCER207
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=newfi-newfdom-messengers214-backupv2-producer-contract-readonly-audit
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=ead8fdf05c4cb0a9b8b49f67777a3e68a7a96170d3e4b5061fa03171a66917da
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=99d8dcf2767bb4aeb57e414153ec37f086162257482529c3dcce3939c780c5ec
SANITIZED_OUTPUT_SHA256=99d8dcf2767bb4aeb57e414153ec37f086162257482529c3dcce3939c780c5ec
OUTPUT_BEGIN
NEWFI207_BEGIN=true
MODE=read-only
IMMUTABLE_PLAN_CHECK=PASS
CHANGES_MADE=false
MUTATION_OUTCOME=NO_MUTATION
PIN_CHECK=PASS
ACCEPTED_RELEASE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b
RELEASE_FILE_COUNT=6
INTERESTING_FILE_COUNT=6
FILE_1_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
FILE_1_BYTES=10566
FILE_1_MODE=0o400
FILE_1_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793
FILE_1_KEYWORD_SCORE=13
FILE_1_AST_DEF_COUNT=0
FILE_1_AST_IMPORT_COUNT=0
FILE_1_AST_STRING_COUNT=7
FILE_1_STRING_1_LINE=4
FILE_1_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
FILE_1_STRING_2_LINE=62
FILE_1_STRING_2_VALUE=backup_target
FILE_1_STRING_3_LINE=62
FILE_1_STRING_3_VALUE=ssh_remote
FILE_1_STRING_4_LINE=135
FILE_1_STRING_4_VALUE=payload_sha256
FILE_1_STRING_5_LINE=135
FILE_1_STRING_5_VALUE=manifest_sha256
FILE_1_STRING_6_LINE=135
FILE_1_STRING_6_VALUE=replicas
FILE_1_STRING_7_LINE=132
FILE_1_STRING_7_VALUE=homelab-scheduler-proof-
FILE_2_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
FILE_2_BYTES=13825
FILE_2_MODE=0o400
FILE_2_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d
FILE_2_KEYWORD_SCORE=9
FILE_2_AST_DEF_COUNT=2
FILE_2_DEF_1_LINE=35
FILE_2_DEF_1_NAME=_remote_sha
FILE_2_DEF_2_LINE=117
FILE_2_DEF_2_NAME=_execute_remote
FILE_2_AST_IMPORT_COUNT=0
FILE_2_AST_STRING_COUNT=17
FILE_2_STRING_1_LINE=79
FILE_2_STRING_1_VALUE=/var/tmp/homelab-vzdump-v2-plan-only
FILE_2_STRING_2_LINE=118
FILE_2_STRING_2_VALUE=REMOTE_NODE
FILE_2_STRING_3_LINE=119
FILE_2_STRING_3_VALUE=REMOTE_ARGV
FILE_2_STRING_4_LINE=120
FILE_2_STRING_4_VALUE=REMOTE_ARGV_NODE
FILE_2_STRING_5_LINE=121
FILE_2_STRING_5_VALUE=REMOTE_CAP_VALUE
FILE_2_STRING_6_LINE=124
FILE_2_STRING_6_VALUE=REMOTE_WORKDIR
FILE_2_STRING_7_LINE=158
FILE_2_STRING_7_VALUE=remote-bounded-ssh-cwd-root
FILE_2_STRING_8_LINE=198
FILE_2_STRING_8_VALUE=/var/tmp/homelab-vzdump-v2-
FILE_2_STRING_9_LINE=149
FILE_2_STRING_9_VALUE=REMOTE_TIMEOUT
FILE_2_STRING_10_LINE=151
FILE_2_STRING_10_VALUE=REMOTE_RC
FILE_2_STRING_11_LINE=152
FILE_2_STRING_11_VALUE=REMOTE_EMPTY
FILE_2_STRING_12_LINE=155
FILE_2_STRING_12_VALUE=REMOTE_FILE_IDENTITY
FILE_2_STRING_13_LINE=162
FILE_2_STRING_13_VALUE=remote-bounded-ssh-cwd-root
FILE_2_STRING_14_LINE=204
FILE_2_STRING_14_VALUE=payload.bin
FILE_2_STRING_15_LINE=210
FILE_2_STRING_15_VALUE=VZDUMP_PAYLOAD_BOUND
FILE_2_STRING_16_LINE=138
FILE_2_STRING_16_VALUE=REMOTE_TIMEOUT
FILE_2_STRING_17_LINE=143
FILE_2_STRING_17_VALUE=REMOTE_CAP
FILE_3_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
FILE_3_BYTES=4627
FILE_3_MODE=0o400
FILE_3_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b
FILE_3_KEYWORD_SCORE=9
FILE_3_AST_DEF_COUNT=1
FILE_3_DEF_1_LINE=11
FILE_3_DEF_1_NAME=_remote_sha
FILE_3_AST_IMPORT_COUNT=0
FILE_3_AST_STRING_COUNT=3
FILE_3_STRING_1_LINE=48
FILE_3_STRING_1_VALUE=/var/tmp/homelab-vzdump-v2-
FILE_3_STRING_2_LINE=66
FILE_3_STRING_2_VALUE=payload.bin
FILE_3_STRING_3_LINE=70
FILE_3_STRING_3_VALUE=QEMU_PAYLOAD_MISSING
FILE_4_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
FILE_4_BYTES=4097
FILE_4_MODE=0o400
FILE_4_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96
FILE_4_KEYWORD_SCORE=9
FILE_4_AST_DEF_COUNT=0
FILE_4_AST_IMPORT_COUNT=0
FILE_4_AST_STRING_COUNT=9
FILE_4_STRING_1_LINE=44
FILE_4_STRING_1_VALUE=last_success_payload_sha256
FILE_4_STRING_2_LINE=45
FILE_4_STRING_2_VALUE=last_success_manifest_sha256
FILE_4_STRING_3_LINE=45
FILE_4_STRING_3_VALUE=last_success_replicas
FILE_4_STRING_4_LINE=37
FILE_4_STRING_4_VALUE=payload_sha256
FILE_4_STRING_5_LINE=37
FILE_4_STRING_5_VALUE=last_success_payload_sha256
FILE_4_STRING_6_LINE=38
FILE_4_STRING_6_VALUE=manifest_sha256
FILE_4_STRING_7_LINE=38
FILE_4_STRING_7_VALUE=last_success_manifest_sha256
FILE_4_STRING_8_LINE=38
FILE_4_STRING_8_VALUE=replicas
FILE_4_STRING_9_LINE=38
FILE_4_STRING_9_VALUE=last_success_replicas
FILE_5_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
FILE_5_BYTES=3449
FILE_5_MODE=0o400
FILE_5_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3
FILE_5_KEYWORD_SCORE=7
FILE_5_AST_DEF_COUNT=0
FILE_5_AST_IMPORT_COUNT=0
FILE_5_AST_STRING_COUNT=2
FILE_5_STRING_1_LINE=4
FILE_5_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411
FILE_5_STRING_2_LINE=45
FILE_5_STRING_2_VALUE=payload.bin
FILE_6_PATH=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
FILE_6_BYTES=2320
FILE_6_MODE=0o400
FILE_6_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011
FILE_6_KEYWORD_SCORE=3
FILE_6_AST_DEF_COUNT=0
FILE_6_AST_IMPORT_COUNT=0
FILE_6_AST_STRING_COUNT=1
FILE_6_STRING_1_LINE=4
FILE_6_STRING_1_VALUE=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
CTX_1_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_1_START_LINE=15
CTX_1_END_LINE=21
CTX_1_L15=}
CTX_1_L16=
CTX_1_L17=def _sha(p):
CTX_1_L18= h=hashlib.sha256()
CTX_1_L19= with open(p,'rb',buffering=0) as f:
CTX_1_L20= while True:
CTX_1_L21= b=f.read(1<<20)
CTX_2_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_2_START_LINE=34
CTX_2_END_LINE=40
CTX_2_L34=
CTX_2_L35=class _GlobalsProxy:
CTX_2_L36= __slots__=('_g',)
CTX_2_L37= def __init__(self,g): object.__setattr__(self,'_g',g)
CTX_2_L38= def __getattr__(self,n):
CTX_2_L39= try: return self._g[n]
CTX_2_L40= except KeyError as e: raise AttributeError(n) from e
CTX_3_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_3_START_LINE=59
CTX_3_END_LINE=72
CTX_3_L59= if len(found)!=1:
CTX_3_L60= raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY')
CTX_3_L61= g=next(iter(found.values()))
CTX_3_L62= required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',
CTX_3_L63= '_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run',
CTX_3_L64= 'choose_due_target','write_state','epoch')
CTX_3_L65= if any(not callable(g.get(n)) for n in required):
CTX_3_L66= raise RuntimeError('LEGACY_PROVENANCE_API')
CTX_3_L67= original=g['capture_pve_guest']
CTX_3_L68= proxy=_GlobalsProxy(g)
CTX_3_L69= if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'):
CTX_3_L70= raise RuntimeError('LEGACY_SCP_API')
CTX_3_L71= qemu_patched=qemu_adapter.bind(proxy,original)
CTX_3_L72= if not callable(qemu_patched):
CTX_4_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_4_START_LINE=75
CTX_4_END_LINE=82
CTX_4_L75= if not callable(patched):
CTX_4_L76= raise RuntimeError('LXC_ADAPTER_BIND_RESULT')
CTX_4_L77= g['capture_pve_guest']=patched
CTX_4_L78= scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])
CTX_4_L79= if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:
CTX_4_L80= raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')
CTX_4_L81= return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}
CTX_4_L82=
CTX_5_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_5_START_LINE=96
CTX_5_END_LINE=117
CTX_5_L96= wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)
CTX_5_L97= return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired
CTX_5_L98=
CTX_5_L99=def _target(wrapper,lid):
CTX_5_L100= rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]
CTX_5_L101= if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')
CTX_5_L102= return hits[0]
CTX_5_L103=
CTX_5_L104=def selftest():
CTX_5_L105= wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()
CTX_5_L106= if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']:
CTX_5_L107= raise RuntimeError('PATCH_BINDING')
CTX_5_L108= if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:
CTX_5_L109= raise RuntimeError('SCHEDULER_CHOOSE_BINDING')
CTX_5_L110= if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:
CTX_5_L111= raise RuntimeError('SCHEDULER_WRITE_BINDING')
CTX_5_L112= if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:
CTX_5_L113= raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')
CTX_5_L114= if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):
CTX_5_L115= raise RuntimeError('WRAPPER_PUBLIC_API')
CTX_5_L116= print('SELFTEST_OVERLAY504=PASS',flush=True)
CTX_5_L117= return 0
CTX_6_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/entry504.py
CTX_6_START_LINE=125
CTX_6_END_LINE=187
CTX_6_L125= if argv==['scheduler-proof']:
CTX_6_L126= import tempfile
CTX_6_L127= legacy=wired['legacy']; g=wired['legacy_globals']
CTX_6_L128= old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch')
CTX_6_L129= if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')
CTX_6_L130= now=[1000]
CTX_6_L131= try:
CTX_6_L132= with tempfile.TemporaryDirectory(prefix='homelab-scheduler-proof-',dir='/run') as td:
CTX_6_L133= g['STATE_ROOT']=pathlib.Path(td); (g['STATE_ROOT']/'state').mkdir(mode=0o700)
CTX_6_L134= g['epoch']=lambda: now[0]
CTX_6_L135= common={'payload_sha256':'a'*64,'manifest_sha256':'b'*64,'replicas':['proof-r1','proof-r2']}
CTX_6_L136= legacy.write_state('proof-a','SUCCESS',generation='proof-a-good',**common)
CTX_6_L137= legacy.write_state('proof-b','SUCCESS',generation='proof-b-good',**common)
CTX_6_L138= now[0]=100000
CTX_6_L139= legacy.write_state('proof-a','FAIL',generation='proof-a-bad',reason='PROOF_FAILURE',sealed=False)
CTX_6_L140= state=legacy.load_state_all(); a=state['proof-a']
CTX_6_L141= targets=[{'logical_id':'proof-a','enabled':True,'due_seconds':100},{'logical_id':'proof-b','enabled':True,'due_seconds':100}]
CTX_6_L142= first=legacy.choose_due_target(targets,state,now[0])
CTX_6_L143= if not isinstance(first,dict) or first.get('logical_id')!='proof-b': raise RuntimeError('SCHEDULER_PROOF_PEER_NOT_SELECTED')
CTX_6_L144= retry=int(a.get('retry_after_epoch',0)); preserved=int(a.get('last_success_epoch',0))
CTX_6_L145= if preserved!=1000 or a.get('last_success_generation')!='proof-a-good' or int(a.get('consecutive_failures',0))!=1 or retry!=101800:
CTX_6_L146= raise RuntimeError('SCHEDULER_PROOF_FAILURE_STATE')
CTX_6_L147= now[0]=retry+1
CTX_6_L148= second=legacy.choose_due_target(targets,legacy.load_state_all(),now[0])
CTX_6_L149= if not isinstance(second,dict) or second.get('logical_id')!='proof-a': raise RuntimeError('SCHEDULER_PROOF_RETRY_NOT_REELIGIBLE')
CTX_6_L150= legacy.write_state('proof-a','SUCCESS',generation='proof-a-recovered',**common)
CTX_6_L151= recovered=legacy.load_state_all()['proof-a']
CTX_6_L152= if int(recovered.get('consecutive_failures',-1))!=0 or int(recovered.get('retry_after_epoch',-1))!=0:
CTX_6_L153= raise RuntimeError('SCHEDULER_PROOF_SUCCESS_RESET')
CTX_6_L154= 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}
CTX_6_L155= print('SCHEDULER_FAILURE_ISOLATION_PROOF='+json.dumps(proof,separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L156= return 0
CTX_6_L157= finally:
CTX_6_L158= g['STATE_ROOT']=old_root; g['epoch']=old_epoch
CTX_6_L159= if argv==['scheduler-select-live']:
CTX_6_L160= state=legacy.load_state_all(); targets=wrapper.load_targets()
CTX_6_L161= chosen=legacy.choose_due_target(targets,state)
CTX_6_L162= if chosen is None:
CTX_6_L163= print('SCHEDULER_LIVE_SELECTION=DEFER_NO_DUE_TARGET',flush=True)
CTX_6_L164= else:
CTX_6_L165= 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)
CTX_6_L166= return 0
CTX_6_L167= if len(argv)==2 and argv[0]=='plan-lxc':
CTX_6_L168= t=_target(wrapper,argv[1])
CTX_6_L169= if t.get('guest_type')!='lxc' or t.get('logical_id')=='guest-pve01-lxc-112':
CTX_6_L170= raise RuntimeError('PLAN_TARGET_NOT_LEGACY_LXC')
CTX_6_L171= out=lxc_adapter.plan_only(legacy,t)
CTX_6_L172= 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)
CTX_6_L173= return 0
CTX_6_L174= if len(argv)==2 and argv[0]=='verify-target':
CTX_6_L175= t=_target(wrapper,argv[1])
CTX_6_L176= if t.get('logical_id')=='guest-pve01-lxc-112':
CTX_6_L177= raise RuntimeError('VERIFY_SYNTHETIC_CT112_FORBIDDEN')
CTX_6_L178= try:
CTX_6_L179= out=wrapper.backup_target(t,True)
CTX_6_L180= except legacy.BackupError as e:
CTX_6_L181= print('VERIFY_TARGET_RESULT=FAIL',flush=True)
CTX_6_L182= print('VERIFY_TARGET_REASON='+str(e.code),flush=True)
CTX_6_L183= return 2
CTX_6_L184= print('VERIFY_TARGET_RESULT='+json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_6_L185= return 0
CTX_6_L186= return wrapper.main([sys.argv[0],*argv])
CTX_6_L187=
CTX_7_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_7_START_LINE=20
CTX_7_END_LINE=26
CTX_7_L20= except Exception as e: raise AdapterError(code) from e
CTX_7_L21=
CTX_7_L22=def _sha_file(p):
CTX_7_L23= h=hashlib.sha256()
CTX_7_L24= with open(p,'rb',buffering=0) as f:
CTX_7_L25= for b in iter(lambda:f.read(1<<20),b''): h.update(b)
CTX_7_L26= return h.hexdigest()
CTX_8_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_8_START_LINE=32
CTX_8_END_LINE=62
CTX_8_L32= if n<=0: raise AdapterError('WRITE_FAILED')
CTX_8_L33= view=view[n:]
CTX_8_L34=
CTX_8_L35=def _remote_sha(legacy,node,path):
CTX_8_L36= p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)
CTX_8_L37= parts=p.stdout.decode('ascii','strict').strip().split()
CTX_8_L38= _need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT')
CTX_8_L39= return parts[0]
CTX_8_L40=
CTX_8_L41=def _live_inputs(legacy,node,vmid,scratch):
CTX_8_L42= _need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')
CTX_8_L43= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')
CTX_8_L44= rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')
CTX_8_L45= stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')
CTX_8_L46= _need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA')
CTX_8_L47= configs=[]
CTX_8_L48= for r in rows:
CTX_8_L49= if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue
CTX_8_L50= try: rid=int(r.get('vmid'))
CTX_8_L51= except Exception: raise AdapterError('RESOURCE_VMID')
CTX_8_L52= cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r["type"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')
CTX_8_L53= _need(type(cfg) is dict,'CONFIG_SCHEMA')
CTX_8_L54= configs.append([rid,cfg])
CTX_8_L55= tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')
CTX_8_L56= _need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA')
CTX_8_L57= q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)
CTX_8_L58= defaults=None
CTX_8_L59= if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout
CTX_8_L60= elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE')
CTX_8_L61= st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize)
CTX_8_L62= return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,
CTX_9_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_9_START_LINE=85
CTX_9_END_LINE=91
CTX_9_L85= a=_helper(_live_inputs(legacy,node,vmid,scratch)); b=_helper(_live_inputs(legacy,node,vmid,scratch))
CTX_9_L86= _need(_stable_job(a['job'])==_stable_job(b['job']),'FRESH_PLAN_UNSTABLE')
CTX_9_L87= _need(a['argv']==b['argv'],'FRESH_ARGV_UNSTABLE')
CTX_9_L88= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_POST')
CTX_9_L89= return b
CTX_9_L90=
CTX_9_L91=def _execute_local(legacy,node,argv,dest,cap,timeout):
CTX_10_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_10_START_LINE=94
CTX_10_END_LINE=109
CTX_10_L94= data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode()
CTX_10_L95= p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)
CTX_10_L96= if p.stderr or not p.stdout or len(p.stdout)>262144:
CTX_10_L97= raise ExecFailure('LOCAL_HELPER_PROTOCOL',{'executor':'local-proven-pve270','producer_rc':None,'stderr_stream_sha256':hashlib.sha256(p.stderr).hexdigest(),'stderr_bytes_observed':len(p.stderr)})
CTX_10_L98= try: out=json.loads(p.stdout)
CTX_10_L99= except Exception:
CTX_10_L100= raise ExecFailure('LOCAL_HELPER_JSON',{'executor':'local-proven-pve270','producer_rc':None,'stderr_stream_sha256':hashlib.sha256(p.stderr).hexdigest(),'stderr_bytes_observed':len(p.stderr)})
CTX_10_L101= summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')}
CTX_10_L102= if isinstance(out.get('process'),dict): summary.update(out['process'])
CTX_10_L103= if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary)
CTX_10_L104= result=out.get('result'); _need(type(result) is dict,'LOCAL_RESULT_SCHEMA')
CTX_10_L105= _need(pathlib.Path(dest).is_file() and pathlib.Path(dest).stat().st_size==int(result.get('size',-1)),'LOCAL_RESULT_FILE')
CTX_10_L106= return summary|{'size':result['size'],'sha256':result['sha256'],'producer_rc':result.get('producer_rc')}
CTX_10_L107=
CTX_10_L108=def _kill(p):
CTX_10_L109= try: os.killpg(p.pid,signal.SIGTERM)
CTX_11_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_11_START_LINE=114
CTX_11_END_LINE=166
CTX_11_L114= except ProcessLookupError: pass
CTX_11_L115= p.wait()
CTX_11_L116=
CTX_11_L117=def _execute_remote(legacy,node,argv,dest,cap,timeout):
CTX_11_L118= _need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')
CTX_11_L119= _need(type(argv) is list and argv and argv[0]=='/usr/bin/vzdump' and all(type(x) is str and '\x00' not in x for x in argv),'REMOTE_ARGV')
CTX_11_L120= _need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')
CTX_11_L121= _need(type(cap) is int and 0<cap<=16*1024**3,'REMOTE_CAP_VALUE')
CTX_11_L122= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_PRE')
CTX_11_L123= dest=pathlib.Path(dest); parent=dest.parent
CTX_11_L124= st=os.lstat(parent); _need(stat.S_ISDIR(st.st_mode) and not stat.S_ISLNK(st.st_mode) and st.st_uid==0 and stat.S_IMODE(st.st_mode)==0o700,'REMOTE_WORKDIR')
CTX_11_L125= errp=parent/'producer.stderr.log'; metap=parent/'PRODUCER_PROCESS.json'
CTX_11_L126= fd=os.open(dest,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600); efd=os.open(errp,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
CTX_11_L127= initial=os.fstat(fd)
CTX_11_L128= digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False
CTX_11_L129= remote='cd / && exec '+shlex.join(argv)
CTX_11_L130= ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]
CTX_11_L131= deadline=time.monotonic()+timeout
CTX_11_L132= try:
CTX_11_L133= p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)
CTX_11_L134= sel=selectors.DefaultSelector()
CTX_11_L135= for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ)
CTX_11_L136= while sel.get_map():
CTX_11_L137= now=time.monotonic()
CTX_11_L138= if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{})
CTX_11_L139= for key,_ in sel.select(min(.2,max(0,deadline-now))):
CTX_11_L140= b=os.read(key.fileobj.fileno(),65536)
CTX_11_L141= if not b: sel.unregister(key.fileobj); continue
CTX_11_L142= if key.fileobj is p.stdout:
CTX_11_L143= if total+len(b)>cap: raise ExecFailure('REMOTE_CAP',{})
CTX_11_L144= _write_all(fd,b); digest.update(b); total+=len(b)
CTX_11_L145= else:
CTX_11_L146= err_total+=len(b); eh.update(b); keep=b[:max(0,MAX_STDERR-err_kept)]
CTX_11_L147= if keep: _write_all(efd,keep); err_kept+=len(keep)
CTX_11_L148= left=deadline-time.monotonic()
CTX_11_L149= if left<=0: raise ExecFailure('REMOTE_TIMEOUT',{})
CTX_11_L150= rc=p.wait(timeout=left)
CTX_11_L151= if rc!=0: raise ExecFailure('REMOTE_RC',{})
CTX_11_L152= if total<=0: raise ExecFailure('REMOTE_EMPTY',{})
CTX_11_L153= stf=os.fstat(fd); named=os.stat(dest,follow_symlinks=False)
CTX_11_L154= if (stf.st_dev,stf.st_ino)!=(initial.st_dev,initial.st_ino) or (named.st_dev,named.st_ino)!=(initial.st_dev,initial.st_ino) or stf.st_nlink!=1 or stf.st_size!=total:
CTX_11_L155= raise ExecFailure('REMOTE_FILE_IDENTITY',{})
CTX_11_L156= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')
CTX_11_L157= os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True
CTX_11_L158= return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(),
CTX_11_L159= 'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}
CTX_11_L160= except ExecFailure as e:
CTX_11_L161= if p is not None and p.poll() is None: _kill(p)
CTX_11_L162= summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total,
CTX_11_L163= 'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}
CTX_11_L164= summary.update(e.summary); raise ExecFailure(e.code,summary)
CTX_11_L165= finally:
CTX_11_L166= if p is not None:
CTX_12_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_12_START_LINE=171
CTX_12_END_LINE=178
CTX_12_L171= try: os.fsync(fd); os.fsync(efd)
CTX_12_L172= except OSError: pass
CTX_12_L173= os.close(fd); os.close(efd)
CTX_12_L174= summary={'process_started':p is not None,'producer_rc':None if p is None else p.returncode,'capture_success':good,'archive_bytes':total,
CTX_12_L175= 'stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest(),'raw_stderr_exported':False,'cwd':'/'}
CTX_12_L176= try:
CTX_12_L177= mb=(json.dumps(summary,separators=(',',':'),sort_keys=True)+'\n').encode()
CTX_12_L178= mfd=os.open(metap,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
CTX_13_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_13_START_LINE=182
CTX_13_END_LINE=188
CTX_13_L182=
CTX_13_L183=def _emit_diag(node,summary):
CTX_13_L184= safe={'node':node}
CTX_13_L185= for k in ('executor','failure_code','helper_rc','producer_rc','archive_bytes','stderr_bytes_observed','stderr_bytes_retained','stderr_truncated','stderr_stream_sha256','exception_class','exception_message_sha256'):
CTX_13_L186= if k in summary: safe[k]=summary[k]
CTX_13_L187= print('LXC_EXECUTION_DIAG='+json.dumps(safe,separators=(',',':'),sort_keys=True),flush=True)
CTX_13_L188=
CTX_14_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/lxc_adapter.py
CTX_14_START_LINE=196
CTX_14_END_LINE=218
CTX_14_L196= _need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT')
CTX_14_L197= legacy._default_unprivileged_lxc(node,vmid)
CTX_14_L198= scratch=f'/var/tmp/homelab-vzdump-v2-{gen}'
CTX_14_L199= legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)
CTX_14_L200= q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)
CTX_14_L201= _need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT')
CTX_14_L202= try:
CTX_14_L203= legacy.mapped_scratch_probe(node,scratch)
CTX_14_L204= p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes'])
CTX_14_L205= try:
CTX_14_L206= result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)
CTX_14_L207= except ExecFailure as e:
CTX_14_L208= _emit_diag(node,e.summary|{'failure_code':e.code})
CTX_14_L209= raise legacy.BackupError('LXC_PRODUCER_FAILED') from None
CTX_14_L210= _need(local.is_file() and 0<local.stat().st_size<=cap,'VZDUMP_PAYLOAD_BOUND')
CTX_14_L211= _emit_diag(node,result)
CTX_14_L212= except Exception:
CTX_14_L213= legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise
CTX_14_L214= cleanup={'kind':'pve_source_dir','node':node,'path':scratch}
CTX_14_L215= meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),
CTX_14_L216= 'producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}
CTX_14_L217= return local,meta,cleanup
CTX_14_L218= capture_pve_guest.__name__='capture_pve_guest'; return capture_pve_guest
CTX_15_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
CTX_15_START_LINE=8
CTX_15_END_LINE=37
CTX_15_L8=def _need(ok,code):
CTX_15_L9= if not ok: raise QemuAdapterError(code)
CTX_15_L10=
CTX_15_L11=def _remote_sha(legacy,node,path):
CTX_15_L12= p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)
CTX_15_L13= parts=p.stdout.decode('ascii','strict').strip().split()
CTX_15_L14= _need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT')
CTX_15_L15= return parts[0]
CTX_15_L16=
CTX_15_L17=def _select_qemu_outputs(vmid,files):
CTX_15_L18= _need(type(vmid) is int and vmid>0,'QEMU_VMID')
CTX_15_L19= _need(type(files) is list and files and all(type(x) is str and x.startswith('/') and '\x00' not in x for x in files),'QEMU_OUTPUT_LIST')
CTX_15_L20= _need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE')
CTX_15_L21= 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$')
CTX_15_L22= archives=[]
CTX_15_L23= for f in files:
CTX_15_L24= name=pathlib.PurePosixPath(f).name
CTX_15_L25= m=pat.fullmatch(name)
CTX_15_L26= if m: archives.append((f,m.group(1)))
CTX_15_L27= _need(len(archives)==1,'QEMU_ARCHIVE_NOT_UNIQUE')
CTX_15_L28= archive,stamp=archives[0]; parent=pathlib.PurePosixPath(archive).parent
CTX_15_L29= expected_log=parent/f'vzdump-qemu-{vmid}-{stamp}.log'
CTX_15_L30= allowed={archive}; log=None
CTX_15_L31= if str(expected_log) in files:
CTX_15_L32= log=str(expected_log); allowed.add(log)
CTX_15_L33= _need(set(files)==allowed,'QEMU_OUTPUT_UNEXPECTED_FILE')
CTX_15_L34= return archive,log
CTX_15_L35=
CTX_15_L36=def _emit_diag(**kw):
CTX_15_L37= print('QEMU_EXECUTION_DIAG='+json.dumps(kw,separators=(',',':'),sort_keys=True),flush=True)
CTX_16_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/qemu_adapter.py
CTX_16_START_LINE=44
CTX_16_END_LINE=78
CTX_16_L44= _need(len(rows)==1,'PVE_GUEST_NOT_UNIQUE')
CTX_16_L45= row=rows[0]; node=row.get('node'); typ=row.get('type')
CTX_16_L46= _need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT')
CTX_16_L47= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')
CTX_16_L48= srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}'
CTX_16_L49= legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)
CTX_16_L50= try:
CTX_16_L51= vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)
CTX_16_L52= if vp.returncode!=0:
CTX_16_L53= _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)
CTX_16_L54= raise legacy.BackupError('QEMU_VZDUMP_FAILED')
CTX_16_L55= _need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')
CTX_16_L56= p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\n'],timeout=30)
CTX_16_L57= files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x]
CTX_16_L58= try: src,log=_select_qemu_outputs(vmid,files)
CTX_16_L59= except QemuAdapterError as e:
CTX_16_L60= _emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))
CTX_16_L61= raise legacy.BackupError(str(e)) from None
CTX_16_L62= q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)
CTX_16_L63= raw=q.stdout.decode('ascii','strict').strip()
CTX_16_L64= _need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT')
CTX_16_L65= size=int(raw)
CTX_16_L66= local=pathlib.Path(work)/'payload.bin'
CTX_16_L67= if node=='pve01': local=pathlib.Path(src)
CTX_16_L68= else:
CTX_16_L69= legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)
CTX_16_L70= _need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING')
CTX_16_L71= _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)
CTX_16_L72= except Exception:
CTX_16_L73= legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise
CTX_16_L74= cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}
CTX_16_L75= meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),
CTX_16_L76= 'producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'}
CTX_16_L77= return pathlib.Path(local),meta,cleanup
CTX_16_L78= capture_pve_guest.__name__='capture_pve_guest'
CTX_17_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_17_START_LINE=20
CTX_17_END_LINE=28
CTX_17_L20= n=max(1,_as_nonneg_int(consecutive_failures,1))
CTX_17_L21= return min(MAX_BACKOFF,MIN_BACKOFF*(2**min(n-1,4)))
CTX_17_L22=
CTX_17_L23=def _read_prior(legacy,logical_id):
CTX_17_L24= root=pathlib.Path(legacy.STATE_ROOT)/'state'
CTX_17_L25= p=root/(str(logical_id)+'.json')
CTX_17_L26= try:
CTX_17_L27= if not p.is_file(): return {}
CTX_17_L28= d=json.loads(p.read_text(encoding='utf-8'))
CTX_18_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_18_START_LINE=34
CTX_18_END_LINE=48
CTX_18_L34= if not isinstance(prior,dict): return {}
CTX_18_L35= if prior.get('result')=='SUCCESS':
CTX_18_L36= out={'last_success_epoch':_as_nonneg_int(prior.get('last_success_epoch'),0)}
CTX_18_L37= mapping=(('generation','last_success_generation'),('payload_sha256','last_success_payload_sha256'),
CTX_18_L38= ('manifest_sha256','last_success_manifest_sha256'),('replicas','last_success_replicas'),
CTX_18_L39= ('green_verified','last_success_green_verified'))
CTX_18_L40= for src,dst in mapping:
CTX_18_L41= if src in prior: out[dst]=prior[src]
CTX_18_L42= return out
CTX_18_L43= out={}
CTX_18_L44= for k in ('last_success_epoch','last_success_generation','last_success_payload_sha256',
CTX_18_L45= 'last_success_manifest_sha256','last_success_replicas','last_success_green_verified'):
CTX_18_L46= if k in prior: out[k]=prior[k]
CTX_18_L47= return out
CTX_18_L48=
CTX_19_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_19_START_LINE=50
CTX_19_END_LINE=65
CTX_19_L50= _need(callable(original_choose),'ORIGINAL_CHOOSE_REQUIRED')
CTX_19_L51= _need(callable(original_write),'ORIGINAL_WRITE_REQUIRED')
CTX_19_L52= _need(callable(getattr(legacy,'epoch',None)),'LEGACY_EPOCH_REQUIRED')
CTX_19_L53= _need(hasattr(legacy,'STATE_ROOT'),'LEGACY_STATE_ROOT_REQUIRED')
CTX_19_L54=
CTX_19_L55= def choose_due_target(targets,state,now=None):
CTX_19_L56= now=_as_nonneg_int(legacy.epoch() if now is None else now,0)
CTX_19_L57= _need(isinstance(targets,list) and isinstance(state,dict),'SCHEDULER_INPUT_SCHEMA')
CTX_19_L58= due=[]
CTX_19_L59= for order,t in enumerate(targets):
CTX_19_L60= if not isinstance(t,dict) or t.get('enabled') is not True: continue
CTX_19_L61= lid=t.get('logical_id'); seconds=_as_nonneg_int(t.get('due_seconds'),0)
CTX_19_L62= _need(isinstance(lid,str) and lid and seconds>0,'SCHEDULER_TARGET_SCHEMA')
CTX_19_L63= s=state.get(lid,{})
CTX_19_L64= if not isinstance(s,dict): s={}
CTX_19_L65= retry_after=_as_nonneg_int(s.get('retry_after_epoch'),0)
CTX_20_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/scheduler_adapter.py
CTX_20_START_LINE=72
CTX_20_END_LINE=93
CTX_20_L72= if not due: return None
CTX_20_L73= return max(due,key=lambda x:(x[0],x[1]))[2]
CTX_20_L74=
CTX_20_L75= def write_state(logical_id,result,**kw):
CTX_20_L76= now=_as_nonneg_int(legacy.epoch(),0)
CTX_20_L77= prior=_read_prior(legacy,logical_id)
CTX_20_L78= if result=='SUCCESS':
CTX_20_L79= clean=dict(kw)
CTX_20_L80= clean.update({'last_attempt_epoch':now,'consecutive_failures':0,'retry_after_epoch':0,'failure_backoff_seconds':0})
CTX_20_L81= return original_write(logical_id,result,**clean)
CTX_20_L82= failures=_as_nonneg_int(prior.get('consecutive_failures'),0)+1
CTX_20_L83= backoff=backoff_seconds(failures)
CTX_20_L84= clean=dict(kw)
CTX_20_L85= clean.update(_success_snapshot(prior))
CTX_20_L86= clean.update({'last_attempt_epoch':now,'consecutive_failures':failures,
CTX_20_L87= 'retry_after_epoch':now+backoff,'failure_backoff_seconds':backoff})
CTX_20_L88= return original_write(logical_id,result,**clean)
CTX_20_L89=
CTX_20_L90= legacy.choose_due_target=choose_due_target
CTX_20_L91= legacy.write_state=write_state
CTX_20_L92= return {'choose_due_target':choose_due_target,'write_state':write_state,
CTX_20_L93= 'original_choose':original_choose,'original_write':original_write}
CTX_21_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_21_START_LINE=7
CTX_21_END_LINE=13
CTX_21_L7=MAX_INPUT=262144
CTX_21_L8=
CTX_21_L9=def sha_file(p:pathlib.Path)->str:
CTX_21_L10= h=hashlib.sha256()
CTX_21_L11= with open(p,'rb',buffering=0) as f:
CTX_21_L12= for b in iter(lambda:f.read(1<<20),b''): h.update(b)
CTX_21_L13= return h.hexdigest()
CTX_22_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_22_START_LINE=20
CTX_22_END_LINE=33
CTX_22_L20= if not p.is_file() or p.is_symlink(): return None
CTX_22_L21= try: d=json.loads(p.read_bytes())
CTX_22_L22= except Exception: return {'summary_read':'FAILED'}
CTX_22_L23= keys=('process_started','producer_rc','capture_success','archive_bytes','stderr_bytes_observed','stderr_bytes_retained','stderr_truncated','stderr_stream_sha256','raw_stderr_exported','child_umask')
CTX_22_L24= return {k:d.get(k) for k in keys if k in d}
CTX_22_L25=
CTX_22_L26=def selftest()->int:
CTX_22_L27= if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')
CTX_22_L28= sys.path.insert(0,str(BASE))
CTX_22_L29= import adapter
CTX_22_L30= adapter.verify_sources(); adapter.load_graph()
CTX_22_L31= print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)
CTX_22_L32= return 0
CTX_22_L33=
CTX_23_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_23_START_LINE=42
CTX_23_END_LINE=66
CTX_23_L42= argv=x['argv']; dest=pathlib.Path(x['dest']); cap=x['cap']; seconds=x['seconds']
CTX_23_L43= 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')
CTX_23_L44= if argv[0]!='/usr/bin/vzdump': fail('VZDUMP_PATH')
CTX_23_L45= if not (dest.is_absolute() and dest.name=='payload.bin' and '..' not in dest.parts): fail('DEST')
CTX_23_L46= if not (type(cap) is int and 0<cap<=16*1024**3): fail('CAP')
CTX_23_L47= if not (type(seconds) is int and 0<seconds<=86400): fail('SECONDS')
CTX_23_L48= if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')
CTX_23_L49= sys.path.insert(0,str(BASE))
CTX_23_L50= import adapter
CTX_23_L51= adapter.verify_sources()
CTX_23_L52= _g,p265,p270,_p282=adapter.load_graph()
CTX_23_L53= os.chdir('/')
CTX_23_L54= def guard():
CTX_23_L55= if sha_file(VZDUMP)!=VZDUMP_SHA: raise p265.PVEError('VZDUMP_CHANGED')
CTX_23_L56= try:
CTX_23_L57= result=p270.capture_archive(argv,dest,cap,seconds,guard)
CTX_23_L58= out={'status':'OK','result':result,'process':safe_process_summary(dest.parent)}
CTX_23_L59= print(json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_23_L60= return 0
CTX_23_L61= except Exception as e:
CTX_23_L62= out={'status':'FAIL','exception_class':type(e).__module__+'.'+type(e).__name__,
CTX_23_L63= 'exception_message_sha256':hashlib.sha256(str(e).encode()).hexdigest(),
CTX_23_L64= 'process':safe_process_summary(dest.parent)}
CTX_23_L65= print(json.dumps(out,separators=(',',':'),sort_keys=True),flush=True)
CTX_23_L66= return 2
CTX_24_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/producer_exec_helper.py
CTX_24_START_LINE=69
CTX_24_END_LINE=74
CTX_24_L69= try: raise SystemExit(main())
CTX_24_L70= except Exception as e:
CTX_24_L71= print(json.dumps({'status':'FAIL','exception_class':type(e).__module__+'.'+type(e).__name__,
CTX_24_L72= 'exception_message_sha256':hashlib.sha256(str(e).encode()).hexdigest(),
CTX_24_L73= 'process':None},separators=(',',':'),sort_keys=True),flush=True)
CTX_24_L74= raise SystemExit(2)
CTX_25_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_25_START_LINE=6
CTX_25_END_LINE=12
CTX_25_L6=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be'
CTX_25_L7=
CTX_25_L8=def sha(p:pathlib.Path)->str:
CTX_25_L9= return hashlib.sha256(p.read_bytes()).hexdigest()
CTX_25_L10=
CTX_25_L11=def fail(code:str):
CTX_25_L12= raise RuntimeError(code)
CTX_26_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_26_START_LINE=17
CTX_26_END_LINE=23
CTX_26_L17= if not p.is_file() or p.is_symlink() or sha(p)!=PVE265_SHA: fail('PVE265_IDENTITY')
CTX_26_L18= sys.path.insert(0,str(C411))
CTX_26_L19= import adapter
CTX_26_L20= adapter.verify_sources()
CTX_26_L21= guest266,pve265,_pve270,_pve282=adapter.load_graph()
CTX_26_L22= data=sys.stdin.buffer.read(4_000_001)
CTX_26_L23= if not data or len(data)>4_000_000: fail('INPUT_BOUND')
CTX_27_FILE=/opt/homelab-backup-v2/releases/backup-v2-overlay-504r1-ca6876fa9c3b/fresh_lxc_helper.py
CTX_27_START_LINE=36
CTX_27_END_LINE=42
CTX_27_L36= if job.get('configured_full_cycle_fits') is not True or job.get('compression_dependent') is not False: fail('JOB_CAPACITY_POLICY')
CTX_27_L37= guest266.no_active_tasks(raw.get('tasks'),vmid)
CTX_27_L38= argv=pve265.dump_argv(job,'/usr/bin/vzdump',scratch,now)
CTX_27_L39= 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')
CTX_27_L40= out={'schema':1,'argv':argv,'job':{k:job.get(k) for k in keep}}
CTX_27_L41= sys.stdout.write(json.dumps(out,separators=(',',':'),sort_keys=True)+'\n')
CTX_27_L42= return 0
USA_STATE_FULL_SAFE_BEGIN=true
USA_STATE_FIELD=$.consecutive_failures=0
USA_STATE_FIELD=$.failure_backoff_seconds=0
USA_STATE_FIELD=$.generation=v2-md-relay-20260919T070058Z-0e409ea129e2
USA_STATE_FIELD=$.green_verified=False
USA_STATE_FIELD=$.last_attempt_epoch=1789801278
USA_STATE_FIELD=$.last_success_epoch=1789801278
USA_STATE_FIELD=$.logical_id=md-relay
USA_STATE_FIELD=$.manifest_sha256=6887c5423640738aeb2bc1d104d515df1d1a21e2cd2d3291481475aa81cb6838
USA_STATE_FIELD=$.payload_sha256=187401a5fbf6c29b4dfd77e5d272db77951aa45003d0d80e0be834235571f32f
USA_STATE_FIELD=$.replicas[0].crypt=pve03-mail-04-crypt
USA_STATE_FIELD=$.replicas[0].physical=pve03-mail-04
USA_STATE_FIELD=$.replicas[1].crypt=pve03-mail-01-crypt
USA_STATE_FIELD=$.replicas[1].physical=pve03-mail-01
USA_STATE_FIELD=$.result=SUCCESS
USA_STATE_FIELD=$.retry_after_epoch=0
USA_STATE_FIELD=$.schema=1
USA_STATE_FIELD=$.updated_at_utc=2026-09-19T07:01:18Z
USA_STATE_FULL_SAFE_END=true
MOLDOVA_STATE_FULL_SAFE_BEGIN=true
MOLDOVA_STATE_FIELD=$.consecutive_failures=6
MOLDOVA_STATE_FIELD=$.failure_backoff_seconds=21600
MOLDOVA_STATE_FIELD=$.generation=v2-us-netbird-20260920T000652Z-7ecdcfcafc12
MOLDOVA_STATE_FIELD=$.last_attempt_epoch=1789862827
MOLDOVA_STATE_FIELD=$.last_success_epoch=1789704670
MOLDOVA_STATE_FIELD=$.last_success_generation=v2-us-netbird-20260918T041032Z-d7648be4c16b
MOLDOVA_STATE_FIELD=$.last_success_green_verified=False
MOLDOVA_STATE_FIELD=$.last_success_manifest_sha256=f82c761cafe8aa43d90d0b4b6124933799b5087d34daf880791d850d0d15cee5
MOLDOVA_STATE_FIELD=$.last_success_payload_sha256=e41e3e012442ef41da1c667d7f5fbe4fd52786b0bb5ffca195660750c773efbf
MOLDOVA_STATE_FIELD=$.last_success_replicas[0].crypt=pve01-mail-05-crypt
MOLDOVA_STATE_FIELD=$.last_success_replicas[0].physical=pve01-mail-05
MOLDOVA_STATE_FIELD=$.last_success_replicas[1].crypt=pve03-mail-04-crypt
MOLDOVA_STATE_FIELD=$.last_success_replicas[1].physical=pve03-mail-04
MOLDOVA_STATE_FIELD=$.logical_id=us-netbird
MOLDOVA_STATE_FIELD=$.reason=PIPE_FAILED
MOLDOVA_STATE_FIELD=$.result=FAIL
MOLDOVA_STATE_FIELD=$.retry_after_epoch=1789884427
MOLDOVA_STATE_FIELD=$.schema=1
MOLDOVA_STATE_FIELD=$.sealed=False
MOLDOVA_STATE_FIELD=$.updated_at_utc=2026-09-20T00:07:07Z
MOLDOVA_STATE_FULL_SAFE_END=true
HAS_RCLONE_SOURCE=false
HAS_GENERATION_MANIFEST_PAYLOAD_SOURCE=true
HAS_REMOTE_REPLICA_SOURCE=true
DECISION=HOLD_BACKUP207_PRODUCER_CONTRACT_INCOMPLETE
NEXT_GATE=READ_ONLY_TARGETED_MODULE_FOLLOWUP
CLOUD_READS=0
CLOUD_WRITES=0
VPS_SSH_ATTEMPTS=0
MESSENGERS214_CLOSED=false
MAJOR_STAGES_REMAINING=8
NEWFI207_END=true
OUTPUT_END
CHAT_OUTPUT_END