39 lines
43 KiB
JSON
39 lines
43 KiB
JSON
{
|
|
"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(0<len(data)<=4_000_000,'FRESH_HELPER_INPUT_BOUND')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0068=p=subprocess.run(['/usr/bin/python3','-I','-B',str(HELPER)],input=data,capture_output=True,timeout=120,cwd='/',env=ENV)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0069=_need(p.returncode==0 and not p.stderr and 0<len(p.stdout)<=262144,'FRESH_HELPER_FAILED')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0070=try: out=json.loads(p.stdout)\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0071=except Exception as e: raise AdapterError('FRESH_HELPER_JSON') from e\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0072=_need(type(out) is dict and out.get('schema')==1 and type(out.get('argv')) is list and type(out.get('job')) is dict,'FRESH_HELPER_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0073=return out\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0074=\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0075=def _stable_job(job):\nOVERLAY_CONTEXT_lxc_adapter_py_02_LINE_0076=_need(type(job) is dict,'JOB_SCHEMA')\nOVERLAY_CONTEXT_lxc_adapter_py_03_RANGE=91-103\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0091=def _execute_local(legacy,node,argv,dest,cap,timeout):\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0092=_need(node=='pve01','LOCAL_NODE')\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0093=inp={'argv':argv,'dest':str(dest),'cap':int(cap),'seconds':int(timeout)}\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0094=data=json.dumps(inp,separators=(',',':'),sort_keys=True).encode()\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0095=p=subprocess.run(['/usr/bin/python3','-I','-B',str(EXEC_HELPER)],input=data,capture_output=True,timeout=timeout+120,cwd='/',env=ENV)\nOVERLAY_CONTEXT_lxc_adapter_py_03_LINE_0096=if p.stderr or not p.stdout or len(p.stdout)>262144:\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 0<local.stat().st_size<=cap,'VZDUMP_PAYLOAD_BOUND')\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0211=_emit_diag(node,result)\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0212=except Exception:\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0213=legacy.ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False); raise\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0214=cleanup={'kind':'pve_source_dir','node':node,'path':scratch}\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0215=meta={'generation':gen,'source_class':'pve_guest','vmid':vmid,'guest_type':'lxc','node':node,'status':row.get('status'),\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0216='producer_contract':'fresh-pve265-plan-bounded-producer-overlay502'}\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0217=return local,meta,cleanup\nOVERLAY_CONTEXT_lxc_adapter_py_07_LINE_0218=capture_pve_guest.__name__='capture_pve_guest'; return capture_pve_guest\nOVERLAY_MATCH_FILE=producer_exec_helper.py\nOVERLAY_MATCH_SHA256=b3b97099bcd7126670f866e81faae6a42a96d869d9989e6a67f6ea6c871c90b3\nOVERLAY_MATCH_LINE_COUNT=2\nOVERLAY_MATCH_LINES=4,31\nOVERLAY_CONTEXT_producer_exec_helper_py_01_RANGE=1-12\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0001=from __future__ import annotations\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0002=import hashlib, json, os, pathlib, sys\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0003=\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0004=BASE=pathlib.Path('/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411')\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0005=VZDUMP=pathlib.Path('/usr/bin/vzdump')\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0006=VZDUMP_SHA='21339d009afd55cb7ec613b64c1f493b2a7dbd18b85b4d712909ef6d6710f4ea'\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0007=MAX_INPUT=262144\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0008=\nOVERLAY_CONTEXT_producer_exec_helper_py_01_LINE_0009=def sha_file(p:pathlib.Path)->str:\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"
|
|
}
|