Files
archy/scripts/tests/qualify_os_updater_activation.py

77 lines
4.0 KiB
Python

#!/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))