diff --git a/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.json b/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.json new file mode 100644 index 00000000..2b2e5cda --- /dev/null +++ b/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.json @@ -0,0 +1,38 @@ +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3", + "status": "OK", + "rc": 0, + "host": "pve01", + "mode": "read-only", + "component": "infra-pve1-moldova-overlay504-transport-readonly", + "started_at_utc": "2026-09-18T21:10:33Z", + "finished_at_utc": "2026-09-18T21:10:33Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "7f9a19052a0b35d999a1d13fd46c335e82b069a6b5a3f06d5b760c4f88083520", + "duplicate_failed_command_blocked": false, + "block_reason": null, + "execution_started": true, + "change_declared": false, + "result_contract_valid": true, + "result_contract_status": null, + "result_contract_error": null, + "command_rc": 0, + "changes_made": false, + "rollback_started": false, + "rollback_restored": null, + "mutation_outcome": "NO_MUTATION", + "sanitized": true, + "secrets_included": false, + "private_addresses_included": false, + "raw_evidence_retained_locally": true, + "raw_evidence_sha256": "e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7", + "sanitized_output_sha256": "e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "ERROR_REGISTER_CHECK=OK\nREFERENCE_CHECK=OK\nAUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED\nOVERLAY_ROOT_PRESENT=True\nOVERLAY_FILE_COUNT=6\nOVERLAY_FILE_01_PATH=entry504.py\nOVERLAY_FILE_01_MODE=0o400\nOVERLAY_FILE_01_UID=0\nOVERLAY_FILE_01_GID=0\nOVERLAY_FILE_01_SIZE=10566\nOVERLAY_FILE_01_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793\nOVERLAY_FILE_02_PATH=fresh_lxc_helper.py\nOVERLAY_FILE_02_MODE=0o400\nOVERLAY_FILE_02_UID=0\nOVERLAY_FILE_02_GID=0\nOVERLAY_FILE_02_SIZE=2320\nOVERLAY_FILE_02_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011\nOVERLAY_FILE_03_PATH=lxc_adapter.py\nOVERLAY_FILE_03_MODE=0o400\nOVERLAY_FILE_03_UID=0\nOVERLAY_FILE_03_GID=0\nOVERLAY_FILE_03_SIZE=13825\nOVERLAY_FILE_03_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d\nOVERLAY_FILE_04_PATH=producer_exec_helper.py\nOVERLAY_FILE_04_MODE=0o400\nOVERLAY_FILE_04_UID=0\nOVERLAY_FILE_04_GID=0\nOVERLAY_FILE_04_SIZE=3449\nOVERLAY_FILE_04_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3\nOVERLAY_FILE_05_PATH=qemu_adapter.py\nOVERLAY_FILE_05_MODE=0o400\nOVERLAY_FILE_05_UID=0\nOVERLAY_FILE_05_GID=0\nOVERLAY_FILE_05_SIZE=4627\nOVERLAY_FILE_05_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b\nOVERLAY_FILE_06_PATH=scheduler_adapter.py\nOVERLAY_FILE_06_MODE=0o400\nOVERLAY_FILE_06_UID=0\nOVERLAY_FILE_06_GID=0\nOVERLAY_FILE_06_SIZE=4097\nOVERLAY_FILE_06_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96\nOVERLAY_MATCH_FILE=entry504.py\nOVERLAY_MATCH_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793\nOVERLAY_MATCH_LINE_COUNT=13\nOVERLAY_MATCH_LINES=4,7,43,44,62,78,80,93,96,97,105,112,123\nOVERLAY_CONTEXT_entry504_py_01_RANGE=1-15\nOVERLAY_CONTEXT_entry504_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_entry504_py_01_LINE_0002=import hashlib, importlib, json, os, pathlib, stat, sys, types\nOVERLAY_CONTEXT_entry504_py_01_LINE_0003=\nOVERLAY_CONTEXT_entry504_py_01_LINE_0004=BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')\nOVERLAY_CONTEXT_entry504_py_01_LINE_0005=HERE=pathlib.Path(__file__).resolve().parent\nOVERLAY_CONTEXT_entry504_py_01_LINE_0006=BASE_EXPECTED={\nOVERLAY_CONTEXT_entry504_py_01_LINE_0007='legacy_engine.py':'b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0008='wrapper.py':'2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0009='ct112_handler.py':'8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0010='representative_driver.py':'b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0011='candidate411/adapter.py':'18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0012='candidate411/pve265.py':'cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0013='candidate411/pve270.py':'97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0014='candidate411/pve282.py':'73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0015=}\nOVERLAY_CONTEXT_entry504_py_02_RANGE=39-52\nOVERLAY_CONTEXT_entry504_py_02_LINE_0039=try: return self._g[n]\nOVERLAY_CONTEXT_entry504_py_02_LINE_0040=except KeyError as e: raise AttributeError(n) from e\nOVERLAY_CONTEXT_entry504_py_02_LINE_0041=def __setattr__(self,n,v): self._g[n]=v\nOVERLAY_CONTEXT_entry504_py_02_LINE_0042=\nOVERLAY_CONTEXT_entry504_py_02_LINE_0043=def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0044=legacy_path=(pathlib.Path(base)/'legacy_engine.py').resolve()\nOVERLAY_CONTEXT_entry504_py_02_LINE_0045=found={}\nOVERLAY_CONTEXT_entry504_py_02_LINE_0046=for value in vars(wrapper).values():\nOVERLAY_CONTEXT_entry504_py_02_LINE_0047=if isinstance(value,types.ModuleType):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0048=g=vars(value); raw=g.get('__file__')\nOVERLAY_CONTEXT_entry504_py_02_LINE_0049=elif isinstance(value,types.FunctionType):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0050=g=value.__globals__; raw=g.get('__file__')\nOVERLAY_CONTEXT_entry504_py_02_LINE_0051=else:\nOVERLAY_CONTEXT_entry504_py_02_LINE_0052=continue\nOVERLAY_CONTEXT_entry504_py_03_RANGE=58-70\nOVERLAY_CONTEXT_entry504_py_03_LINE_0058=found[id(g)]=g\nOVERLAY_CONTEXT_entry504_py_03_LINE_0059=if len(found)!=1:\nOVERLAY_CONTEXT_entry504_py_03_LINE_0060=raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0061=g=next(iter(found.values()))\nOVERLAY_CONTEXT_entry504_py_03_LINE_0062=required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',\nOVERLAY_CONTEXT_entry504_py_03_LINE_0063='_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run',\nOVERLAY_CONTEXT_entry504_py_03_LINE_0064='choose_due_target','write_state','epoch')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0065=if any(not callable(g.get(n)) for n in required):\nOVERLAY_CONTEXT_entry504_py_03_LINE_0066=raise RuntimeError('LEGACY_PROVENANCE_API')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0067=original=g['capture_pve_guest']\nOVERLAY_CONTEXT_entry504_py_03_LINE_0068=proxy=_GlobalsProxy(g)\nOVERLAY_CONTEXT_entry504_py_03_LINE_0069=if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'):\nOVERLAY_CONTEXT_entry504_py_03_LINE_0070=raise RuntimeError('LEGACY_SCP_API')\nOVERLAY_CONTEXT_entry504_py_04_RANGE=74-131\nOVERLAY_CONTEXT_entry504_py_04_LINE_0074=patched=lxc_adapter.bind(proxy,qemu_patched)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0075=if not callable(patched):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0076=raise RuntimeError('LXC_ADAPTER_BIND_RESULT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0077=g['capture_pve_guest']=patched\nOVERLAY_CONTEXT_entry504_py_04_LINE_0078=scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])\nOVERLAY_CONTEXT_entry504_py_04_LINE_0079=if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0080=raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0081=return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}\nOVERLAY_CONTEXT_entry504_py_04_LINE_0082=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0083=def _load():\nOVERLAY_CONTEXT_entry504_py_04_LINE_0084=_verify_base()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0085=sys.dont_write_bytecode=True\nOVERLAY_CONTEXT_entry504_py_04_LINE_0086=sys.path.insert(0,str(BASE))\nOVERLAY_CONTEXT_entry504_py_04_LINE_0087=wrapper=importlib.import_module('wrapper')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0088=# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced.\nOVERLAY_CONTEXT_entry504_py_04_LINE_0089=wrapper.selftest()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0090=sys.path.insert(0,str(HERE))\nOVERLAY_CONTEXT_entry504_py_04_LINE_0091=lxc_adapter=importlib.import_module('lxc_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0092=qemu_adapter=importlib.import_module('qemu_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0093=scheduler_adapter=importlib.import_module('scheduler_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0094=if _sha(HERE/'lxc_adapter.py')!='3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d':\nOVERLAY_CONTEXT_entry504_py_04_LINE_0095=raise RuntimeError('LXC_502_BYTE_IDENTITY')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0096=wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0097=return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired\nOVERLAY_CONTEXT_entry504_py_04_LINE_0098=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0099=def _target(wrapper,lid):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0100=rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0101=if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0102=return hits[0]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0103=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0104=def selftest():\nOVERLAY_CONTEXT_entry504_py_04_LINE_0105=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0106=if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0107=raise RuntimeError('PATCH_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0108=if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0109=raise RuntimeError('SCHEDULER_CHOOSE_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0110=if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0111=raise RuntimeError('SCHEDULER_WRITE_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0112=if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0113=raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0114=if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0115=raise RuntimeError('WRAPPER_PUBLIC_API')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0116=print('SELFTEST_OVERLAY504=PASS',flush=True)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0117=return 0\nOVERLAY_CONTEXT_entry504_py_04_LINE_0118=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0119=def main(argv=None):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0120=argv=list(sys.argv[1:] if argv is None else argv)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0121=if argv==['selftest']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0122=return selftest()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0123=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0124=legacy=wired['legacy']\nOVERLAY_CONTEXT_entry504_py_04_LINE_0125=if argv==['scheduler-proof']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0126=import tempfile\nOVERLAY_CONTEXT_entry504_py_04_LINE_0127=legacy=wired['legacy']; g=wired['legacy_globals']\nOVERLAY_CONTEXT_entry504_py_04_LINE_0128=old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0129=if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0130=now=[1000]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0131=try:\nOVERLAY_MATCH_FILE=fresh_lxc_helper.py\nOVERLAY_MATCH_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011\nOVERLAY_MATCH_LINE_COUNT=1\nOVERLAY_MATCH_LINES=4\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_RANGE=1-12\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0002=import base64, hashlib, json, pathlib, sys\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0003=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0004=BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0005=C411=BASE_RELEASE/'candidate411'\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0006=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be'\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0007=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0008=def sha(p:pathlib.Path)->str:\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0009=return hashlib.sha256(p.read_bytes()).hexdigest()\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0010=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0011=def fail(code:str):\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0012=raise RuntimeError(code)\nOVERLAY_MATCH_FILE=lxc_adapter.py\nOVERLAY_MATCH_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d\nOVERLAY_MATCH_LINE_COUNT=19\nOVERLAY_MATCH_LINES=2,7,36,44,45,52,55,57,59,68,95,112,130,133,158,162,199,200,213\nOVERLAY_CONTEXT_lxc_adapter_py_01_RANGE=1-15\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0002=import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0003=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0004=PVESH_SHA='9ed13d4c2d82e7864ff0192c428da7669af263f81dfcc84d5a981ca98fee8439'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0005=VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0006=HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0007=EXEC_HELPER=pathlib.Path(__file__).resolve().parent/'producer_exec_helper.py'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0008=MAX_STDERR=262144\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0009=ENV={'PATH':'/usr/sbin:/usr/bin:/sbin:/bin','LC_ALL':'C','LANG':'C','HOME':'/root','PYTHONDONTWRITEBYTECODE':'1'}\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0010=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0011=class AdapterError(RuntimeError): pass\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0012=class ExecFailure(AdapterError):\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0013=def __init__(self,code,summary): super().__init__(code); self.code=code; self.summary=summary\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0014=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0015=def _need(ok:bool,code:str):\nOVERLAY_CONTEXT_lxc_adapter_py_02_RANGE=32-76\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0032=if n<=0: raise AdapterError('WRITE_FAILED')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0033=view=view[n:]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0034=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0035=def _remote_sha(legacy,node,path):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0036=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0037=parts=p.stdout.decode('ascii','strict').strip().split()\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0038=_need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0039=return parts[0]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0040=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0041=def _live_inputs(legacy,node,vmid,scratch):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0042=_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0043=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0044=rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0045=stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0046=_need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0047=configs=[]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0048=for r in rows:\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0049=if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0050=try: rid=int(r.get('vmid'))\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0051=except Exception: raise AdapterError('RESOURCE_VMID')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0052=cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r[\"type\"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0053=_need(type(cfg) is dict,'CONFIG_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0054=configs.append([rid,cfg])\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0055=tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0056=_need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0057=q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0058=defaults=None\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0059=if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0060=elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0061=st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0062=return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0063='defaults_b64':None if defaults is None else base64.b64encode(defaults).decode('ascii'),'staging_free':free,'tasks':tasks}\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0064=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0065=def _helper(inp):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0066=data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode('utf-8')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0067=_need(0262144:\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0097=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)})\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0098=try: out=json.loads(p.stdout)\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0099=except Exception:\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0100=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)})\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0101=summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')}\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0102=if isinstance(out.get('process'),dict): summary.update(out['process'])\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0103=if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary)\nOVERLAY_CONTEXT_lxc_adapter_py_04_RANGE=108-120\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0108=def _kill(p):\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0109=try: os.killpg(p.pid,signal.SIGTERM)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0110=except ProcessLookupError: pass\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0111=try: p.wait(timeout=10)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0112=except subprocess.TimeoutExpired:\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0113=try: os.killpg(p.pid,signal.SIGKILL)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0114=except ProcessLookupError: pass\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0115=p.wait()\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0116=\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0117=def _execute_remote(legacy,node,argv,dest,cap,timeout):\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0118=_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0119=_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')\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0120=_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')\nOVERLAY_CONTEXT_lxc_adapter_py_05_RANGE=126-141\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0126=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)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0127=initial=os.fstat(fd)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0128=digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0129=remote='cd / && exec '+shlex.join(argv)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0130=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0131=deadline=time.monotonic()+timeout\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0132=try:\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0133=p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0134=sel=selectors.DefaultSelector()\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0135=for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0136=while sel.get_map():\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0137=now=time.monotonic()\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0138=if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{})\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0139=for key,_ in sel.select(min(.2,max(0,deadline-now))):\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0140=b=os.read(key.fileobj.fileno(),65536)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0141=if not b: sel.unregister(key.fileobj); continue\nOVERLAY_CONTEXT_lxc_adapter_py_06_RANGE=154-170\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0154=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:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0155=raise ExecFailure('REMOTE_FILE_IDENTITY',{})\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0156=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0157=os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0158=return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(),\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0159='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0160=except ExecFailure as e:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0161=if p is not None and p.poll() is None: _kill(p)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0162=summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total,\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0163='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0164=summary.update(e.summary); raise ExecFailure(e.code,summary)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0165=finally:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0166=if p is not None:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0167=if p.poll() is None: _kill(p)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0168=if p.stdout: p.stdout.close()\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0169=if p.stderr: p.stderr.close()\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0170=if sel is not None: sel.close()\nOVERLAY_CONTEXT_lxc_adapter_py_07_RANGE=195-218\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0195=row=rows[0]; node=row.get('node'); typ=row.get('type')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0196=_need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0197=legacy._default_unprivileged_lxc(node,vmid)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0198=scratch=f'/var/tmp/homelab-vzdump-v2-{gen}'\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0199=legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0200=q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0201=_need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0202=try:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0203=legacy.mapped_scratch_probe(node,scratch)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0204=p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes'])\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0205=try:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0206=result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0207=except ExecFailure as e:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0208=_emit_diag(node,e.summary|{'failure_code':e.code})\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0209=raise legacy.BackupError('LXC_PRODUCER_FAILED') from None\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0210=_need(local.is_file() and 0str:\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0010=h=hashlib.sha256()\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0011=with open(p,'rb',buffering=0) as f:\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0012=for b in iter(lambda:f.read(1<<20),b''): h.update(b)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_RANGE=27-39\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0027=if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0028=sys.path.insert(0,str(BASE))\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0029=import adapter\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0030=adapter.verify_sources(); adapter.load_graph()\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0031=print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0032=return 0\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0033=\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0034=def main()->int:\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0035=if sys.argv[1:]==['selftest']: return selftest()\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0036=if sys.argv[1:]: fail('ARGC')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0037=raw=sys.stdin.buffer.read(MAX_INPUT+1)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0038=if not raw or len(raw)>MAX_INPUT: fail('INPUT_BOUND')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0039=try: x=json.loads(raw)\nOVERLAY_MATCH_FILE=qemu_adapter.py\nOVERLAY_MATCH_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b\nOVERLAY_MATCH_LINE_COUNT=7\nOVERLAY_MATCH_LINES=12,49,51,56,62,69,73\nOVERLAY_CONTEXT_qemu_adapter_py_01_RANGE=8-20\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0008=def _need(ok,code):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0009=if not ok: raise QemuAdapterError(code)\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0010=\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0011=def _remote_sha(legacy,node,path):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0012=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0013=parts=p.stdout.decode('ascii','strict').strip().split()\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0014=_need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0015=return parts[0]\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0016=\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0017=def _select_qemu_outputs(vmid,files):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0018=_need(type(vmid) is int and vmid>0,'QEMU_VMID')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0019=_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')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0020=_need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE')\nOVERLAY_CONTEXT_qemu_adapter_py_02_RANGE=45-79\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0045=row=rows[0]; node=row.get('node'); typ=row.get('type')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0046=_need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0047=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0048=srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0049=legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0050=try:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0051=vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0052=if vp.returncode!=0:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0053=_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)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0054=raise legacy.BackupError('QEMU_VZDUMP_FAILED')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0055=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0056=p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0057=files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x]\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0058=try: src,log=_select_qemu_outputs(vmid,files)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0059=except QemuAdapterError as e:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0060=_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0061=raise legacy.BackupError(str(e)) from None\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0062=q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0063=raw=q.stdout.decode('ascii','strict').strip()\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0064=_need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0065=size=int(raw)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0066=local=pathlib.Path(work)/'payload.bin'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0067=if node=='pve01': local=pathlib.Path(src)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0068=else:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0069=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0070=_need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0071=_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)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0072=except Exception:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0073=legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0074=cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0075=meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0076='producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'}\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0077=return pathlib.Path(local),meta,cleanup\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0078=capture_pve_guest.__name__='capture_pve_guest'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0079=return capture_pve_guest\nOVERLAY_AST_FILE=entry504.py\nOVERLAY_AST_FUNCTION_COUNT=2\nOVERLAY_AST_FUNCTION_01_LINE=99\nOVERLAY_AST_FUNCTION_01_NAME=_target\nOVERLAY_AST_FUNCTION_02_LINE=119\nOVERLAY_AST_FUNCTION_02_NAME=main\nOVERLAY_AST_IMPORT_COUNT=10\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=importlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=os\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=pathlib\nOVERLAY_AST_IMPORT_07_LINE=2\nOVERLAY_AST_IMPORT_07_NAME=stat\nOVERLAY_AST_IMPORT_08_LINE=2\nOVERLAY_AST_IMPORT_08_NAME=sys\nOVERLAY_AST_IMPORT_09_LINE=2\nOVERLAY_AST_IMPORT_09_NAME=types\nOVERLAY_AST_IMPORT_10_LINE=126\nOVERLAY_AST_IMPORT_10_NAME=tempfile\nOVERLAY_AST_CALL_COUNT=4\nOVERLAY_AST_CALL_01_LINE=87\nOVERLAY_AST_CALL_01_KIND=import_module\nOVERLAY_AST_CALL_01_TEXT=importlib.import_module('wrapper')\nOVERLAY_AST_CALL_02_LINE=91\nOVERLAY_AST_CALL_02_KIND=import_module\nOVERLAY_AST_CALL_02_TEXT=importlib.import_module('lxc_adapter')\nOVERLAY_AST_CALL_03_LINE=92\nOVERLAY_AST_CALL_03_KIND=import_module\nOVERLAY_AST_CALL_03_TEXT=importlib.import_module('qemu_adapter')\nOVERLAY_AST_CALL_04_LINE=93\nOVERLAY_AST_CALL_04_KIND=import_module\nOVERLAY_AST_CALL_04_TEXT=importlib.import_module('scheduler_adapter')\nOVERLAY_AST_FILE=fresh_lxc_helper.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=14\nOVERLAY_AST_FUNCTION_01_NAME=main\nOVERLAY_AST_IMPORT_COUNT=7\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=base64\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=hashlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=pathlib\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=sys\nOVERLAY_AST_IMPORT_07_LINE=19\nOVERLAY_AST_IMPORT_07_NAME=adapter\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_AST_FILE=lxc_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=191\nOVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest\nOVERLAY_AST_IMPORT_COUNT=14\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=base64\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=hashlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=os\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=pathlib\nOVERLAY_AST_IMPORT_07_LINE=2\nOVERLAY_AST_IMPORT_07_NAME=re\nOVERLAY_AST_IMPORT_08_LINE=2\nOVERLAY_AST_IMPORT_08_NAME=selectors\nOVERLAY_AST_IMPORT_09_LINE=2\nOVERLAY_AST_IMPORT_09_NAME=shlex\nOVERLAY_AST_IMPORT_10_LINE=2\nOVERLAY_AST_IMPORT_10_NAME=signal\nOVERLAY_AST_IMPORT_11_LINE=2\nOVERLAY_AST_IMPORT_11_NAME=stat\nOVERLAY_AST_IMPORT_12_LINE=2\nOVERLAY_AST_IMPORT_12_NAME=subprocess\nOVERLAY_AST_IMPORT_13_LINE=2\nOVERLAY_AST_IMPORT_13_NAME=sys\nOVERLAY_AST_IMPORT_14_LINE=2\nOVERLAY_AST_IMPORT_14_NAME=time\nOVERLAY_AST_CALL_COUNT=3\nOVERLAY_AST_CALL_01_LINE=68\nOVERLAY_AST_CALL_01_KIND=run\nOVERLAY_AST_CALL_01_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)\nOVERLAY_AST_CALL_02_LINE=95\nOVERLAY_AST_CALL_02_KIND=run\nOVERLAY_AST_CALL_02_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)\nOVERLAY_AST_CALL_03_LINE=133\nOVERLAY_AST_CALL_03_KIND=Popen\nOVERLAY_AST_CALL_03_TEXT=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)\nOVERLAY_AST_FILE=producer_exec_helper.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=34\nOVERLAY_AST_FUNCTION_01_NAME=main\nOVERLAY_AST_IMPORT_COUNT=8\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=json\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=os\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=pathlib\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=sys\nOVERLAY_AST_IMPORT_07_LINE=29\nOVERLAY_AST_IMPORT_07_NAME=adapter\nOVERLAY_AST_IMPORT_08_LINE=50\nOVERLAY_AST_IMPORT_08_NAME=adapter\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_AST_FILE=qemu_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=41\nOVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest\nOVERLAY_AST_IMPORT_COUNT=5\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=json\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=pathlib\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=re\nOVERLAY_AST_CALL_COUNT=1\nOVERLAY_AST_CALL_01_LINE=69\nOVERLAY_AST_CALL_01_KIND=run\nOVERLAY_AST_CALL_01_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nOVERLAY_AST_FILE=scheduler_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=55\nOVERLAY_AST_FUNCTION_01_NAME=choose_due_target\nOVERLAY_AST_IMPORT_COUNT=3\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=json\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=pathlib\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_REFERENCED_PATH_COUNT=2\nOVERLAY_REF_01_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1\nOVERLAY_REF_01_EXISTS=True\nOVERLAY_REF_01_IS_FILE=False\nOVERLAY_REF_02_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411\nOVERLAY_REF_02_EXISTS=True\nOVERLAY_REF_02_IS_FILE=False\nOVERLAY_TRANSPORT_SIGNATURE_COUNT=2\nOVERLAY_TRANSPORT_SIG_01_FILE=lxc_adapter.py\nOVERLAY_TRANSPORT_SIG_01_LINE=130\nOVERLAY_TRANSPORT_SIG_01_TEXT=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]\nOVERLAY_TRANSPORT_SIG_02_FILE=qemu_adapter.py\nOVERLAY_TRANSPORT_SIG_02_LINE=69\nOVERLAY_TRANSPORT_SIG_02_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nVPS557R3_DECISION=OVERLAY504_DELEGATES_TO_BASE_ENGINE\nVPS557R3_NEXT_GATE=READ_OVERLAY504_BASE_ENGINE_BINDING\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" +} diff --git a/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.txt b/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.txt new file mode 100644 index 00000000..7cee2ef1 --- /dev/null +++ b/runtime/history/SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3.txt @@ -0,0 +1,610 @@ +CHAT_OUTPUT_BEGIN +COMMAND_ID=SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3 +STATUS=OK +RC=0 +HOST=pve01 +MODE=read-only +COMPONENT=infra-pve1-moldova-overlay504-transport-readonly +REFERENCE_REGISTER_CHECK=OK +REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 +ERROR_REGISTER_CHECK=OK +ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 +COMMAND_SHA256=7f9a19052a0b35d999a1d13fd46c335e82b069a6b5a3f06d5b760c4f88083520 +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=e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7 +SANITIZED_OUTPUT_SHA256=e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7 +OUTPUT_BEGIN +ERROR_REGISTER_CHECK=OK +REFERENCE_CHECK=OK +AUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED +OVERLAY_ROOT_PRESENT=True +OVERLAY_FILE_COUNT=6 +OVERLAY_FILE_01_PATH=entry504.py +OVERLAY_FILE_01_MODE=0o400 +OVERLAY_FILE_01_UID=0 +OVERLAY_FILE_01_GID=0 +OVERLAY_FILE_01_SIZE=10566 +OVERLAY_FILE_01_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793 +OVERLAY_FILE_02_PATH=fresh_lxc_helper.py +OVERLAY_FILE_02_MODE=0o400 +OVERLAY_FILE_02_UID=0 +OVERLAY_FILE_02_GID=0 +OVERLAY_FILE_02_SIZE=2320 +OVERLAY_FILE_02_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011 +OVERLAY_FILE_03_PATH=lxc_adapter.py +OVERLAY_FILE_03_MODE=0o400 +OVERLAY_FILE_03_UID=0 +OVERLAY_FILE_03_GID=0 +OVERLAY_FILE_03_SIZE=13825 +OVERLAY_FILE_03_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d +OVERLAY_FILE_04_PATH=producer_exec_helper.py +OVERLAY_FILE_04_MODE=0o400 +OVERLAY_FILE_04_UID=0 +OVERLAY_FILE_04_GID=0 +OVERLAY_FILE_04_SIZE=3449 +OVERLAY_FILE_04_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3 +OVERLAY_FILE_05_PATH=qemu_adapter.py +OVERLAY_FILE_05_MODE=0o400 +OVERLAY_FILE_05_UID=0 +OVERLAY_FILE_05_GID=0 +OVERLAY_FILE_05_SIZE=4627 +OVERLAY_FILE_05_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b +OVERLAY_FILE_06_PATH=scheduler_adapter.py +OVERLAY_FILE_06_MODE=0o400 +OVERLAY_FILE_06_UID=0 +OVERLAY_FILE_06_GID=0 +OVERLAY_FILE_06_SIZE=4097 +OVERLAY_FILE_06_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96 +OVERLAY_MATCH_FILE=entry504.py +OVERLAY_MATCH_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793 +OVERLAY_MATCH_LINE_COUNT=13 +OVERLAY_MATCH_LINES=4,7,43,44,62,78,80,93,96,97,105,112,123 +OVERLAY_CONTEXT_entry504_py_01_RANGE=1-15 +OVERLAY_CONTEXT_entry504_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_entry504_py_01_LINE_0002=import hashlib, importlib, json, os, pathlib, stat, sys, types +OVERLAY_CONTEXT_entry504_py_01_LINE_0003= +OVERLAY_CONTEXT_entry504_py_01_LINE_0004=BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1') +OVERLAY_CONTEXT_entry504_py_01_LINE_0005=HERE=pathlib.Path(__file__).resolve().parent +OVERLAY_CONTEXT_entry504_py_01_LINE_0006=BASE_EXPECTED={ +OVERLAY_CONTEXT_entry504_py_01_LINE_0007='legacy_engine.py':'b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7', +OVERLAY_CONTEXT_entry504_py_01_LINE_0008='wrapper.py':'2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5', +OVERLAY_CONTEXT_entry504_py_01_LINE_0009='ct112_handler.py':'8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c', +OVERLAY_CONTEXT_entry504_py_01_LINE_0010='representative_driver.py':'b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2', +OVERLAY_CONTEXT_entry504_py_01_LINE_0011='candidate411/adapter.py':'18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3', +OVERLAY_CONTEXT_entry504_py_01_LINE_0012='candidate411/pve265.py':'cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be', +OVERLAY_CONTEXT_entry504_py_01_LINE_0013='candidate411/pve270.py':'97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef', +OVERLAY_CONTEXT_entry504_py_01_LINE_0014='candidate411/pve282.py':'73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012', +OVERLAY_CONTEXT_entry504_py_01_LINE_0015=} +OVERLAY_CONTEXT_entry504_py_02_RANGE=39-52 +OVERLAY_CONTEXT_entry504_py_02_LINE_0039=try: return self._g[n] +OVERLAY_CONTEXT_entry504_py_02_LINE_0040=except KeyError as e: raise AttributeError(n) from e +OVERLAY_CONTEXT_entry504_py_02_LINE_0041=def __setattr__(self,n,v): self._g[n]=v +OVERLAY_CONTEXT_entry504_py_02_LINE_0042= +OVERLAY_CONTEXT_entry504_py_02_LINE_0043=def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE): +OVERLAY_CONTEXT_entry504_py_02_LINE_0044=legacy_path=(pathlib.Path(base)/'legacy_engine.py').resolve() +OVERLAY_CONTEXT_entry504_py_02_LINE_0045=found={} +OVERLAY_CONTEXT_entry504_py_02_LINE_0046=for value in vars(wrapper).values(): +OVERLAY_CONTEXT_entry504_py_02_LINE_0047=if isinstance(value,types.ModuleType): +OVERLAY_CONTEXT_entry504_py_02_LINE_0048=g=vars(value); raw=g.get('__file__') +OVERLAY_CONTEXT_entry504_py_02_LINE_0049=elif isinstance(value,types.FunctionType): +OVERLAY_CONTEXT_entry504_py_02_LINE_0050=g=value.__globals__; raw=g.get('__file__') +OVERLAY_CONTEXT_entry504_py_02_LINE_0051=else: +OVERLAY_CONTEXT_entry504_py_02_LINE_0052=continue +OVERLAY_CONTEXT_entry504_py_03_RANGE=58-70 +OVERLAY_CONTEXT_entry504_py_03_LINE_0058=found[id(g)]=g +OVERLAY_CONTEXT_entry504_py_03_LINE_0059=if len(found)!=1: +OVERLAY_CONTEXT_entry504_py_03_LINE_0060=raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY') +OVERLAY_CONTEXT_entry504_py_03_LINE_0061=g=next(iter(found.values())) +OVERLAY_CONTEXT_entry504_py_03_LINE_0062=required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote', +OVERLAY_CONTEXT_entry504_py_03_LINE_0063='_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run', +OVERLAY_CONTEXT_entry504_py_03_LINE_0064='choose_due_target','write_state','epoch') +OVERLAY_CONTEXT_entry504_py_03_LINE_0065=if any(not callable(g.get(n)) for n in required): +OVERLAY_CONTEXT_entry504_py_03_LINE_0066=raise RuntimeError('LEGACY_PROVENANCE_API') +OVERLAY_CONTEXT_entry504_py_03_LINE_0067=original=g['capture_pve_guest'] +OVERLAY_CONTEXT_entry504_py_03_LINE_0068=proxy=_GlobalsProxy(g) +OVERLAY_CONTEXT_entry504_py_03_LINE_0069=if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'): +OVERLAY_CONTEXT_entry504_py_03_LINE_0070=raise RuntimeError('LEGACY_SCP_API') +OVERLAY_CONTEXT_entry504_py_04_RANGE=74-131 +OVERLAY_CONTEXT_entry504_py_04_LINE_0074=patched=lxc_adapter.bind(proxy,qemu_patched) +OVERLAY_CONTEXT_entry504_py_04_LINE_0075=if not callable(patched): +OVERLAY_CONTEXT_entry504_py_04_LINE_0076=raise RuntimeError('LXC_ADAPTER_BIND_RESULT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0077=g['capture_pve_guest']=patched +OVERLAY_CONTEXT_entry504_py_04_LINE_0078=scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state']) +OVERLAY_CONTEXT_entry504_py_04_LINE_0079=if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0080=raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0081=return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired} +OVERLAY_CONTEXT_entry504_py_04_LINE_0082= +OVERLAY_CONTEXT_entry504_py_04_LINE_0083=def _load(): +OVERLAY_CONTEXT_entry504_py_04_LINE_0084=_verify_base() +OVERLAY_CONTEXT_entry504_py_04_LINE_0085=sys.dont_write_bytecode=True +OVERLAY_CONTEXT_entry504_py_04_LINE_0086=sys.path.insert(0,str(BASE)) +OVERLAY_CONTEXT_entry504_py_04_LINE_0087=wrapper=importlib.import_module('wrapper') +OVERLAY_CONTEXT_entry504_py_04_LINE_0088=# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced. +OVERLAY_CONTEXT_entry504_py_04_LINE_0089=wrapper.selftest() +OVERLAY_CONTEXT_entry504_py_04_LINE_0090=sys.path.insert(0,str(HERE)) +OVERLAY_CONTEXT_entry504_py_04_LINE_0091=lxc_adapter=importlib.import_module('lxc_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0092=qemu_adapter=importlib.import_module('qemu_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0093=scheduler_adapter=importlib.import_module('scheduler_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0094=if _sha(HERE/'lxc_adapter.py')!='3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d': +OVERLAY_CONTEXT_entry504_py_04_LINE_0095=raise RuntimeError('LXC_502_BYTE_IDENTITY') +OVERLAY_CONTEXT_entry504_py_04_LINE_0096=wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE) +OVERLAY_CONTEXT_entry504_py_04_LINE_0097=return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired +OVERLAY_CONTEXT_entry504_py_04_LINE_0098= +OVERLAY_CONTEXT_entry504_py_04_LINE_0099=def _target(wrapper,lid): +OVERLAY_CONTEXT_entry504_py_04_LINE_0100=rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid] +OVERLAY_CONTEXT_entry504_py_04_LINE_0101=if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY') +OVERLAY_CONTEXT_entry504_py_04_LINE_0102=return hits[0] +OVERLAY_CONTEXT_entry504_py_04_LINE_0103= +OVERLAY_CONTEXT_entry504_py_04_LINE_0104=def selftest(): +OVERLAY_CONTEXT_entry504_py_04_LINE_0105=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load() +OVERLAY_CONTEXT_entry504_py_04_LINE_0106=if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0107=raise RuntimeError('PATCH_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0108=if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0109=raise RuntimeError('SCHEDULER_CHOOSE_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0110=if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0111=raise RuntimeError('SCHEDULER_WRITE_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0112=if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]: +OVERLAY_CONTEXT_entry504_py_04_LINE_0113=raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0114=if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets): +OVERLAY_CONTEXT_entry504_py_04_LINE_0115=raise RuntimeError('WRAPPER_PUBLIC_API') +OVERLAY_CONTEXT_entry504_py_04_LINE_0116=print('SELFTEST_OVERLAY504=PASS',flush=True) +OVERLAY_CONTEXT_entry504_py_04_LINE_0117=return 0 +OVERLAY_CONTEXT_entry504_py_04_LINE_0118= +OVERLAY_CONTEXT_entry504_py_04_LINE_0119=def main(argv=None): +OVERLAY_CONTEXT_entry504_py_04_LINE_0120=argv=list(sys.argv[1:] if argv is None else argv) +OVERLAY_CONTEXT_entry504_py_04_LINE_0121=if argv==['selftest']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0122=return selftest() +OVERLAY_CONTEXT_entry504_py_04_LINE_0123=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load() +OVERLAY_CONTEXT_entry504_py_04_LINE_0124=legacy=wired['legacy'] +OVERLAY_CONTEXT_entry504_py_04_LINE_0125=if argv==['scheduler-proof']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0126=import tempfile +OVERLAY_CONTEXT_entry504_py_04_LINE_0127=legacy=wired['legacy']; g=wired['legacy_globals'] +OVERLAY_CONTEXT_entry504_py_04_LINE_0128=old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch') +OVERLAY_CONTEXT_entry504_py_04_LINE_0129=if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE') +OVERLAY_CONTEXT_entry504_py_04_LINE_0130=now=[1000] +OVERLAY_CONTEXT_entry504_py_04_LINE_0131=try: +OVERLAY_MATCH_FILE=fresh_lxc_helper.py +OVERLAY_MATCH_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011 +OVERLAY_MATCH_LINE_COUNT=1 +OVERLAY_MATCH_LINES=4 +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_RANGE=1-12 +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0002=import base64, hashlib, json, pathlib, sys +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0003= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0004=BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1') +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0005=C411=BASE_RELEASE/'candidate411' +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0006=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be' +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0007= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0008=def sha(p:pathlib.Path)->str: +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0009=return hashlib.sha256(p.read_bytes()).hexdigest() +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0010= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0011=def fail(code:str): +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0012=raise RuntimeError(code) +OVERLAY_MATCH_FILE=lxc_adapter.py +OVERLAY_MATCH_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d +OVERLAY_MATCH_LINE_COUNT=19 +OVERLAY_MATCH_LINES=2,7,36,44,45,52,55,57,59,68,95,112,130,133,158,162,199,200,213 +OVERLAY_CONTEXT_lxc_adapter_py_01_RANGE=1-15 +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0002=import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0003= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0004=PVESH_SHA='9ed13d4c2d82e7864ff0192c428da7669af263f81dfcc84d5a981ca98fee8439' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0005=VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0006=HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0007=EXEC_HELPER=pathlib.Path(__file__).resolve().parent/'producer_exec_helper.py' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0008=MAX_STDERR=262144 +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0009=ENV={'PATH':'/usr/sbin:/usr/bin:/sbin:/bin','LC_ALL':'C','LANG':'C','HOME':'/root','PYTHONDONTWRITEBYTECODE':'1'} +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0010= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0011=class AdapterError(RuntimeError): pass +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0012=class ExecFailure(AdapterError): +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0013=def __init__(self,code,summary): super().__init__(code); self.code=code; self.summary=summary +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0014= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0015=def _need(ok:bool,code:str): +OVERLAY_CONTEXT_lxc_adapter_py_02_RANGE=32-76 +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0032=if n<=0: raise AdapterError('WRITE_FAILED') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0033=view=view[n:] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0034= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0035=def _remote_sha(legacy,node,path): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0036=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0037=parts=p.stdout.decode('ascii','strict').strip().split() +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0038=_need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0039=return parts[0] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0040= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0041=def _live_inputs(legacy,node,vmid,scratch): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0042=_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0043=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0044=rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0045=stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0046=_need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0047=configs=[] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0048=for r in rows: +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0049=if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0050=try: rid=int(r.get('vmid')) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0051=except Exception: raise AdapterError('RESOURCE_VMID') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0052=cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r["type"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0053=_need(type(cfg) is dict,'CONFIG_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0054=configs.append([rid,cfg]) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0055=tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0056=_need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0057=q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0058=defaults=None +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0059=if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0060=elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0061=st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0062=return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs, +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0063='defaults_b64':None if defaults is None else base64.b64encode(defaults).decode('ascii'),'staging_free':free,'tasks':tasks} +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0064= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0065=def _helper(inp): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0066=data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode('utf-8') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0067=_need(0262144: +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0097=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)}) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0098=try: out=json.loads(p.stdout) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0099=except Exception: +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0100=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)}) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0101=summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')} +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0102=if isinstance(out.get('process'),dict): summary.update(out['process']) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0103=if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary) +OVERLAY_CONTEXT_lxc_adapter_py_04_RANGE=108-120 +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0108=def _kill(p): +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0109=try: os.killpg(p.pid,signal.SIGTERM) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0110=except ProcessLookupError: pass +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0111=try: p.wait(timeout=10) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0112=except subprocess.TimeoutExpired: +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0113=try: os.killpg(p.pid,signal.SIGKILL) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0114=except ProcessLookupError: pass +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0115=p.wait() +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0116= +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0117=def _execute_remote(legacy,node,argv,dest,cap,timeout): +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0118=_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE') +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0119=_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') +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0120=_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE') +OVERLAY_CONTEXT_lxc_adapter_py_05_RANGE=126-141 +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0126=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) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0127=initial=os.fstat(fd) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0128=digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0129=remote='cd / && exec '+shlex.join(argv) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0130=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote] +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0131=deadline=time.monotonic()+timeout +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0132=try: +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0133=p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0134=sel=selectors.DefaultSelector() +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0135=for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0136=while sel.get_map(): +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0137=now=time.monotonic() +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0138=if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{}) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0139=for key,_ in sel.select(min(.2,max(0,deadline-now))): +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0140=b=os.read(key.fileobj.fileno(),65536) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0141=if not b: sel.unregister(key.fileobj); continue +OVERLAY_CONTEXT_lxc_adapter_py_06_RANGE=154-170 +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0154=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: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0155=raise ExecFailure('REMOTE_FILE_IDENTITY',{}) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0156=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST') +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0157=os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0158=return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(), +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0159='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()} +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0160=except ExecFailure as e: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0161=if p is not None and p.poll() is None: _kill(p) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0162=summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total, +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0163='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()} +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0164=summary.update(e.summary); raise ExecFailure(e.code,summary) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0165=finally: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0166=if p is not None: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0167=if p.poll() is None: _kill(p) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0168=if p.stdout: p.stdout.close() +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0169=if p.stderr: p.stderr.close() +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0170=if sel is not None: sel.close() +OVERLAY_CONTEXT_lxc_adapter_py_07_RANGE=195-218 +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0195=row=rows[0]; node=row.get('node'); typ=row.get('type') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0196=_need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0197=legacy._default_unprivileged_lxc(node,vmid) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0198=scratch=f'/var/tmp/homelab-vzdump-v2-{gen}' +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0199=legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0200=q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0201=_need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0202=try: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0203=legacy.mapped_scratch_probe(node,scratch) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0204=p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes']) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0205=try: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0206=result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0207=except ExecFailure as e: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0208=_emit_diag(node,e.summary|{'failure_code':e.code}) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0209=raise legacy.BackupError('LXC_PRODUCER_FAILED') from None +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0210=_need(local.is_file() and 0str: +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0010=h=hashlib.sha256() +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0011=with open(p,'rb',buffering=0) as f: +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0012=for b in iter(lambda:f.read(1<<20),b''): h.update(b) +OVERLAY_CONTEXT_producer_exec_helper_py_02_RANGE=27-39 +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0027=if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0028=sys.path.insert(0,str(BASE)) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0029=import adapter +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0030=adapter.verify_sources(); adapter.load_graph() +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0031=print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0032=return 0 +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0033= +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0034=def main()->int: +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0035=if sys.argv[1:]==['selftest']: return selftest() +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0036=if sys.argv[1:]: fail('ARGC') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0037=raw=sys.stdin.buffer.read(MAX_INPUT+1) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0038=if not raw or len(raw)>MAX_INPUT: fail('INPUT_BOUND') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0039=try: x=json.loads(raw) +OVERLAY_MATCH_FILE=qemu_adapter.py +OVERLAY_MATCH_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b +OVERLAY_MATCH_LINE_COUNT=7 +OVERLAY_MATCH_LINES=12,49,51,56,62,69,73 +OVERLAY_CONTEXT_qemu_adapter_py_01_RANGE=8-20 +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0008=def _need(ok,code): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0009=if not ok: raise QemuAdapterError(code) +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0010= +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0011=def _remote_sha(legacy,node,path): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0012=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0013=parts=p.stdout.decode('ascii','strict').strip().split() +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0014=_need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0015=return parts[0] +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0016= +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0017=def _select_qemu_outputs(vmid,files): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0018=_need(type(vmid) is int and vmid>0,'QEMU_VMID') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0019=_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') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0020=_need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE') +OVERLAY_CONTEXT_qemu_adapter_py_02_RANGE=45-79 +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0045=row=rows[0]; node=row.get('node'); typ=row.get('type') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0046=_need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0047=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0048=srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0049=legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0050=try: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0051=vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0052=if vp.returncode!=0: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0053=_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) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0054=raise legacy.BackupError('QEMU_VZDUMP_FAILED') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0055=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0056=p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\n'],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0057=files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x] +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0058=try: src,log=_select_qemu_outputs(vmid,files) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0059=except QemuAdapterError as e: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0060=_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e)) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0061=raise legacy.BackupError(str(e)) from None +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0062=q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0063=raw=q.stdout.decode('ascii','strict').strip() +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0064=_need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0065=size=int(raw) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0066=local=pathlib.Path(work)/'payload.bin' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0067=if node=='pve01': local=pathlib.Path(src) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0068=else: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0069=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0070=_need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0071=_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) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0072=except Exception: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0073=legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0074=cleanup={'kind':'pve_source_dir','node':node,'path':srcdir} +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0075=meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'), +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0076='producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'} +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0077=return pathlib.Path(local),meta,cleanup +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0078=capture_pve_guest.__name__='capture_pve_guest' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0079=return capture_pve_guest +OVERLAY_AST_FILE=entry504.py +OVERLAY_AST_FUNCTION_COUNT=2 +OVERLAY_AST_FUNCTION_01_LINE=99 +OVERLAY_AST_FUNCTION_01_NAME=_target +OVERLAY_AST_FUNCTION_02_LINE=119 +OVERLAY_AST_FUNCTION_02_NAME=main +OVERLAY_AST_IMPORT_COUNT=10 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=importlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=os +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=pathlib +OVERLAY_AST_IMPORT_07_LINE=2 +OVERLAY_AST_IMPORT_07_NAME=stat +OVERLAY_AST_IMPORT_08_LINE=2 +OVERLAY_AST_IMPORT_08_NAME=sys +OVERLAY_AST_IMPORT_09_LINE=2 +OVERLAY_AST_IMPORT_09_NAME=types +OVERLAY_AST_IMPORT_10_LINE=126 +OVERLAY_AST_IMPORT_10_NAME=tempfile +OVERLAY_AST_CALL_COUNT=4 +OVERLAY_AST_CALL_01_LINE=87 +OVERLAY_AST_CALL_01_KIND=import_module +OVERLAY_AST_CALL_01_TEXT=importlib.import_module('wrapper') +OVERLAY_AST_CALL_02_LINE=91 +OVERLAY_AST_CALL_02_KIND=import_module +OVERLAY_AST_CALL_02_TEXT=importlib.import_module('lxc_adapter') +OVERLAY_AST_CALL_03_LINE=92 +OVERLAY_AST_CALL_03_KIND=import_module +OVERLAY_AST_CALL_03_TEXT=importlib.import_module('qemu_adapter') +OVERLAY_AST_CALL_04_LINE=93 +OVERLAY_AST_CALL_04_KIND=import_module +OVERLAY_AST_CALL_04_TEXT=importlib.import_module('scheduler_adapter') +OVERLAY_AST_FILE=fresh_lxc_helper.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=14 +OVERLAY_AST_FUNCTION_01_NAME=main +OVERLAY_AST_IMPORT_COUNT=7 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=base64 +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=hashlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=pathlib +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=sys +OVERLAY_AST_IMPORT_07_LINE=19 +OVERLAY_AST_IMPORT_07_NAME=adapter +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_AST_FILE=lxc_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=191 +OVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest +OVERLAY_AST_IMPORT_COUNT=14 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=base64 +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=hashlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=os +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=pathlib +OVERLAY_AST_IMPORT_07_LINE=2 +OVERLAY_AST_IMPORT_07_NAME=re +OVERLAY_AST_IMPORT_08_LINE=2 +OVERLAY_AST_IMPORT_08_NAME=selectors +OVERLAY_AST_IMPORT_09_LINE=2 +OVERLAY_AST_IMPORT_09_NAME=shlex +OVERLAY_AST_IMPORT_10_LINE=2 +OVERLAY_AST_IMPORT_10_NAME=signal +OVERLAY_AST_IMPORT_11_LINE=2 +OVERLAY_AST_IMPORT_11_NAME=stat +OVERLAY_AST_IMPORT_12_LINE=2 +OVERLAY_AST_IMPORT_12_NAME=subprocess +OVERLAY_AST_IMPORT_13_LINE=2 +OVERLAY_AST_IMPORT_13_NAME=sys +OVERLAY_AST_IMPORT_14_LINE=2 +OVERLAY_AST_IMPORT_14_NAME=time +OVERLAY_AST_CALL_COUNT=3 +OVERLAY_AST_CALL_01_LINE=68 +OVERLAY_AST_CALL_01_KIND=run +OVERLAY_AST_CALL_01_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV) +OVERLAY_AST_CALL_02_LINE=95 +OVERLAY_AST_CALL_02_KIND=run +OVERLAY_AST_CALL_02_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV) +OVERLAY_AST_CALL_03_LINE=133 +OVERLAY_AST_CALL_03_KIND=Popen +OVERLAY_AST_CALL_03_TEXT=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True) +OVERLAY_AST_FILE=producer_exec_helper.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=34 +OVERLAY_AST_FUNCTION_01_NAME=main +OVERLAY_AST_IMPORT_COUNT=8 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=json +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=os +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=pathlib +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=sys +OVERLAY_AST_IMPORT_07_LINE=29 +OVERLAY_AST_IMPORT_07_NAME=adapter +OVERLAY_AST_IMPORT_08_LINE=50 +OVERLAY_AST_IMPORT_08_NAME=adapter +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_AST_FILE=qemu_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=41 +OVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest +OVERLAY_AST_IMPORT_COUNT=5 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=json +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=pathlib +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=re +OVERLAY_AST_CALL_COUNT=1 +OVERLAY_AST_CALL_01_LINE=69 +OVERLAY_AST_CALL_01_KIND=run +OVERLAY_AST_CALL_01_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +OVERLAY_AST_FILE=scheduler_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=55 +OVERLAY_AST_FUNCTION_01_NAME=choose_due_target +OVERLAY_AST_IMPORT_COUNT=3 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=json +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=pathlib +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_REFERENCED_PATH_COUNT=2 +OVERLAY_REF_01_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1 +OVERLAY_REF_01_EXISTS=True +OVERLAY_REF_01_IS_FILE=False +OVERLAY_REF_02_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411 +OVERLAY_REF_02_EXISTS=True +OVERLAY_REF_02_IS_FILE=False +OVERLAY_TRANSPORT_SIGNATURE_COUNT=2 +OVERLAY_TRANSPORT_SIG_01_FILE=lxc_adapter.py +OVERLAY_TRANSPORT_SIG_01_LINE=130 +OVERLAY_TRANSPORT_SIG_01_TEXT=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote] +OVERLAY_TRANSPORT_SIG_02_FILE=qemu_adapter.py +OVERLAY_TRANSPORT_SIG_02_LINE=69 +OVERLAY_TRANSPORT_SIG_02_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +VPS557R3_DECISION=OVERLAY504_DELEGATES_TO_BASE_ENGINE +VPS557R3_NEXT_GATE=READ_OVERLAY504_BASE_ENGINE_BINDING +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} + +OUTPUT_END +CHAT_OUTPUT_END diff --git a/runtime/latest.json b/runtime/latest.json index 767cb163..2b2e5cda 100644 --- a/runtime/latest.json +++ b/runtime/latest.json @@ -1,27 +1,27 @@ { "schema_version": 1, "channel": "homelab-runtime", - "command_id": "NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102", - "status": "FAIL", - "rc": 3, + "command_id": "SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3", + "status": "OK", + "rc": 0, "host": "pve01", - "mode": "change", - "component": "newfi-newfdom-articles205-pack1-two-articles-public-smoke-corrected", - "started_at_utc": "2026-09-18T21:08:58Z", - "finished_at_utc": "2026-09-18T21:09:02Z", + "mode": "read-only", + "component": "infra-pve1-moldova-overlay504-transport-readonly", + "started_at_utc": "2026-09-18T21:10:33Z", + "finished_at_utc": "2026-09-18T21:10:33Z", "reference_register_checked": true, "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", "error_register_checked": true, "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", - "command_sha256": "52df1dc3ff6172b8b5f56dcda9503a23848dadf9b8443bc5d36b9affc45185b4", + "command_sha256": "7f9a19052a0b35d999a1d13fd46c335e82b069a6b5a3f06d5b760c4f88083520", "duplicate_failed_command_blocked": false, "block_reason": null, "execution_started": true, - "change_declared": true, + "change_declared": false, "result_contract_valid": true, - "result_contract_status": "FAIL", + "result_contract_status": null, "result_contract_error": null, - "command_rc": 3, + "command_rc": 0, "changes_made": false, "rollback_started": false, "rollback_restored": null, @@ -30,9 +30,9 @@ "secrets_included": false, "private_addresses_included": false, "raw_evidence_retained_locally": true, - "raw_evidence_sha256": "3b326b94cda2adf7220a7666df72b149dced195c3f8243e4edd1318e63484711", - "sanitized_output_sha256": "3b326b94cda2adf7220a7666df72b149dced195c3f8243e4edd1318e63484711", + "raw_evidence_sha256": "e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7", + "sanitized_output_sha256": "e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7", "output_truncated_in_json": false, "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", - "output": "NEWFI102_BEGIN\nCOMMAND_ID=NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102\nNEWFI102_SAFE_REPORT={\"changes_made\": false, \"decision\": \"FAIL_ARTICLES205_PACK1_HOLD\", \"error\": \"RuntimeError:GUEST:RuntimeError:PERR\", \"rollback_restored\": null, \"rollback_started\": false}\nHOMELAB_RESULT_CONTRACT={\"version\": 1, \"command_id\": \"NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102\", \"status\": \"FAIL\", \"changes_made\": false, \"rollback_started\": false, \"rollback_restored\": null}\n" + "output": "ERROR_REGISTER_CHECK=OK\nREFERENCE_CHECK=OK\nAUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED\nOVERLAY_ROOT_PRESENT=True\nOVERLAY_FILE_COUNT=6\nOVERLAY_FILE_01_PATH=entry504.py\nOVERLAY_FILE_01_MODE=0o400\nOVERLAY_FILE_01_UID=0\nOVERLAY_FILE_01_GID=0\nOVERLAY_FILE_01_SIZE=10566\nOVERLAY_FILE_01_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793\nOVERLAY_FILE_02_PATH=fresh_lxc_helper.py\nOVERLAY_FILE_02_MODE=0o400\nOVERLAY_FILE_02_UID=0\nOVERLAY_FILE_02_GID=0\nOVERLAY_FILE_02_SIZE=2320\nOVERLAY_FILE_02_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011\nOVERLAY_FILE_03_PATH=lxc_adapter.py\nOVERLAY_FILE_03_MODE=0o400\nOVERLAY_FILE_03_UID=0\nOVERLAY_FILE_03_GID=0\nOVERLAY_FILE_03_SIZE=13825\nOVERLAY_FILE_03_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d\nOVERLAY_FILE_04_PATH=producer_exec_helper.py\nOVERLAY_FILE_04_MODE=0o400\nOVERLAY_FILE_04_UID=0\nOVERLAY_FILE_04_GID=0\nOVERLAY_FILE_04_SIZE=3449\nOVERLAY_FILE_04_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3\nOVERLAY_FILE_05_PATH=qemu_adapter.py\nOVERLAY_FILE_05_MODE=0o400\nOVERLAY_FILE_05_UID=0\nOVERLAY_FILE_05_GID=0\nOVERLAY_FILE_05_SIZE=4627\nOVERLAY_FILE_05_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b\nOVERLAY_FILE_06_PATH=scheduler_adapter.py\nOVERLAY_FILE_06_MODE=0o400\nOVERLAY_FILE_06_UID=0\nOVERLAY_FILE_06_GID=0\nOVERLAY_FILE_06_SIZE=4097\nOVERLAY_FILE_06_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96\nOVERLAY_MATCH_FILE=entry504.py\nOVERLAY_MATCH_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793\nOVERLAY_MATCH_LINE_COUNT=13\nOVERLAY_MATCH_LINES=4,7,43,44,62,78,80,93,96,97,105,112,123\nOVERLAY_CONTEXT_entry504_py_01_RANGE=1-15\nOVERLAY_CONTEXT_entry504_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_entry504_py_01_LINE_0002=import hashlib, importlib, json, os, pathlib, stat, sys, types\nOVERLAY_CONTEXT_entry504_py_01_LINE_0003=\nOVERLAY_CONTEXT_entry504_py_01_LINE_0004=BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')\nOVERLAY_CONTEXT_entry504_py_01_LINE_0005=HERE=pathlib.Path(__file__).resolve().parent\nOVERLAY_CONTEXT_entry504_py_01_LINE_0006=BASE_EXPECTED={\nOVERLAY_CONTEXT_entry504_py_01_LINE_0007='legacy_engine.py':'b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0008='wrapper.py':'2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0009='ct112_handler.py':'8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0010='representative_driver.py':'b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0011='candidate411/adapter.py':'18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0012='candidate411/pve265.py':'cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0013='candidate411/pve270.py':'97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0014='candidate411/pve282.py':'73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012',\nOVERLAY_CONTEXT_entry504_py_01_LINE_0015=}\nOVERLAY_CONTEXT_entry504_py_02_RANGE=39-52\nOVERLAY_CONTEXT_entry504_py_02_LINE_0039=try: return self._g[n]\nOVERLAY_CONTEXT_entry504_py_02_LINE_0040=except KeyError as e: raise AttributeError(n) from e\nOVERLAY_CONTEXT_entry504_py_02_LINE_0041=def __setattr__(self,n,v): self._g[n]=v\nOVERLAY_CONTEXT_entry504_py_02_LINE_0042=\nOVERLAY_CONTEXT_entry504_py_02_LINE_0043=def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0044=legacy_path=(pathlib.Path(base)/'legacy_engine.py').resolve()\nOVERLAY_CONTEXT_entry504_py_02_LINE_0045=found={}\nOVERLAY_CONTEXT_entry504_py_02_LINE_0046=for value in vars(wrapper).values():\nOVERLAY_CONTEXT_entry504_py_02_LINE_0047=if isinstance(value,types.ModuleType):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0048=g=vars(value); raw=g.get('__file__')\nOVERLAY_CONTEXT_entry504_py_02_LINE_0049=elif isinstance(value,types.FunctionType):\nOVERLAY_CONTEXT_entry504_py_02_LINE_0050=g=value.__globals__; raw=g.get('__file__')\nOVERLAY_CONTEXT_entry504_py_02_LINE_0051=else:\nOVERLAY_CONTEXT_entry504_py_02_LINE_0052=continue\nOVERLAY_CONTEXT_entry504_py_03_RANGE=58-70\nOVERLAY_CONTEXT_entry504_py_03_LINE_0058=found[id(g)]=g\nOVERLAY_CONTEXT_entry504_py_03_LINE_0059=if len(found)!=1:\nOVERLAY_CONTEXT_entry504_py_03_LINE_0060=raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0061=g=next(iter(found.values()))\nOVERLAY_CONTEXT_entry504_py_03_LINE_0062=required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',\nOVERLAY_CONTEXT_entry504_py_03_LINE_0063='_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run',\nOVERLAY_CONTEXT_entry504_py_03_LINE_0064='choose_due_target','write_state','epoch')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0065=if any(not callable(g.get(n)) for n in required):\nOVERLAY_CONTEXT_entry504_py_03_LINE_0066=raise RuntimeError('LEGACY_PROVENANCE_API')\nOVERLAY_CONTEXT_entry504_py_03_LINE_0067=original=g['capture_pve_guest']\nOVERLAY_CONTEXT_entry504_py_03_LINE_0068=proxy=_GlobalsProxy(g)\nOVERLAY_CONTEXT_entry504_py_03_LINE_0069=if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'):\nOVERLAY_CONTEXT_entry504_py_03_LINE_0070=raise RuntimeError('LEGACY_SCP_API')\nOVERLAY_CONTEXT_entry504_py_04_RANGE=74-131\nOVERLAY_CONTEXT_entry504_py_04_LINE_0074=patched=lxc_adapter.bind(proxy,qemu_patched)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0075=if not callable(patched):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0076=raise RuntimeError('LXC_ADAPTER_BIND_RESULT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0077=g['capture_pve_guest']=patched\nOVERLAY_CONTEXT_entry504_py_04_LINE_0078=scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])\nOVERLAY_CONTEXT_entry504_py_04_LINE_0079=if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0080=raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0081=return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}\nOVERLAY_CONTEXT_entry504_py_04_LINE_0082=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0083=def _load():\nOVERLAY_CONTEXT_entry504_py_04_LINE_0084=_verify_base()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0085=sys.dont_write_bytecode=True\nOVERLAY_CONTEXT_entry504_py_04_LINE_0086=sys.path.insert(0,str(BASE))\nOVERLAY_CONTEXT_entry504_py_04_LINE_0087=wrapper=importlib.import_module('wrapper')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0088=# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced.\nOVERLAY_CONTEXT_entry504_py_04_LINE_0089=wrapper.selftest()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0090=sys.path.insert(0,str(HERE))\nOVERLAY_CONTEXT_entry504_py_04_LINE_0091=lxc_adapter=importlib.import_module('lxc_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0092=qemu_adapter=importlib.import_module('qemu_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0093=scheduler_adapter=importlib.import_module('scheduler_adapter')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0094=if _sha(HERE/'lxc_adapter.py')!='3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d':\nOVERLAY_CONTEXT_entry504_py_04_LINE_0095=raise RuntimeError('LXC_502_BYTE_IDENTITY')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0096=wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0097=return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired\nOVERLAY_CONTEXT_entry504_py_04_LINE_0098=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0099=def _target(wrapper,lid):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0100=rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0101=if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0102=return hits[0]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0103=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0104=def selftest():\nOVERLAY_CONTEXT_entry504_py_04_LINE_0105=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0106=if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0107=raise RuntimeError('PATCH_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0108=if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0109=raise RuntimeError('SCHEDULER_CHOOSE_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0110=if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0111=raise RuntimeError('SCHEDULER_WRITE_BINDING')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0112=if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0113=raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0114=if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0115=raise RuntimeError('WRAPPER_PUBLIC_API')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0116=print('SELFTEST_OVERLAY504=PASS',flush=True)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0117=return 0\nOVERLAY_CONTEXT_entry504_py_04_LINE_0118=\nOVERLAY_CONTEXT_entry504_py_04_LINE_0119=def main(argv=None):\nOVERLAY_CONTEXT_entry504_py_04_LINE_0120=argv=list(sys.argv[1:] if argv is None else argv)\nOVERLAY_CONTEXT_entry504_py_04_LINE_0121=if argv==['selftest']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0122=return selftest()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0123=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()\nOVERLAY_CONTEXT_entry504_py_04_LINE_0124=legacy=wired['legacy']\nOVERLAY_CONTEXT_entry504_py_04_LINE_0125=if argv==['scheduler-proof']:\nOVERLAY_CONTEXT_entry504_py_04_LINE_0126=import tempfile\nOVERLAY_CONTEXT_entry504_py_04_LINE_0127=legacy=wired['legacy']; g=wired['legacy_globals']\nOVERLAY_CONTEXT_entry504_py_04_LINE_0128=old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0129=if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE')\nOVERLAY_CONTEXT_entry504_py_04_LINE_0130=now=[1000]\nOVERLAY_CONTEXT_entry504_py_04_LINE_0131=try:\nOVERLAY_MATCH_FILE=fresh_lxc_helper.py\nOVERLAY_MATCH_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011\nOVERLAY_MATCH_LINE_COUNT=1\nOVERLAY_MATCH_LINES=4\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_RANGE=1-12\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0002=import base64, hashlib, json, pathlib, sys\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0003=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0004=BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1')\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0005=C411=BASE_RELEASE/'candidate411'\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0006=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be'\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0007=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0008=def sha(p:pathlib.Path)->str:\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0009=return hashlib.sha256(p.read_bytes()).hexdigest()\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0010=\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0011=def fail(code:str):\nOVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0012=raise RuntimeError(code)\nOVERLAY_MATCH_FILE=lxc_adapter.py\nOVERLAY_MATCH_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d\nOVERLAY_MATCH_LINE_COUNT=19\nOVERLAY_MATCH_LINES=2,7,36,44,45,52,55,57,59,68,95,112,130,133,158,162,199,200,213\nOVERLAY_CONTEXT_lxc_adapter_py_01_RANGE=1-15\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0002=import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0003=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0004=PVESH_SHA='9ed13d4c2d82e7864ff0192c428da7669af263f81dfcc84d5a981ca98fee8439'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0005=VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0006=HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0007=EXEC_HELPER=pathlib.Path(__file__).resolve().parent/'producer_exec_helper.py'\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0008=MAX_STDERR=262144\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0009=ENV={'PATH':'/usr/sbin:/usr/bin:/sbin:/bin','LC_ALL':'C','LANG':'C','HOME':'/root','PYTHONDONTWRITEBYTECODE':'1'}\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0010=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0011=class AdapterError(RuntimeError): pass\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0012=class ExecFailure(AdapterError):\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0013=def __init__(self,code,summary): super().__init__(code); self.code=code; self.summary=summary\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0014=\nOVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0015=def _need(ok:bool,code:str):\nOVERLAY_CONTEXT_lxc_adapter_py_02_RANGE=32-76\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0032=if n<=0: raise AdapterError('WRITE_FAILED')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0033=view=view[n:]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0034=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0035=def _remote_sha(legacy,node,path):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0036=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0037=parts=p.stdout.decode('ascii','strict').strip().split()\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0038=_need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0039=return parts[0]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0040=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0041=def _live_inputs(legacy,node,vmid,scratch):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0042=_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0043=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0044=rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0045=stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0046=_need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0047=configs=[]\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0048=for r in rows:\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0049=if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0050=try: rid=int(r.get('vmid'))\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0051=except Exception: raise AdapterError('RESOURCE_VMID')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0052=cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r[\"type\"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0053=_need(type(cfg) is dict,'CONFIG_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0054=configs.append([rid,cfg])\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0055=tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0056=_need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0057=q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0058=defaults=None\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0059=if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0060=elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0061=st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0062=return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs,\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0063='defaults_b64':None if defaults is None else base64.b64encode(defaults).decode('ascii'),'staging_free':free,'tasks':tasks}\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0064=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0065=def _helper(inp):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0066=data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode('utf-8')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0067=_need(0262144:\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0097=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)})\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0098=try: out=json.loads(p.stdout)\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0099=except Exception:\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0100=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)})\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0101=summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')}\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0102=if isinstance(out.get('process'),dict): summary.update(out['process'])\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0103=if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary)\nOVERLAY_CONTEXT_lxc_adapter_py_04_RANGE=108-120\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0108=def _kill(p):\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0109=try: os.killpg(p.pid,signal.SIGTERM)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0110=except ProcessLookupError: pass\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0111=try: p.wait(timeout=10)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0112=except subprocess.TimeoutExpired:\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0113=try: os.killpg(p.pid,signal.SIGKILL)\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0114=except ProcessLookupError: pass\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0115=p.wait()\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0116=\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0117=def _execute_remote(legacy,node,argv,dest,cap,timeout):\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0118=_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE')\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0119=_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')\nOVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0120=_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE')\nOVERLAY_CONTEXT_lxc_adapter_py_05_RANGE=126-141\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0126=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)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0127=initial=os.fstat(fd)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0128=digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0129=remote='cd / && exec '+shlex.join(argv)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0130=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0131=deadline=time.monotonic()+timeout\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0132=try:\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0133=p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0134=sel=selectors.DefaultSelector()\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0135=for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0136=while sel.get_map():\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0137=now=time.monotonic()\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0138=if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{})\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0139=for key,_ in sel.select(min(.2,max(0,deadline-now))):\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0140=b=os.read(key.fileobj.fileno(),65536)\nOVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0141=if not b: sel.unregister(key.fileobj); continue\nOVERLAY_CONTEXT_lxc_adapter_py_06_RANGE=154-170\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0154=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:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0155=raise ExecFailure('REMOTE_FILE_IDENTITY',{})\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0156=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST')\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0157=os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0158=return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(),\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0159='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0160=except ExecFailure as e:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0161=if p is not None and p.poll() is None: _kill(p)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0162=summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total,\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0163='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()}\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0164=summary.update(e.summary); raise ExecFailure(e.code,summary)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0165=finally:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0166=if p is not None:\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0167=if p.poll() is None: _kill(p)\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0168=if p.stdout: p.stdout.close()\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0169=if p.stderr: p.stderr.close()\nOVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0170=if sel is not None: sel.close()\nOVERLAY_CONTEXT_lxc_adapter_py_07_RANGE=195-218\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0195=row=rows[0]; node=row.get('node'); typ=row.get('type')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0196=_need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0197=legacy._default_unprivileged_lxc(node,vmid)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0198=scratch=f'/var/tmp/homelab-vzdump-v2-{gen}'\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0199=legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0200=q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0201=_need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0202=try:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0203=legacy.mapped_scratch_probe(node,scratch)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0204=p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes'])\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0205=try:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0206=result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0207=except ExecFailure as e:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0208=_emit_diag(node,e.summary|{'failure_code':e.code})\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0209=raise legacy.BackupError('LXC_PRODUCER_FAILED') from None\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0210=_need(local.is_file() and 0str:\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0010=h=hashlib.sha256()\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0011=with open(p,'rb',buffering=0) as f:\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0012=for b in iter(lambda:f.read(1<<20),b''): h.update(b)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_RANGE=27-39\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0027=if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0028=sys.path.insert(0,str(BASE))\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0029=import adapter\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0030=adapter.verify_sources(); adapter.load_graph()\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0031=print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0032=return 0\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0033=\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0034=def main()->int:\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0035=if sys.argv[1:]==['selftest']: return selftest()\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0036=if sys.argv[1:]: fail('ARGC')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0037=raw=sys.stdin.buffer.read(MAX_INPUT+1)\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0038=if not raw or len(raw)>MAX_INPUT: fail('INPUT_BOUND')\nOVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0039=try: x=json.loads(raw)\nOVERLAY_MATCH_FILE=qemu_adapter.py\nOVERLAY_MATCH_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b\nOVERLAY_MATCH_LINE_COUNT=7\nOVERLAY_MATCH_LINES=12,49,51,56,62,69,73\nOVERLAY_CONTEXT_qemu_adapter_py_01_RANGE=8-20\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0008=def _need(ok,code):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0009=if not ok: raise QemuAdapterError(code)\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0010=\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0011=def _remote_sha(legacy,node,path):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0012=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0013=parts=p.stdout.decode('ascii','strict').strip().split()\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0014=_need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0015=return parts[0]\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0016=\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0017=def _select_qemu_outputs(vmid,files):\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0018=_need(type(vmid) is int and vmid>0,'QEMU_VMID')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0019=_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')\nOVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0020=_need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE')\nOVERLAY_CONTEXT_qemu_adapter_py_02_RANGE=45-79\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0045=row=rows[0]; node=row.get('node'); typ=row.get('type')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0046=_need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0047=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0048=srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0049=legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0050=try:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0051=vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0052=if vp.returncode!=0:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0053=_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)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0054=raise legacy.BackupError('QEMU_VZDUMP_FAILED')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0055=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0056=p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\\n'],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0057=files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x]\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0058=try: src,log=_select_qemu_outputs(vmid,files)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0059=except QemuAdapterError as e:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0060=_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e))\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0061=raise legacy.BackupError(str(e)) from None\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0062=q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0063=raw=q.stdout.decode('ascii','strict').strip()\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0064=_need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0065=size=int(raw)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0066=local=pathlib.Path(work)/'payload.bin'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0067=if node=='pve01': local=pathlib.Path(src)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0068=else:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0069=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0070=_need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING')\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0071=_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)\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0072=except Exception:\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0073=legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0074=cleanup={'kind':'pve_source_dir','node':node,'path':srcdir}\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0075=meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'),\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0076='producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'}\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0077=return pathlib.Path(local),meta,cleanup\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0078=capture_pve_guest.__name__='capture_pve_guest'\nOVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0079=return capture_pve_guest\nOVERLAY_AST_FILE=entry504.py\nOVERLAY_AST_FUNCTION_COUNT=2\nOVERLAY_AST_FUNCTION_01_LINE=99\nOVERLAY_AST_FUNCTION_01_NAME=_target\nOVERLAY_AST_FUNCTION_02_LINE=119\nOVERLAY_AST_FUNCTION_02_NAME=main\nOVERLAY_AST_IMPORT_COUNT=10\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=importlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=os\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=pathlib\nOVERLAY_AST_IMPORT_07_LINE=2\nOVERLAY_AST_IMPORT_07_NAME=stat\nOVERLAY_AST_IMPORT_08_LINE=2\nOVERLAY_AST_IMPORT_08_NAME=sys\nOVERLAY_AST_IMPORT_09_LINE=2\nOVERLAY_AST_IMPORT_09_NAME=types\nOVERLAY_AST_IMPORT_10_LINE=126\nOVERLAY_AST_IMPORT_10_NAME=tempfile\nOVERLAY_AST_CALL_COUNT=4\nOVERLAY_AST_CALL_01_LINE=87\nOVERLAY_AST_CALL_01_KIND=import_module\nOVERLAY_AST_CALL_01_TEXT=importlib.import_module('wrapper')\nOVERLAY_AST_CALL_02_LINE=91\nOVERLAY_AST_CALL_02_KIND=import_module\nOVERLAY_AST_CALL_02_TEXT=importlib.import_module('lxc_adapter')\nOVERLAY_AST_CALL_03_LINE=92\nOVERLAY_AST_CALL_03_KIND=import_module\nOVERLAY_AST_CALL_03_TEXT=importlib.import_module('qemu_adapter')\nOVERLAY_AST_CALL_04_LINE=93\nOVERLAY_AST_CALL_04_KIND=import_module\nOVERLAY_AST_CALL_04_TEXT=importlib.import_module('scheduler_adapter')\nOVERLAY_AST_FILE=fresh_lxc_helper.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=14\nOVERLAY_AST_FUNCTION_01_NAME=main\nOVERLAY_AST_IMPORT_COUNT=7\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=base64\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=hashlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=pathlib\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=sys\nOVERLAY_AST_IMPORT_07_LINE=19\nOVERLAY_AST_IMPORT_07_NAME=adapter\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_AST_FILE=lxc_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=191\nOVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest\nOVERLAY_AST_IMPORT_COUNT=14\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=base64\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=hashlib\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=json\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=os\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=pathlib\nOVERLAY_AST_IMPORT_07_LINE=2\nOVERLAY_AST_IMPORT_07_NAME=re\nOVERLAY_AST_IMPORT_08_LINE=2\nOVERLAY_AST_IMPORT_08_NAME=selectors\nOVERLAY_AST_IMPORT_09_LINE=2\nOVERLAY_AST_IMPORT_09_NAME=shlex\nOVERLAY_AST_IMPORT_10_LINE=2\nOVERLAY_AST_IMPORT_10_NAME=signal\nOVERLAY_AST_IMPORT_11_LINE=2\nOVERLAY_AST_IMPORT_11_NAME=stat\nOVERLAY_AST_IMPORT_12_LINE=2\nOVERLAY_AST_IMPORT_12_NAME=subprocess\nOVERLAY_AST_IMPORT_13_LINE=2\nOVERLAY_AST_IMPORT_13_NAME=sys\nOVERLAY_AST_IMPORT_14_LINE=2\nOVERLAY_AST_IMPORT_14_NAME=time\nOVERLAY_AST_CALL_COUNT=3\nOVERLAY_AST_CALL_01_LINE=68\nOVERLAY_AST_CALL_01_KIND=run\nOVERLAY_AST_CALL_01_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)\nOVERLAY_AST_CALL_02_LINE=95\nOVERLAY_AST_CALL_02_KIND=run\nOVERLAY_AST_CALL_02_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)\nOVERLAY_AST_CALL_03_LINE=133\nOVERLAY_AST_CALL_03_KIND=Popen\nOVERLAY_AST_CALL_03_TEXT=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True)\nOVERLAY_AST_FILE=producer_exec_helper.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=34\nOVERLAY_AST_FUNCTION_01_NAME=main\nOVERLAY_AST_IMPORT_COUNT=8\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=json\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=os\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=pathlib\nOVERLAY_AST_IMPORT_06_LINE=2\nOVERLAY_AST_IMPORT_06_NAME=sys\nOVERLAY_AST_IMPORT_07_LINE=29\nOVERLAY_AST_IMPORT_07_NAME=adapter\nOVERLAY_AST_IMPORT_08_LINE=50\nOVERLAY_AST_IMPORT_08_NAME=adapter\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_AST_FILE=qemu_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=41\nOVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest\nOVERLAY_AST_IMPORT_COUNT=5\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=hashlib\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=json\nOVERLAY_AST_IMPORT_04_LINE=2\nOVERLAY_AST_IMPORT_04_NAME=pathlib\nOVERLAY_AST_IMPORT_05_LINE=2\nOVERLAY_AST_IMPORT_05_NAME=re\nOVERLAY_AST_CALL_COUNT=1\nOVERLAY_AST_CALL_01_LINE=69\nOVERLAY_AST_CALL_01_KIND=run\nOVERLAY_AST_CALL_01_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nOVERLAY_AST_FILE=scheduler_adapter.py\nOVERLAY_AST_FUNCTION_COUNT=1\nOVERLAY_AST_FUNCTION_01_LINE=55\nOVERLAY_AST_FUNCTION_01_NAME=choose_due_target\nOVERLAY_AST_IMPORT_COUNT=3\nOVERLAY_AST_IMPORT_01_LINE=1\nOVERLAY_AST_IMPORT_01_NAME=__future__.annotations\nOVERLAY_AST_IMPORT_02_LINE=2\nOVERLAY_AST_IMPORT_02_NAME=json\nOVERLAY_AST_IMPORT_03_LINE=2\nOVERLAY_AST_IMPORT_03_NAME=pathlib\nOVERLAY_AST_CALL_COUNT=0\nOVERLAY_REFERENCED_PATH_COUNT=2\nOVERLAY_REF_01_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1\nOVERLAY_REF_01_EXISTS=True\nOVERLAY_REF_01_IS_FILE=False\nOVERLAY_REF_02_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411\nOVERLAY_REF_02_EXISTS=True\nOVERLAY_REF_02_IS_FILE=False\nOVERLAY_TRANSPORT_SIGNATURE_COUNT=2\nOVERLAY_TRANSPORT_SIG_01_FILE=lxc_adapter.py\nOVERLAY_TRANSPORT_SIG_01_LINE=130\nOVERLAY_TRANSPORT_SIG_01_TEXT=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote]\nOVERLAY_TRANSPORT_SIG_02_FILE=qemu_adapter.py\nOVERLAY_TRANSPORT_SIG_02_LINE=69\nOVERLAY_TRANSPORT_SIG_02_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)\nVPS557R3_DECISION=OVERLAY504_DELEGATES_TO_BASE_ENGINE\nVPS557R3_NEXT_GATE=READ_OVERLAY504_BASE_ENGINE_BINDING\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" } diff --git a/runtime/latest.txt b/runtime/latest.txt index 3c16fca0..7cee2ef1 100644 --- a/runtime/latest.txt +++ b/runtime/latest.txt @@ -1,22 +1,22 @@ CHAT_OUTPUT_BEGIN -COMMAND_ID=NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102 -STATUS=FAIL -RC=3 +COMMAND_ID=SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3 +STATUS=OK +RC=0 HOST=pve01 -MODE=change -COMPONENT=newfi-newfdom-articles205-pack1-two-articles-public-smoke-corrected +MODE=read-only +COMPONENT=infra-pve1-moldova-overlay504-transport-readonly REFERENCE_REGISTER_CHECK=OK REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 ERROR_REGISTER_CHECK=OK ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 -COMMAND_SHA256=52df1dc3ff6172b8b5f56dcda9503a23848dadf9b8443bc5d36b9affc45185b4 +COMMAND_SHA256=7f9a19052a0b35d999a1d13fd46c335e82b069a6b5a3f06d5b760c4f88083520 DUPLICATE_FAILED_COMMAND_BLOCKED=false EXECUTION_STARTED=true -CHANGE_DECLARED=true +CHANGE_DECLARED=false RESULT_CONTRACT_VALID=true -RESULT_CONTRACT_STATUS=FAIL +RESULT_CONTRACT_STATUS=NOT_APPLICABLE RESULT_CONTRACT_ERROR=NONE -COMMAND_RC=3 +COMMAND_RC=0 CHANGES_MADE=false ROLLBACK_STARTED=false ROLLBACK_RESTORED=null @@ -24,13 +24,587 @@ MUTATION_OUTCOME=NO_MUTATION SANITIZED=yes SECRETS_INCLUDED=no PRIVATE_ADDRESSES_INCLUDED=no -RAW_EVIDENCE_SHA256=3b326b94cda2adf7220a7666df72b149dced195c3f8243e4edd1318e63484711 -SANITIZED_OUTPUT_SHA256=3b326b94cda2adf7220a7666df72b149dced195c3f8243e4edd1318e63484711 +RAW_EVIDENCE_SHA256=e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7 +SANITIZED_OUTPUT_SHA256=e28442fce699135a678d87f47199ecead0bb39ff250c5f9b54c7acbfe40c08d7 OUTPUT_BEGIN -NEWFI102_BEGIN -COMMAND_ID=NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102 -NEWFI102_SAFE_REPORT={"changes_made": false, "decision": "FAIL_ARTICLES205_PACK1_HOLD", "error": "RuntimeError:GUEST:RuntimeError:PERR", "rollback_restored": null, "rollback_started": false} -HOMELAB_RESULT_CONTRACT={"version": 1, "command_id": "NEWFI-260918-NEWFDOM-ARTICLES205-PACK1-102", "status": "FAIL", "changes_made": false, "rollback_started": false, "rollback_restored": null} +ERROR_REGISTER_CHECK=OK +REFERENCE_CHECK=OK +AUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED +OVERLAY_ROOT_PRESENT=True +OVERLAY_FILE_COUNT=6 +OVERLAY_FILE_01_PATH=entry504.py +OVERLAY_FILE_01_MODE=0o400 +OVERLAY_FILE_01_UID=0 +OVERLAY_FILE_01_GID=0 +OVERLAY_FILE_01_SIZE=10566 +OVERLAY_FILE_01_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793 +OVERLAY_FILE_02_PATH=fresh_lxc_helper.py +OVERLAY_FILE_02_MODE=0o400 +OVERLAY_FILE_02_UID=0 +OVERLAY_FILE_02_GID=0 +OVERLAY_FILE_02_SIZE=2320 +OVERLAY_FILE_02_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011 +OVERLAY_FILE_03_PATH=lxc_adapter.py +OVERLAY_FILE_03_MODE=0o400 +OVERLAY_FILE_03_UID=0 +OVERLAY_FILE_03_GID=0 +OVERLAY_FILE_03_SIZE=13825 +OVERLAY_FILE_03_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d +OVERLAY_FILE_04_PATH=producer_exec_helper.py +OVERLAY_FILE_04_MODE=0o400 +OVERLAY_FILE_04_UID=0 +OVERLAY_FILE_04_GID=0 +OVERLAY_FILE_04_SIZE=3449 +OVERLAY_FILE_04_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3 +OVERLAY_FILE_05_PATH=qemu_adapter.py +OVERLAY_FILE_05_MODE=0o400 +OVERLAY_FILE_05_UID=0 +OVERLAY_FILE_05_GID=0 +OVERLAY_FILE_05_SIZE=4627 +OVERLAY_FILE_05_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b +OVERLAY_FILE_06_PATH=scheduler_adapter.py +OVERLAY_FILE_06_MODE=0o400 +OVERLAY_FILE_06_UID=0 +OVERLAY_FILE_06_GID=0 +OVERLAY_FILE_06_SIZE=4097 +OVERLAY_FILE_06_SHA256=a6f67159a64067773323f028126e3109e15cf17a8142cea5e6129970f1d4da96 +OVERLAY_MATCH_FILE=entry504.py +OVERLAY_MATCH_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793 +OVERLAY_MATCH_LINE_COUNT=13 +OVERLAY_MATCH_LINES=4,7,43,44,62,78,80,93,96,97,105,112,123 +OVERLAY_CONTEXT_entry504_py_01_RANGE=1-15 +OVERLAY_CONTEXT_entry504_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_entry504_py_01_LINE_0002=import hashlib, importlib, json, os, pathlib, stat, sys, types +OVERLAY_CONTEXT_entry504_py_01_LINE_0003= +OVERLAY_CONTEXT_entry504_py_01_LINE_0004=BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1') +OVERLAY_CONTEXT_entry504_py_01_LINE_0005=HERE=pathlib.Path(__file__).resolve().parent +OVERLAY_CONTEXT_entry504_py_01_LINE_0006=BASE_EXPECTED={ +OVERLAY_CONTEXT_entry504_py_01_LINE_0007='legacy_engine.py':'b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7', +OVERLAY_CONTEXT_entry504_py_01_LINE_0008='wrapper.py':'2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5', +OVERLAY_CONTEXT_entry504_py_01_LINE_0009='ct112_handler.py':'8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c', +OVERLAY_CONTEXT_entry504_py_01_LINE_0010='representative_driver.py':'b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2', +OVERLAY_CONTEXT_entry504_py_01_LINE_0011='candidate411/adapter.py':'18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3', +OVERLAY_CONTEXT_entry504_py_01_LINE_0012='candidate411/pve265.py':'cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be', +OVERLAY_CONTEXT_entry504_py_01_LINE_0013='candidate411/pve270.py':'97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef', +OVERLAY_CONTEXT_entry504_py_01_LINE_0014='candidate411/pve282.py':'73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012', +OVERLAY_CONTEXT_entry504_py_01_LINE_0015=} +OVERLAY_CONTEXT_entry504_py_02_RANGE=39-52 +OVERLAY_CONTEXT_entry504_py_02_LINE_0039=try: return self._g[n] +OVERLAY_CONTEXT_entry504_py_02_LINE_0040=except KeyError as e: raise AttributeError(n) from e +OVERLAY_CONTEXT_entry504_py_02_LINE_0041=def __setattr__(self,n,v): self._g[n]=v +OVERLAY_CONTEXT_entry504_py_02_LINE_0042= +OVERLAY_CONTEXT_entry504_py_02_LINE_0043=def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE): +OVERLAY_CONTEXT_entry504_py_02_LINE_0044=legacy_path=(pathlib.Path(base)/'legacy_engine.py').resolve() +OVERLAY_CONTEXT_entry504_py_02_LINE_0045=found={} +OVERLAY_CONTEXT_entry504_py_02_LINE_0046=for value in vars(wrapper).values(): +OVERLAY_CONTEXT_entry504_py_02_LINE_0047=if isinstance(value,types.ModuleType): +OVERLAY_CONTEXT_entry504_py_02_LINE_0048=g=vars(value); raw=g.get('__file__') +OVERLAY_CONTEXT_entry504_py_02_LINE_0049=elif isinstance(value,types.FunctionType): +OVERLAY_CONTEXT_entry504_py_02_LINE_0050=g=value.__globals__; raw=g.get('__file__') +OVERLAY_CONTEXT_entry504_py_02_LINE_0051=else: +OVERLAY_CONTEXT_entry504_py_02_LINE_0052=continue +OVERLAY_CONTEXT_entry504_py_03_RANGE=58-70 +OVERLAY_CONTEXT_entry504_py_03_LINE_0058=found[id(g)]=g +OVERLAY_CONTEXT_entry504_py_03_LINE_0059=if len(found)!=1: +OVERLAY_CONTEXT_entry504_py_03_LINE_0060=raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY') +OVERLAY_CONTEXT_entry504_py_03_LINE_0061=g=next(iter(found.values())) +OVERLAY_CONTEXT_entry504_py_03_LINE_0062=required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote', +OVERLAY_CONTEXT_entry504_py_03_LINE_0063='_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run', +OVERLAY_CONTEXT_entry504_py_03_LINE_0064='choose_due_target','write_state','epoch') +OVERLAY_CONTEXT_entry504_py_03_LINE_0065=if any(not callable(g.get(n)) for n in required): +OVERLAY_CONTEXT_entry504_py_03_LINE_0066=raise RuntimeError('LEGACY_PROVENANCE_API') +OVERLAY_CONTEXT_entry504_py_03_LINE_0067=original=g['capture_pve_guest'] +OVERLAY_CONTEXT_entry504_py_03_LINE_0068=proxy=_GlobalsProxy(g) +OVERLAY_CONTEXT_entry504_py_03_LINE_0069=if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'): +OVERLAY_CONTEXT_entry504_py_03_LINE_0070=raise RuntimeError('LEGACY_SCP_API') +OVERLAY_CONTEXT_entry504_py_04_RANGE=74-131 +OVERLAY_CONTEXT_entry504_py_04_LINE_0074=patched=lxc_adapter.bind(proxy,qemu_patched) +OVERLAY_CONTEXT_entry504_py_04_LINE_0075=if not callable(patched): +OVERLAY_CONTEXT_entry504_py_04_LINE_0076=raise RuntimeError('LXC_ADAPTER_BIND_RESULT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0077=g['capture_pve_guest']=patched +OVERLAY_CONTEXT_entry504_py_04_LINE_0078=scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state']) +OVERLAY_CONTEXT_entry504_py_04_LINE_0079=if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0080=raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0081=return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired} +OVERLAY_CONTEXT_entry504_py_04_LINE_0082= +OVERLAY_CONTEXT_entry504_py_04_LINE_0083=def _load(): +OVERLAY_CONTEXT_entry504_py_04_LINE_0084=_verify_base() +OVERLAY_CONTEXT_entry504_py_04_LINE_0085=sys.dont_write_bytecode=True +OVERLAY_CONTEXT_entry504_py_04_LINE_0086=sys.path.insert(0,str(BASE)) +OVERLAY_CONTEXT_entry504_py_04_LINE_0087=wrapper=importlib.import_module('wrapper') +OVERLAY_CONTEXT_entry504_py_04_LINE_0088=# Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced. +OVERLAY_CONTEXT_entry504_py_04_LINE_0089=wrapper.selftest() +OVERLAY_CONTEXT_entry504_py_04_LINE_0090=sys.path.insert(0,str(HERE)) +OVERLAY_CONTEXT_entry504_py_04_LINE_0091=lxc_adapter=importlib.import_module('lxc_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0092=qemu_adapter=importlib.import_module('qemu_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0093=scheduler_adapter=importlib.import_module('scheduler_adapter') +OVERLAY_CONTEXT_entry504_py_04_LINE_0094=if _sha(HERE/'lxc_adapter.py')!='3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d': +OVERLAY_CONTEXT_entry504_py_04_LINE_0095=raise RuntimeError('LXC_502_BYTE_IDENTITY') +OVERLAY_CONTEXT_entry504_py_04_LINE_0096=wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE) +OVERLAY_CONTEXT_entry504_py_04_LINE_0097=return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired +OVERLAY_CONTEXT_entry504_py_04_LINE_0098= +OVERLAY_CONTEXT_entry504_py_04_LINE_0099=def _target(wrapper,lid): +OVERLAY_CONTEXT_entry504_py_04_LINE_0100=rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid] +OVERLAY_CONTEXT_entry504_py_04_LINE_0101=if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY') +OVERLAY_CONTEXT_entry504_py_04_LINE_0102=return hits[0] +OVERLAY_CONTEXT_entry504_py_04_LINE_0103= +OVERLAY_CONTEXT_entry504_py_04_LINE_0104=def selftest(): +OVERLAY_CONTEXT_entry504_py_04_LINE_0105=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load() +OVERLAY_CONTEXT_entry504_py_04_LINE_0106=if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0107=raise RuntimeError('PATCH_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0108=if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0109=raise RuntimeError('SCHEDULER_CHOOSE_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0110=if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0111=raise RuntimeError('SCHEDULER_WRITE_BINDING') +OVERLAY_CONTEXT_entry504_py_04_LINE_0112=if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]: +OVERLAY_CONTEXT_entry504_py_04_LINE_0113=raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT') +OVERLAY_CONTEXT_entry504_py_04_LINE_0114=if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets): +OVERLAY_CONTEXT_entry504_py_04_LINE_0115=raise RuntimeError('WRAPPER_PUBLIC_API') +OVERLAY_CONTEXT_entry504_py_04_LINE_0116=print('SELFTEST_OVERLAY504=PASS',flush=True) +OVERLAY_CONTEXT_entry504_py_04_LINE_0117=return 0 +OVERLAY_CONTEXT_entry504_py_04_LINE_0118= +OVERLAY_CONTEXT_entry504_py_04_LINE_0119=def main(argv=None): +OVERLAY_CONTEXT_entry504_py_04_LINE_0120=argv=list(sys.argv[1:] if argv is None else argv) +OVERLAY_CONTEXT_entry504_py_04_LINE_0121=if argv==['selftest']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0122=return selftest() +OVERLAY_CONTEXT_entry504_py_04_LINE_0123=wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load() +OVERLAY_CONTEXT_entry504_py_04_LINE_0124=legacy=wired['legacy'] +OVERLAY_CONTEXT_entry504_py_04_LINE_0125=if argv==['scheduler-proof']: +OVERLAY_CONTEXT_entry504_py_04_LINE_0126=import tempfile +OVERLAY_CONTEXT_entry504_py_04_LINE_0127=legacy=wired['legacy']; g=wired['legacy_globals'] +OVERLAY_CONTEXT_entry504_py_04_LINE_0128=old_root=g.get('STATE_ROOT'); old_epoch=g.get('epoch') +OVERLAY_CONTEXT_entry504_py_04_LINE_0129=if old_root is None or not callable(old_epoch): raise RuntimeError('SCHEDULER_PROOF_BASE') +OVERLAY_CONTEXT_entry504_py_04_LINE_0130=now=[1000] +OVERLAY_CONTEXT_entry504_py_04_LINE_0131=try: +OVERLAY_MATCH_FILE=fresh_lxc_helper.py +OVERLAY_MATCH_SHA256=dbb3e6dbb71b10797df736431d9501a752a0f8c439163c9a0bddb7f76747f011 +OVERLAY_MATCH_LINE_COUNT=1 +OVERLAY_MATCH_LINES=4 +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_RANGE=1-12 +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0002=import base64, hashlib, json, pathlib, sys +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0003= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0004=BASE_RELEASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1') +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0005=C411=BASE_RELEASE/'candidate411' +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0006=PVE265_SHA='cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be' +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0007= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0008=def sha(p:pathlib.Path)->str: +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0009=return hashlib.sha256(p.read_bytes()).hexdigest() +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0010= +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0011=def fail(code:str): +OVERLAY_CONTEXT_fresh_lxc_helper_py_01_LINE_0012=raise RuntimeError(code) +OVERLAY_MATCH_FILE=lxc_adapter.py +OVERLAY_MATCH_SHA256=3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d +OVERLAY_MATCH_LINE_COUNT=19 +OVERLAY_MATCH_LINES=2,7,36,44,45,52,55,57,59,68,95,112,130,133,158,162,199,200,213 +OVERLAY_CONTEXT_lxc_adapter_py_01_RANGE=1-15 +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0001=from __future__ import annotations +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0002=import base64, hashlib, json, os, pathlib, re, selectors, shlex, signal, stat, subprocess, sys, time +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0003= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0004=PVESH_SHA='9ed13d4c2d82e7864ff0192c428da7669af263f81dfcc84d5a981ca98fee8439' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0005=VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0006=HELPER=pathlib.Path(__file__).resolve().parent/'fresh_lxc_helper.py' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0007=EXEC_HELPER=pathlib.Path(__file__).resolve().parent/'producer_exec_helper.py' +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0008=MAX_STDERR=262144 +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0009=ENV={'PATH':'/usr/sbin:/usr/bin:/sbin:/bin','LC_ALL':'C','LANG':'C','HOME':'/root','PYTHONDONTWRITEBYTECODE':'1'} +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0010= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0011=class AdapterError(RuntimeError): pass +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0012=class ExecFailure(AdapterError): +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0013=def __init__(self,code,summary): super().__init__(code); self.code=code; self.summary=summary +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0014= +OVERLAY_CONTEXT_lxc_adapter_py_01_LINE_0015=def _need(ok:bool,code:str): +OVERLAY_CONTEXT_lxc_adapter_py_02_RANGE=32-76 +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0032=if n<=0: raise AdapterError('WRITE_FAILED') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0033=view=view[n:] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0034= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0035=def _remote_sha(legacy,node,path): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0036=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0037=parts=p.stdout.decode('ascii','strict').strip().split() +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0038=_need(len(parts)>=2 and parts[1]==path,'TOOL_SHA_OUTPUT') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0039=return parts[0] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0040= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0041=def _live_inputs(legacy,node,vmid,scratch): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0042=_need(_remote_sha(legacy,node,'/usr/bin/pvesh')==PVESH_SHA,'PVESH_IDENTITY') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0043=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0044=rows=_j(legacy.ssh_remote(node,['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60),'RESOURCES_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0045=stores=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/storage','--output-format','json'],timeout=60),'STORAGE_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0046=_need(type(rows) is list and type(stores) is list,'PVE_LIST_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0047=configs=[] +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0048=for r in rows: +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0049=if not isinstance(r,dict) or r.get('node')!=node or r.get('type') not in ('lxc','qemu'): continue +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0050=try: rid=int(r.get('vmid')) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0051=except Exception: raise AdapterError('RESOURCE_VMID') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0052=cfg=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/{r["type"]}/{rid}/config','--output-format','json'],timeout=60),'CONFIG_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0053=_need(type(cfg) is dict,'CONFIG_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0054=configs.append([rid,cfg]) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0055=tasks=_j(legacy.ssh_remote(node,['pvesh','get',f'/nodes/{node}/tasks','--limit','999','--output-format','json'],timeout=60),'TASKS_JSON') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0056=_need(type(tasks) is list and len(tasks)<1000,'TASKS_SCHEMA') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0057=q=legacy.ssh_remote(node,['test','-f','/etc/vzdump.conf'],timeout=30,check=False) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0058=defaults=None +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0059=if q.returncode==0: defaults=legacy.ssh_remote(node,['cat','--','/etc/vzdump.conf'],timeout=30).stdout +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0060=elif q.returncode!=1: raise AdapterError('DEFAULTS_PROBE') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0061=st=os.statvfs('/mnt/staging'); free=int(st.f_bavail*st.f_frsize) +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0062=return {'node':node,'vmid':vmid,'scratch':scratch,'now':int(time.time()),'rows':rows,'storage_rows':stores,'configs':configs, +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0063='defaults_b64':None if defaults is None else base64.b64encode(defaults).decode('ascii'),'staging_free':free,'tasks':tasks} +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0064= +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0065=def _helper(inp): +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0066=data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode('utf-8') +OVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0067=_need(0262144: +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0097=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)}) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0098=try: out=json.loads(p.stdout) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0099=except Exception: +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0100=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)}) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0101=summary={'executor':'local-proven-pve270','helper_rc':p.returncode,'exception_class':out.get('exception_class'),'exception_message_sha256':out.get('exception_message_sha256')} +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0102=if isinstance(out.get('process'),dict): summary.update(out['process']) +OVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0103=if p.returncode!=0 or out.get('status')!='OK': raise ExecFailure('LOCAL_PRODUCER_FAILED',summary) +OVERLAY_CONTEXT_lxc_adapter_py_04_RANGE=108-120 +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0108=def _kill(p): +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0109=try: os.killpg(p.pid,signal.SIGTERM) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0110=except ProcessLookupError: pass +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0111=try: p.wait(timeout=10) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0112=except subprocess.TimeoutExpired: +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0113=try: os.killpg(p.pid,signal.SIGKILL) +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0114=except ProcessLookupError: pass +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0115=p.wait() +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0116= +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0117=def _execute_remote(legacy,node,argv,dest,cap,timeout): +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0118=_need(re.fullmatch(r'pve0[123]',str(node)) is not None and node!='pve01','REMOTE_NODE') +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0119=_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') +OVERLAY_CONTEXT_lxc_adapter_py_04_LINE_0120=_need('--node' in argv and argv[argv.index('--node')+1]==node,'REMOTE_ARGV_NODE') +OVERLAY_CONTEXT_lxc_adapter_py_05_RANGE=126-141 +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0126=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) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0127=initial=os.fstat(fd) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0128=digest=hashlib.sha256(); eh=hashlib.sha256(); total=err_total=err_kept=0; p=None; sel=None; good=False +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0129=remote='cd / && exec '+shlex.join(argv) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0130=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote] +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0131=deadline=time.monotonic()+timeout +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0132=try: +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0133=p=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0134=sel=selectors.DefaultSelector() +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0135=for pipe in (p.stdout,p.stderr): os.set_blocking(pipe.fileno(),False); sel.register(pipe,selectors.EVENT_READ) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0136=while sel.get_map(): +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0137=now=time.monotonic() +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0138=if now>=deadline: raise ExecFailure('REMOTE_TIMEOUT',{}) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0139=for key,_ in sel.select(min(.2,max(0,deadline-now))): +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0140=b=os.read(key.fileobj.fileno(),65536) +OVERLAY_CONTEXT_lxc_adapter_py_05_LINE_0141=if not b: sel.unregister(key.fileobj); continue +OVERLAY_CONTEXT_lxc_adapter_py_06_RANGE=154-170 +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0154=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: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0155=raise ExecFailure('REMOTE_FILE_IDENTITY',{}) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0156=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'VZDUMP_IDENTITY_EXEC_POST') +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0157=os.fchmod(fd,0o400); os.fsync(fd); os.fsync(efd); good=True +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0158=return {'executor':'remote-bounded-ssh-cwd-root','producer_rc':rc,'size':total,'sha256':digest.hexdigest(), +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0159='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()} +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0160=except ExecFailure as e: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0161=if p is not None and p.poll() is None: _kill(p) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0162=summary={'executor':'remote-bounded-ssh-cwd-root','producer_rc':None if p is None else p.returncode,'archive_bytes':total, +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0163='stderr_bytes_observed':err_total,'stderr_bytes_retained':err_kept,'stderr_truncated':err_total>err_kept,'stderr_stream_sha256':eh.hexdigest()} +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0164=summary.update(e.summary); raise ExecFailure(e.code,summary) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0165=finally: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0166=if p is not None: +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0167=if p.poll() is None: _kill(p) +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0168=if p.stdout: p.stdout.close() +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0169=if p.stderr: p.stderr.close() +OVERLAY_CONTEXT_lxc_adapter_py_06_LINE_0170=if sel is not None: sel.close() +OVERLAY_CONTEXT_lxc_adapter_py_07_RANGE=195-218 +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0195=row=rows[0]; node=row.get('node'); typ=row.get('type') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0196=_need(typ==t.get('guest_type')=='lxc','PVE_GUEST_TYPE_DRIFT') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0197=legacy._default_unprivileged_lxc(node,vmid) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0198=scratch=f'/var/tmp/homelab-vzdump-v2-{gen}' +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0199=legacy.ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0200=q=legacy.ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0201=_need(q.stdout.decode().strip()=='710:0:100000','PVE_MAPPED_SCRATCH_ACCESS_CONTRACT') +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0202=try: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0203=legacy.mapped_scratch_probe(node,scratch) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0204=p=plan_only(legacy,t,scratch); local=pathlib.Path(work)/'payload.bin'; cap=int(p['job']['archive_cap_bytes']) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0205=try: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0206=result=_execute_local(legacy,node,p['argv'],local,cap,7200) if node=='pve01' else _execute_remote(legacy,node,p['argv'],local,cap,7200) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0207=except ExecFailure as e: +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0208=_emit_diag(node,e.summary|{'failure_code':e.code}) +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0209=raise legacy.BackupError('LXC_PRODUCER_FAILED') from None +OVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0210=_need(local.is_file() and 0str: +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0010=h=hashlib.sha256() +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0011=with open(p,'rb',buffering=0) as f: +OVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0012=for b in iter(lambda:f.read(1<<20),b''): h.update(b) +OVERLAY_CONTEXT_producer_exec_helper_py_02_RANGE=27-39 +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0027=if sha_file(VZDUMP)!=VZDUMP_SHA: fail('VZDUMP_IDENTITY') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0028=sys.path.insert(0,str(BASE)) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0029=import adapter +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0030=adapter.verify_sources(); adapter.load_graph() +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0031=print('PRODUCER_EXEC_HELPER_SELFTEST=PASS',flush=True) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0032=return 0 +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0033= +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0034=def main()->int: +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0035=if sys.argv[1:]==['selftest']: return selftest() +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0036=if sys.argv[1:]: fail('ARGC') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0037=raw=sys.stdin.buffer.read(MAX_INPUT+1) +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0038=if not raw or len(raw)>MAX_INPUT: fail('INPUT_BOUND') +OVERLAY_CONTEXT_producer_exec_helper_py_02_LINE_0039=try: x=json.loads(raw) +OVERLAY_MATCH_FILE=qemu_adapter.py +OVERLAY_MATCH_SHA256=1906db42bd34bbe85eb46fd9797b3572d46e0a41c29d1c29be5f9df5e448f15b +OVERLAY_MATCH_LINE_COUNT=7 +OVERLAY_MATCH_LINES=12,49,51,56,62,69,73 +OVERLAY_CONTEXT_qemu_adapter_py_01_RANGE=8-20 +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0008=def _need(ok,code): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0009=if not ok: raise QemuAdapterError(code) +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0010= +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0011=def _remote_sha(legacy,node,path): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0012=p=legacy.ssh_remote(node,['sha256sum','--',path],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0013=parts=p.stdout.decode('ascii','strict').strip().split() +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0014=_need(len(parts)>=2 and parts[1]==path,'QEMU_TOOL_SHA_OUTPUT') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0015=return parts[0] +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0016= +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0017=def _select_qemu_outputs(vmid,files): +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0018=_need(type(vmid) is int and vmid>0,'QEMU_VMID') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0019=_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') +OVERLAY_CONTEXT_qemu_adapter_py_01_LINE_0020=_need(len(files)==len(set(files)),'QEMU_OUTPUT_DUPLICATE') +OVERLAY_CONTEXT_qemu_adapter_py_02_RANGE=45-79 +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0045=row=rows[0]; node=row.get('node'); typ=row.get('type') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0046=_need(typ==t.get('guest_type')=='qemu','PVE_GUEST_TYPE_DRIFT') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0047=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_PRE') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0048=srcdir=f'/var/tmp/homelab-vzdump-v2-{gen}' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0049=legacy.ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0050=try: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0051=vp=legacy.ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200,check=False) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0052=if vp.returncode!=0: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0053=_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) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0054=raise legacy.BackupError('QEMU_VZDUMP_FAILED') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0055=_need(_remote_sha(legacy,node,'/usr/bin/vzdump')==VZDUMP_SHA,'QEMU_VZDUMP_IDENTITY_POST') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0056=p=legacy.ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\n'],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0057=files=[x for x in p.stdout.decode('utf-8','strict').splitlines() if x] +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0058=try: src,log=_select_qemu_outputs(vmid,files) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0059=except QemuAdapterError as e: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0060=_emit_diag(vmid=vmid,node=node,producer_rc=0,regular_file_count=len(files),archive_selected=False,selector_error=str(e)) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0061=raise legacy.BackupError(str(e)) from None +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0062=q=legacy.ssh_remote(node,['stat','-c','%s','--',src],timeout=30) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0063=raw=q.stdout.decode('ascii','strict').strip() +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0064=_need(raw.isdigit() and int(raw)>0,'QEMU_ARCHIVE_STAT') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0065=size=int(raw) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0066=local=pathlib.Path(work)/'payload.bin' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0067=if node=='pve01': local=pathlib.Path(src) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0068=else: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0069=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0070=_need(pathlib.Path(local).is_file() and pathlib.Path(local).stat().st_size==size,'QEMU_PAYLOAD_MISSING') +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0071=_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) +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0072=except Exception: +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0073=legacy.ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False); raise +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0074=cleanup={'kind':'pve_source_dir','node':node,'path':srcdir} +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0075=meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'qemu','node':node,'status':row.get('status'), +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0076='producer_contract':'strict-qemu-vma-zst-plus-matching-log-overlay503'} +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0077=return pathlib.Path(local),meta,cleanup +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0078=capture_pve_guest.__name__='capture_pve_guest' +OVERLAY_CONTEXT_qemu_adapter_py_02_LINE_0079=return capture_pve_guest +OVERLAY_AST_FILE=entry504.py +OVERLAY_AST_FUNCTION_COUNT=2 +OVERLAY_AST_FUNCTION_01_LINE=99 +OVERLAY_AST_FUNCTION_01_NAME=_target +OVERLAY_AST_FUNCTION_02_LINE=119 +OVERLAY_AST_FUNCTION_02_NAME=main +OVERLAY_AST_IMPORT_COUNT=10 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=importlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=os +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=pathlib +OVERLAY_AST_IMPORT_07_LINE=2 +OVERLAY_AST_IMPORT_07_NAME=stat +OVERLAY_AST_IMPORT_08_LINE=2 +OVERLAY_AST_IMPORT_08_NAME=sys +OVERLAY_AST_IMPORT_09_LINE=2 +OVERLAY_AST_IMPORT_09_NAME=types +OVERLAY_AST_IMPORT_10_LINE=126 +OVERLAY_AST_IMPORT_10_NAME=tempfile +OVERLAY_AST_CALL_COUNT=4 +OVERLAY_AST_CALL_01_LINE=87 +OVERLAY_AST_CALL_01_KIND=import_module +OVERLAY_AST_CALL_01_TEXT=importlib.import_module('wrapper') +OVERLAY_AST_CALL_02_LINE=91 +OVERLAY_AST_CALL_02_KIND=import_module +OVERLAY_AST_CALL_02_TEXT=importlib.import_module('lxc_adapter') +OVERLAY_AST_CALL_03_LINE=92 +OVERLAY_AST_CALL_03_KIND=import_module +OVERLAY_AST_CALL_03_TEXT=importlib.import_module('qemu_adapter') +OVERLAY_AST_CALL_04_LINE=93 +OVERLAY_AST_CALL_04_KIND=import_module +OVERLAY_AST_CALL_04_TEXT=importlib.import_module('scheduler_adapter') +OVERLAY_AST_FILE=fresh_lxc_helper.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=14 +OVERLAY_AST_FUNCTION_01_NAME=main +OVERLAY_AST_IMPORT_COUNT=7 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=base64 +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=hashlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=pathlib +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=sys +OVERLAY_AST_IMPORT_07_LINE=19 +OVERLAY_AST_IMPORT_07_NAME=adapter +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_AST_FILE=lxc_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=191 +OVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest +OVERLAY_AST_IMPORT_COUNT=14 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=base64 +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=hashlib +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=json +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=os +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=pathlib +OVERLAY_AST_IMPORT_07_LINE=2 +OVERLAY_AST_IMPORT_07_NAME=re +OVERLAY_AST_IMPORT_08_LINE=2 +OVERLAY_AST_IMPORT_08_NAME=selectors +OVERLAY_AST_IMPORT_09_LINE=2 +OVERLAY_AST_IMPORT_09_NAME=shlex +OVERLAY_AST_IMPORT_10_LINE=2 +OVERLAY_AST_IMPORT_10_NAME=signal +OVERLAY_AST_IMPORT_11_LINE=2 +OVERLAY_AST_IMPORT_11_NAME=stat +OVERLAY_AST_IMPORT_12_LINE=2 +OVERLAY_AST_IMPORT_12_NAME=subprocess +OVERLAY_AST_IMPORT_13_LINE=2 +OVERLAY_AST_IMPORT_13_NAME=sys +OVERLAY_AST_IMPORT_14_LINE=2 +OVERLAY_AST_IMPORT_14_NAME=time +OVERLAY_AST_CALL_COUNT=3 +OVERLAY_AST_CALL_01_LINE=68 +OVERLAY_AST_CALL_01_KIND=run +OVERLAY_AST_CALL_01_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV) +OVERLAY_AST_CALL_02_LINE=95 +OVERLAY_AST_CALL_02_KIND=run +OVERLAY_AST_CALL_02_TEXT=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV) +OVERLAY_AST_CALL_03_LINE=133 +OVERLAY_AST_CALL_03_KIND=Popen +OVERLAY_AST_CALL_03_TEXT=subprocess.Popen(ssh,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/',env=ENV,start_new_session=True,close_fds=True) +OVERLAY_AST_FILE=producer_exec_helper.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=34 +OVERLAY_AST_FUNCTION_01_NAME=main +OVERLAY_AST_IMPORT_COUNT=8 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=json +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=os +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=pathlib +OVERLAY_AST_IMPORT_06_LINE=2 +OVERLAY_AST_IMPORT_06_NAME=sys +OVERLAY_AST_IMPORT_07_LINE=29 +OVERLAY_AST_IMPORT_07_NAME=adapter +OVERLAY_AST_IMPORT_08_LINE=50 +OVERLAY_AST_IMPORT_08_NAME=adapter +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_AST_FILE=qemu_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=41 +OVERLAY_AST_FUNCTION_01_NAME=capture_pve_guest +OVERLAY_AST_IMPORT_COUNT=5 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=hashlib +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=json +OVERLAY_AST_IMPORT_04_LINE=2 +OVERLAY_AST_IMPORT_04_NAME=pathlib +OVERLAY_AST_IMPORT_05_LINE=2 +OVERLAY_AST_IMPORT_05_NAME=re +OVERLAY_AST_CALL_COUNT=1 +OVERLAY_AST_CALL_01_LINE=69 +OVERLAY_AST_CALL_01_KIND=run +OVERLAY_AST_CALL_01_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +OVERLAY_AST_FILE=scheduler_adapter.py +OVERLAY_AST_FUNCTION_COUNT=1 +OVERLAY_AST_FUNCTION_01_LINE=55 +OVERLAY_AST_FUNCTION_01_NAME=choose_due_target +OVERLAY_AST_IMPORT_COUNT=3 +OVERLAY_AST_IMPORT_01_LINE=1 +OVERLAY_AST_IMPORT_01_NAME=__future__.annotations +OVERLAY_AST_IMPORT_02_LINE=2 +OVERLAY_AST_IMPORT_02_NAME=json +OVERLAY_AST_IMPORT_03_LINE=2 +OVERLAY_AST_IMPORT_03_NAME=pathlib +OVERLAY_AST_CALL_COUNT=0 +OVERLAY_REFERENCED_PATH_COUNT=2 +OVERLAY_REF_01_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1 +OVERLAY_REF_01_EXISTS=True +OVERLAY_REF_01_IS_FILE=False +OVERLAY_REF_02_PATH=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411 +OVERLAY_REF_02_EXISTS=True +OVERLAY_REF_02_IS_FILE=False +OVERLAY_TRANSPORT_SIGNATURE_COUNT=2 +OVERLAY_TRANSPORT_SIG_01_FILE=lxc_adapter.py +OVERLAY_TRANSPORT_SIG_01_LINE=130 +OVERLAY_TRANSPORT_SIG_01_TEXT=ssh=['/usr/bin/ssh','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ConnectTimeout=15',f'root@{node}',remote] +OVERLAY_TRANSPORT_SIG_02_FILE=qemu_adapter.py +OVERLAY_TRANSPORT_SIG_02_LINE=69 +OVERLAY_TRANSPORT_SIG_02_TEXT=legacy.run([legacy.SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200) +VPS557R3_DECISION=OVERLAY504_DELEGATES_TO_BASE_ENGINE +VPS557R3_NEXT_GATE=READ_OVERLAY504_BASE_ENGINE_BINDING +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-INFRA-PVE1-MOLDOVA-OVERLAY504-TRANSPORT-READONLY-557R3","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} OUTPUT_END CHAT_OUTPUT_END