1
0
Files
homelab-public-context/runtime/latest.txt
T
2026-09-23 22:17:38 +00:00

640 lines
60 KiB
Plaintext

CHAT_OUTPUT_BEGIN
COMMAND_ID=SUPPORT-260924-HOMELAB-MOLDOVA-BASE-RELEASE-AUTH-1147R1
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=homelab-moldova-base-release-auth
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=f3fe1cb2e034d22c5917b5946f86b1c8ea517c0abd0a92891868a481e2aa5da7
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=add93d5fb111ea9426df8d172911f8506ad95531ae42be7e0c338901a61b8608
SANITIZED_OUTPUT_SHA256=e60b4493bf44bffbb9ab84838090dbefdb74cfb16219ea4cc0d3a9e834e59ae4
OUTPUT_BEGIN
WORKERS2_MOLDOVA_BASE_RELEASE_AUTH_BEGIN=1
COMMAND_ID=SUPPORT-260924-HOMELAB-MOLDOVA-BASE-RELEASE-AUTH-1147R1
MODE=read-only
COMPONENT=homelab-moldova-base-release-auth
MUTATION_BOUNDARY=NONE;ENTRY504_PROVENANCE_AND_LITERAL_BASE_RELEASE_STATIC_INSPECTION_ONLY;NO_MOLDOVA_CONNECTION;NO_REMOTE_SSH;NO_PROVIDER_CALL;NO_SYSTEMD_ACTION;NO_BACKUP_RUN;NO_BACKUP_MUTATION;NO_TARGET_POLICY_MUTATION;NO_NETBIRD_MUTATION;NO_MONITORING_MUTATION;NO_GIT_WRITE;NO_SECRET_VALUE_READOUT
PREDECESSOR_1146=PASS_MOLDOVA_1146_RELEASE_AUTH_EXACT_COLLECTED
PREDECESSOR_1146_CLASS=VPS_MD_HANDLER_NOT_LOCATED
CARRIER_BASELINE=KNOWN_GOOD_1137_BYTE_SEMANTICS
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
RUNNER_SHA256=b248a4c32c9cc64e5747e7dce6c7fc0a23f5124a77c71ce72e27a81aceae9d2d
TARGETS_SHA256=5cba5f1e14c65211c9fab6d11594c19279ab68369b4db3f7283708c368348288
ENTRY504_SHA256=ca6876fa9c3b1465b045344a8ad46962de16972c7dadc4ac6257c7d225047793
MD_RELAY_COUNT=1
MD_RELAY_ENABLED=false
ENTRY504_PROVENANCE_BLOCK_BEGIN=1
ENTRY504|line=20|text= while True:
ENTRY504|line=21|text= b=f.read(1<<20)
ENTRY504|line=22|text= if not b: break
ENTRY504|line=23|text= h.update(b)
ENTRY504|line=24|text= return h.hexdigest()
ENTRY504|line=25|text=
ENTRY504|line=26|text=def _verify_base():
ENTRY504|line=27|text= s=os.lstat(BASE)
ENTRY504|line=28|text= if not stat.S_ISDIR(s.st_mode) or stat.S_ISLNK(s.st_mode) or s.st_uid!=0 or s.st_gid!=0:
ENTRY504|line=29|text= raise RuntimeError('BASE_RELEASE_ROOT')
ENTRY504|line=30|text= for rel,want in BASE_EXPECTED.items():
ENTRY504|line=31|text= p=BASE/rel; st=os.lstat(p)
ENTRY504|line=32|text= if not stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode) or st.st_uid!=0 or st.st_gid!=0 or _sha(p)!=want:
ENTRY504|line=33|text= raise RuntimeError('BASE_RELEASE_FILE_'+rel)
ENTRY504|line=34|text=
ENTRY504|line=35|text=class _GlobalsProxy:
ENTRY504|line=36|text= __slots__=('_g',)
ENTRY504|line=37|text= def __init__(self,g): object.__setattr__(self,'_g',g)
ENTRY504|line=38|text= def __getattr__(self,n):
ENTRY504|line=39|text= try: return self._g[n]
ENTRY504|line=40|text= except KeyError as e: raise AttributeError(n) from e
ENTRY504|line=41|text= def __setattr__(self,n,v): self._g[n]=v
ENTRY504|line=42|text=
ENTRY504|line=43|text=def _wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,base=BASE):
ENTRY504|line=44|text= legacy_path=(pathlib.Path(base)/'legacy_engine.py').resolve()
ENTRY504|line=45|text= found={}
ENTRY504|line=46|text= for value in vars(wrapper).values():
ENTRY504|line=47|text= if isinstance(value,types.ModuleType):
ENTRY504|line=48|text= g=vars(value); raw=g.get('__file__')
ENTRY504|line=49|text= elif isinstance(value,types.FunctionType):
ENTRY504|line=50|text= g=value.__globals__; raw=g.get('__file__')
ENTRY504|line=51|text= else:
ENTRY504|line=52|text= continue
ENTRY504|line=53|text= if not isinstance(raw,str):
ENTRY504|line=54|text= continue
ENTRY504|line=55|text= try: gp=pathlib.Path(raw).resolve()
ENTRY504|line=56|text= except Exception: continue
ENTRY504|line=57|text= if gp==legacy_path:
ENTRY504|line=58|text= found[id(g)]=g
ENTRY504|line=59|text= if len(found)!=1:
ENTRY504|line=60|text= raise RuntimeError('LEGACY_PROVENANCE_CARDINALITY')
ENTRY504|line=61|text= g=next(iter(found.values()))
ENTRY504|line=62|text= required=('capture_pve_guest','backup_target','load_targets','cluster_inventory','ssh_remote',
ENTRY504|line=63|text= '_default_unprivileged_lxc','mapped_scratch_probe','_stream_argv_to_local','run',
ENTRY504|line=64|text= 'choose_due_target','write_state','epoch')
ENTRY504|line=65|text= if any(not callable(g.get(n)) for n in required):
ENTRY504|line=66|text= raise RuntimeError('LEGACY_PROVENANCE_API')
ENTRY504|line=67|text= original=g['capture_pve_guest']
ENTRY504|line=68|text= proxy=_GlobalsProxy(g)
ENTRY504|line=69|text= if not isinstance(g.get('SCP'),str) or not g['SCP'].startswith('/'):
ENTRY504|line=70|text= raise RuntimeError('LEGACY_SCP_API')
ENTRY504|line=71|text= qemu_patched=qemu_adapter.bind(proxy,original)
ENTRY504|line=72|text= if not callable(qemu_patched):
ENTRY504|line=73|text= raise RuntimeError('QEMU_ADAPTER_BIND_RESULT')
ENTRY504|line=74|text= patched=lxc_adapter.bind(proxy,qemu_patched)
ENTRY504|line=75|text= if not callable(patched):
ENTRY504|line=76|text= raise RuntimeError('LXC_ADAPTER_BIND_RESULT')
ENTRY504|line=77|text= g['capture_pve_guest']=patched
ENTRY504|line=78|text= scheduler_wired=scheduler_adapter.bind(proxy,g['choose_due_target'],g['write_state'])
ENTRY504|line=79|text= if g.get('choose_due_target') is not scheduler_wired['choose_due_target'] or g.get('write_state') is not scheduler_wired['write_state']:
ENTRY504|line=80|text= raise RuntimeError('SCHEDULER_ADAPTER_BIND_RESULT')
ENTRY504|line=81|text= return {'legacy_globals':g,'legacy':proxy,'original_capture':original,'qemu_patched_capture':qemu_patched,'patched_capture':patched,'scheduler_wired':scheduler_wired}
ENTRY504|line=82|text=
ENTRY504|line=83|text=def _load():
ENTRY504|line=84|text= _verify_base()
ENTRY504|line=85|text= sys.dont_write_bytecode=True
ENTRY504|line=86|text= sys.path.insert(0,str(BASE))
ENTRY504|line=87|text= wrapper=importlib.import_module('wrapper')
ENTRY504|line=88|text= # Baseline accepted wrapper selftest stays the compatibility gate; no full old legacy selftest is reintroduced.
ENTRY504|line=89|text= wrapper.selftest()
ENTRY504|line=90|text= sys.path.insert(0,str(HERE))
ENTRY504|line=91|text= lxc_adapter=importlib.import_module('lxc_adapter')
ENTRY504|line=92|text= qemu_adapter=importlib.import_module('qemu_adapter')
ENTRY504|line=93|text= scheduler_adapter=importlib.import_module('scheduler_adapter')
ENTRY504|line=94|text= if _sha(HERE/'lxc_adapter.py')!='3fa7d194010d76f7c8bc95035ae8876262e9337903e310f45f45df88c266dc8d':
ENTRY504|line=95|text= raise RuntimeError('LXC_502_BYTE_IDENTITY')
ENTRY504|line=96|text= wired=_wire(wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,BASE)
ENTRY504|line=97|text= return wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired
ENTRY504|line=98|text=
ENTRY504|line=99|text=def _target(wrapper,lid):
ENTRY504|line=100|text= rows=wrapper.load_targets(); hits=[x for x in rows if x.get('logical_id')==lid]
ENTRY504|line=101|text= if len(hits)!=1: raise RuntimeError('TARGET_CARDINALITY')
ENTRY504|line=102|text= return hits[0]
ENTRY504|line=103|text=
ENTRY504|line=104|text=def selftest():
ENTRY504|line=105|text= wrapper,lxc_adapter,qemu_adapter,scheduler_adapter,wired=_load()
ENTRY504|line=106|text= if wired['legacy_globals'].get('capture_pve_guest') is not wired['patched_capture']:
ENTRY504|line=107|text= raise RuntimeError('PATCH_BINDING')
ENTRY504|line=108|text= if wired['legacy_globals'].get('choose_due_target') is not wired['scheduler_wired']['choose_due_target']:
ENTRY504|line=109|text= raise RuntimeError('SCHEDULER_CHOOSE_BINDING')
ENTRY504|line=110|text= if wired['legacy_globals'].get('write_state') is not wired['scheduler_wired']['write_state']:
ENTRY504|line=111|text= raise RuntimeError('SCHEDULER_WRITE_BINDING')
ENTRY504|line=112|text= if [scheduler_adapter.backoff_seconds(n) for n in range(1,7)]!=[1800,3600,7200,14400,21600,21600]:
ENTRY504|line=113|text= raise RuntimeError('SCHEDULER_BACKOFF_CONTRACT')
ENTRY504|line=114|text= if not callable(wrapper.backup_target) or not callable(wrapper.main) or not callable(wrapper.load_targets):
ENTRY504|line=115|text= raise RuntimeError('WRAPPER_PUBLIC_API')
ENTRY504|line=116|text= print('SELFTEST_OVERLAY504=PASS',flush=True)
ENTRY504|line=117|text= return 0
ENTRY504|line=118|text=
ENTRY504|line=119|text=def main(argv=None):
ENTRY504|line=120|text= argv=list(sys.argv[1:] if argv is None else argv)
ENTRY504_PROVENANCE_BLOCK_END=1
ENTRY504_RELEASE_LITERAL_COUNT=1
ENTRY504_RELEASE_LITERAL=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1
BASE_CANDIDATE_COUNT=1
BASE_CANDIDATE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1|kind=dir|mode=500|uid=0|gid=0
BASE_PY_FILE_COUNT=21
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/adapter.py|bytes=2989|sha256=18eb29cef165371b48bcb78e1a456e1939e6eff253787218133162cc89ab9fa3|mode=500|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/guest266.py|bytes=7385|sha256=86433bc424d5fa5017c20f7a237c82874b02357a3283660d8a6b0039ef2bc868|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/large264.py|bytes=16514|sha256=5cc4641fc35e4dd554495a36146da7dbbb7f142d1450e04cc5d3c89678b8497a|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/nodeplan263.py|bytes=4603|sha256=db5c16ee24d25aa1694530332d3190ab7cc5d4f8eb69067d025e27ad5c995060|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py|bytes=12888|sha256=cd2f634414a8e38a3789015aeca5a9b47821f77d7d1fa61dcdbdc866172963be|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|bytes=19595|sha256=97015277a4f3f8129c0fd11eb70c06293026366f1f8232a97feeed513a2dbcef|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve282.py|bytes=6195|sha256=73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/restore262.py|bytes=14701|sha256=56d1b961c8d5654d5e2ee2755268db46bd2202bca11e69788febf991cfaa79f1|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/stream263.py|bytes=8831|sha256=a83d03a86b93a855716658652dd073fcb281cd387fc6200fe4bc2a922f39ea16|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_guest266.py|bytes=10752|sha256=460b950924a475ce0a28dc759512e7dbe2323ae2cc42f7ef4c6181710a2a13da|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_perl270.py|bytes=5441|sha256=50fc10865078a7b9b255dc627059824184441a47c4ede52e23f24c1186e3512f|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|bytes=12215|sha256=a67d927cc428935791f9eecc3acf571d089f80761162f4589b7d684fba6b8af7|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve265.py|bytes=11781|sha256=16a9407d01bf73db687ef38684c59205fc2e6a9223cd9cee6ec6e8dde9d38707|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|bytes=12077|sha256=9fccd20b490613fdd5b14b4105cf0d9fd744f204e1ed1d6893e54c9f69bf6fb4|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve282.py|bytes=5785|sha256=1056407aab76e17181b05e043cb42c086058545a8e0027689ab4e03eee6531c4|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/transport261.py|bytes=15364|sha256=b9b92f957bf441cb5d1702f4881897328e6c0338f8c3f6d41d27d9a349b37688|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/v2core.py|bytes=11755|sha256=e285bf9a5678d07dcbb90261f9f93e7826ff524e04cfec780bf5a3c4b0dc29f2|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ct112_handler.py|bytes=10955|sha256=8cac6e627d5e7abe5d3163cdd24911995a1e3f45c776f9373c2aa68784f5ec6c|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|bytes=59719|sha256=b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/representative_driver.py|bytes=4214|sha256=b3050a8f95e6d9826a4f0786cd3ca32012b6ab10486d10e4981b50b8a0affff2|mode=400|uid=0|gid=0
BASE_FILE|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|bytes=5055|sha256=2b5eb4fc0f6f466a0d3e5a007af987092b6c17baa3ff9241a6afc2c2e97df1d5|mode=400|uid=0|gid=0
BASE_AUTH_SNIPPETS_BEGIN=1
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/large264.py|line=12|text=import subprocess
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/large264.py|line=27|text= p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/large264.py|line=41|text= except subprocess.TimeoutExpired:raise t.Stop('STREAM_TIMEOUT') from None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py|line=13|text=import subprocess
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py|line=144|text= except subprocess.TimeoutExpired:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py|line=160|text= p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve265.py|line=176|text= except subprocess.TimeoutExpired:raise PVEError('PRODUCER_TIMEOUT') from None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=6|text=import hashlib,json,os,re,secrets,selectors,signal,stat,subprocess,sys,time
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=110|text= p=subprocess.Popen(['/proc/self/fd/'+str(self.fd),*args],pass_fds=(self.fd,),
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=111|text= stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=124|text= except subprocess.TimeoutExpired:raise old.PVEError('PERL_TIMEOUT') from None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=217|text= p=subprocess.run([sys.executable,'-I','-B','-c',code,*args],stdin=subprocess.DEVNULL,stdout=subprocess.DEVNULL,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=218|text= stderr=subprocess.DEVNULL,env=dict(old.ENV),user=u,group=g,extra_groups=[],close_fds=True,timeout=15)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=247|text= p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/pve270.py|line=266|text= except subprocess.TimeoutExpired:raise old.PVEError('PRODUCER_TIMEOUT') from None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=2|text=import copy,hashlib,json,os,stat,subprocess,sys,tempfile,time,unittest
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=10|text= return subprocess.run([sys.executable,'-I','-B','-c',code,*map(str,args)],user=uid,group=gid,extra_groups=[],stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=10)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=134|text= """Actual subprocess + tar/zstd, synthetic data; never runs vzdump on a guest."""
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=152|text= code='''import os,sys,subprocess,shutil
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=158|text=a=subprocess.run(['/usr/bin/tar','-cf','-','-C',str(p),'./etc/vzdump/pct.conf'],user=100000,group=100000,extra_groups=[],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=161|text=z=subprocess.run(['/usr/bin/zstd','-q','-c'],input=a.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_producer282.py|line=193|text= def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve265.py|line=1|text="""Synthetic PVE fixtures; subprocess tests never execute real PVE tools."""
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=2|text=import copy,hashlib,json,os,stat,subprocess,sys,tempfile,time,unittest
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=10|text= return subprocess.run([sys.executable,'-I','-B','-c',code,*map(str,args)],user=uid,group=gid,extra_groups=[],stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=10)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=134|text= """Actual subprocess + tar/zstd, synthetic data; never runs vzdump on a guest."""
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=152|text= code='''import os,sys,subprocess,shutil
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=157|text=a=subprocess.run(['/usr/bin/tar','-cf','-','-C',str(p),'./etc/vzdump/pct.conf'],user=100000,group=100000,extra_groups=[],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=160|text=z=subprocess.run(['/usr/bin/zstd','-q','-c'],input=a.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve270.py|line=192|text= def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/test_pve282.py|line=2|text=import copy, json, unittest, tempfile, time, subprocess
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/transport261.py|line=15|text=import subprocess
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/transport261.py|line=149|text= p=subprocess.Popen(argv,stdin=subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/candidate411/transport261.py|line=163|text= except subprocess.TimeoutExpired:raise Stop('PROCESS_TIMEOUT') from None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ct112_handler.py|line=3|text=import hashlib,json,os,secrets,shutil,stat,subprocess,sys,time
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ct112_handler.py|line=26|text= p=subprocess.run(argv,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=45,check=False,env=ENV)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/ct112_handler.py|line=166|text= p=subprocess.run([str(ZSTD),'--test','--quiet','--',str(path)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,timeout=3600,check=False,env=ENV)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=2|text=import ast, base64, datetime as dt, hashlib, io, json, os, pathlib, random, re, select, shlex, shutil, stat, subprocess, sys, tarfile, tempfile, time
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=12|text=SSH=shutil.which('ssh') or '/usr/bin/ssh'
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=13|text=SCP=shutil.which('scp') or '/usr/bin/scp'
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=14|text=SSH_KEYSCAN=shutil.which('ssh-keyscan') or '/usr/bin/ssh-keyscan'
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=15|text=SSHPASS=shutil.which('sshpass') or '/usr/bin/sshpass'
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=16|text=OPERATOR_KEY=pathlib.Path('[SENSITIVE_PATH]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=158|text= {'logical_id':'md-relay','scope':'vps','type':'vps_md','host':'[ADDR]','port':22,'user':'ops','hostkey_fingerprint':'SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY','due_seconds':d,'enabled':True,'green1':True},
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=159|text= {'logical_id':'spb-ingress','scope':'vps','type':'vps_spb','host':'[ADDR]','port':22,'user':'edgeadmin','hostkey_fingerprint':'SHA256:Ef+HsZb8lIXoadvYBXuGKIL3H7NyJMmf9EYCoJRoSv8','due_seconds':d,'enabled':True,'green1':True},
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=160|text= {'logical_id':'us-netbird','scope':'vps','type':'vps_us','host':'[ADDR]','port':22,'user':'root','hostkey_fingerprint':'SHA256:805Q9eh/fePUci42dfY58I6q0lFiiPHn0/M+mckypmE','due_seconds':d,'enabled':True,'green1':True},
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=191|text= p=subprocess.run(argv,input=input,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=timeout,env=env)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=192|text= except subprocess.TimeoutExpired: raise BackupError('COMMAND_TIMEOUT')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=199|text= try:p=subprocess.run(argv,input=input,stdout=f,stderr=subprocess.PIPE,timeout=timeout)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=200|text= except subprocess.TimeoutExpired: raise BackupError('STREAM_COMMAND_TIMEOUT')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=206|text= src=subprocess.Popen(argv,stdin=subprocess.PIPE if input is not None else None,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=207|text= z=subprocess.Popen([zstd,'-T0','-3','-q','-o',str(out_path)],stdin=src.stdout,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=213|text= except subprocess.TimeoutExpired:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=216|text= except subprocess.TimeoutExpired:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=236|text=def load_targets():
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=289|text= p=subprocess.Popen(argv,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=311|text= with subprocess.Popen(rclone_base_args()+['cat',remote_path,'--contimeout','20s','--timeout','5m'],stdout=subprocess.PIPE,stderr=subprocess.PIPE) as p:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=365|text= with subprocess.Popen(rclone_base_args()+['cat',base+'/parts/'+part['name'],'--contimeout','20s','--timeout','5m'],stdout=subprocess.PIPE,stderr=subprocess.PIPE) as p:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=379|text= p1=subprocess.Popen([zstd,'-dc',str(path)],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=380|text= p2=subprocess.Popen([tar,'-tf','-'],stdin=p1.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=389|text= if typ in ('pve_node_bundle','vps_md','vps_spb','vps_us','router'):
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=399|text= p1=subprocess.Popen([zstd,'-dc',str(path)],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=400|text= p2=subprocess.Popen([tar,'-xOf','-','db.sql'],stdin=p1.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=405|text=def cluster_inventory():
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=410|text=def ssh_remote(node,argv,input=None,timeout=1800,check=True):
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=413|text= return run([SSH,'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node,cmd],input=input,timeout=timeout,check=check)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=430|text= p=subprocess.run([sys.executable,'-B','-c',_HISTORICAL_HELPER,'import_all'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=env,cwd='/',timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=441|text= p=subprocess.run([sys.executable,'-B','-c',_HISTORICAL_HELPER,'dump_argv',str(GUEST266)],input=canonical_json(req),stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=env,cwd='/',timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=442|text= if p.returncode!=0: raise BackupError('GUEST266_SUBPROCESS_FAILED',f'rc_{p.returncode}_stderr_sha256_{hashlib.sha256(p.stderr).hexdigest()}')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=444|text= except Exception: raise BackupError('GUEST266_SUBPROCESS_JSON')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=476|text= q=ssh_remote(node,['pct','config',str(vmid)],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=484|text= q=ssh_remote(node,pos,timeout=30,check=False)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=492|text= cmd=[SSH,'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node,remote]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=494|text= try:p=subprocess.run(cmd,stdout=f,stderr=subprocess.PIPE,timeout=timeout)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=495|text= except subprocess.TimeoutExpired:
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=514|text= ssh_remote(node,['install','-d','-m','710','-o','0','-g','100000',scratch],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=515|text= q=ssh_remote(node,['stat','-c','%a:%u:%g',scratch],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=524|text= ssh_remote(node,['rm','-rf','--',scratch],timeout=60,check=False);raise
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=529|text= ssh_remote(node,['install','-d','-m','700','-o','0','-g','0',srcdir],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=531|text= ssh_remote(node,['vzdump',str(vmid),'--mode','snapshot','--compress','zstd','--dumpdir',srcdir],timeout=7200)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=532|text= p=ssh_remote(node,['find',srcdir,'-maxdepth','1','-type','f','-printf','%p\n'],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=537|text= else: run([SCP,'-q','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node+':'+src,str(local)],timeout=7200)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=540|text= ssh_remote(node,['rm','-rf','--',srcdir],timeout=60,check=False);raise
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=545|text= p=run(['ssh-keygen','-lf',str(OPERATOR_KEY),'-E','sha256'],timeout=30)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=552|text= p=run([SSH_KEYSCAN,'-T','8','-p',str(port),'-t','ed25519',host],timeout=15)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=557|text= if len(f)<3 or f[1]!='ssh-ed25519': continue
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=568|text= if t['type'] not in ('vps_md','vps_spb','vps_us'): continue
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=569|text= lines.append(scan_hostkey_line(t['host'],t['port'],t['hostkey_fingerprint']))
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=572|text=def vps_ssh_argv(t, *, use_agent=False):
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=573|text= a=[SSH,'-p',str(t['port']),'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','UserKnownHostsFile='+str(VPS_KNOWN_HOSTS),'-o','ConnectTimeout=15']
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=575|text= a += ['-o','IdentitiesOnly=no']
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=577|text= a += ['-i',str(OPERATOR_KEY),'-o','IdentitiesOnly=yes','-o','IdentityAgent=none']
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=583|text= return run(vps_ssh_argv(t,use_agent=use_agent)+[remote],input=input,timeout=timeout,check=check)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=588|text= pub=run(['ssh-keygen','-y','-f',str(OPERATOR_KEY)],timeout=30).stdout.strip()+b'\n'
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=591|text= if t['type'] not in ('vps_md','vps_spb'): continue
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=595|text= if not os.environ.get('SSH_AUTH_SOCK'): raise BackupError('FORWARDED_AGENT_REQUIRED_FOR_BOOTSTRAP')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=596|text= script=b"umask 077; mkdir -p \"$HOME/.ssh\"; chmod 700 \"$HOME/.ssh\"; touch \"$HOME/.ssh/authorized_keys\"; chmod 600 \"$HOME/.ssh/authorized_keys\"; IFS= read -r k; if grep -qF -- \"$k\" \"$HOME/.ssh/authorized_keys\"; then printf 'ALREADY\\n'; else printf '%s\\n' \"$k\" >> \"$HOME/.ssh/authorized_keys\"; printf 'ADDED\\n'; fi"
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=612|text=def capture_vps_md(t,gen,work):
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=617|text= argv=vps_ssh_argv(t,use_agent=False)+[remote]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=621|text= return payload,{'generation':gen,'source_class':'vps_md','consistency':'FILESET_PRE_POST_HASH_STABILITY','hashset_sha256':pre},None
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=627|text= argv=vps_ssh_argv(t,use_agent=False)+[remote]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=664|text= argv=vps_ssh_argv(t,use_agent=False)+[remote]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=732|text= pat=re.compile(r"\bsshpass\b[^\n]*?(?:^|\s)-f\s+(\"[^\"]*\"|'[^']*'|[^\s;]+)")
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=756|text= roots=[pathlib.Path('/etc'),pathlib.Path('[SENSITIVE_PATH]'),pathlib.Path('/var/lib/homelab-backup'),pathlib.Path('/var/lib/homelab-backup-v2')]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=784|text= # sshpass requires password prompting to remain enabled; batch mode must stay off.
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=785|text= # The proven SSHPASS_FILE credential path otherwise cannot be used.
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=786|text= argv=[SSHPASS,'-f',str(pf),SSH,'-p','2222','-o','BatchMode=no','-o','NumberOfPasswordPrompts=1','-o','StrictHostKeyChecking=yes','-o','UserKnownHostsFile='+str(ROUTER_KNOWN_HOSTS),'-o','ConnectTimeout=15','routerbackup@'+target,'show running-config']
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=806|text= p=ssh_remote(node,args,input=input_bytes,timeout=timeout+60)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=818|text= return f'''import hashlib,json,os,pathlib,select,shutil,subprocess,tempfile,time\nroot={root!r}; db={db!r}; strategy={strategy!r}; token=[REDACTED] not root.startswith('/var/www/forums/') or not db.startswith('xf_'): raise SystemExit(20)\ntmp=pathlib.Path('/tmp/homelab-v2-xf-'+token); tmp.mkdir(mode=0o700,exist_ok=False)\ndump=tmp/'db.sql'; out=pathlib.Path('/tmp/homelab-v2-xf-'+token+'.tar.zst')\nlock=None\ntry:\n if strategy=='global_read_lock':\n lock=subprocess.Popen(['mariadb','--user=root','--batch','--skip-column-names','--unbuffered'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.DEVNULL,text=True,bufsize=1)\n lock.stdin.write("FLUSH TABLES WITH READ LOCK; SELECT 'LOCKED';\\n"); lock.stdin.flush()\n rr,_,_=select.select([lock.stdout],[],[],5)\n if not rr or lock.stdout.readline().strip()!='LOCKED': raise RuntimeError('LOCK_ACQUIRE')\n dump_timeout=15\n else: dump_timeout=180\n with open(dump,'wb') as f:\n argv=['mariadb-dump','--user=ro...[TRUNCATED]
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=851|text= if OPERATOR_KEY.exists(): p.append('root/.ssh/id_ed25519_netbird_operator')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=852|text= if pathlib.Path(str(OPERATOR_KEY)+'.pub').exists(): p.append('root/.ssh/id_ed25519_netbird_operator.pub')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=859|text= else: ok=(ssh_remote(node,['test','-e','/'+rel],timeout=20,check=False).returncode==0)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=868|text= pipe_to_zstd([SSH,'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node,remote],payload,timeout=600)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=875|text= if typ=='vps_md': return capture_vps_md(t,gen,work)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=885|text= ssh_remote(cleanup['node'],['rm','-rf','--',cleanup['path']],timeout=60)
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=903|text=def backup_target(t,green_verify=False):
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=991|text= assert {t['logical_id'] for t in default_targets() if t.get('green1')}=={'ct112','node-pve01','md-relay','spb-ingress','us-netbird','router-netcraze','xf-codevipe','xf-zakrutim','control-bootstrap-v2'}
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/representative_driver.py|line=17|text= 'md-relay',
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|line=7|text=LEGACY_IDS=('node-pve01','md-relay','spb-ingress','us-netbird','router-netcraze','xf-codevipe','xf-zakrutim','control-bootstrap-v2')
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|line=37|text=def load_targets():
BASE_SRC|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|line=40|text=def backup_target(t,green_verify=False):
BASE_AUTH_SNIPPET_COUNT=121
BASE_AUTH_SNIPPETS_END=1
BASE_KEY_FUNCTIONS_BEGIN=1
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=load_targets|line=236
def load_targets():
j=json.loads(TARGETS_PATH.read_text())
if j.get('schema')!=1 or not isinstance(j.get('targets'),list): raise BackupError('TARGET_MANIFEST_SCHEMA')
ids=[x.get('logical_id') for x in j['targets']]
if len(ids)!=len(set(ids)): raise BackupError('TARGET_MANIFEST_DUPLICATE')
return j['targets']
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=load_targets
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=cluster_inventory|line=405
def cluster_inventory():
p=run(['pvesh','get','/cluster/resources','--type','vm','--output-format','json'],timeout=60)
try:return json.loads(p.stdout)
except Exception: raise BackupError('PVE_INVENTORY_JSON')
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=cluster_inventory
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=ssh_remote|line=410
def ssh_remote(node,argv,input=None,timeout=1800,check=True):
cmd='PATH=/usr/sbin:/usr/bin:/sbin:/bin; export PATH; exec '+shlex.join([str(x) for x in argv])
if node=='pve01': return run([str(x) for x in argv],input=input,timeout=timeout,check=check)
return run([SSH,'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node,cmd],input=input,timeout=timeout,check=check)
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=ssh_remote
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=backup_target|line=903
def backup_target(t,green_verify=False):
if t['type']=='control': return control_verify(t)
gen=generation_id(t['logical_id']); work=ensure_dir(WORK_ROOT/gen,0o700)
payload=None; cleanup=None; sealed=False
try:
payload,meta,cleanup=capture_target(t,gen,work); meta['generation']=gen
manifest,msha,alloc=upload_and_seal(t,payload,meta); sealed=True
# SEALED-first cleanup invariant: only now remove source/local payload.
try:
if pathlib.Path(payload).exists(): pathlib.Path(payload).unlink()
finally: cleanup_source(cleanup)
if green_verify:
a=work/'verify-a.bin'; b=work/'verify-b.bin'
ha=reconstruct_replica(manifest,manifest['replicas'][0],a); validate_payload(t,a)
hb=reconstruct_replica(manifest,manifest['replicas'][1],b); validate_payload(t,b)
if ha!=hb or ha!=manifest['payload_sha256']: raise BackupError('GREEN_REPLICA_COMPARE')
a.unlink(missing_ok=True); b.unlink(missing_ok=True)
shutil.rmtree(work,ignore_errors=True)
write_state(t['logical_id'],'SUCCESS',generation=gen,payload_sha256=manifest['payload_sha256'],manifest_sha256=msha,replicas=manifest['replicas'],green_verified=bool(green_verify),last_success_epoch=epoch())
return {'logical_id':t['logical_id'],'generation':gen,'result':'SUCCESS','payload_bytes':manifest['payload_bytes'],'replicas':2,'allocator_healthy':alloc['healthy']}
except BackupError as e:
result='PARTIAL_VALID' if sealed else 'FAIL'
write_state(t['logical_id'],result,generation=gen,reason=e.code,sealed=sealed)
raise
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|name=backup_target
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|name=load_targets|line=37
def load_targets():
base=canonical_targets();return base+[_ct_descriptor(base)]
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|name=load_targets
FUNCTION_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|name=backup_target|line=40
def backup_target(t,green_verify=False):
if not isinstance(t,dict) or t.get('logical_id')!=CT_ID:
return _legacy_backup_target(t,green_verify)
try:
r=ct112.run_target(t,state_writer=legacy.write_state)
return {'logical_id':CT_ID,'generation':r['generation'],'result':'SUCCESS','payload_bytes':r['payload_bytes'],
'replicas':2,'manifest_sha256':r['manifest_sha256'],'payload_sha256':r['payload_sha256']}
except BaseException:
try: legacy.write_state(CT_ID,'FAIL',reason='CT112_PIPELINE_FAILED')
except BaseException: pass
raise legacy.BackupError('CT112_PIPELINE_FAILED') from None
FUNCTION_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|name=backup_target
BASE_KEY_FUNCTION_COUNT=6
BASE_KEY_FUNCTIONS_END=1
BASE_VPS_MD_CONTEXT_BEGIN=1
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=158
146:def utcnow(): return dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace('+00:00','Z')
147:def epoch(): return int(time.time())
148:
149:def default_targets():
150: d=86400
151: out=[]
152: # PVE guests. Source node is resolved live every run.
153: for vmid,typ in [(110,'lxc'),(111,'lxc'),(112,'lxc'),(113,'lxc'),(130,'qemu'),(150,'qemu'),(160,'qemu'),(170,'qemu'),(171,'qemu'),(190,'qemu'),(210,'qemu'),(211,'qemu'),(9130,'qemu')]:
154: out.append({'logical_id':('ct' if typ=='lxc' else 'vm')+str(vmid),'scope':'pve','type':'pve_guest','vmid':vmid,'guest_type':typ,'due_seconds':d,'enabled':True,'green1':vmid==112})
155: for node in ('pve01','pve02','pve03'):
156: out.append({'logical_id':'node-'+node,'scope':'node','type':'pve_node_bundle','node':node,'due_seconds':7*d,'enabled':True,'green1':node=='pve01'})
157: out += [
158: {'logical_id':'md-relay','scope':'vps','type':'vps_md','host':'[ADDR]','port':22,'user':'ops','hostkey_fingerprint':'SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY','due_seconds':d,'enabled':True,'green1':True},
159: {'logical_id':'spb-ingress','scope':'vps','type':'vps_spb','host':'[ADDR]','port':22,'user':'edgeadmin','hostkey_fingerprint':'SHA256:Ef+HsZb8lIXoadvYBXuGKIL3H7NyJMmf9EYCoJRoSv8','due_seconds':d,'enabled':True,'green1':True},
160: {'logical_id':'us-netbird','scope':'vps','type':'vps_us','host':'[ADDR]','port':22,'user':'root','hostkey_fingerprint':'SHA256:805Q9eh/fePUci42dfY58I6q0lFiiPHn0/M+mckypmE','due_seconds':d,'enabled':True,'green1':True},
161: {'logical_id':'router-netcraze','scope':'router','type':'router','due_seconds':d,'enabled':True,'green1':True},
162: ]
163: sites=[
164: ('codevipe',160,'pve02','/var/www/forums/codevipe/public','xf_codevipe','single_transaction'),
165: ('dsmods',160,'pve02','/var/www/forums/dsmods/public','xf_dsmods','single_transaction'),
166: ('kingofwolk',160,'pve02','/var/www/forums/kingofwolk/public','xf_kingofwolk','single_transaction'),
167: ('newfi',210,'pve01','/var/www/forums/newfi/public','xf_newfi','single_transaction'),
168: ('gamevipe',160,'pve02','/var/www/forums/gamevipe/public','xf_gamevipe','global_read_lock'),
169: ('hkmods',160,'pve02','/var/www/forums/hkmods/public','xf_hkmods','global_read_lock'),
170: ('zakrutim',160,'pve02','/var/www/forums/zakrutim/public','xf_zakrutim','global_read_lock')]
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=158
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=389
377: zstd=shutil.which('zstd') or '/usr/bin/zstd'; tar=shutil.which('tar') or '/usr/bin/tar'
378: p=run([zstd,'-t','-q',str(path)],timeout=300)
379: p1=subprocess.Popen([zstd,'-dc',str(path)],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
380: p2=subprocess.Popen([tar,'-tf','-'],stdin=p1.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
381: p1.stdout.close(); out,err2=p2.communicate(timeout=300); err1=p1.stderr.read(); r1=p1.wait()
382: if r1!=0 or p2.returncode!=0: raise BackupError('TAR_ZST_LIST_FAILED')
383: names=out.decode('utf-8','replace').splitlines()
384: if not names: raise BackupError('TAR_ZST_EMPTY')
385: if required_member and required_member not in names: raise BackupError('REQUIRED_MEMBER_MISSING')
386:
387:def validate_payload(t,path):
388: typ=t['type']
389: if typ in ('pve_node_bundle','vps_md','vps_spb','vps_us','router'):
390: validate_tar_zst(path)
391: elif typ=='pve_guest':
392: if t['guest_type']=='lxc': validate_tar_zst(path)
393: else:
394: # Green set is intentionally CT-only. Scheduled QEMU backups still get dual remote byte readback.
395: run([shutil.which('zstd') or '/usr/bin/zstd','-t','-q',str(path)],timeout=600)
396: elif typ=='xenforo':
397: validate_tar_zst(path,'db.sql')
398: zstd=shutil.which('zstd') or '/usr/bin/zstd'; tar=shutil.which('tar') or '/usr/bin/tar'
399: p1=subprocess.Popen([zstd,'-dc',str(path)],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
400: p2=subprocess.Popen([tar,'-xOf','-','db.sql'],stdin=p1.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
401: p1.stdout.close(); data,err=p2.communicate(timeout=300); p1.wait()
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=389
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=568
556: f=line.split()
557: if len(f)<3 or f[1]!='ssh-ed25519': continue
558: try: blob=base64.b64decode(f[2])
559: except Exception: continue
560: fp='SHA256:'+base64.b64encode(hashlib.sha256(blob).digest()).decode().rstrip('=')
561: if fp==expected: good.append(line)
562: if len(good)!=1: raise BackupError('HOSTKEY_PIN_MISMATCH')
563: return good[0]
564:
565:def ensure_vps_known_hosts(targets):
566: lines=[]
567: for t in targets:
568: if t['type'] not in ('vps_md','vps_spb','vps_us'): continue
569: lines.append(scan_hostkey_line(t['host'],t['port'],t['hostkey_fingerprint']))
570: atomic_write(VPS_KNOWN_HOSTS,('\n'.join(lines)+'\n').encode(),0o600)
571:
572:def vps_ssh_argv(t, *, use_agent=False):
573: a=[SSH,'-p',str(t['port']),'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','UserKnownHostsFile='+str(VPS_KNOWN_HOSTS),'-o','ConnectTimeout=15']
574: if use_agent:
575: a += ['-o','IdentitiesOnly=no']
576: else:
577: a += ['-i',str(OPERATOR_KEY),'-o','IdentitiesOnly=yes','-o','IdentityAgent=none']
578: a += [t['user']+'@'+t['host']]
579: return a
580:
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=568
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=591
579: return a
580:
581:def vps_run(t, remote_argv, *, input=None, timeout=300, use_agent=False, check=True):
582: remote=shlex.join([str(x) for x in remote_argv])
583: return run(vps_ssh_argv(t,use_agent=use_agent)+[remote],input=input,timeout=timeout,check=check)
584:
585:def bootstrap_vps_keys(targets):
586: operator_key_fingerprint()
587: ensure_vps_known_hosts(targets)
588: pub=run(['ssh-keygen','-y','-f',str(OPERATOR_KEY)],timeout=30).stdout.strip()+b'\n'
589: results={}
590: for t in targets:
591: if t['type'] not in ('vps_md','vps_spb'): continue
592: probe=vps_run(t,['true'],timeout=30,use_agent=False,check=False)
593: if probe.returncode==0:
594: results[t['logical_id']]='ALREADY_OPERATOR_KEY'; continue
595: if not os.environ.get('SSH_AUTH_SOCK'): raise BackupError('FORWARDED_AGENT_REQUIRED_FOR_BOOTSTRAP')
596: script=b"umask 077; mkdir -p \"$HOME/.ssh\"; chmod 700 \"$HOME/.ssh\"; touch \"$HOME/.ssh/authorized_keys\"; chmod 600 \"$HOME/.ssh/authorized_keys\"; IFS= read -r k; if grep -qF -- \"$k\" \"$HOME/.ssh/authorized_keys\"; then printf 'ALREADY\\n'; else printf '%s\\n' \"$k\" >> \"$HOME/.ssh/authorized_keys\"; printf 'ADDED\\n'; fi"
597: p=vps_run(t,['sh','-c',script.decode()],input=pub,timeout=45,use_agent=True)
598: tag=p.stdout.decode().strip()
599: if tag not in ('ADDED','ALREADY'): raise BackupError('VPS_AUTHORIZED_KEY_BOOTSTRAP_RESULT')
600: vps_run(t,['true'],timeout=30,use_agent=False)
601: results[t['logical_id']]=tag
602: # US was already operator-key based; prove it agentless too.
603: us=[x for x in targets if x['type']=='vps_us'][0]
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=591
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=612
600: vps_run(t,['true'],timeout=30,use_agent=False)
601: results[t['logical_id']]=tag
602: # US was already operator-key based; prove it agentless too.
603: us=[x for x in targets if x['type']=='vps_us'][0]
604: vps_run(us,['true'],timeout=30,use_agent=False)
605: results[us['logical_id']]='ALREADY_US_OPERATOR_KEY'
606: return results
607:
608:def remote_hashset(t,command):
609: p=vps_run(t,['sh','-c',command],timeout=120,use_agent=False)
610: return sha256_bytes(p.stdout)
611:
612:def capture_vps_md(t,gen,work):
613: files=['etc/netbird/install.conf','var/lib/netbird/state.json','var/lib/netbird/service.json','var/lib/netbird/active_profile.json','var/lib/netbird/default.json']
614: cmd="sudo -n sha256sum -- "+' '.join(shlex.quote('/'+x) for x in files)
615: pre=remote_hashset(t,cmd)
616: remote=shlex.join(['sudo','-n','tar','--numeric-owner','-C','/','-cf','-']+files)
617: argv=vps_ssh_argv(t,use_agent=False)+[remote]
618: payload=work/'payload.tar.zst'; pipe_to_zstd(argv,payload,timeout=600)
619: post=remote_hashset(t,cmd)
620: if pre!=post: raise BackupError('MD_SOURCE_CHANGED_DURING_CAPTURE')
621: return payload,{'generation':gen,'source_class':'vps_md','consistency':'FILESET_PRE_POST_HASH_STABILITY','hashset_sha256':pre},None
622:
623:def capture_vps_spb(t,gen,work):
624: hcmd="find /etc/nginx -xdev -type f -print0 | sort -z | xargs -0 sha256sum"
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=612
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=621
609: p=vps_run(t,['sh','-c',command],timeout=120,use_agent=False)
610: return sha256_bytes(p.stdout)
611:
612:def capture_vps_md(t,gen,work):
613: files=['etc/netbird/install.conf','var/lib/netbird/state.json','var/lib/netbird/service.json','var/lib/netbird/active_profile.json','var/lib/netbird/default.json']
614: cmd="sudo -n sha256sum -- "+' '.join(shlex.quote('/'+x) for x in files)
615: pre=remote_hashset(t,cmd)
616: remote=shlex.join(['sudo','-n','tar','--numeric-owner','-C','/','-cf','-']+files)
617: argv=vps_ssh_argv(t,use_agent=False)+[remote]
618: payload=work/'payload.tar.zst'; pipe_to_zstd(argv,payload,timeout=600)
619: post=remote_hashset(t,cmd)
620: if pre!=post: raise BackupError('MD_SOURCE_CHANGED_DURING_CAPTURE')
621: return payload,{'generation':gen,'source_class':'vps_md','consistency':'FILESET_PRE_POST_HASH_STABILITY','hashset_sha256':pre},None
622:
623:def capture_vps_spb(t,gen,work):
624: hcmd="find /etc/nginx -xdev -type f -print0 | sort -z | xargs -0 sha256sum"
625: pre=remote_hashset(t,hcmd)
626: remote=shlex.join(['tar','--numeric-owner','-C','/','-cf','-','etc/nginx'])
627: argv=vps_ssh_argv(t,use_agent=False)+[remote]
628: payload=work/'payload.tar.zst'; pipe_to_zstd(argv,payload,timeout=900)
629: post=remote_hashset(t,hcmd)
630: if pre!=post: raise BackupError('SPB_SOURCE_CHANGED_DURING_CAPTURE')
631: return payload,{'generation':gen,'source_class':'vps_spb','consistency':'STATIC_CONFIG_FILESET_PRE_POST_HASH_STABILITY','tls_recovery':'REISSUE_TLS_ON_RESTORE','hashset_sha256':pre},None
632:
633:US_REMOTE_SCRIPT=r'''import io,os,sqlite3,sys,tarfile,time,json,hashlib
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=621
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=875
863: payload=work/'payload.tar.zst'
864: argv=['tar','--numeric-owner','--xattrs','--acls','-C','/','-cf','-']+paths
865: if node=='pve01': pipe_to_zstd(argv,payload,timeout=300)
866: else:
867: remote='PATH=/usr/sbin:/usr/bin:/sbin:/bin; export PATH; exec '+shlex.join(argv)
868: pipe_to_zstd([SSH,'-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','root@'+node,remote],payload,timeout=600)
869: return payload,{'generation':gen,'source_class':'pve_node_bundle','node':node,'recovery_policy':'CLEAN_INSTALL_JOIN_RECONCILE_NOT_BLIND_PMXCFS_OVERWRITE','member_roots':len(paths)},None
870:
871:def capture_target(t,gen,work):
872: typ=t['type']
873: if typ=='pve_guest': return capture_pve_guest(t,gen,work)
874: if typ=='pve_node_bundle': return capture_node_bundle(t,gen,work)
875: if typ=='vps_md': return capture_vps_md(t,gen,work)
876: if typ=='vps_spb': return capture_vps_spb(t,gen,work)
877: if typ=='vps_us': return capture_vps_us(t,gen,work)
878: if typ=='router': return capture_router(t,gen,work)
879: if typ=='xenforo': return capture_xenforo(t,gen,work)
880: raise BackupError('CAPTURE_TYPE_UNKNOWN')
881:
882:def cleanup_source(cleanup):
883: if not cleanup: return
884: if cleanup.get('kind')=='pve_source_dir':
885: ssh_remote(cleanup['node'],['rm','-rf','--',cleanup['path']],timeout=60)
886:
887:def control_verify(t):
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=875
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=991
979: try:j=json.loads(q.stdout)
980: except Exception: continue
981: if j.get('status')=='SEALED' and j.get('generation')==g: bygen.setdefault(g,set()).add(physical)
982: good=sorted(g for g,phys in bygen.items() if len(phys)>=2)
983: print('DISCOVER_LOGICAL_ID='+logical_id); print('DISCOVER_TWO_PHYSICAL_SEALED_COUNT='+str(len(good)))
984: for g in good[-20:]: print('DISCOVER_GENERATION='+g)
985: return 0 if good else 2
986:
987:def selftest():
988: assert PART_SIZE==536870912
989: assert len(REMOTES)==13 and len({p for _,p in REMOTES})==13
990: assert len(default_targets())>=28
991: assert {t['logical_id'] for t in default_targets() if t.get('green1')}=={'ct112','node-pve01','md-relay','spb-ingress','us-netbird','router-netcraze','xf-codevipe','xf-zakrutim','control-bootstrap-v2'}
992: assert _pve_dumpdir_spec('lxc')==(0o710,100000)
993: assert _pve_dumpdir_spec('qemu')==(0o700,0)
994: assert GUEST266_SHA=='86433bc424d5fa5017c20f7a237c82874b02357a3283660d8a6b0039ef2bc868'
995: assert P282_SHA=='73c6cb7773eb8e82d1e7ed5ab4733b4afb88f74ae69c09125d0378d6e480e012'
996: if GUEST266.is_file():
997: assert _isolated_release_graph_selftest() is True
998: av,_=proven_lxc_dump_argv({'vmid':112},{'maxdisk':8350298112,'maxmem':536870912,'status':'running','name':'unbound1'},'pve01','/var/tmp/homelab-vzdump-selftest')
999: assert '--stdout' in av and '--tmpdir' in av and '/var/tmp/homelab-vzdump-selftest' in av
1000: print('SELFTEST_ENGINE396=10')
1001: return 0
1002:
1003:def main(argv):
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/legacy_engine.py|line=991
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/representative_driver.py|line=17
5:CT112 producer/cloud path. It routes CT112 to an explicitly supplied callback and
6:isolates legacy engine state writes into a candidate-owned state directory.
7:"""
8:from __future__ import annotations
9:
10:import json
11:import os
12:from pathlib import Path
13:from typing import Callable, Iterable, Mapping, Any
14:
15:LEGACY_IDS=(
16: 'node-pve01',
17: 'md-relay',
18: 'spb-ingress',
19: 'us-netbird',
20: 'router-netcraze',
21: 'xf-codevipe',
22: 'xf-zakrutim',
23: 'control-bootstrap-v2',
24:)
25:CT112_ID='guest-pve01-lxc-112'
26:REPRESENTATIVE_IDS=(CT112_ID,)+LEGACY_IDS
27:CANDIDATE_ROOT=Path(__file__).resolve().parent
28:STATE_ROOT=CANDIDATE_ROOT/'state'
29:
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/representative_driver.py|line=17
VPS_CONTEXT_BEGIN|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|line=7
1:#!/usr/bin/env python3
2:from __future__ import annotations
3:import errno,fcntl,importlib.util,os,sys
4:from pathlib import Path
5:ROOT=Path(__file__).resolve().parent
6:CT_ID='guest-pve01-lxc-112'
7:LEGACY_IDS=('node-pve01','md-relay','spb-ingress','us-netbird','router-netcraze','xf-codevipe','xf-zakrutim','control-bootstrap-v2')
8:LOCK=Path('/run/homelab-backup-heavy.lock')
9:
10:def _load(name,path):
11: spec=importlib.util.spec_from_file_location(name,str(path))
12: if spec is None or spec.loader is None: raise RuntimeError('MODULE_SPEC')
13: mod=importlib.util.module_from_spec(spec);sys.modules[name]=mod;spec.loader.exec_module(mod);return mod
14:
15:legacy=_load('_backupv2_legacy486',ROOT/'legacy_engine.py')
16:ct112=_load('_backupv2_ct112_486',ROOT/'ct112_handler.py')
17:driver=_load('_backupv2_driver454_479',ROOT/'representative_driver.py')
18:_legacy_load_targets=legacy.load_targets
19:_legacy_backup_target=legacy.backup_target
VPS_CONTEXT_END|path=/opt/homelab-backup-v2/releases/backup-v2-accepted-486r1/wrapper.py|line=7
BASE_VPS_MD_CONTEXT_COUNT=10
BASE_VPS_MD_CONTEXT_END=1
BASE_RELEASE_AUTH_CLASS=BASE_VPS_MD_BACKUP_TARGET_LOCATED
DECISION=PASS_MOLDOVA_1147_BASE_RELEASE_AUTH_COLLECTED
NEXT_GATE=READ_EXACT_1147_AND_BUILD_REMOTE_ROLE_PREFLIGHT_WITH_PROVEN_LEGACY_AUTH
TASK_RESULT=PASS_MOLDOVA_BASE_RELEASE_AUTH
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260924-HOMELAB-MOLDOVA-BASE-RELEASE-AUTH-1147R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
WORKERS2_MOLDOVA_BASE_RELEASE_AUTH_END=1
OUTPUT_END
CHAT_OUTPUT_END