45 lines
2.1 KiB
Python
Executable File
45 lines
2.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Append a test-only stage-2 check while preserving the exported service database."""
|
|
import io
|
|
import pathlib
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tarfile
|
|
|
|
project = pathlib.Path(__file__).resolve().parent.parent
|
|
if len(sys.argv) != 2:
|
|
sys.exit('Usage: tools/make-vm-image EMPTY_WORK_DIRECTORY')
|
|
work = pathlib.Path(sys.argv[1]).resolve()
|
|
if not work.is_dir() or any(work.iterdir()):
|
|
sys.exit('ERROR: VM image creation requires an existing empty work directory')
|
|
rootfs = (project / 'out/rootfs-cli.tar').resolve()
|
|
stage2 = 'etc/s6-linux-init/current/scripts/rc.init'
|
|
wrapper = (f'#!/bin/bash\nset -euo pipefail\n/{stage2}.fds-base "$@"\n'
|
|
'exec /usr/libexec/fds/m2-guest\n').encode()
|
|
found_stage2 = False
|
|
with tarfile.open(rootfs, 'r') as original, tarfile.open(work / 'test-rootfs.tar', 'w', format=tarfile.PAX_FORMAT) as output:
|
|
for member in original:
|
|
if member.name == stage2:
|
|
# Preserve the actual stage-2 script and run it to completion first.
|
|
member.name += '.fds-base'
|
|
found_stage2 = True
|
|
output.addfile(member, original.extractfile(member) if member.isfile() else None)
|
|
if not found_stage2:
|
|
sys.exit('ERROR: rootfs has no native stage-2 script; rebuild it first')
|
|
def root_owned(info):
|
|
info.uid = info.gid = 0
|
|
info.uname = info.gname = ''
|
|
return info
|
|
hook = tarfile.TarInfo(stage2)
|
|
hook.mode = 0o755
|
|
hook.size = len(wrapper)
|
|
output.addfile(hook, io.BytesIO(wrapper))
|
|
output.add(project / 'tests/integration/m2-guest', arcname='usr/libexec/fds/m2-guest', filter=root_owned)
|
|
subprocess.run(['mkfs.ext4', '-q', '-F', '-b', '4096', '-m', '0', '-L', 'FDS_M2_TEST',
|
|
'-E', 'root_owner=0:0,lazy_itable_init=0,lazy_journal_init=0',
|
|
'-d', str(work / 'test-rootfs.tar'), str(work / 'rootfs.ext4'), '768M'],
|
|
env=dict(os.environ, LC_ALL='C.UTF-8'), check=True)
|
|
(work / 'command-line').write_text('console=ttyAMA0 root=/dev/sda rootfstype=ext4 ro rootwait init=/sbin/init panic=-1\n')
|
|
print('PASS: isolated VM image created from the exported rootfs')
|