From b8f3927e48467ecf196e91a95dd29c4f409709d8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 23 Mar 2017 10:29:27 +0200 Subject: Initial bootstrap script --- bootstrap | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100755 bootstrap (limited to 'bootstrap') diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..5ac3b46 --- /dev/null +++ b/bootstrap @@ -0,0 +1,344 @@ +#! /usr/bin/env bash + +# Bootstrap build2 buildos. +# +# Assumptions/expectations: +# +# - host debootstrap/debian-archive-keyring matching release +# +# - /btrfs/ is a btrfs directory where the current user can create +# snapshots +# +# - sudo is passwordless (used to run debootstrap, systemd-nspawn, etc) +# +# Options: +# +# --stage +# Jump straigh to stage by clonning the previous stage snapshot. +# Stages are: +# +# 1 - bootstrap phase 1 +# 2 - bootstrap phase 2 +# 3 - setup +# 4 - create footfs +# 5 - create kernel image and initrd +# +usage="usage: $0" + +id="$(id -un)" +btrfs=/btrfs +release="unstable" +mirror="https://deb.debian.org/debian/" +passwd="123" #@@ TMP root passwd. + +root="$btrfs/$id/buildos" + +owd="$(pwd)" +trap "{ cd '$owd'; exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +stage="1" +stage_max="5" + +while [ "$#" -gt 0 ]; do + case "$1" in + --stage) + shift + stage="$1" + shift + ;; + -*) + error "unknown option: $1" + ;; + *) + break + ;; + esac +done + +if [ "$stage" -lt "1" -o "$stage" -gt "$stage_max" ]; then + error "invalid stage number $stage" +fi + +# Btrfs subvolume manipulation. +# +function subvol_delete () # +{ + # The subvol show (just as list) needs root. + # + if sudo btrfs subvol show "$1" 1>/dev/null 2>&1; then + btrfs property set -ts "$1" ro false + btrfs subvol delete "$1" + fi +} + +function subvol_create () # +{ + btrfs subvol create "$@" +} + +function subvol_snapshot () # [-r] +{ + btrfs subvol snapshot "$@" +} + +# Clean up the working subvolume and all the snapshots starting from the +# requested stage. Also, if stage is not 1, then restore the working subvolume +# from the previous stage snapshot. +# +subvol_delete "$root" + +for i in $(seq "$stage" "$stage_max"); do + subvol_delete "$root-$i" +done + +if [ "$stage" -gt "1" ]; then + i="$(($stage - 1))" + info "restoring working subvolume from stage $i snapshot" + subvol_snapshot "$root-$i" "$root" +fi + +# Spawn a systemd namespace container (systemd-nspawn) +# +function nspawn () # +{ + sudo systemd-nspawn --register=no -D "$root" "$@" + + # systemd-nspawn may create the /var/lib/machines subvolume which prevents + # the deletion of the containing submodule. So we clean it up. + # + if sudo btrfs subvol show "$root/var/lib/machines" 1>/dev/null 2>&1; then + sudo btrfs subvol delete "$root/var/lib/machines" + fi +} + +# (Over)write or append to a file in the installation root, for example: +# +# write <<<'unknown' /etc/hostname +# +function write () # +{ + sudo tee "$root$1" >/dev/null +} + +function append () # +{ + sudo tee -a "$root$1" >/dev/null +} + +# Stage 1: debootstrap, phase 1. +# +if [ "$stage" -eq "1" ]; then + + subvol_create "$root" + + # Notes: + # + # - systemd-container seems to be required by host systemd-nspawn. + # + pkgs="locales,systemd-container" + pkgs+=",net-tools,iproute2,isc-dhcp-client,wget" + pkgs+=",linux-image-amd64" + + sudo debootstrap \ + --foreign \ + --arch=amd64 \ + --merged-usr \ + --variant=minbase \ + --include="$pkgs" \ + "$release" "$root" "$mirror" + + # Post-phase 1 fixups. + # + write <<<'unknown' /etc/hostname + + # Set timezone to UTC (picked up by tzdata package during stage 2). + # + write <<<'Etc/UTC' /etc/timezone + + subvol_snapshot -r "$root" "$root-1" +fi + +# Stage 2: debootstrap, phase 2. +# +if [ "$stage" -le "2" ]; then + + # Create a bootstrap script that will finish the bootstrap from within the + # installation via systemd-nspawn. + # + sudo mkdir "$root/bootstrap" + + write </etc/default/locale +LANG="en_US.UTF-8" +LANGUAGE="en_US:en" +EOF1 + +EOF + sudo chmod u+x "$root/bootstrap/bootstrap" + + # Notes: + # + # - Failed to create directory .../sys/fs/selinux: Read-only file system is + # harmless and fixed upstream (systemd issue#3748). + # + nspawn /bootstrap/bootstrap + + subvol_snapshot -r "$root" "$root-2" +fi + +# Stage 3: setup. +# +if [ "$stage" -le "3" ]; then + + # Create the setup script/service that will finish the setup from within the + # installation via systemd-nspawn --boot. + # + sudo mkdir -p "$root/bootstrap" + write < "$owd/buildos-rootfs.cpio.gz" + + cd "$owd" + + subvol_snapshot -r "$root" "$root-4" +fi + +# Stage 5: generate initrd. +# +if [ "$stage" -le "5" ]; then + + # @@ TODO: init location + # + sudo cp -f ./init "$root/" + + info "generating buildos-init.cpio.gz..." + sudo echo 'init' | \ + sudo cpio -o -H newc | \ + gzip -9 > "$owd/buildos-init.cpio.gz" + + cat buildos-rootfs.cpio.gz buildos-init.cpio.gz >buildos-initrd + + # Copy the kernel image next to the initramfs for convenience. + # + cp "$root/vmlinuz" buildos-image + + subvol_snapshot -r "$root" "$root-5" +fi + +# Test. +# +sudo kvm \ + -m 8G \ + -kernel buildos-image -initrd buildos-initrd -- cgit v1.1