diff --git a/live-build/auto/build b/live-build/auto/build index 70287baa..08d85c1f 100755 --- a/live-build/auto/build +++ b/live-build/auto/build @@ -254,7 +254,11 @@ rm -f /usr/sbin/update-initramfs dpkg-divert --quiet --remove --rename /usr/sbin/update-initramfs EOF - lb chroot "$@" + if [ "${IMAGEFORMAT:-}" = live-layered ]; then + PATH="config/:$PATH" lb chroot_layered "$@" + else + lb chroot "$@" + fi if [ "${SUBPROJECT:-}" = minimized ]; then # force removal of initramfs-tools, which we assert is not @@ -474,6 +478,28 @@ EOF /usr/share/livecd-rootfs/minimize-manual chroot lb binary "$@" + + # Create layered squashfs system + if [ "${IMAGEFORMAT:-}" = live-layered ]; then + for _PASS in $PASSES + do + squashfs_f="${PWD}/livecd.${PROJECT}.${_PASS}.squashfs" + + (cd "chroot.${_PASS}/" && + mksquashfs . ${squashfs_f} \ + -no-progress -xattrs -comp xz ) + + squashfs_f_manifest="${squashfs_f}.manifest" + create_manifest "chroot.${_PASS}/" "${squashfs_f_manifest}" + done + # We are skipping lb_binary_rootfs + fi + + # Teardown mount points in layered mode + if [ -x config/teardown_chroot_layered ]; then + config/teardown_chroot_layered + fi + touch binary.success ) 2>&1 | tee binary.log diff --git a/live-build/auto/clean b/live-build/auto/clean index 9ddf752e..4794c311 100755 --- a/live-build/auto/clean +++ b/live-build/auto/clean @@ -8,3 +8,4 @@ rm -rf config rm -f binary.manifest binary.manifest-desktop binary.log rm -f livecd.* rm -rf userdata +rm -rf chroot.* diff --git a/live-build/auto/config b/live-build/auto/config index 2ec19bfe..27a319e1 100755 --- a/live-build/auto/config +++ b/live-build/auto/config @@ -33,6 +33,7 @@ fi mkdir -p config cp -af /usr/share/livecd-rootfs/live-build/functions config/functions +cp -af /usr/share/livecd-rootfs/live-build/lb_chroot_layered config/lb_chroot_layered cp -af /usr/share/livecd-rootfs/live-build/snap-seed-parse.py config/snap-seed-parse mkdir -p config/package-lists @@ -69,6 +70,9 @@ add_binary_hook () } if [ -z "${IMAGEFORMAT:-}" ]; then + if [ ${SUBPROJECT:-} = layered ]; then + IMAGEFORMAT=live-layered + fi case $PROJECT:${SUBPROJECT:-} in ubuntu-cpc:*) if [ "$SUBARCH" = "raspi3" ]; then @@ -189,6 +193,12 @@ case $IMAGEFORMAT in exit 0 ;; + live-layered) + # Stop lb creating filesystem.squashfs by skipping lb_binary_rootfs and lb_binary_manifest + skip_lb_stage binary_rootfs + skip_lb_stage binary_manifest + ;; + none) OPTS="${OPTS:+$OPTS }--chroot-filesystem $IMAGEFORMAT" ;; @@ -321,8 +331,19 @@ esac case $PROJECT in ubuntu|ubuntu-dvd) - add_task install minimal standard ubuntu-desktop - LIVE_TASK='ubuntu-live' + case ${SUBPROJECT:-} in + layered) + PASSES="install-minimal install live" + add_task install-minimal minimal standard + add_task install ubuntu-desktop + LIVE_TASK='ubuntu-live' + ;; + *) + add_task install minimal standard ubuntu-desktop + LIVE_TASK='ubuntu-live' + ;; + esac + case $ARCH in amd64) add_package live $SIGNED_KERNEL_PACKAGE ;; esac @@ -686,54 +707,56 @@ case $SUBPROJECT in ;; esac -# we'll expand the base seed given here according to the STRUCTURE file, and -# then look in all of the seeds found to see which snaps are seeded -case $PROJECT:${SUBPROJECT:-} in - ubuntu:*|kubuntu*:*|lubuntu*:*|xubuntu*:*|ubuntu-mate*:*|ubuntustudio*:*|ubuntukylin*:*|ubuntu-budgie*:*) - BASE_SEED='desktop' - ;; - ubuntu-cpc:*) - BASE_SEED='server' - ;; - ubuntu-server:live) - BASE_SEED='server' - # subiquity is seeded but in a separate squashfs via hooks; set HOOK_SNAPS and ALL_SNAPS. - HOOK_SNAPS='subiquity' - ALL_SNAPS='' - ;; -esac +if [ "${IMAGEFORMAT:-}" != live-layered ]; then + # we'll expand the base seed given here according to the STRUCTURE file, and + # then look in all of the seeds found to see which snaps are seeded + case $PROJECT:${SUBPROJECT:-} in + ubuntu:*|kubuntu*:*|lubuntu*:*|xubuntu*:*|ubuntu-mate*:*|ubuntustudio*:*|ubuntukylin*:*|ubuntu-budgie*:*) + BASE_SEED='desktop' + ;; + ubuntu-cpc:*) + BASE_SEED='server' + ;; + ubuntu-server:live) + BASE_SEED='server' + # subiquity is seeded but in a separate squashfs via hooks; set HOOK_SNAPS and ALL_SNAPS. + HOOK_SNAPS='subiquity' + ALL_SNAPS='' + ;; + esac -if [ -n "${BASE_SEED}" ]; then - SEEDS_EXPANDED=$(inheritance ${BASE_SEED}) - for seed in ${SEEDS_EXPANDED}; do - echo "snap: considering ${seed}" - file=config/germinate-output/${seed}.snaps - [ -e "${file}" ] || continue - # extract the first column (snap package name) from germinate's output - # translate the human-readable "foo (classic)" into a - # more machine readable "foo/classic" - seed_snaps=$(sed -rn '1,/-----/d;/-----/,$d; s/(.*) \|.*/\1/; s, \(classic\),/classic,; p' "${file}") - for snap in ${seed_snaps}; do - echo "snap: found ${snap}" - ALL_SNAPS="${ALL_SNAPS:+${ALL_SNAPS} }${snap}" + if [ -n "${BASE_SEED}" ]; then + SEEDS_EXPANDED=$(inheritance ${BASE_SEED}) + for seed in ${SEEDS_EXPANDED}; do + echo "snap: considering ${seed}" + file=config/germinate-output/${seed}.snaps + [ -e "${file}" ] || continue + # extract the first column (snap package name) from germinate's output + # translate the human-readable "foo (classic)" into a + # more machine readable "foo/classic" + seed_snaps=$(sed -rn '1,/-----/d;/-----/,$d; s/(.*) \|.*/\1/; s, \(classic\),/classic,; p' "${file}") + for snap in ${seed_snaps}; do + echo "snap: found ${snap}" + ALL_SNAPS="${ALL_SNAPS:+${ALL_SNAPS} }${snap}" + done done - done - if [ -n "${ALL_SNAPS}" ] || [ -n "${HOOK_SNAPS}" ]; then - echo "${ALL_SNAPS}" > config/seeded-snaps + if [ -n "${ALL_SNAPS}" ] || [ -n "${HOOK_SNAPS}" ]; then + echo "${ALL_SNAPS}" > config/seeded-snaps + fi fi -fi -# grab a list of packags to remove for a "minimal" installation from the seed -# mirror for this project -if [ -n "${BASE_SEED}" ] && [ -n "${BASE_SEED}" ]; then - minimal_packages_url=${SEEDMIRROR}/${SEED}/${BASE_SEED}.minimal-remove - echo -n "Checking ${minimal_packages_url} for a minimal installation list... " - minimal_packages_remove=$(wget -q -O- ${minimal_packages_url} | sed -e '/\s*#.*$/d' -e '/^\s*$/d') - if [ -n "${minimal_packages_remove}" ]; then - echo "${minimal_packages_remove}" > config/manifest-minimal-remove - echo "$(echo ${minimal_packages_remove} | tr '\n' ' ')" - else - echo "failed to retrieve, not including." + # grab a list of packags to remove for a "minimal" installation from the seed + # mirror for this project + if [ -n "${BASE_SEED}" ] && [ -n "${BASE_SEED}" ]; then + minimal_packages_url=${SEEDMIRROR}/${SEED}/${BASE_SEED}.minimal-remove + echo -n "Checking ${minimal_packages_url} for a minimal installation list... " + minimal_packages_remove=$(wget -q -O- ${minimal_packages_url} | sed -e '/\s*#.*$/d' -e '/^\s*$/d') + if [ -n "${minimal_packages_remove}" ]; then + echo "${minimal_packages_remove}" > config/manifest-minimal-remove + echo "$(echo ${minimal_packages_remove} | tr '\n' ' ')" + else + echo "failed to retrieve, not including." + fi fi fi @@ -857,6 +880,10 @@ lb config noauto \ echo "LB_CHROOT_HOOKS=\"$CHROOT_HOOKS\"" >> config/chroot echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/chroot echo "LB_DISTRIBUTION=\"$SUITE\"" >> config/chroot +echo "IMAGEFORMAT=$IMAGEFORMAT" >> config/common +if [ -n "$PASSES" ]; then + echo "PASSES=\"$PASSES\"" >> config/common +fi echo "LB_BINARY_HOOKS=\"$BINARY_HOOKS\"" >> config/binary echo "BUILDSTAMP=\"$NOW\"" >> config/binary echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/binary diff --git a/live-build/lb_chroot_layered b/live-build/lb_chroot_layered new file mode 100755 index 00000000..2b7f13e3 --- /dev/null +++ b/live-build/lb_chroot_layered @@ -0,0 +1,141 @@ +#!/bin/sh + +## live-build(7) - System Build Scripts +## Copyright (C) 2006-2012 Daniel Baumann +## +## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING. +## This is free software, and you are welcome to redistribute it +## under certain conditions; see COPYING for details. + +## This is a fork of lb_chroot for layered live system. +## We don't want leaking host configuratino in each layer, and so, +## we clean and setup the chroot each time. +## In addition, we create the squashfs for each layer, but top one (live) +## which still can be configured after lb chroot call. + +set -e + +# Including common functions +( . "${LIVE_BUILD}/scripts/build.sh" > /dev/null 2>&1 || true ) || . /usr/lib/live/build.sh + +# Automatically populating config tree +if [ -x auto/config ] && [ ! -e .build/config ] +then + Echo_message "Automatically populating config tree." + lb config +fi + +# Setting static variables +DESCRIPTION="$(Echo 'customize the Debian system')" +HELP="" +USAGE="${PROGRAM} [--force]" + +Arguments "${@}" + +# Reading configuration files +Read_conffiles config/all config/common config/bootstrap config/chroot config/binary config/source +Set_defaults + +# Setup cleanup function +Setup_cleanup + +. config/functions + +teardownPath="config/teardown_chroot_layered" +cat >> $teardownPath << EOF +#!/bin/sh +set -e +EOF +chmod +x $teardownPath + +PASSES="${PASSES:-install live}" +CURPASS=1 +LASTPASS=$(echo $PASSES|wc -w) +for _PASS in $PASSES +do + + if [ $CURPASS -gt 1 ]; then + mkdir chroot.${_PASS} + mount_overlay chroot/ "chroot.${_PASS}/" chroot/ + cat >> $teardownPath << EOF +umount chroot/ +EOF + fi + + # Configuring chroot + lb chroot_cache restore ${*} + lb chroot_devpts install ${*} + lb chroot_proc install ${*} + lb chroot_selinuxfs install ${*} + lb chroot_sysfs install ${*} + lb chroot_debianchroot install ${*} + lb chroot_dpkg install ${*} + lb chroot_tmpfs install ${*} + lb chroot_sysv-rc install ${*} + lb chroot_upstart install ${*} + lb chroot_hosts install ${*} + lb chroot_resolv install ${*} + lb chroot_hostname install ${*} + lb chroot_apt install ${*} + lb chroot_archives chroot install ${*} + + # Customizing chroot + lb chroot_linux-image ${*} + lb chroot_preseed ${*} + lb chroot_early_hooks ${*} + + lb chroot_package-lists ${_PASS} ${*} + lb chroot_install-packages ${_PASS} ${*} + + # Kernel should be in first layer + if [ $CURPASS -eq 1 ]; then + Chroot chroot "dpkg -l linux-headers-3* linux-headers-4*" 2>/dev/null \ + | awk '/^i/ {print $2}' > chroot.headers + for i in $(cat chroot.headers); do + Chroot chroot "apt-mark auto $i" + done + fi + + Chroot chroot "apt-get --purge -y autoremove" + + # Add live packages to top layer + if [ $CURPASS -eq $LASTPASS ]; then + lb chroot_live-packages ${*} + fi + + lb chroot_includes ${*} + # TODO: look if this is what copies distro hooks + lb chroot_hooks ${*} + lb chroot_hacks ${*} + lb chroot_interactive ${*} + + Chroot chroot "dpkg-query -W" > chroot.packages.${_PASS} + + # Deconfiguring chroot + lb chroot_archives chroot remove ${*} + lb chroot_apt remove ${*} + lb chroot_hostname remove ${*} + lb chroot_resolv remove ${*} + lb chroot_hosts remove ${*} + lb chroot_sysv-rc remove ${*} + lb chroot_upstart remove ${*} + lb chroot_tmpfs remove ${*} + lb chroot_dpkg remove ${*} + lb chroot_debianchroot remove ${*} + lb chroot_sysfs remove ${*} + lb chroot_selinuxfs remove ${*} + lb chroot_proc remove ${*} + lb chroot_devpts remove ${*} + lb chroot_cache save ${*} + + if [ $CURPASS -eq 1 ]; then + cp -a chroot chroot.${_PASS} + fi + + CURPASS=$(( CURPASS + 1 )) +done + +# Remove unused chroot binary corresponding to bottom layer (once everything is unmount) +cat >> $teardownPath << EOF +rm -rf chroot/ +EOF