Dan Bungert 8acf29a786 live-server: place kernel in the minimal layer
By placing the kernel in minimal, we can achieve the following
improvements:

1. Space savings - there are redundant packages present in the ship-live
   pool and in the live layer.  Adding the kernel to minimal means that
   the kernel is already in the live layer, and we don't then also need
   it in the pool.
2. Time savings - informal vm testing suggests more than a minute
   improvement to have the kernel preinstalled over installing it at
   runtime.

As always, there is a cost tradeoff:

1. If a different kernel is desired, we need to be able to remove this
   preinstalled kernel.  Relevant curtin and subiquity changes are
   already landed.
2. When installing that other kernel, it'll take longer than today due
   to still needing to install a kernel at runtime + the time cost of
   removing the preinstalled kernel.
2024-09-10 17:00:56 -06:00

1604 lines
46 KiB
Bash
Executable File

#! /bin/sh
set -e
case $ARCH:$SUBARCH in
amd64:|amd64:generic|amd64:intel-iot|\
arm64:|arm64:generic|arm64:raspi|arm64:snapdragon|\
arm64:tegra|arm64:tegra-igx|arm64:x13s|arm64:largemem|\
armhf:|\
i386:|\
ppc64el:|\
riscv64:|riscv64:generic|riscv64:icicle|riscv64:licheerv|\
riscv64:milkvmars|riscv64:nezha|riscv64:pic64gx|riscv64:unmatched|\
riscv64:visionfive|riscv64:visionfive2|\
s390x:|\
*appliance*)
;;
*)
echo "Unknown architecture target $ARCH:$SUBARCH"
exit 1
;;
esac
if [ -e config/germinate-output ]; then
mv -T config/germinate-output germ-tmp
rm -rf config
mkdir config
mv -T germ-tmp config/germinate-output
else
rm -rf config
fi
echo "Building on $(hostname --fqdn)"
SEEDMIRROR=https://ubuntu-archive-team.ubuntu.com/seeds/
if [ -z "$MIRROR" ]; then
case $(hostname --fqdn) in
*.ubuntu.com|*.buildd|*.ppa|*.scalingstack)
MIRROR=http://ftpmaster.internal/ubuntu/
SEEDMIRROR=http://archive-team.internal/seeds/
;;
*)
case $ARCH in
i386|amd64) MIRROR=http://archive.ubuntu.com/ubuntu/ ;;
*) MIRROR=http://ports.ubuntu.com/ubuntu-ports/ ;;
esac
;;
esac
fi
mkdir -p config
cp -af /usr/share/livecd-rootfs/live-build/functions config/functions
cp -af /usr/share/livecd-rootfs/live-build/lb_*_layered config/
cp -af /usr/share/livecd-rootfs/live-build/snap-seed-parse.py config/snap-seed-parse
cp -af /usr/share/livecd-rootfs/live-build/expand-task config/expand-task
cp -af /usr/share/livecd-rootfs/live-build/squashfs-exclude-files config/
mkdir -p config/package-lists
. config/functions
OPTS=
COMPONENTS=
BINARY_REMOVE_LINUX=:
BINARY_IMAGES=none
MEMTEST=none
SOURCE='--source false'
BOOTLOADER=none
BOOTAPPEND_LIVE=
LIVE_TASK=
PREINSTALLED=false
PREINSTALL_POOL=
PREINSTALL_POOL_SEEDS=
PREFIX="livecd.$PROJECT${SUBARCH:+-$SUBARCH}"
CHROOT_HOOKS=
BINARY_HOOKS=
APT_OPTIONS=" --yes -oDebug::pkgDepCache::AutoInstall=yes "
PASSES_TO_LAYERS=false
_PASSES_TO_LAYERS= # Stores the initial value of PASSES_TO_LAYERS
PASSES=
_check_immutable_passes_to_layers () {
# Check that PASSES_TO_LAYERS didn't change ie we didn't switch from layer
# to non-layer image format and vice versa.
if [ -z "$_PASSES_TO_LAYERS" ]; then
_PASSES_TO_LAYERS=$PASSES_TO_LAYERS
fi
if [ "$_PASSES_TO_LAYERS" != "$PASSES_TO_LAYERS" ]; then
echo "ERROR: PASSES_TO_LAYERS has changed from $_PASSES_TO_LAYERS to $PASSES_TO_LAYERS between 2 API calls. Please set it first."
exit 1
fi
}
_check_layers_only_API () {
# Check if a function is designed only for layered mode
# $1 name of the function
if [ "$PASSES_TO_LAYERS" != "true" ]; then
echo "$1 should only be used in layered mode, with PASSES_TO_LAYERS set to true"
exit 1
fi
}
_register_pass () {
# In layer mode, record a pass into the list of passes
# $1 Name of the pass
[ "$PASSES_TO_LAYERS" != "true" ] && return
case "$PASSES" in
*$1*)
# The pass is already registered in the list of layers.
# If PASSES_TO_LAYERS is true, then the above if statement's error
# code will be non-zero and a return statement with no argument
# will return the error code of the if statement, non-zero, thus
# exiting the script and build. This is not our intent. So we need
# to return 0 here.
return 0
;;
esac
# live-build/ubuntu/hooks/020-ubuntu-live.chroot_early assumes the
# layer ending in '.live' is THE live layer to use, so ensure that
# we only define a single layer ending in '.live'. It principle it
# is not invalid to have multiple layers with .live in the name but
# we should not let this happen accidentally.
case "$PASSES $1" in
*.live\ *.live)
echo "ERROR: only one 'live' layer allowed"
exit 1
;;
*)
;;
esac
PASSES="$PASSES $1"
}
add_pass ()
{
local pass="$1"
_check_immutable_passes_to_layers
_register_pass "$pass"
}
add_task ()
{
local pass="$1"
shift
local file pkg_file snap_file task
_check_immutable_passes_to_layers
_register_pass "$pass"
if [ ! -e config/germinate-output/structure ]; then
echo "add_task too soon" >&2
exit 1
fi
pkg_file="config/package-lists/livecd-rootfs.list.chroot_$pass"
if [ $PASSES_TO_LAYERS = "true" ]; then
snap_file="config/package-lists/livecd-rootfs.snaplist.chroot_$pass.full"
else
snap_file="config/seeded-snaps"
fi
for task; do
./config/expand-task config/germinate-output $FLAVOUR $task packages >> "$pkg_file"
./config/expand-task config/germinate-output $FLAVOUR $task snaps >> "$snap_file"
done
for file in $pkg_file $snap_file; do
if [ -s $file ]; then
sort -u -o $file $file
else
rm -f $file
fi
done
}
add_package ()
{
# Adds a pass named pass_name composed of packages to install
# $1 pass
# $@ list of packages
local pass="$1"
shift
local pkg
_check_immutable_passes_to_layers
_register_pass "$pass"
for pkg; do
echo "$pkg" >> "config/package-lists/livecd-rootfs.list.chroot_$pass"
done
}
remove_package ()
{
# Adds a pass named pass_name composed of packages to remove
# $1 pass
# $@ list of packages
local pass="$1"
shift
local pkg
_check_immutable_passes_to_layers
_check_layers_only_API "remove_package"
_register_pass "$pass"
for pkg; do
echo "$pkg" >> "config/package-lists/livecd-rootfs.removal-list.chroot_$pass"
done
}
add_snap ()
{
# Adds a pass named pass_name composed of snaps to install
# $1 pass
# $@ list of snaps
local pass="$1"
shift
local pkg
_check_immutable_passes_to_layers
_register_pass "$pass"
local channel=""
if [ -n "$CHANNEL" ] ; then
channel="=$CHANNEL"
fi
for pkg; do
echo "$pkg$channel" >> "config/package-lists/livecd-rootfs.snaplist.chroot_$pass.full"
done
}
get_seeded_languages () {
# We assume any seed name of the form ${no_lang_seed}-${foo} where
# ${foo} is only two or three characters long is a default language
# seed.
langs=''
for no_lang_seed in "$@"; do
seed_regex="${no_lang_seed}"'-[^-.]{2,3}$'
for seed in $(ls config/germinate-output | grep -E "${seed_regex}"); do
lang=$(echo "${seed}" | grep -oE '[^-.]{2,3}$')
langs="$langs $lang"
done
done
echo $langs | tr ' ' '\n' | sort -u | tr '\n' ' '
}
derive_language_layers () {
# create special layers for each default language
#
# $1 base pass
# $2 base seed (without any languages)
# $3 default language seed
# $4 space separated list of default languages
# e.g.:
# derive_language_layers minimal desktop-minimal desktop-minimal-default-languages
# derive_language_layers minimal.standard desktop desktop-default-languages
#
# The way this works is perhaps a little counterintuitive.
#
# The first goal here is that the installed system should contain
# language support for the language the user selected. One way to do
# this using layers would be to have a layer that contained no
# language support and a derived layer for each (default) language. So
# something like:
#
# filesystem.squashfs (contains no language support)
# filesystem.en.squashfs (contains English language support)
# filesystem.fr.squashfs (contains French language support)
# ...
#
# Then if the user selects French as their language, we just copy
# filesystem.fr.squashfs to the target system.
#
# But we want the live session to support these languages too and
# simply adding all the language support to the live layer would mean
# we'd have the each language's support files on the ISO twice (once
# in filesystem.$LANG.squashfs and once in filesystem.live.squashfs).
#
# So what is done instead is that we add support for all the default
# languages to the base layer and then create derived layers that
# _remove_ support for all languages but the desired language and
# because file removals are cheap to represent in overlays, this all
# ends up taking way less space, and filesystem.live.squashfs gets
# support for all languages from the base layer. We also create a
# layer than has support for all languages removed, which can be used
# for the base of an install for a non-default language.
local pass base_pass=$1 no_lang_seed=$2 def_lang_seed=$3 langs=$4
_check_immutable_passes_to_layers
_check_layers_only_API "derive_language_layers"
for lang in $langs; do
pass="${base_pass}.${lang}"
_register_pass ${pass}
# Remove packages from the default language seed that are not
# in the language specific seed from the language specific layer.
# I find this expression helps a little to make this make sense:
# ((base) + (en fr de)) - ( (en fr de) - (fr)) == (base + fr)
# `layer will all langs' `def_lang_seed' `lang' `what we want to install'
subtract_package_lists ${def_lang_seed} ${no_lang_seed}-${lang} >> config/package-lists/livecd-rootfs.removal-list.chroot_$pass
done
no_lang_pass=$base_pass.no-languages
_register_pass ${no_lang_pass}
# Remove all packages from the default language seed that are not in
# the no_lang_seed from the no-languages layer.
subtract_package_lists ${def_lang_seed} ${no_lang_seed} >> config/package-lists/livecd-rootfs.removal-list.chroot_${no_lang_pass}
}
add_chroot_hook ()
{
CHROOT_HOOKS="${CHROOT_HOOKS:+$CHROOT_HOOKS }$1"
}
add_binary_hook ()
{
BINARY_HOOKS="${BINARY_HOOKS:+$BINARY_HOOKS }$1"
}
_sanitize_passes ()
{
# Returns an uniquely ordered list of passes and ensure dependency tree is coherent
# $1 list of passes
local passes="$1"
[ -z "$passes" ] && return
passes=$(echo $passes | tr ' ' '\n' | sort -u)
for pass in $passes; do
parent=$(get_parent_pass $pass)
# if root pass, no parent to find
[ -z "$parent" ] && continue
if [ $(echo "$passes"|grep -cE "^$parent\$") -ne 1 ]; then
echo "ERROR: '$parent' is required by '$pass' but is missing. Registered passes are:\n$passes" >&2
exit 1
fi
done
# return the list of passes
echo $passes
}
_get_live_passes ()
{
# Returns a list of all passes that ends with .live for automated live passes detection
# $1 list of passes
local passes="$1"
local livepasses=""
[ -z "$passes" ] && return
for pass in $passes; do
if echo $pass | grep -Eq '\.live$'; then
livepasses="$pass $livepasses"
fi
done
echo $livepasses
}
if [ -z "${IMAGEFORMAT:-}" ]; then
case $PROJECT:${SUBPROJECT:-} in
ubuntu-cpc:*|ubuntu:desktop-preinstalled|ubuntu-wsl:*)
case $ARCH+${SUBARCH:-} in
arm64+raspi)
# All raspi images use ubuntu-image.
IMAGEFORMAT=ubuntu-image
;;
arm64+tegra|arm64+tegra-igx)
# Pre-installed Tegra images use
# ubuntu-image
IMAGEFORMAT=ubuntu-image
;;
*)
IMAGEFORMAT=ext4
;;
esac
;;
ubuntu-server:live|ubuntu-mini-iso:|ubuntu-core-installer:*)
IMAGEFORMAT=plain
;;
esac
fi
# Configure preinstalled ubuntu-cpc images with included password
# one also must request disk1-img-xz image format
if [ "$IMAGEFORMAT" = "ext4" ] && [ "$PROJECT" = "ubuntu-cpc" ]; then
case $ARCH:$SUBARCH in
riscv64:icicle | \
riscv64:licheerv | \
riscv64:milkvmars | \
riscv64:nezha | \
riscv64:pic64gx | \
riscv64:unmatched | \
riscv64:visionfive | \
riscv64:visionfive2 | \
*:generic)
IMAGE_HAS_HARDCODED_PASSWORD=1
if [ -z "${IMAGE_TARGETS:-}" ]; then
export IMAGE_TARGETS="disk-image-non-cloud"
fi
;;
esac
fi
skip_lb_stage() {
STAGE="$1"
mkdir -p .build
touch ".build/$STAGE"
}
case $IMAGEFORMAT in
ext2|ext3|ext4)
OPTS="${OPTS:+$OPTS }--initramfs none --chroot-filesystem $IMAGEFORMAT"
PREINSTALLED=true
;;
plain)
case $PROJECT:${SUBPROJECT:-} in
ubuntu-server:live|ubuntu-core-installer:*)
touch config/universe-enabled
;;
ubuntu-mini-iso:)
;;
*)
PREINSTALLED=true
;;
esac
OPTS="${OPTS:+$OPTS }--initramfs none --chroot-filesystem $IMAGEFORMAT"
;;
ubuntu-image)
UBUNTU_IMAGE_ARGS=""
case "$ARCH+${SUBARCH:-}" in
amd64+intel-iot)
MODEL=intel-iot ;;
amd64+*)
MODEL=pc-amd64 ;;
arm64+snapdragon)
MODEL=dragonboard ;;
arm64+raspi)
MODEL=pi-arm64 ;;
arm64+raspi3)
MODEL=pi3-arm64 ;;
arm64+tegra)
MODEL=tegra ;;
arm64+tegra-igx)
MODEL=tegra-igx ;;
arm64+*)
MODEL=pc-arm64 ;;
*)
echo "Model $ARCH+${SUBARCH:-} unknown to livecd-rootfs" >&2
exit 1
;;
esac
# If we have a datestamp coming from cdimage, use that to populate
# .disk/info on the target image
if [ -n "$NOW" ]; then
echo "$NOW" > config/disk-info
UBUNTU_IMAGE_ARGS="$UBUNTU_IMAGE_ARGS --disk-info config/disk-info"
fi
if [ -n "$SECTOR_SIZE" ]; then
UBUNTU_IMAGE_ARGS="$UBUNTU_IMAGE_ARGS --sector-size=$SECTOR_SIZE"
fi
if [ $PROJECT = "ubuntu-core" ]; then
# snap-based core images
CHANNEL="${CHANNEL:-edge}"
case $MODEL in
pc-amd64|pc-arm64)
if [ -z "${SUBARCH:-}" ]; then
# This is to make sure there's enough writable space
UBUNTU_IMAGE_ARGS="$UBUNTU_IMAGE_ARGS --image-size 3700M"
fi
;;
*) ;;
esac
# Ubuntu Core 24
# For now we stick to updating this by hand, but a more tasteful solution
# will follow
CORE_MAJOR=24
# Currently uc24 assertions do not support global channel overrides,
# instead we have per-channel models
case $CHANNEL in
stable)
MODEL="ubuntu-core-${CORE_MAJOR}-${MODEL#pc-}"
;;
candidate|beta|edge|dangerous)
MODEL="ubuntu-core-${CORE_MAJOR}-${MODEL#pc-}-${CHANNEL}"
;;
dangerous-*)
# That being said, the dangerous grade *does*
# support channel overrides, so we can use the
# dangerous model assertion and override the channel
# freely.
MODEL="ubuntu-core-${CORE_MAJOR}-${MODEL#pc-}-dangerous"
CHANNEL=${CHANNEL#dangerous-}
UBUNTU_IMAGE_ARGS="$UBUNTU_IMAGE_ARGS -c $CHANNEL"
;;
*)
echo "Unknown CHANNEL ${CHANNEL} specification for ${SUITE}"
exit 1
;;
esac
case "$ARCH+${SUBARCH:-}" in
amd64+kassel)
EXTRA_SNAPS="$EXTRA_SNAPS core bluez alsa-utils"
;;
*)
# For all Ubuntu Core 24 reference images, add console-conf
EXTRA_SNAPS="$EXTRA_SNAPS console-conf"
;;
esac
for snap in $EXTRA_SNAPS; do
UBUNTU_IMAGE_ARGS="$UBUNTU_IMAGE_ARGS --snap=$snap"
done
echo "IMAGEFORMAT=$IMAGEFORMAT" >> config/common
# Store model assertion in top dir to get it picked up later as a build artifact
env SNAPPY_STORE_NO_CDN=1 snap known --remote model series=16 model="$MODEL" brand-id=canonical > "$PREFIX".model-assertion
echo "Configured ubuntu-image for the following model assertion:"
cat "$PREFIX".model-assertion
echo "----------------------------------------------------------"
else
# classic images
# Sometimes per-project quirks are necessary
IMAGE_PROJECT=$PROJECT
case "$IMAGE_PROJECT" in
ubuntu-cpc)
IMAGE_PROJECT="ubuntu-server"
;;
esac
LB_UBUNTU_IMAGES_REPO="${LB_UBUNTU_IMAGES_REPO:-git://git.launchpad.net/ubuntu-images}"
LB_UBUNTU_IMAGES_BRANCH="${LB_UBUNTU_IMAGES_BRANCH:-$SUITE}"
git clone "$LB_UBUNTU_IMAGES_REPO" -b "$LB_UBUNTU_IMAGES_BRANCH" image-definitions
IMAGE_DEFINITION="image-definitions/$IMAGE_PROJECT-$MODEL.yaml"
echo "IMAGE_DEFINITION=$IMAGE_DEFINITION" >> config/common
echo "Configured ubuntu-image to use image definition file $IMAGE_DEFINITION which has the following contents:"
cat "$IMAGE_DEFINITION"
echo "----------------------------------------------------------"
fi
# Save the model name used for building, mostly for any model-specific hook execution
echo "MODEL=$MODEL" >> config/common
echo "IMAGEFORMAT=$IMAGEFORMAT" >> config/common
echo "UBUNTU_IMAGE_ARGS=\"$UBUNTU_IMAGE_ARGS\"" >> config/common
# Fake finished configuration for lb build
mkdir -p .build
touch .build/config
exit 0
;;
none)
# Currently the IMAGEFORMAT none format is used only for ubuntu-image
# targeted image builds which, currently, only target physical devices.
OPTS="${OPTS:+$OPTS }--chroot-filesystem $IMAGEFORMAT"
PREINSTALLED=true
;;
*)
case $PROJECT in
kubuntu|lubuntu|ubuntu-unity)
add_package live casper
;;
esac
;;
esac
if [ "$PREINSTALLED" = "true" ]; then
# LP Bug: 2044154 Enable universe on pre-installed images
touch config/universe-enabled
fi
case $BINARYFORMAT in
iso*|usb*)
BINARY_IMAGES="$BINARYFORMAT"
MEMTEST=memtest86+
BOOTLOADER=syslinux
OPTS="${OPTS:+$OPTS }--zsync=false"
;;
esac
if [ "${SUBPROJECT:-}" = minimized ]; then
OPTS="${OPTS:+$OPTS }--bootstrap-flavour=minimal --linux-packages=linux-image"
fi
mkdir -p config/germinate-output
case $PROJECT in
edubuntu*)
FLAVOUR=edubuntu
;;
kubuntu*)
FLAVOUR=kubuntu
;;
xubuntu*)
FLAVOUR=xubuntu
;;
ubuntu-mate*)
FLAVOUR=ubuntu-mate
;;
ubuntu-unity*)
FLAVOUR=ubuntu-unity
;;
lubuntu*)
FLAVOUR=lubuntu
;;
ubuntu-budgie*)
FLAVOUR=ubuntu-budgie
;;
ubuntukylin*)
FLAVOUR=ubuntukylin
;;
ubuntustudio*)
FLAVOUR=ubuntustudio
;;
ubuntucinnamon*)
FLAVOUR=ubuntucinnamon
;;
*)
FLAVOUR=ubuntu
;;
esac
case $PROJECT in
ubuntu-server|ubuntu-mini-iso)
COMPONENTS='main'
;;
edubuntu|ubuntu-budgie|ubuntucinnamon|ubuntukylin)
COMPONENTS='main restricted universe'
;;
lubuntu|kubuntu|ubuntu-mate|ubuntu-unity|ubuntustudio|xubuntu)
COMPONENTS='main restricted universe multiverse'
;;
esac
case $SUBPROJECT in
buildd)
COMPONENTS='main restricted universe multiverse'
;;
esac
if ! [ -e config/germinate-output/structure ]; then
echo "Running germinate..."
if [ -n "$COMPONENTS" ]; then
GERMINATE_ARG="-c $(echo $COMPONENTS | sed -e's/ \+/,/g')"
fi
(cd config/germinate-output && germinate --no-rdepends --no-installer \
-S $SEEDMIRROR -m $MIRROR -d $SUITE,$SUITE-updates \
-s $FLAVOUR.$SUITE $GERMINATE_ARG -a $ARCH)
fi
do_layered_desktop_image() {
touch config/universe-enabled
PASSES_TO_LAYERS="true"
if [ -n "$HAS_MINIMAL" ]; then
if [ -z "$MINIMAL_TASKS" ]; then
MINIMAL_TASKS="${FLAVOUR}-desktop-minimal"
if [ -n "$HAS_DEFAULT_LANGUAGES" ]; then
MINIMAL_TASKS="$MINIMAL_TASKS ${FLAVOUR}-desktop-minimal-default-languages"
fi
fi
# the minimal layer, for minimal installs
add_task minimal minimal standard $MINIMAL_TASKS
# fixme: this should go in seeds, not be in code here
add_package minimal cloud-init
MINIMAL_PREFIX=minimal.
fi
LIVE_PREFIX=$MINIMAL_PREFIX
# the standard layer, contains all base common packages for later layers
if [ "$HAS_STANDARD" != no ]; then
if [ -z "$STANDARD_TASKS" ]; then
STANDARD_TASKS="${FLAVOUR}-desktop"
if [ -n "$HAS_DEFAULT_LANGUAGES" ]; then
STANDARD_TASKS="$STANDARD_TASKS ${FLAVOUR}-desktop-default-languages"
fi
fi
if [ -z "$HAS_MINIMAL" ]; then
STANDARD_TASKS="minimal standard $STANDARD_TASKS"
add_package standard cloud-init
fi
add_task ${MINIMAL_PREFIX}standard $STANDARD_TASKS
LIVE_PREFIX="${LIVE_PREFIX}standard."
fi
# the live layer, contains all packages for the live session installer
[ -n "$LIVE_TASK" ] || LIVE_TASK=${FLAVOUR}-live
add_task ${LIVE_PREFIX}live "$LIVE_TASK"
add_package ${LIVE_PREFIX}live linux-$KERNEL_FLAVOURS casper
if [ -n "$LANGUAGE_BASE" ]; then
# language support
seeded_langs="$(get_seeded_languages $LANGUAGE_BASE)"
echo "$seeded_langs" | tr ' ' ',' > config/seeded-languages
if [ -n "$HAS_MINIMAL" ]; then
derive_language_layers minimal \
${LANGUAGE_BASE}-minimal \
${LANGUAGE_BASE}-minimal-default-languages \
"$seeded_langs"
fi
if [ "$HAS_STANDARD" != no ]; then
derive_language_layers ${LIVE_PREFIX%.} $LANGUAGE_BASE \
${LANGUAGE_BASE}-default-languages \
"$seeded_langs"
fi
fi
# now let's create the necessary catalog files
[ -n "$LOCALE_SUPPORT" ] || LOCALE_SUPPORT=langpack
[ -n "$UCFLAVOUR" ] || UCFLAVOUR=$(echo $FLAVOUR | sed -e's/^./\U&\E/')
[ -n "$STANDARD_NAME" ] || STANDARD_NAME="$UCFLAVOUR Desktop"
[ -n "$STANDARD_DESC" ] \
|| STANDARD_DESC="A full featured $UCFLAVOUR Desktop."
if [ -z "$MINIMAL_IS_DEFAULT" ]; then
if [ "$HAS_STANDARD" = no ]; then
MINIMAL_IS_DEFAULT=yes
else
MINIMAL_IS_DEFAULT=no
fi
fi
if [ "$MINIMAL_IS_DEFAULT" = yes ]; then
STANDARD_IS_DEFAULT=no
else
STANDARD_IS_DEFAULT=yes
fi
if [ -n "$HAS_MINIMAL" ]; then
[ -n "$MINIMAL_NAME" ] \
|| MINIMAL_NAME="$STANDARD_NAME (minimized)"
cat <<-EOF > config/minimal.catalog-in.yaml
name: "$MINIMAL_NAME"
description: >-
$MINIMAL_DESC
id: ${FLAVOUR}-desktop-minimal
type: fsimage-layered
default: $MINIMAL_IS_DEFAULT
variant: desktop
locale_support: $LOCALE_SUPPORT
EOF
fi
if [ "$HAS_STANDARD" != no ]; then
cat <<-EOF > config/${MINIMAL_PREFIX}standard.catalog-in.yaml
name: "$STANDARD_NAME"
description: >-
$STANDARD_DESC
id: ${FLAVOUR}-desktop
type: fsimage-layered
default: $STANDARD_IS_DEFAULT
variant: desktop
locale_support: $LOCALE_SUPPORT
EOF
fi
if [ "$LOCALE_SUPPORT" != none ]; then
/usr/share/livecd-rootfs/checkout-translations-branch \
https://git.launchpad.net/subiquity po \
config/catalog-translations
fi
}
case $PROJECT in
ubuntu)
case ${SUBPROJECT:-} in
desktop-preinstalled)
add_task install minimal standard ubuntu-desktop
case $SUBARCH in
raspi)
add_task install ubuntu-desktop-raspi
# XXX: Are those actually needed? I see we use those for ubuntu-cpc, which is the project
# for existing raspi preinstalled images
# XXX: I would prefer to use --hdd-label=desktop-rootfs like 040-hyperv-desktop-images.binary
OPTS="${OPTS:+$OPTS }--initramfs=none"
OPTS="${OPTS:+$OPTS }--system=normal"
OPTS="${OPTS:+$OPTS }--hdd-label=cloudimg-rootfs"
OPTS="${OPTS:+$OPTS }--ext-resize-blocks=536870912 --ext-block-size=4096"
OPTS="${OPTS:+$OPTS }--ext-fudge-factor=15"
;;
intel-iot)
KERNEL_FLAVOURS='intel-iotg'
OPTS="${OPTS:+$OPTS }--initramfs=none"
OPTS="${OPTS:+$OPTS }--system=normal"
OPTS="${OPTS:+$OPTS }--hdd-label=cloudimg-rootfs"
OPTS="${OPTS:+$OPTS }--ext-resize-blocks=536870912 --ext-block-size=4096"
OPTS="${OPTS:+$OPTS }--ext-fudge-factor=15"
;;
*)
## Otherwise HYPERV image options.... *crickets* see the hyperv hook
;;
esac
;;
*)
HAS_MINIMAL=yes
MINIMAL_DESC="A minimal but usable Ubuntu Desktop."
MINIMAL_IS_DEFAULT=yes
HAS_DEFAULT_LANGUAGES=yes
LANGUAGE_BASE=desktop
KERNEL_FLAVOURS='generic-hwe-24.04'
do_layered_desktop_image
# Enchanced secureboot stuff
case "$ARCH" in
amd64)
# the enhanced-secureboot layer, contains all packages for the enhanced secureboot install
add_package minimal.enhanced-secureboot cryptsetup boot-managed-by-snapd
add_package minimal.standard.enhanced-secureboot cryptsetup boot-managed-by-snapd
derive_language_layers minimal.enhanced-secureboot desktop-minimal desktop-default-languages "$seeded_langs"
derive_language_layers minimal.standard.enhanced-secureboot desktop desktop-default-languages "$seeded_langs"
cat <<-EOF > config/minimal.enhanced-secureboot.catalog-in.yaml
id: ubuntu-desktop-minimal
variations:
minimal:
path: minimal.squashfs
minimal-enhanced-secureboot:
path: minimal.enhanced-secureboot.squashfs
snapd_system_label: enhanced-secureboot-desktop
EOF
cat <<-EOF > config/minimal.standard.enhanced-secureboot.catalog-in.yaml
id: ubuntu-desktop
variations:
standard:
path: minimal.standard.squashfs
enhanced-secureboot:
path: minimal.standard.enhanced-secureboot.squashfs
snapd_system_label: enhanced-secureboot-desktop
EOF
;;
esac
;;
esac
;;
ubuntu-oem)
HAS_MINIMAL=yes
MINIMAL_NAME="Ubuntu Desktop for OEM (minimal)"
MINIMAL_DESC="Ubuntu Desktop (minimal) for OEM preinstallation."
STANDARD_NAME="Ubuntu Desktop for OEM"
STANDARD_DESC="Ubuntu Desktop for OEM preinstallation."
HAS_DEFAULT_LANGUAGES=yes
#KERNEL_FLAVOURS='oem-24.04'
KERNEL_FLAVOURS='generic-hwe-24.04'
LOCALE_SUPPORT=none
do_layered_desktop_image
;;
kubuntu)
add_task install minimal standard
add_task install kubuntu-desktop
LIVE_TASK='kubuntu-live'
add_chroot_hook remove-gnome-icon-cache
;;
edubuntu)
# Edubuntu now ships the new installer.
HAS_MINIMAL=yes
MINIMAL_TASKS=edubuntu-desktop-gnome-minimal
MINIMAL_DESC="A minimal installation of the Edubuntu Desktop."
STANDARD_TASKS=edubuntu-desktop-gnome
KERNEL_FLAVOURS=generic
do_layered_desktop_image
;;
ubuntucinnamon)
# Ubuntu Cinnamon now ships the new installer.
UCFLAVOUR="Ubuntu Cinnamon"
HAS_MINIMAL=yes
MINIMAL_DESC="A minimal installation of the $UCFLAVOUR Desktop."
KERNEL_FLAVOURS=generic
do_layered_desktop_image
;;
lubuntu|ubuntu-unity)
add_task install minimal standard ${PROJECT}-desktop
LIVE_TASK=${PROJECT}-live
;;
ubuntukylin)
# Ubuntu Kylin now ships the new installer.
UCFLAVOUR="Ubuntu Kylin"
HAS_MINIMAL=yes
MINIMAL_DESC="A minimal installation of the $UCFLAVOUR Desktop."
KERNEL_FLAVOURS=generic
do_layered_desktop_image
;;
xubuntu)
# Xubuntu now ships the new installer.
HAS_MINIMAL=yes
MINIMAL_TASKS=xubuntu-minimal
MINIMAL_NAME="Xubuntu Minimal"
MINIMAL_DESC="A minimal installation of the Xubuntu Desktop."
KERNEL_FLAVOURS=generic
case ${SUBPROJECT:-} in
minimal)
HAS_STANDARD=no
;;
esac
do_layered_desktop_image
;;
ubuntu-budgie)
# Ubuntu Budgie now ships the new installer.
UCFLAVOUR="Ubuntu Budgie"
HAS_MINIMAL=yes
MINIMAL_DESC="A minimal but usable $UCFLAVOUR Desktop."
HAS_DEFAULT_LANGUAGES=yes
LANGUAGE_BASE=desktop
KERNEL_FLAVOURS='generic-hwe-24.04'
do_layered_desktop_image
;;
ubuntu-mate)
# Ubuntu MATE now ships the new installer.
UCFLAVOUR="Ubuntu MATE"
HAS_MINIMAL=yes
MINIMAL_TASKS=ubuntu-mate-core
MINIMAL_DESC="A minimal installation of the $UCFLAVOUR Desktop."
KERNEL_FLAVOURS=generic
do_layered_desktop_image
;;
ubuntustudio)
# By default Ubuntu Studio now ships the new installer.
UCFLAVOUR="Ubuntu Studio"
HAS_MINIMAL=yes
MINIMAL_TASKS=ubuntustudio-desktop-core
MINIMAL_DESC="A minimal installation of $UCFLAVOUR. Customize afterwards with $UCFLAVOUR Installer."
STANDARD_DESC="A full installation of $UCFLAVOUR."
KERNEL_FLAVOURS=generic
do_layered_desktop_image
;;
ubuntu-server)
case ${SUBPROJECT:-} in
live)
OPTS="${OPTS:+$OPTS }--bootstrap-flavour=minimal"
PASSES_TO_LAYERS=true
add_task ubuntu-server-minimal server-minimal
add_package ubuntu-server-minimal lxd-installer
add_task ubuntu-server-minimal.ubuntu-server minimal standard server
add_package ubuntu-server-minimal.ubuntu-server cloud-init
add_task ubuntu-server-minimal.ubuntu-server.installer server-live
# Live server ISOs for LTS point releases past .2 offer both
# the GA and HWE kernels (in separate layers) so this code is
# written generically to support both even though a lot of the
# time only one kernel is offered.
case ${SUBARCH:-} in
intel-iot)
variants='intel'
;;
tegra)
variants='tegra'
;;
tegra-igx)
variants='tegra-igx'
;;
largemem)
# variants='ga-64k hwe-64k'
variants='ga-64k'
;;
*)
# variants='ga hwe'
variants='ga'
;;
esac
for variant in $variants; do
if [ "$variant" = "ga" ]; then
kernel_metapkg=linux-generic
flavor=generic
elif [ "$variant" = "hwe" ]; then
kernel_metapkg=linux-generic-hwe-$(lsb_release -sr)
flavor=generic-hwe
elif [ "$variant" = "ga-64k" ]; then
kernel_metapkg=linux-generic-64k
flavor=generic-64k
elif [ "$variant" = "hwe-64k" ]; then
kernel_metapkg=linux-generic-64k-hwe-$(lsb_release -sr)
flavor=generic-64k-hwe
elif [ "$variant" = "intel" ]; then
kernel_metapkg=linux-intel-iotg
flavor=intel-iotg
elif [ "$variant" = "tegra" ]; then
kernel_metapkg=linux-nvidia-tegra
flavor=nvidia-tegra
elif [ "$variant" = "tegra-igx" ]; then
kernel_metapkg=linux-nvidia-tegra-igx
flavor=nvidia-tegra-igx
else
echo "bogus variant: $variant"
exit 1
fi
add_pass ubuntu-server-minimal.ubuntu-server.installer.$flavor
if [ $flavor == ga ]; then
kernel_layer=ubuntu-server-minimal
else
kernel_layer=ubuntu-server-minimal.ubuntu-server.installer.$flavor
fi
add_package $kernel_layer $kernel_metapkg
LIVE_PASSES="${LIVE_PASSES:+$LIVE_PASSES }ubuntu-server-minimal.ubuntu-server.installer.$flavor"
done
case $ARCH in
amd64)
add_package ubuntu-server-minimal.ubuntu-server.installer.$flavor.netboot grub-pc shim-signed pxelinux
;;
arm64)
add_package ubuntu-server-minimal.ubuntu-server.installer.$flavor.netboot shim-signed
;;
*)
add_package ubuntu-server-minimal.ubuntu-server.installer.$flavor.netboot
;;
esac
NO_SQUASHFS_PASSES=ubuntu-server-minimal.ubuntu-server.installer.$flavor.netboot
/usr/share/livecd-rootfs/checkout-translations-branch \
https://git.launchpad.net/subiquity po config/catalog-translations
;;
*)
echo "unrecognized subproject for server: '$SUBPROJECT'"
exit 1
;;
esac
PREINSTALL_POOL_SEEDS='server-ship'
;;
ubuntu-core-installer)
# The ubuntu-core-installer image is an installer that installs ubuntu
# core. The environment the installer runs in is similar to the server
# installer but it has a source catalog entry that points to the model
# created in ubuntu-core-installer/hooks/05-prepare-image.binary, which
# subiquity knows how to install.
if [ ${SUBPROJECT} == "desktop" ]; then
cp /usr/share/livecd-rootfs/live-build/${PROJECT}/ubuntu-core-desktop-24-amd64.model-assertion config/
fi
OPTS="${OPTS:+$OPTS }--bootstrap-flavour=minimal"
PASSES_TO_LAYERS=true
add_task base server-minimal server
add_task base.live server-live
add_package base.live linux-image-generic
/usr/share/livecd-rootfs/checkout-translations-branch \
https://git.launchpad.net/subiquity po config/catalog-translations
;;
ubuntu-mini-iso)
OPTS="${OPTS:+$OPTS }--bootstrap-flavour=minimal"
OPTS="${OPTS:+$OPTS }--linux-packages=none --initramfs=none"
KERNEL_FLAVOURS=none
BINARY_REMOVE_LINUX=false
add_package install mini-iso-tools linux-generic
case $ARCH in
amd64)
add_package install cd-boot-images-amd64
;;
*)
echo "unexpected architecture for $PROJECT: '$ARCH'"
exit 1
;;
esac
;;
ubuntu-base|ubuntu-oci)
OPTS="${OPTS:+$OPTS }--bootstrap-flavour=minimal"
;;
ubuntu-wsl)
add_task install minimal ubuntu-wsl
OPTS="${OPTS:+$OPTS }--linux-packages=none --initramfs=none"
KERNEL_FLAVOURS=none
BINARY_REMOVE_LINUX=false
;;
ubuntu-cpc)
KERNEL_FLAVOURS=virtual
if [ "${SUBPROJECT:-}" = minimized ]; then
# For minimized images we do not want to install any recommended packages.
# We can do this by setting APT::Install-Recommends to false in apt config
# or by passing --no-install-recommends to apt-get install.
# Apt config is set using `APT_OPTIONS` variable in this script.
# This fixes LP: #2031640
APT_OPTIONS="${APT_OPTIONS:+$APT_OPTIONS }--no-install-recommends"
add_package install ubuntu-cloud-minimal
else
add_task install minimal standard cloud-image
add_package install ubuntu-minimal
case $ARCH in
armhf|arm64|ppc64el|powerpc)
add_task install server
;;
esac
fi
BINARY_REMOVE_LINUX=false
OPTS="${OPTS:+$OPTS }--initramfs=none"
case "$ARCH+${SUBARCH:-}" in
arm64+raspi)
add_task install ubuntu-server-raspi
;;
arm64*)
if [ "${SUBARCH:-}" = "generic" ]; then
KERNEL_FLAVOURS=generic
fi
;;
amd64*)
if [ "${SUBARCH:-}" = "generic" ]; then
KERNEL_FLAVOURS=generic
elif [ "${SUBARCH:-}" = "intel-iot" ]; then
KERNEL_FLAVOURS=intel-iotg
OPTS="${OPTS:+$OPTS }--initramfs=none"
fi
;;
riscv64*)
if [ -n "$SUBARCH" ]; then
case "${SUBARCH:-}" in
nezha|licheerv)
KERNEL_FLAVOURS=allwinner
;;
visionfive)
KERNEL_FLAVOURS=starfive
;;
*)
KERNEL_FLAVOURS=generic
;;
esac
fi
;;
esac
OPTS="${OPTS:+$OPTS }--system=normal"
OPTS="${OPTS:+$OPTS }--hdd-label=cloudimg-rootfs"
OPTS="${OPTS:+$OPTS }--ext-resize-blocks=536870912 --ext-block-size=4096"
OPTS="${OPTS:+$OPTS }--ext-fudge-factor=15"
;;
*)
echo "unknown project $PROJECT" >&2
exit 2
;;
esac
case $SUBPROJECT in
buildd)
OPTS="${OPTS:+$OPTS }--archive-areas main"
OPTS="${OPTS:+$OPTS }--apt-recommends false"
OPTS="${OPTS:+$OPTS }--apt-secure false"
OPTS="${OPTS:+$OPTS }--parent-mirror-binary ${MIRROR}"
# XXX cjwatson 2018-04-27: We need to work out how to make
# this conditional so that we can do things like building
# buildd chroots with -updates. This probably involves
# either extending the PROPOSED hack or fixing the strange
# way that SUITE is in fact a series; in either case it's
# likely to involve work both here and in launchpad-buildd.
OPTS="${OPTS:+$OPTS }--security false --volatile false"
add_package install adduser
add_package install pkgbinarymangler
add_package install ca-certificates
add_package install gpg
add_package install gpg-agent
add_package install fakeroot
add_package install build-essential
# Needed for LXD-based builds.
add_package install init
# Needed for bootable buildd systems which don't get injected
# nameserver configuration. (LP: 2007419)
add_package install systemd-resolved
# Not strictly build-essential, but traditionally present
# and a variety of things fail without it.
add_package install tzdata
cp -af /usr/share/livecd-rootfs/live-build/make-lxd-metadata.py config/make-lxd-metadata
;;
esac
if [ "$PROJECT:${SUBPROJECT:-}" = ubuntu-cpc:minimized ]; then
# We install a lxc script that installs the snap when invoked and
# don't want any other snaps.
if [ -s config/seeded-snaps ]; then
echo "Unexpected seeded snaps for ubuntu-cpc:minimized build:"
cat config/seeded-snaps
exit 1
fi
# Create an empty file to trigger initialization of assertions.
truncate --size 0 config/seeded-snaps
fi
# grab a list of packags to remove for a "minimal" installation from the seed
# mirror for this project
case $PROJECT in
kubuntu|ubuntu-mate|ubuntu-unity|ubuntukylin)
# only used now for the 'minimal-remove' functionality,
# which is not used at all in layered images
BASE_SEED='desktop'
;;
esac
if [ -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
export APT_OPTIONS
if [ "$PREINSTALLED" != "true" ] && [ "$PASSES_TO_LAYERS" != "true" ] && [ "$LIVE_TASK" ]; then
add_task live "$LIVE_TASK"
fi
case "$ARCH${SUBARCH:++$SUBARCH}" in
arm64+raspi)
# Common configuration for all Raspberry Pi image variants (server,
# desktop etc.)
KERNEL_FLAVOURS="$SUBARCH"
# Most Pi-specific package installation is handled via the seeds in the
# per-project/subproject cases above
add_package install linux-firmware-raspi pi-bluetooth u-boot-rpi u-boot-tools
BINARY_REMOVE_LINUX=false
;;
arm64+tegra|arm64+tegra-igx)
# Common configuration for all NVIDIA Tegra image variants
# (server, desktop etc.)
KERNEL_FLAVOURS="nvidia-$SUBARCH"
;;
riscv*+*)
# We'll add wpasupplicant to the seeds when we work on RISC-V seeds.
add_package install wpasupplicant
;;
esac
case $PROJECT:${SUBPROJECT:-} in
ubuntu-server:*|ubuntu-base:*|ubuntu-oci:*|ubuntu-core-installer:*)
OPTS="${OPTS:+$OPTS }--linux-packages=none --initramfs=none"
KERNEL_FLAVOURS=none
BINARY_REMOVE_LINUX=false
;;
esac
add_chroot_hook update-apt-file-cache
add_chroot_hook update-apt-xapian-index
add_chroot_hook update-mlocate-database
add_chroot_hook remove-dbus-machine-id
add_chroot_hook remove-openssh-server-host-keys
add_chroot_hook remove-udev-persistent-rules
case $PROJECT in
# if any flavours want to strip .pyc files from their live images, add them here
_)
add_chroot_hook remove-python-py
;;
esac
lb config noauto \
--mode ubuntu \
--distribution "$SUITE" \
--iso-preparer "livecd-rootfs" \
--bootstrap-keyring ubuntu-keyring \
--binary-images "$BINARY_IMAGES" \
--memtest "$MEMTEST" \
$SOURCE \
--build-with-chroot false \
${MIRROR:+--parent-mirror-bootstrap $MIRROR} \
${COMPONENTS:+--parent-archive-areas "$COMPONENTS"} \
--apt-source-archives false \
${KERNEL_FLAVOURS:+--linux-flavours "$KERNEL_FLAVOURS"} \
--initsystem none \
--bootloader "$BOOTLOADER" \
${INITRAMFS_COMPRESSION:+--initramfs-compression "$INITRAMFS_COMPRESSION"} \
--checksums none \
--cache false \
${BOOTAPPEND_LIVE:+--bootappend-live "$BOOTAPPEND_LIVE"} \
$OPTS \
"$@"
PASSES=$(_sanitize_passes "$PASSES")
LIVE_PASSES=${LIVE_PASSES:-$(_get_live_passes "$PASSES")}
if [ -n "$PASSES" ] && [ -z "$LIVE_PASSES" ]; then
echo "W: Multi-layered mode is enabled, but we didn't find any live pass." \
"Either set \$LIVE_PASSES or add a pass ending with '.live'."
fi
echo "LB_CHROOT_HOOKS=\"$CHROOT_HOOKS\"" >> config/chroot
echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/chroot
echo "LB_DISTRIBUTION=\"$SUITE\"" >> config/chroot
echo "IMAGEFORMAT=\"$IMAGEFORMAT\"" >> config/chroot
if [ -n "$PASSES" ]; then
echo "PASSES=\"$PASSES\"" >> config/common
fi
if [ -n "$NO_SQUASHFS_PASSES" ]; then
echo "NO_SQUASHFS_PASSES=\"$NO_SQUASHFS_PASSES\"" >> config/common
fi
if [ -n "$LIVE_PASSES" ]; then
echo "LIVE_PASSES=\"$LIVE_PASSES\"" >> config/common
fi
echo "LB_BINARY_HOOKS=\"$BINARY_HOOKS\"" >> config/binary
echo "BUILDSTAMP=\"$NOW\"" >> config/binary
echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/binary
echo "LB_DISTRIBUTION=\"$SUITE\"" >> config/binary
echo "CHANNEL=\"${CHANNEL:-}\"" >> config/binary
if [ "${IMAGE_HAS_HARDCODED_PASSWORD:-}" = "1" ]; then
echo IMAGE_HAS_HARDCODED_PASSWORD=1 >> config/binary
if [ -n "${IMAGE_TARGETS:-}" ]; then
echo "IMAGE_TARGETS=\"${IMAGE_TARGETS:-}\"" >> config/binary
fi
fi
# apply this hook unconditionally to remove files from the chroot that
# are supposed to be install-specific secrets and therefore must never
# be shipped in any image.
# this hook should be extended if we discover any more files that are
# supposed to be private but aren't.
cat > config/hooks/100-too-many-secrets.chroot <<EOF
#!/bin/sh
rm -fv /etc/ssl/private/ssl-cert-snakeoil.key \
/etc/ssl/certs/ssl-cert-snakeoil.pem
EOF
case $PROJECT in
ubuntu-cpc|ubuntu-core|ubuntu-base|ubuntu-oci|ubuntu-wsl|ubuntu-mini-iso)
# ubuntu-cpc gets this added in 025-create-groups.chroot, and we do
# not want this group in projects that are effectively just chroots
;;
*)
# We add the lxd group at image build time so that the default user
# created by the installer or cloud-init is added to it (cloud-init
# will create any group the user is configured to be added to, but as
# a normal group not a system group, see
# https://bugs.launchpad.net/cloud-images/+bug/1844498).
cat > config/hooks/100-add-lxd-group.chroot <<EOF
#!/bin/bash
echo "Adding lxd group..."
addgroup --system --quiet lxd
EOF
;;
esac
case "$ARCH+${SUBARCH:-}" in
arm64+raspi)
cat > config/hooks/01-firmware-directory.chroot_early <<EOF
#!/bin/sh -ex
mkdir -p /boot/firmware
EOF
cat > config/hooks/999-raspi-fixes.chroot <<EOF
#!/bin/sh -ex
cat >> /etc/fstab << EOM
LABEL=system-boot /boot/firmware vfat defaults 0 1
EOM
EOF
;;
*)
;;
esac
if [ $PROJECT != ubuntu-cpc ]; then
cat > config/hooks/100-preserve-apt-prefs.chroot <<\EOF
#! /bin/sh -ex
# live-build "helpfully" removes /etc/apt/preferences.d/* so we put a
# copy somewhere it won't touch it.
if [ -n "$(ls -A /etc/apt/preferences.d)" ]; then
cp -a /etc/apt/preferences.d /etc/apt/preferences.d.save
fi
EOF
fi
if [ $PROJECT = ubuntukylin ]; then
cat > config/hooks/100-ubuntukylin.chroot <<EOF
#! /bin/sh
set -e
HOOK=/usr/share/ubuntukylin-default-settings/hooks/chroot
if [ -x \$HOOK ]; then
exec \$HOOK
fi
exit 0
EOF
fi
if $BINARY_REMOVE_LINUX; then
cat > config/binary_rootfs/excludes << EOF
boot/vmlinu?-*
boot/initrd.img-*
EOF
fi
if [ "$PROPOSED" ]; then
. config/bootstrap
cat > config/archives/proposed.list.chroot << EOF
deb $LB_PARENT_MIRROR_BINARY_VOLATILE $SUITE-proposed $LB_PARENT_ARCHIVE_AREAS
EOF
cp -a config/archives/proposed.list.chroot \
config/archives/proposed.list.binary
mkdir -p config/chroot_apt/
cat > config/chroot_apt/proposed.pref <<EOF
# override for NotAutomatic: yes
Package: *
Pin: release a=*-proposed
Pin-Priority: 500
EOF
fi
case $PROJECT:${SUBPROJECT:-} in
ubuntu-cpc:*|ubuntu-server:live|ubuntu:desktop-preinstalled| \
ubuntu-wsl:*|ubuntu-mini-iso:*|ubuntu:|ubuntu-oem:*| \
ubuntustudio:*|edubuntu:*|ubuntu-budgie:*|ubuntucinnamon:*|xubuntu:*| \
ubuntukylin:*|ubuntu-mate:*|ubuntu-core-installer:*)
# Ensure that most things e.g. includes.chroot are copied as is
for entry in /usr/share/livecd-rootfs/live-build/${PROJECT}/*; do
case $entry in
*hooks*)
# But hooks are shared across the projects with symlinks
# dereference them
cp -afL $entry config/
;;
*)
# Most places want to preserve symlinks as is
cp -af $entry config/
;;
esac
done
if [ "$PROJECT" = "ubuntu-cpc" ] || [ "$PROJECT" = "ubuntu-oem" ] ; then
case ${IMAGE_TARGETS:-} in
"")
config/hooks.d/make-hooks --hooks-dir config/hooks all
;;
*)
config/hooks.d/make-hooks --hooks-dir config/hooks \
"$IMAGE_TARGETS"
;;
esac
fi
if [ "$IMAGEFORMAT" = none ]; then
rm -f config/hooks/*.binary*
fi
;;
esac
case $PROJECT in
ubuntu-oem|ubuntustudio|edubuntu|ubuntu-budgie|ubuntucinnamon| \
xubuntu|ubuntukylin|ubuntu-mate)
cp -af /usr/share/livecd-rootfs/live-build/ubuntu/includes.chroot \
config/includes.chroot
LIVE_LAYER=${LIVE_PREFIX}live
cp -af /usr/share/livecd-rootfs/live-build/ubuntu/includes.chroot.minimal.standard.live \
config/includes.chroot.$LIVE_LAYER
if [ $PROJECT != ubuntu-oem ]; then
# Per note at
# https://code.launchpad.net/~dbungert/livecd-rootfs/+git/livecd-rootfs/+merge/461665/comments/1240590,
# these files are expected to be moved out of livecd-rootfs,
# and are also incorrect for flavors.
rm -f config/includes.chroot.$LIVE_LAYER/usr/lib/systemd/user/ubuntu-desktop-installer.service
rm -f config/includes.chroot.$LIVE_LAYER/share/glib-2.0/schemas/livecd-rootfs.gschema.override
fi
;;
esac
case $SUBPROJECT in
buildd)
cp -af /usr/share/livecd-rootfs/live-build/buildd/* config/
;;
esac
if [ "$EXTRA_PPAS" ]; then
rm -f config/archives/extra-ppas.list.chroot \
config/archives/extra-ppas.pref.chroot \
config/archives/extra-ppas.key.chroot
gpg_tmpdir="$(mktemp -d)"
run_gpg () {
gpg --no-default-keyring --no-options --homedir "$gpg_tmpdir" \
--secret-keyring "$gpg_tmpdir/secring.gpg" \
--keyserver hkp://keyserver.ubuntu.com:80/ \
"$@"
}
for extra_ppa in $EXTRA_PPAS; do
extra_ppa_pin=''
extra_ppa_origin=''
case $extra_ppa in
*:*)
extra_ppa_pin=${extra_ppa#*:}
extra_ppa=${extra_ppa%:*}
;;
esac
extra_ppa_fingerprint="$(/usr/share/livecd-rootfs/get-ppa-fingerprint "$extra_ppa")"
cat >> config/archives/extra-ppas.list.chroot <<EOF
deb http://ppa.launchpad.net/$extra_ppa/ubuntu @DISTRIBUTION@ main
deb-src http://ppa.launchpad.net/$extra_ppa/ubuntu @DISTRIBUTION@ main
EOF
if [ -n "$extra_ppa_pin" ]; then
extra_ppa_origin="LP-PPA-$(echo $extra_ppa | sed -e 's,/ppa$,,' -e 's,/,-,')"
echo "Package: *" >> config/archives/extra-ppas.pref.chroot
echo "Pin: release o=$extra_ppa_origin" >> config/archives/extra-ppas.pref.chroot
echo "Pin-Priority: $extra_ppa_pin" >> config/archives/extra-ppas.pref.chroot
echo "" >> config/archives/extra-ppas.pref.chroot
fi
run_gpg --keyring "$gpg_tmpdir/pubring.gpg" \
--recv "$extra_ppa_fingerprint"
run_gpg --keyring "$gpg_tmpdir/pubring.gpg" \
--output "$gpg_tmpdir/export.gpg" \
--export "$extra_ppa_fingerprint"
got_fingerprint="$(
run_gpg --keyring "$gpg_tmpdir/export.gpg" \
--fingerprint --batch --with-colons |
grep '^fpr:' | cut -d: -f10)"
if [ "$got_fingerprint" != "$extra_ppa_fingerprint" ]; then
echo "Fingerprints do not match. Got:" >&2
echo "$got_fingerprint" | sed 's/^/ /' >&2
echo "Expected:" >&2
echo " $extra_ppa_fingerprint" >&2
exit 1
fi
cat "$gpg_tmpdir/export.gpg" >> config/archives/extra-ppas.key.chroot
rm -f "$gpg_tmpdir/export.gpg"
done
rm -rf "$gpg_tmpdir"
cp -a config/archives/extra-ppas.list.chroot \
config/archives/extra-ppas.list.binary
cp -a config/archives/extra-ppas.key.chroot \
config/archives/extra-ppas.key.binary
if [ -f config/archives/extra-ppas.pref.chroot ]; then
cp -a config/archives/extra-ppas.pref.chroot \
config/archives/extra-ppas.pref.binary
fi
fi
if [ "$PREINSTALLED" = "true" ]; then
if [ -n "$PREINSTALL_POOL_SEEDS" ]; then
UNWANTED_SEEDS="${LIVE_TASK:+$LIVE_TASK }boot installer required"
for i in $UNWANTED_SEEDS; do
UNWANTED_SEEDS="${UNWANTED_SEEDS:+$UNWANTED_SEEDS }$(inheritance $i)"
done
for i in $PREINSTALL_POOL_SEEDS; do
PREINSTALL_POOL_SEEDS="${PREINSTALL_POOL_SEEDS:+$PREINSTALL_POOL_SEEDS }$(inheritance $i)"
done
for i in $PREINSTALL_POOL_SEEDS; do
case " $UNWANTED_SEEDS " in
*" $i "*)
;;
*)
PPS_EXP="${PPS_EXP:+$PPS_EXP }$i"
;;
esac
done
for i in $PPS_EXP; do
PREINSTALL_POOL="$PREINSTALL_POOL $(awk '{print $1}' \
config/germinate-output/$i | egrep -v '^-|^Package|^\|' | tr '\n' ' ')"
done
fi
if [ -n "$PREINSTALL_POOL" ]; then
mkdir -p config/gnupg
mkdir -p config/indices
for component in $COMPONENTS; do
(cd config/indices && \
wget $MIRROR/indices/override.$SUITE.$component && \
wget $MIRROR/indices/override.$SUITE.extra.$component \
)
done
cat > config/hooks/100-preinstall-pool.chroot <<EOF
#! /bin/sh
mkdir -p /var/lib/preinstalled-pool/pool/
cd /var/lib/preinstalled-pool/pool/
apt-get -y download $PREINSTALL_POOL
EOF
fi
fi