88 lines
5.0 KiB
Python
88 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Fresh installed Debian -> genuine fixture crypto -> bootstrap/D09 -> BIOS.
|
|
|
|
One durable CPU2/8G/no-swap job; each heavyweight child takes release-heavy.lock.
|
|
The minimal native artifact's test anchor is not production/candidate trust.
|
|
"""
|
|
import argparse
|
|
import fcntl
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tarfile
|
|
|
|
p=argparse.ArgumentParser(description=__doc__)
|
|
p.add_argument('--output',type=Path,required=True)
|
|
p.add_argument('--rootfs',type=Path,required=True)
|
|
p.add_argument('--receipt',type=Path,required=True)
|
|
p.add_argument('--crypto-fixture',type=Path,required=True)
|
|
p.add_argument('--production-control',type=Path,required=True)
|
|
p.add_argument('--baseline-only',action='store_true')
|
|
p.add_argument('--baseline-disk',type=Path)
|
|
p.add_argument('--baseline-boot',type=Path)
|
|
a=p.parse_args()
|
|
a.output.mkdir(mode=0o755,exist_ok=False)
|
|
source=Path(__file__).resolve().parents[2]
|
|
live_source=source
|
|
with open('/tmp/opencode/release-heavy.lock','a') as freeze_lock:
|
|
fcntl.flock(freeze_lock,fcntl.LOCK_EX)
|
|
spec=importlib.util.spec_from_file_location('vm_freeze',source/'scripts/tests/os_ota_installed_vm.py')
|
|
vm=importlib.util.module_from_spec(spec);spec.loader.exec_module(vm)
|
|
manifest=vm.source_archive(source,a.output/'frozen-source.tar')
|
|
source=a.output/'frozen-source'
|
|
source.mkdir(mode=0o755)
|
|
with tarfile.open(a.output/'frozen-source.tar') as archive:
|
|
archive.extractall(source,filter='data')
|
|
assert all(vm.sha(source/name)==expected for name,expected in manifest.items())
|
|
(a.output/'frozen-source-sha256.json').write_text(json.dumps(manifest,indent=2)+'\n')
|
|
harness=source/'scripts/tests/os_ota_installed_vm.py'
|
|
results=[]
|
|
def step(name,*args):
|
|
command=[sys.executable,'-B',str(harness),'--output',str(a.output/name),*map(str,args)]
|
|
with (a.output/(name+'.driver.log')).open('x') as log:
|
|
r=subprocess.run(command,stdout=log,stderr=subprocess.STDOUT)
|
|
results.append(dict(name=name,exit=r.returncode,command=command))
|
|
(a.output/'progress.json').write_text(json.dumps(results,indent=2)+'\n')
|
|
r.check_returncode()
|
|
try:
|
|
if a.baseline_disk:
|
|
assert a.baseline_boot
|
|
step('disk','clone','--disk',a.baseline_disk)
|
|
baseline=a.baseline_boot
|
|
else:
|
|
step('disk','prepare','--rootfs',a.rootfs,'--receipt',a.receipt,'--kernel-release','6.12.73+deb13-amd64')
|
|
step('baseline','boot','--disk',a.output/'disk/installed.raw',
|
|
'--kernel',a.output/'disk/vmlinuz-6.12.73+deb13-amd64',
|
|
'--initrd',a.output/'disk/initrd.img-6.12.73+deb13-amd64',
|
|
'--source-root',source,'--guest',source/'tests/regression/os-ota-crypto-baseline.py')
|
|
step('baseline-boot','export','--disk',a.output/'disk/installed.raw','--kernel-release','6.12.107+deb13-amd64')
|
|
baseline=a.output/'baseline-boot'
|
|
if not a.baseline_only:
|
|
step('activation','boot','--disk',a.output/'disk/installed.raw',
|
|
'--kernel',baseline/'vmlinuz-6.12.107+deb13-amd64',
|
|
'--initrd',baseline/'initrd.img-6.12.107+deb13-amd64',
|
|
'--source-root',source,'--crypto-fixture',a.crypto_fixture,'--native-artifact',a.production_control,
|
|
'--guest',source/'tests/regression/os-ota-crypto-bootstrap.py')
|
|
crypto=json.loads((a.output/'activation/os-ota-stage/crypto-result.json').read_text())
|
|
release=crypto['target_kernel']
|
|
step('updated-boot','export','--disk',a.output/'disk/installed.raw','--kernel-release',release)
|
|
# Retain the complete preboot filesystem for independent observer retries.
|
|
# Failed observer/readmission disks are never reset or reused.
|
|
step('postboot-disk','clone','--disk',a.output/'disk/installed.raw')
|
|
step('postboot','boot','--disk',a.output/'postboot-disk/installed.raw',
|
|
'--kernel',a.output/'updated-boot'/('vmlinuz-'+release),
|
|
'--initrd',a.output/'updated-boot'/('initrd.img-'+release),'--offline','--firmware',
|
|
'--preboot-evidence',a.output/'activation/os-ota-stage/same-boot-complete-ledger.json',
|
|
'--guest',source/'tests/regression/os-ota-installed-owner-postboot.py')
|
|
finally:
|
|
source_changes=[name for name,expected in manifest.items() if vm.sha(source/name)!=expected]
|
|
live_changes=[name for name,expected in manifest.items() if not (live_source/name).exists() or vm.sha(live_source/name)!=expected]
|
|
(a.output/'source-after.json').write_text(json.dumps(dict(frozen_changes=source_changes,live_changes=live_changes),indent=2)+'\n')
|
|
passed=bool(results) and all(r['exit']==0 for r in results) and not source_changes
|
|
(a.output/'result.json').write_text(json.dumps(dict(passed=passed,
|
|
full_flow_under_isolated_test_anchor=passed and not a.baseline_only,
|
|
frozen_source_unchanged=not source_changes,source_manifest_sha256=vm.sha(a.output/'frozen-source-sha256.json'),
|
|
baseline_only=a.baseline_only,production_approved=False,candidate_qualified=False,results=results),indent=2)+'\n')
|