logo

live-bootstrap

Mirror of <https://github.com/fosslinux/live-bootstrap>
commit: 7d50a224c66ced52e15693eaa669d649868b9565
parent ce1522db64cac498291a88ab70b4b6a2aa365d1b
Author: fosslinux <fosslinux@aussies.space>
Date:   Sun, 12 Jan 2025 12:54:31 +1100

Support file:// mirrors

Spawns a simple HTTP server to host the mirror.
Useful for testing mirror support or CI in chroot or bwrap modes.

Diffstat:

Mdownload-distfiles.sh9+++++++--
Alib/simple_mirror.py14++++++++++++++
Mlib/utils.py4+++-
Mrootfs.py42+++++++++++++++++++++++++++++++++++-------
4 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/download-distfiles.sh b/download-distfiles.sh @@ -37,8 +37,13 @@ download_source() { check_source() { local distfiles="${1}" local url="${2}" - local checksum="${3}" - local fname="${4}" + shift 2 + if [[ "${url}" == git://* ]]; then + url="${1}" + shift + fi + local checksum="${1}" + local fname="${2}" # Default to basename of url if not given fname="${fname:-$(basename "${url}")}" diff --git a/lib/simple_mirror.py b/lib/simple_mirror.py @@ -0,0 +1,14 @@ +import http.server +import socketserver + +class SimpleMirror(socketserver.TCPServer): + def __init__(self, directory: str): + self.directory = directory + super().__init__(("localhost", 0), self._handler) + + @property + def port(self): + return self.server_address[1] + + def _handler(self, *args, **kwargs): + return http.server.SimpleHTTPRequestHandler(*args, directory=self.directory, **kwargs) diff --git a/lib/utils.py b/lib/utils.py @@ -12,7 +12,7 @@ import shutil import subprocess import sys -def run(*args, **kwargs): +def run(*args, cleanup=None, **kwargs): """A small wrapper around subprocess.run""" arguments = [str(arg) for arg in args if arg is not None] @@ -23,6 +23,8 @@ def run(*args, **kwargs): return subprocess.run(arguments, check=True, **kwargs) except subprocess.CalledProcessError: print("Bootstrapping failed") + if cleanup: + cleanup() sys.exit(1) def run_as_root(*args, **kwargs): diff --git a/rootfs.py b/rootfs.py @@ -16,10 +16,13 @@ you can run bootstap inside chroot. import argparse import os +import signal +import threading -from lib.utils import run, run_as_root -from lib.target import Target from lib.generator import Generator, stage0_arch_map +from lib.simple_mirror import SimpleMirror +from lib.target import Target +from lib.utils import run, run_as_root def create_configuration_file(args): """ @@ -177,6 +180,19 @@ def main(): # Set constant umask os.umask(0o022) + # file:// mirrors + mirror_servers = [] + if args.mirrors: + for i, mirror in enumerate(args.mirrors): + if mirror.startswith("file://"): + path = mirror.removeprefix("file://") + if not path.startswith("/"): + raise ValueError("A file:// mirror must be an absolute path.") + + server = SimpleMirror(path) + args.mirrors[i] = f"http://127.0.0.1:{server.port}" + mirror_servers.append(server) + # bootstrap.cfg try: os.remove(os.path.join('steps', 'bootstrap.cfg')) @@ -193,15 +209,25 @@ def main(): if args.tmpfs: target.tmpfs(size=args.tmpfs_size) + for server in mirror_servers: + thread = threading.Thread(target=server.serve_forever) + thread.start() + + def cleanup(*_): + for server in mirror_servers: + server.shutdown() + signal.signal(signal.SIGINT, cleanup) + generator = Generator(arch=args.arch, external_sources=args.external_sources, repo_path=args.repo, early_preseed=args.early_preseed, mirrors=args.mirrors) - bootstrap(args, generator, target, args.target_size) + bootstrap(args, generator, target, args.target_size, cleanup) + cleanup() -def bootstrap(args, generator, target, size): +def bootstrap(args, generator, target, size, cleanup): """Kick off bootstrap process.""" print(f"Bootstrapping {args.arch}", flush=True) if args.chroot: @@ -216,7 +242,8 @@ print(shutil.which('chroot')) arch = stage0_arch_map.get(args.arch, args.arch) init = os.path.join(os.sep, 'bootstrap-seeds', 'POSIX', arch, 'kaem-optional-seed') - run_as_root('env', '-i', 'PATH=/bin', chroot_binary, generator.target_dir, init) + run_as_root('env', '-i', 'PATH=/bin', chroot_binary, generator.target_dir, init, + cleanup=cleanup) elif args.bwrap: init = '/init' @@ -245,7 +272,8 @@ print(shutil.which('chroot')) '--proc', '/proc', '--bind', '/sys', '/sys', '--tmpfs', '/tmp', - init) + init, + cleanup=cleanup) elif args.bare_metal: if args.kernel: @@ -303,7 +331,7 @@ print(shutil.which('chroot')) ] if not args.interactive: arg_list += ['-no-reboot', '-nographic'] - run(args.qemu_cmd, *arg_list) + run(args.qemu_cmd, *arg_list, cleanup=cleanup) if __name__ == "__main__": main()