#!/usr/bin/python3 """Clone a completed clean baseline before each actual bootstrap activation test.""" import argparse import fcntl import hashlib import importlib.util import io import json from pathlib import Path import subprocess import sys import tarfile import time p = argparse.ArgumentParser(description=__doc__) p.add_argument('--baseline', type=Path, required=True) p.add_argument('--output', type=Path, required=True) p.add_argument('--native-artifact', type=Path) p.add_argument('--accepted-payload', type=Path) a = p.parse_args() if bool(a.native_artifact) != bool(a.accepted_payload): p.error('native-artifact and accepted-payload are required together') deadline = time.monotonic() + 1800 while not (a.baseline/'result.json').exists(): if time.monotonic() >= deadline: raise TimeoutError('baseline not completed') time.sleep(2) baseline = json.loads((a.baseline/'result.json').read_text()) assert baseline['baseline_only'] and all(r['exit']==0 for r in baseline['results']) a.output.mkdir(mode=0o755,exist_ok=False) root = Path(__file__).resolve().parents[2] harness = root/'scripts/tests/os_ota_installed_vm.py' payload_args = ['--source-root',str(root)] if a.native_artifact: with open('/tmp/opencode/release-heavy.lock','a') as lock: fcntl.flock(lock,fcntl.LOCK_EX) with a.accepted_payload.open('rb') as stream: assert hashlib.file_digest(stream,'sha256').hexdigest() == 'f7563b5e509280782adebb7b75608e45bd5628fa53c58dbccf83ceb954fd4be1' with tarfile.open(a.accepted_payload) as archive: member = archive.getmember('bin/archipelago') assert member.isfile() raw = archive.extractfile(member).read() source_receipt = archive.extractfile('package.json').read() assert hashlib.sha256(source_receipt).hexdigest() == '4847733f1b5f7155e820026ebbb781c158899b5c6b977e528afc532d1c7a6ffd' assert hashlib.sha256(raw).hexdigest() == '2cf004fcc7f207c65b3bbd1eac248f8c9556ec1cd0ec139011fb4b1e1ef96494' spec = importlib.util.spec_from_file_location('harness',harness) module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module) payload = a.output/'bootstrap-native-payload.tar' manifest = module.source_archive(root,payload) with tarfile.open(payload,'a') as archive: entry = tarfile.TarInfo('accepted-old-archipelago') entry.uid=entry.gid=0; entry.mode=0o755; entry.size=len(raw) archive.addfile(entry,io.BytesIO(raw)) entry=tarfile.TarInfo('accepted-source-receipt.json') entry.uid=entry.gid=0; entry.mode=0o644; entry.size=len(source_receipt) archive.addfile(entry,io.BytesIO(source_receipt)) manifest['accepted-old-archipelago']=hashlib.sha256(raw).hexdigest() manifest['accepted-source-receipt.json']=hashlib.sha256(source_receipt).hexdigest() (a.output/'source-sha256.json').write_text(json.dumps(manifest,indent=2)) payload_args = ['--payload',str(payload),'--native-artifact',str(a.native_artifact)] results = [] for name, args in ( ('disk', ['clone','--disk',str(a.baseline/'disk/installed.raw')]), ('activation', ['boot','--disk',str(a.output/'disk/installed.raw'), '--kernel',str(a.baseline/'export/vmlinuz-6.12.107+deb13-amd64'), '--initrd',str(a.baseline/'export/initrd.img-6.12.107+deb13-amd64'), *payload_args,'--guest',str(root/'scripts/tests/os_updater_activation_guest.py')])): argv = [sys.executable,'-B',str(harness),'--output',str(a.output/name),*args] with (a.output/(name+'.log')).open('x') as log: result = subprocess.run(argv,stdout=log,stderr=subprocess.STDOUT) results.append(dict(name=name,exit=result.returncode,argv=argv)) (a.output/'result.json').write_text(json.dumps(dict(passed=False,results=results),indent=2)) if result.returncode: raise SystemExit(result.returncode) (a.output/'result.json').write_text(json.dumps(dict(passed=True,results=results, accepted_native_artifact=bool(a.native_artifact),production_signature_approval=False),indent=2))