Initial commit
This commit is contained in:
commit
968d09e362
88 changed files with 2323 additions and 0 deletions
213
os/build.py
Executable file
213
os/build.py
Executable file
|
|
@ -0,0 +1,213 @@
|
|||
#!/bin/env python3
|
||||
|
||||
# Build a live ISO.
|
||||
# Run this from an empty working directory,
|
||||
# or a directory where you have run this before to reuse caches.
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import pathlib
|
||||
import tomllib
|
||||
import hashlib
|
||||
import datetime
|
||||
import urllib.request
|
||||
|
||||
|
||||
DISTRIBUTION = "bookworm"
|
||||
|
||||
VARIANT_LABEL = {
|
||||
"contestant": "contest",
|
||||
"training-live": "live",
|
||||
"training-installer": "install",
|
||||
}
|
||||
|
||||
VARIANT_BOOT_OPTIONS = {
|
||||
"contestant": [
|
||||
dict(label="SOI contest", cmdline="boot=live toram"),
|
||||
dict(label="SOI contest, run from drive", cmdline="boot=live"),
|
||||
dict(label="SOI contest, fail-safe mode", cmdline="@LB_BOOTAPPEND_LIVE_FAILSAFE@"),
|
||||
],
|
||||
"training-live": [
|
||||
dict(label="SOI live system, run from RAM", cmdline="boot=live toram"),
|
||||
dict(label="SOI live system, run from drive", cmdline="boot=live"),
|
||||
dict(label="SOI live system, fail-safe mode", cmdline="@LB_BOOTAPPEND_LIVE_FAILSAFE@"),
|
||||
],
|
||||
"training-installer": [],
|
||||
}
|
||||
|
||||
VARIANT_EXTRA_LB_CONFIG = {
|
||||
"training-installer": [
|
||||
"--debian-installer", "live",
|
||||
# Linux headers are needed for VirtualBox DKMS.
|
||||
"--linux-packages", "linux-image linux-headers",
|
||||
],
|
||||
}
|
||||
|
||||
VARIANT_EXTRA_BOOTSTRAP = {
|
||||
# Fasttrack keyring is needed for VirtualBox.
|
||||
"training-installer": ",fasttrack-archive-keyring",
|
||||
}
|
||||
|
||||
DOWNLOADS = [
|
||||
dict(
|
||||
name="soi-header.tar.gz",
|
||||
url="https://git.soi.ch/SOI/soi-header/archive/19ddcef24eb55bdb5ddb817c1d91bfa04c8cb8dd.tar.gz",
|
||||
sha256="38042587982af4e9431aea461e5c345bde358bcc79f0a0eadcf5b3ed77aeb8ab",
|
||||
),
|
||||
# From https://soi.ch/wiki/soi-codeblocks/#install-the-soi-project-template
|
||||
dict(
|
||||
name="soi_template_codeblocks_ubuntu.zip",
|
||||
url="https://soi.ch/media/files/soi_template_codeblocks_ubuntu_RzdvSho.zip",
|
||||
sha256="3f4cae26bbb0cbdfd4cf9f94bfce14988e395f847948d9b349c12d0b980386e9",
|
||||
),
|
||||
]
|
||||
|
||||
def run(args, check=True, **kwargs):
|
||||
print(f"> {' '.join(args)}")
|
||||
subprocess.run(args, check=check, **kwargs)
|
||||
|
||||
def edit_file(filename, fn):
|
||||
with open(filename) as f:
|
||||
content = f.read()
|
||||
content = fn(content)
|
||||
with open(filename, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
def sha256sum(filename):
|
||||
with open(filename, "rb", buffering=0) as f:
|
||||
return hashlib.file_digest(f, "sha256").hexdigest()
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"variant",
|
||||
choices=["contestant", "training-live", "training-installer"],
|
||||
help="Variant to build.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
script_dir = pathlib.Path(__file__).parent.resolve()
|
||||
chroot_includes = pathlib.Path("config/includes.chroot")
|
||||
|
||||
with open(script_dir / "config/config.toml", "rb") as f:
|
||||
config = tomllib.load(f)
|
||||
|
||||
# Remove files generated by previous build, but keep cache.
|
||||
run("lb clean".split())
|
||||
run("rm -rf .build config udeb-build".split())
|
||||
|
||||
# Download files.
|
||||
run("mkdir -p downloads".split())
|
||||
for download in DOWNLOADS:
|
||||
filename = f'downloads/{download["name"]}'
|
||||
try:
|
||||
if sha256sum(filename) == download["sha256"]:
|
||||
continue
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
print(f'> Downloading {download["url"]}')
|
||||
urllib.request.urlretrieve(download["url"], filename)
|
||||
if sha256sum(filename) != download["sha256"]:
|
||||
raise Exception(f"Downloaded file {filename} has wrong hash.")
|
||||
|
||||
# Create base configuration directory.
|
||||
run(
|
||||
[
|
||||
"lb", "config",
|
||||
"--clean",
|
||||
"--ignore-system-defaults",
|
||||
"--mode", "debian",
|
||||
"--distribution", DISTRIBUTION,
|
||||
"--archive-areas", "main contrib non-free non-free-firmware",
|
||||
"--firmware-chroot", "false",
|
||||
"--firmware-binary", "false",
|
||||
"--apt-recommends", "false",
|
||||
# isc-dhcp-client and ifupdown are obsoleted by network-manager,
|
||||
# but they still have Priority: important.
|
||||
# We need ca-certificates for fetching https packages repos.
|
||||
"--debootstrap-options", "--exclude=isc-dhcp-client,isc-dhcp-common,ifupdown --include=ca-certificates" +
|
||||
VARIANT_EXTRA_BOOTSTRAP.get(args.variant, ""),
|
||||
"--loadlin", "false",
|
||||
"--iso-volume", f"SOI {VARIANT_LABEL[args.variant]} @ISOVOLUME_TS@",
|
||||
"--bootappend-live", "boot=live toram",
|
||||
]
|
||||
+ VARIANT_EXTRA_LB_CONFIG.get(args.variant, [])
|
||||
)
|
||||
|
||||
# Add our own configuration on top.
|
||||
run(["cp", "-rT", f"{script_dir}/layers/participant", "config"])
|
||||
run(["cp", "-rT", f"{script_dir}/layers/{args.variant}", "config"])
|
||||
|
||||
if args.variant == "training-installer":
|
||||
# Insert admin password into preseed.
|
||||
edit_file("config/includes.installer/preseed.cfg",
|
||||
lambda s: s.replace("@install_admin_password@", config["install_admin_password"]))
|
||||
|
||||
# Copy inventory file.
|
||||
run("mkdir -p config/includes.binary/install".split())
|
||||
run(["cp", f"{script_dir}/config/installer-inventory.txt", "config/includes.binary/install/inventory.txt"])
|
||||
|
||||
# Insert build date in login screen logo.
|
||||
edit_file("config/includes.chroot/usr/local/share/images/login-screen-logo.svg",
|
||||
lambda s: s.replace("@date@", datetime.date.today().isoformat()))
|
||||
|
||||
# Build and install custom udeb packages for installer.
|
||||
run(["cp", "-rT", f"{script_dir}/installer-udeb", "udeb-build"])
|
||||
run("dpkg-buildpackage --build=all".split(), cwd="udeb-build/inventory-hostname")
|
||||
run("mkdir -p config/packages.binary".split())
|
||||
run("cp udeb-build/inventory-hostname_0_all.udeb config/packages.binary/".split())
|
||||
|
||||
# Copy the source lists. The installer deletes everything in sources.list.d,
|
||||
# so we need to copy them somewhere else and restore them after the install.
|
||||
for listpath in pathlib.Path('config/archives').glob('*.list.chroot'):
|
||||
run(["cp", str(listpath), f"config/includes.chroot/usr/local/share/target-sources/{listpath.name.removesuffix('.chroot')}"])
|
||||
elif args.variant == "contestant":
|
||||
# Insert root password into hook script.
|
||||
edit_file("config/hooks/live/2010-contestant.hook.chroot",
|
||||
lambda s: s.replace("@contestant_root_password@", config["contestant_root_password"]))
|
||||
|
||||
# Copy authorized_keys.
|
||||
run("mkdir -p config/includes.chroot/root/.ssh".split())
|
||||
run(["cp", f"{script_dir}/config/contestant_authorized_keys", "config/includes.chroot/root/.ssh/authorized_keys"])
|
||||
|
||||
# Configure boot options.
|
||||
grub_boot_options = '\n'.join(
|
||||
f'menuentry "{option["label"]}" {{\n'
|
||||
f' linux @KERNEL_LIVE@ {option["cmdline"]}\n'
|
||||
f' initrd @INITRD_LIVE@\n'
|
||||
f'}}\n'
|
||||
for option in VARIANT_BOOT_OPTIONS[args.variant]
|
||||
)
|
||||
with open("/usr/share/live/build/bootloaders/grub-pc/grub.cfg") as f:
|
||||
grub_cfg = f.read()
|
||||
grub_cfg = grub_cfg.replace("@LINUX_LIVE@", grub_boot_options)
|
||||
with open("config/bootloaders/grub-pc/grub.cfg", "w") as f:
|
||||
f.write(grub_cfg)
|
||||
|
||||
syslinux_boot_options = ''.join(
|
||||
f"label live-{i}\n"
|
||||
f"\tmenu label {option['label']}\n"
|
||||
+ (f"\tmenu default\n" if i == 0 else "") +
|
||||
f"\tlinux @LINUX@\n"
|
||||
f"\tinitrd @INITRD@\n"
|
||||
f"\tappend {option['cmdline'].replace('@LB_BOOTAPPEND_LIVE_FAILSAFE@', '@APPEND_LIVE_FAILSAFE@')}\n"
|
||||
f"\n"
|
||||
for i, option in enumerate(VARIANT_BOOT_OPTIONS[args.variant])
|
||||
)
|
||||
pathlib.Path("config/bootloaders/syslinux_common").mkdir(parents=True, exist_ok=True)
|
||||
with open("config/bootloaders/syslinux_common/live.cfg.in", "w") as f:
|
||||
f.write(syslinux_boot_options)
|
||||
|
||||
# Install soi header.
|
||||
(chroot_includes / "usr/local/include").mkdir(parents=True, exist_ok=True)
|
||||
run(["tar", "--overwrite", "-xf", f"downloads/soi-header.tar.gz", "-C", f"{chroot_includes}/usr/local/include", "--strip-components=2", "soi-header/include/"])
|
||||
|
||||
# Install codeblocks template.
|
||||
(chroot_includes / "usr/share/codeblocks/templates/wizard").mkdir(parents=True, exist_ok=True)
|
||||
run(["unzip", "-o", f"downloads/soi_template_codeblocks_ubuntu.zip", "-d", f"{chroot_includes}/usr/share/codeblocks/templates/wizard/"])
|
||||
|
||||
# Start the build.
|
||||
run("lb build".split())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue