You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
966 lines
32 KiB
966 lines
32 KiB
#! /bin/sh
|
|
set -e
|
|
|
|
export LC_ALL=C
|
|
|
|
( . "${LIVE_BUILD}/scripts/build.sh" > /dev/null 2>&1 || true ) || . /usr/lib/live/build.sh
|
|
|
|
Arguments "${@}"
|
|
|
|
Read_conffiles config/all config/common config/bootstrap config/chroot config/binary config/source
|
|
Set_defaults
|
|
|
|
if [ -z "${PROJECT:-}" ]; then
|
|
echo "PROJECT environment variable has to be set" >&2
|
|
exit 1
|
|
fi
|
|
|
|
. config/functions
|
|
|
|
if [ -n "$REPO_SNAPSHOT_STAMP" ]; then
|
|
if [ "`whoami`" != "root" ]; then
|
|
echo "Magic repo snapshots only work when running as root." >&2
|
|
exit 1
|
|
fi
|
|
|
|
apt-get -qyy install iptables
|
|
|
|
# Redirect all outgoing traffic to port 80 to proxy instead.
|
|
iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner ! --uid-owner daemon \
|
|
-j REDIRECT --to 8080
|
|
|
|
# Run proxy as "daemon" to avoid infinite loop.
|
|
/usr/share/livecd-rootfs/magic-proxy \
|
|
--address="127.0.0.1" \
|
|
--port=8080 \
|
|
--run-as=daemon \
|
|
--cutoff-time="$REPO_SNAPSHOT_STAMP" \
|
|
--log-file=/build/livecd.magic-proxy.log \
|
|
--pid-file=config/magic-proxy.pid \
|
|
--background \
|
|
--setsid
|
|
fi
|
|
|
|
# Link output files somewhere launchpad-buildd will be able to find them.
|
|
PREFIX="livecd.$PROJECT${SUBARCH:+-$SUBARCH}"
|
|
|
|
if [ "${IMAGEFORMAT:-}" = "ubuntu-image" ]; then
|
|
# Use ubuntu-image instead of live-build
|
|
|
|
if [ "$PROJECT" = "ubuntu-core" ]; then
|
|
CHANNEL="${CHANNEL:-edge}"
|
|
env SNAPPY_STORE_NO_CDN=1 \
|
|
ubuntu-image snap -c "$CHANNEL" $UBUNTU_IMAGE_ARGS \
|
|
-O output "$PREFIX".model-assertion
|
|
# XXX: currently we only have one image generated, but really
|
|
# we should be supporting more than one for models that
|
|
# define those.
|
|
mv output/*.img "$PREFIX".img
|
|
xz -0 -T4 "$PREFIX".img
|
|
mv output/seed.manifest "$PREFIX".manifest
|
|
else
|
|
# First we need to build the gadget tree
|
|
make -C "config/$PREFIX-gadget" ARCH=$ARCH SERIES=$SUITE
|
|
ubuntu-image classic $UBUNTU_IMAGE_ARGS \
|
|
-s $SUITE -p $PROJECT -a $ARCH --subarch $SUBARCH \
|
|
-O output config/$PREFIX-gadget/install
|
|
# XXX: currently we only have one image generated, but really
|
|
# we should be supporting more than one for models that
|
|
# define those.
|
|
mv output/*.img "$PREFIX".img
|
|
xz -0 -T4 "$PREFIX".img
|
|
# Also link the output image to a filename that cdimage expects
|
|
ln "$PREFIX".img.xz livecd.ubuntu-cpc.disk1.img.xz
|
|
mv output/filesystem.manifest "$PREFIX".manifest
|
|
fi
|
|
|
|
exit 0
|
|
fi
|
|
|
|
# Setup cleanup function
|
|
Setup_cleanup
|
|
|
|
preinstall_snaps() {
|
|
lb chroot_resolv install
|
|
snap_prepare chroot
|
|
|
|
for snap in "$@"; do
|
|
snap_preseed chroot "${snap}"
|
|
done
|
|
lb chroot_resolv remove
|
|
}
|
|
|
|
rm -f binary.success
|
|
(
|
|
if [ -d config/gnupg ]; then
|
|
cat << @@EOF > config/gnupg/NEWKEY
|
|
Key-Type: DSA
|
|
Key-Length: 1024
|
|
Key-Usage: sign
|
|
Name-Real: Ubuntu Local Archive One-Time Signing Key
|
|
Name-Email: cdimage@ubuntu.com
|
|
Expire-Date: 0
|
|
@@EOF
|
|
gpg --home config/gnupg --gen-key --batch < config/gnupg/NEWKEY \
|
|
> config/gnupg/generate.log 2>&1 &
|
|
GPG_PROCESS=$!
|
|
fi
|
|
|
|
lb bootstrap "$@"
|
|
|
|
case $PROJECT in
|
|
ubuntu-server|ubuntu-cpc)
|
|
# Set locale to C.UTF-8 by default. We should
|
|
# probably do this for all images early in the
|
|
# 18.10 cycle but for now just do it for
|
|
# server and cpc products.
|
|
echo "LANG=C.UTF-8" > chroot/etc/default/locale
|
|
;;
|
|
esac
|
|
|
|
if [ "${SUBPROJECT:-}" = minimized ] \
|
|
&& ! Chroot chroot dpkg -l tzdata 2>&1 |grep -q ^ii; then
|
|
# workaround for tzdata purge not removing these files
|
|
rm -f chroot/etc/localtime chroot/etc/timezone
|
|
fi
|
|
|
|
if [ "${SUBPROJECT:-}" = minimized ]; then
|
|
# set up dpkg filters to skip installing docs on minimized system
|
|
mkdir -p chroot/etc/dpkg/dpkg.cfg.d
|
|
cat > chroot/etc/dpkg/dpkg.cfg.d/excludes <<EOF
|
|
# Drop all man pages
|
|
path-exclude=/usr/share/man/*
|
|
|
|
# Drop all documentation ...
|
|
path-exclude=/usr/share/doc/*
|
|
|
|
# ... except copyright files ...
|
|
path-include=/usr/share/doc/*/copyright
|
|
|
|
# ... and Debian changelogs
|
|
path-include=/usr/share/doc/*/changelog.Debian.*
|
|
EOF
|
|
|
|
# Remove docs installed by bootstrap
|
|
Chroot chroot dpkg-query -f '${binary:Package}\n' -W | Chroot chroot xargs apt-get install --reinstall
|
|
|
|
# Add unminimizer script which restores default image behavior
|
|
mkdir -p chroot/usr/local/sbin
|
|
cat > chroot/usr/local/sbin/unminimize <<'EOF'
|
|
#!/bin/sh
|
|
|
|
set -e
|
|
|
|
echo "This system has been minimized by removing packages and content that are"
|
|
echo "not required on a system that users do not log into."
|
|
echo ""
|
|
echo "This script restores content and packages that are found on a default"
|
|
echo "Ubuntu server system in order to make this system more suitable for"
|
|
echo "interactive use."
|
|
echo ""
|
|
echo "Reinstallation of packages may fail due to changes to the system"
|
|
echo "configuration, the presence of third-party packages, or for other"
|
|
echo "reasons."
|
|
echo ""
|
|
echo "This operation may take some time."
|
|
echo ""
|
|
read -p "Would you like to continue? [y/N] " REPLY
|
|
echo # (optional) move to a new line
|
|
if [ "$REPLY" != "y" ] && [ "$REPLY" != "Y" ]
|
|
then
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f /etc/dpkg/dpkg.cfg.d/excludes ] || [ -f /etc/dpkg/dpkg.cfg.d/excludes.dpkg-tmp ]; then
|
|
echo "Re-enabling installation of all documentation in dpkg..."
|
|
if [ -f /etc/dpkg/dpkg.cfg.d/excludes ]; then
|
|
mv /etc/dpkg/dpkg.cfg.d/excludes /etc/dpkg/dpkg.cfg.d/excludes.dpkg-tmp
|
|
fi
|
|
echo "Updating package list and upgrading packages..."
|
|
apt-get update
|
|
# apt-get upgrade asks for confirmation before upgrading packages to let the user stop here
|
|
apt-get upgrade
|
|
echo "Restoring system documentation..."
|
|
echo "Reinstalling packages with files in /usr/share/man/ ..."
|
|
# Reinstallation takes place in two steps because a single dpkg --verified
|
|
# command generates very long parameter list for "xargs dpkg -S" and may go
|
|
# over ARG_MAX. Since many packages have man pages the second download
|
|
# handles a much smaller amount of packages.
|
|
dpkg -S /usr/share/man/ |sed 's|, |\n|g;s|: [^:]*$||' | DEBIAN_FRONTEND=noninteractive xargs apt-get install --reinstall -y
|
|
echo "Reinstalling packages with system documentation in /usr/share/doc/ .."
|
|
# This step processes the packages which still have missing documentation
|
|
dpkg --verify --verify-format rpm | awk '/..5...... \/usr\/share\/doc/ {print $2}' | sed 's|/[^/]*$||' | sort |uniq \
|
|
| xargs dpkg -S | sed 's|, |\n|g;s|: [^:]*$||' | uniq | DEBIAN_FRONTEND=noninteractive xargs apt-get install --reinstall -y
|
|
if dpkg --verify --verify-format rpm | awk '/..5...... \/usr\/share\/doc/ {exit 1}'; then
|
|
echo "Documentation has been restored successfully."
|
|
rm /etc/dpkg/dpkg.cfg.d/excludes.dpkg-tmp
|
|
else
|
|
echo "There are still files missing from /usr/share/doc/:"
|
|
dpkg --verify --verify-format rpm | awk '/..5...... \/usr\/share\/doc/ {print " " $2}'
|
|
echo "You may want to try running this script again or you can remove"
|
|
echo "/etc/dpkg/dpkg.cfg.d/excludes.dpkg-tmp and restore the files manually."
|
|
fi
|
|
fi
|
|
|
|
if [ "$(dpkg-divert --truename /usr/bin/man)" = "/usr/bin/man.REAL" ]; then
|
|
# Remove diverted man binary
|
|
rm -f /usr/bin/man
|
|
dpkg-divert --quiet --remove --rename /usr/bin/man
|
|
fi
|
|
EOF
|
|
|
|
if [ "$PROJECT" != "ubuntu-base" ]; then
|
|
# ubuntu-minimal is too much for a docker container (it contains
|
|
# systemd and other things)
|
|
cat >> chroot/usr/local/sbin/unminimize <<'EOF'
|
|
|
|
if ! dpkg-query --show --showformat='${db:Status-Status}\n' ubuntu-minimal 2> /dev/null | grep -q '^installed$'; then
|
|
echo "Installing ubuntu-minimal package to provide the familiar Ubuntu minimal system..."
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y ubuntu-minimal ubuntu-standard
|
|
fi
|
|
|
|
if dpkg-query --show --showformat='${db:Status-Status}\n' ubuntu-server 2> /dev/null | grep -q '^installed$' \
|
|
&& ! dpkg-query --show --showformat='${db:Status-Status}\n' landscape-common 2> /dev/null | grep -q '^installed$'; then
|
|
echo "Installing ubuntu-server recommends..."
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y landscape-common
|
|
fi
|
|
EOF
|
|
fi
|
|
cat >> chroot/usr/local/sbin/unminimize <<'EOF'
|
|
|
|
# unminimization succeeded, there is no need to mention it in motd
|
|
rm -f /etc/update-motd.d/60-unminimize
|
|
EOF
|
|
chmod +x chroot/usr/local/sbin/unminimize
|
|
|
|
# inform users about the unminimize script
|
|
cat > "chroot/etc/update-motd.d/60-unminimize" << EOF
|
|
#!/bin/sh
|
|
#
|
|
# This file is not managed by a package. If you no longer want to
|
|
# see this message you can safely remove the file.
|
|
echo "This system has been minimized by removing packages and content that are"
|
|
echo "not required on a system that users do not log into."
|
|
echo ""
|
|
echo "To restore this content, you can run the 'unminimize' command."
|
|
EOF
|
|
|
|
chmod +x chroot/etc/update-motd.d/60-unminimize
|
|
Chroot chroot "dpkg-divert --quiet --add \
|
|
--divert /usr/bin/man.REAL --rename \
|
|
/usr/bin/man"
|
|
cat > chroot/usr/bin/man << EOF
|
|
#!/bin/sh
|
|
echo "This system has been minimized by removing packages and content that are"
|
|
echo "not required on a system that users do not log into."
|
|
echo ""
|
|
echo "To restore this content, including manpages, you can run the 'unminimize'"
|
|
echo "command. You will still need to ensure the 'man-db' package is installed."
|
|
EOF
|
|
chmod +x chroot/usr/bin/man
|
|
fi
|
|
|
|
if [ -n "${PASSES}" ]; then
|
|
PATH="config/:$PATH" lb chroot_layered "$@"
|
|
else
|
|
divert_update_initramfs
|
|
lb chroot "$@"
|
|
fi
|
|
|
|
# Let all configuration non multi-layered project here.
|
|
# If those are moving to a multi-layer layout, this needs to be
|
|
# done in chroot hooks.
|
|
if [ -z "$PASSES" ]; then
|
|
if [ "${SUBPROJECT:-}" = minimized ]; then
|
|
# force removal of initramfs-tools, which we assert is not
|
|
# required for any minimized images but is still pulled in by
|
|
# default
|
|
# also remove landscape-common, which is heavyweight and
|
|
# in the server seed only to provide /etc/motd content which
|
|
# would only be seen by humans
|
|
Chroot chroot "env DEBIAN_FRONTEND=noninteractive \
|
|
apt-get -y purge initramfs-tools busybox-initramfs \
|
|
busybox-static landscape-common"
|
|
# and if initramfs-tools was configured before our kernel,
|
|
# /etc/kernel/postinst.d/initramfs-tools will have created
|
|
# an initramfs despite the generic dpkg-divert; so remove it
|
|
# here.
|
|
rm -f chroot/boot/initrd.img-*
|
|
|
|
# temporary workaround: don't remove linux-base which
|
|
# may have no other reverse-depends currently
|
|
Chroot chroot "env DEBIAN_FRONTEND=noninteractive \
|
|
apt-mark manual linux-base"
|
|
Chroot chroot "env DEBIAN_FRONTEND=noninteractive \
|
|
apt-get -y --purge autoremove"
|
|
fi
|
|
|
|
clean_debian_chroot
|
|
|
|
if [ "${PROJECT}:${SUBPROJECT:-}" = "ubuntu-base:minimized" ]; then
|
|
# Save even more size by removing apt lists (that are currently removed
|
|
# downstream anyway)
|
|
rm -rf chroot/var/lib/apt/lists/*
|
|
# Having device notes in the docker image can cause problems
|
|
# (https://github.com/tianon/docker-brew-ubuntu-core/issues/62)
|
|
# so remove them. We only do this for docker out of an
|
|
# abundance of caution.
|
|
rm -rf chroot/dev/*
|
|
fi
|
|
|
|
configure_universe
|
|
|
|
if [ -d chroot/var/lib/preinstalled-pool ]; then
|
|
cat > config/indices/apt.conf <<-EOF
|
|
Dir {
|
|
ArchiveDir "chroot/var/lib/preinstalled-pool";
|
|
OverrideDir "config/indices";
|
|
CacheDir "config/indices";
|
|
}
|
|
Default { Packages::Compress ". bzip2"; }
|
|
TreeDefault { Directory "pool"; }
|
|
Tree "dists/$LB_DISTRIBUTION"
|
|
{
|
|
Sections "$LB_PARENT_ARCHIVE_AREAS";
|
|
Architectures "$LB_ARCHITECTURES";
|
|
BinOverride "override.$LB_DISTRIBUTION.\$(SECTION)";
|
|
ExtraOverride "override.$LB_DISTRIBUTION.extra.\$(SECTION)";
|
|
Contents " ";
|
|
}
|
|
EOF
|
|
for component in $LB_PARENT_ARCHIVE_AREAS; do
|
|
mkdir -p chroot/var/lib/preinstalled-pool/dists/$LB_DISTRIBUTION/$component/binary-$LB_ARCHITECTURES
|
|
done
|
|
apt-ftparchive generate config/indices/apt.conf
|
|
cat << @@EOF > chroot/etc/apt/sources.list.preinstall
|
|
# This is a sources.list entry for a small pool of packages
|
|
# provided on your preinstalled filesystem for your convenience.
|
|
#
|
|
# It is perfectly safe to delete both this entry and the directory
|
|
# it references, should you want to save disk space and fetch the
|
|
# packages remotely instead.
|
|
#
|
|
deb file:/var/lib/preinstalled-pool/ $LB_DISTRIBUTION $LB_PARENT_ARCHIVE_AREAS
|
|
#
|
|
@@EOF
|
|
|
|
cp chroot/etc/apt/sources.list chroot/etc/apt/sources.list.orig
|
|
cp chroot/etc/apt/sources.list.preinstall chroot/etc/apt/sources.list
|
|
|
|
echo "Waiting on gnupg ("$GPG_PROCESS") to finish generating a key."
|
|
wait $GPG_PROCESS
|
|
|
|
R_ORIGIN=$(lsb_release -i -s)
|
|
R_CODENAME=$(lsb_release -c -s)
|
|
R_VERSION=$(lsb_release -r -s)
|
|
R_PRETTYNAME=$(echo $R_CODENAME | sed -e 's/^\(.\)/\U\1/')
|
|
|
|
apt-ftparchive -o APT::FTPArchive::Release::Origin=$R_ORIGIN \
|
|
-o APT::FTPArchive::Release::Label=$R_ORIGIN \
|
|
-o APT::FTPArchive::Release::Suite=$R_CODENAME-local \
|
|
-o APT::FTPArchive::Release::Version=$R_VERSION \
|
|
-o APT::FTPArchive::Release::Codename=$R_CODENAME \
|
|
-o APT::FTPArchive::Release::Description="$R_ORIGIN $R_PRETTYNAME Local" \
|
|
release chroot/var/lib/preinstalled-pool/dists/$R_CODENAME/ \
|
|
> config/gnupg/Release
|
|
|
|
gpg --home config/gnupg --detach-sign --armor config/gnupg/Release
|
|
mv config/gnupg/Release \
|
|
chroot/var/lib/preinstalled-pool/dists/$R_CODENAME/Release
|
|
mv config/gnupg/Release.asc \
|
|
chroot/var/lib/preinstalled-pool/dists/$R_CODENAME/Release.gpg
|
|
apt-key --keyring chroot/etc/apt/trusted.gpg add config/gnupg/pubring.gpg
|
|
find chroot/var/lib/preinstalled-pool/ -name Packages | xargs rm
|
|
|
|
Chroot chroot "apt-get update"
|
|
cat chroot/etc/apt/sources.list.preinstall chroot/etc/apt/sources.list.orig \
|
|
> chroot/etc/apt/sources.list
|
|
rm chroot/etc/apt/sources.list.preinstall chroot/etc/apt/sources.list.orig
|
|
fi
|
|
case $PROJECT:$SUBPROJECT in
|
|
*)
|
|
if [ -e "config/seeded-snaps" ]; then
|
|
snap_list=$(cat config/seeded-snaps)
|
|
preinstall_snaps $snap_list
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [ "$PROJECT" = "ubuntu-touch" ] || [ "$PROJECT" = "ubuntu-touch-custom" ]; then
|
|
if [ "$ARCH" = "armhf" ]; then
|
|
INFO_DESC="$(lsb_release -d -s)"
|
|
echo "$INFO_DESC - $ARCH ($BUILDSTAMP)" >chroot/etc/media-info
|
|
mkdir -p chroot/var/log/installer
|
|
Chroot chroot "ln -s /etc/media-info /var/log/installer/media-info"
|
|
fi
|
|
fi
|
|
if [ "$PROJECT" = "ubuntu-cpc" ]; then
|
|
if [ "${SUBPROJECT:-}" = minimized ]; then
|
|
BUILD_NAME=minimal
|
|
else
|
|
BUILD_NAME=server
|
|
fi
|
|
cat > chroot/etc/cloud/build.info << EOF
|
|
build_name: $BUILD_NAME
|
|
serial: $BUILDSTAMP
|
|
EOF
|
|
fi
|
|
|
|
configure_network_manager
|
|
|
|
echo "===== Checking size of /usr/share/doc ====="
|
|
echo BEGIN docdirs
|
|
(cd chroot && find usr/share/doc -maxdepth 1 -type d | xargs du -s | sort -nr)
|
|
echo END docdirs
|
|
|
|
/usr/share/livecd-rootfs/minimize-manual chroot
|
|
fi
|
|
|
|
if [ -n "${PASSES}" ]; then
|
|
PATH="config/:$PATH" lb binary_layered "$@"
|
|
else
|
|
lb binary "$@"
|
|
fi
|
|
|
|
touch binary.success
|
|
) 2>&1 | tee binary.log
|
|
|
|
# bash has trouble with the build.sh sourcing arrangement at the top of this
|
|
# file, so we use this cheap-and-cheerful approach rather than the more
|
|
# correct 'set -o pipefail'.
|
|
if [ -e binary.success ]; then
|
|
rm -f binary.success
|
|
else
|
|
exit 1
|
|
fi
|
|
|
|
case $LB_INITRAMFS in
|
|
casper)
|
|
INITFS="casper"
|
|
;;
|
|
|
|
live-boot)
|
|
INITFS="live"
|
|
;;
|
|
|
|
*)
|
|
INITFS="boot"
|
|
;;
|
|
esac
|
|
|
|
for OUTPUT in ext2 ext3 ext4 manifest manifest-remove size squashfs; do
|
|
[ -e "binary/$INITFS/filesystem.$OUTPUT" ] || continue
|
|
ln "binary/$INITFS/filesystem.$OUTPUT" "$PREFIX.$OUTPUT"
|
|
chmod 644 "$PREFIX.$OUTPUT"
|
|
done
|
|
|
|
# we don't need a manifest-remove for a layered-aware installer
|
|
if [ "$PROJECT" = "ubuntu" ] && [ "$SUBPROJECT" = "canary" ]; then
|
|
rm -f livecd.${PROJECT}-manifest-remove
|
|
rm -f config/manifest-minimal-remove
|
|
fi
|
|
|
|
if [ -e config/manifest-minimal-remove ]; then
|
|
cp config/manifest-minimal-remove "$PREFIX.manifest-minimal-remove"
|
|
fi
|
|
|
|
for ISO in binary.iso binary.hybrid.iso; do
|
|
[ -e "$ISO" ] || continue
|
|
ln "$ISO" "$PREFIX.iso"
|
|
chmod 644 "$PREFIX.iso"
|
|
break
|
|
done
|
|
|
|
if [ -e "binary/$INITFS/filesystem.dir" ]; then
|
|
(cd "binary/$INITFS/filesystem.dir/" && tar -c --xattrs *) | \
|
|
gzip -9 --rsyncable > "$PREFIX.rootfs.tar.gz"
|
|
chmod 644 "$PREFIX.rootfs.tar.gz"
|
|
elif [ -e binary-tar.tar.gz ]; then
|
|
cp -a binary-tar.tar.gz "$PREFIX.rootfs.tar.gz"
|
|
fi
|
|
|
|
if [ "$PROJECT:${SUBPROJECT:-}" = "ubuntu-core:system-image" ]; then
|
|
if [ -e "binary/$INITFS/filesystem.dir" ]; then
|
|
rootfs="binary/$INITFS/filesystem.dir"
|
|
|
|
for dir in lib/modules lib/firmware writable meta; do
|
|
mkdir -p $rootfs/$dir
|
|
done
|
|
|
|
# get a proper version from the chroot
|
|
. $rootfs/etc/os-release
|
|
VERSION="$(echo $PRETTY_NAME | sed 's/[^0-9.]*//g')"
|
|
|
|
CORENAME="ubuntu-core"
|
|
cat > $rootfs/meta/snap.yaml <<EOF
|
|
name: $CORENAME
|
|
version: $VERSION
|
|
summary: The core runtime environment for snapd
|
|
architectures: [$ARCH]
|
|
type: os
|
|
EOF
|
|
|
|
apt-get -y install snapcraft
|
|
snapcraft snap $rootfs
|
|
|
|
snapfile="$(ls ${CORENAME}*.snap)"
|
|
cp -a $snapfile $PREFIX.os.snap
|
|
fi
|
|
fi
|
|
|
|
if [ "$PROJECT" = "ubuntu-touch" ] || [ "$PROJECT" = "ubuntu-touch-custom" ]; then
|
|
(cd "binary/$INITFS/custom.dir/" && tar -c --xattrs *) | \
|
|
gzip -9 --rsyncable > "$PREFIX.custom.tar.gz"
|
|
chmod 644 "$PREFIX.custom.tar.gz"
|
|
fi
|
|
|
|
# '--initramfs none' produces different manifest names.
|
|
if [ -e "binary/$INITFS/filesystem.packages" ]; then
|
|
./config/snap-seed-parse "chroot/" "binary/${INITFS}/filesystem.packages"
|
|
ln "binary/$INITFS/filesystem.packages" "$PREFIX.manifest"
|
|
chmod 644 "$PREFIX.manifest"
|
|
fi
|
|
if [ -e "binary/$INITFS/filesystem.packages-remove" ]; then
|
|
# Not a typo, empty manifest-remove has a single LF in it. :/
|
|
if [ $(cat binary/$INITFS/filesystem.packages-remove | wc -c) -gt 1 ]; then
|
|
ln "binary/$INITFS/filesystem.packages-remove" "$PREFIX.manifest-remove"
|
|
chmod 644 "$PREFIX.manifest-remove"
|
|
fi
|
|
fi
|
|
|
|
# ubuntu-core and ubuntu-desktop-next splits kernel stuff into a "device" tarball so
|
|
# at this point we reset it to "none" as all the work to extract it was done already
|
|
# in a binary hook
|
|
case $PROJECT:${SUBPROJECT:-} in
|
|
ubuntu-core:system-image|ubuntu-desktop-next:system-image)
|
|
|
|
# create device tarball (for snappy only atm)
|
|
if [ "$PROJECT:$SUBPROJECT" = "ubuntu-core:system-image" ]; then
|
|
case $ARCH in
|
|
armhf)
|
|
subarches="generic raspi2"
|
|
;;
|
|
arm64)
|
|
subarches="generic dragonboard"
|
|
;;
|
|
i386|amd64|powerpc|ppc64el|s390x)
|
|
subarches="generic"
|
|
;;
|
|
esac
|
|
|
|
# create a clean chroot
|
|
debootstrap --variant=minbase $LB_DISTRIBUTION chroot-device $LB_PARENT_MIRROR_BOOTSTRAP
|
|
|
|
# ... but keep the PPA setup
|
|
cp -a chroot/etc/apt/* chroot-device/etc/apt/
|
|
|
|
# ... and move it in place
|
|
rm -rf chroot
|
|
mv chroot-device chroot
|
|
|
|
for devarch in $subarches; do
|
|
(echo "I: creating $devarch device tarball for $ARCH"
|
|
HERE="$(pwd)"
|
|
set -x
|
|
|
|
linux_package="linux-image-$devarch"
|
|
case $ARCH in
|
|
amd64)
|
|
linux_package="linux-signed-image-generic"
|
|
;;
|
|
arm64)
|
|
if [ "$devarch" = "dragonboard" ]; then
|
|
linux_package="linux-image-snapdragon linux-firmware-snapdragon"
|
|
fi
|
|
;;
|
|
armhf)
|
|
if [ "$devarch" = "raspi2" ]; then
|
|
linux_package="linux-image-raspi2"
|
|
fi
|
|
;;
|
|
ppc64el|s390x)
|
|
echo "I: skipping kernel and device tarball for $ARCH"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# make sure all virtual filesystems are available
|
|
lb chroot_proc install "$@"
|
|
lb chroot_sysfs install "$@"
|
|
lb chroot_devpts install "$@"
|
|
|
|
# prepare the env
|
|
Chroot chroot "apt-get -y update"
|
|
Chroot chroot "apt-get -y purge linux-image-*"
|
|
Chroot chroot "apt-get -y autoremove"
|
|
rm -rf chroot/boot/initrd.img* chroot/boot/vmlinu?-* chroot/lib/modules/* \
|
|
chroot/boot/abi-* chroot/boot/System.map-* chroot/boot/config-*
|
|
mkdir -p chroot/etc/initramfs-tools/conf.d
|
|
echo "COMPRESS=lzma" >chroot/etc/initramfs-tools/conf.d/snappy-device-tarball.conf
|
|
|
|
# install needed packages and the kernel itself
|
|
Chroot chroot "apt-get -y install initramfs-tools-ubuntu-core linux-firmware xz-utils"
|
|
Chroot chroot "apt-get -y install $linux_package"
|
|
|
|
Chroot chroot "dpkg -l" > chroot/dpkg.list
|
|
|
|
# clean up
|
|
lb chroot_devpts remove "$@"
|
|
lb chroot_sysfs remove "$@"
|
|
lb chroot_proc remove "$@"
|
|
|
|
# now build the actual device tarball
|
|
TMPDIR="$(mktemp -d)"
|
|
mkdir -p $TMPDIR/system/
|
|
mkdir -p $TMPDIR/assets/
|
|
|
|
cd chroot
|
|
cp -ar lib/modules/ $TMPDIR/system/
|
|
cp -ar lib/firmware/ $TMPDIR/system/
|
|
# FIXME: compat with the old kernel spec/old initramfs that
|
|
# expects lib/{modules,firmware}
|
|
#
|
|
# FIXME2: update the initramfs-tools-ubuntu-core scripts/ubuntu-core
|
|
# to look at the new location
|
|
mkdir $TMPDIR/system/lib
|
|
ln -s $TMPDIR/system/modules $TMPDIR/system/lib
|
|
ln -s $TMPDIR/system/firmware $TMPDIR/system/lib
|
|
|
|
# new assets handling
|
|
if [ -f boot/vmlinu?-*.signed ]; then
|
|
kernel=boot/vmlinu?-*.signed
|
|
else
|
|
kernel=boot/vmlinu?-*
|
|
fi
|
|
|
|
initrd=boot/initrd.img-*
|
|
|
|
cp -ar $initrd $TMPDIR/assets/
|
|
cp -ar $kernel $TMPDIR/assets/
|
|
cp -ar boot/abi-* boot/System.map-* boot/config-* $TMPDIR/assets/
|
|
|
|
dtbs=$(find lib/firmware -type d -name 'device-tree' -print0)
|
|
if [ -n "$dtbs" ]; then
|
|
mv "$dtbs" $TMPDIR/assets/dtbs
|
|
case $devarch in
|
|
raspi2)
|
|
# ubuntu-device-flash does not like subdirs here, we need to tar it up
|
|
if [ -e $TMPDIR/assets/dtbs/overlays ]; then
|
|
tar -C $TMPDIR/assets/dtbs -f $TMPDIR/assets/dtbs/overlays.tgz -czv overlays
|
|
rm -rf $TMPDIR/assets/dtbs/overlays
|
|
fi
|
|
;;
|
|
dragonboard)
|
|
cp $TMPDIR/assets/dtbs/qcom/apq8016-sbc-snappy.dtb $TMPDIR/assets/dtbs/apq8016-sbc.dtb
|
|
# add special link needed by the dragonboard wifi driver
|
|
mkdir -p $TMPDIR/system/lib/firmware/wlan/
|
|
ln -s /run/macaddr0 $TMPDIR/system/lib/firmware/wlan/
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# copy dpkg manifest
|
|
cp -ar dpkg.list $TMPDIR/assets
|
|
|
|
# create hardware.yaml
|
|
# this assumes armhf == u-boot
|
|
# and all others grub
|
|
# common bits
|
|
cat > $TMPDIR/hardware.yaml << EOF
|
|
kernel: assets/$(basename $kernel)
|
|
initrd: assets/$(basename $initrd)
|
|
partition-layout: system-AB
|
|
EOF
|
|
# arch specific ones
|
|
if [ "$ARCH" = "armhf" ]; then
|
|
cat >> $TMPDIR/hardware.yaml << EOF
|
|
dtbs: assets/dtbs
|
|
bootloader: u-boot
|
|
EOF
|
|
else
|
|
cat >> $TMPDIR/hardware.yaml << EOF
|
|
bootloader: grub
|
|
EOF
|
|
fi
|
|
|
|
# compress everything
|
|
cd $TMPDIR
|
|
tarname="device.tar.gz"
|
|
manifestname="device.manifest"
|
|
if [ "$devarch" = "raspi2" ];then
|
|
tarname="raspi2.$tarname"
|
|
manifestname="$devarch.$manifestname"
|
|
elif [ "$devarch" = "dragonboard" ];then
|
|
tarname="$devarch.$tarname"
|
|
manifestname="$devarch.$manifestname"
|
|
fi
|
|
# create tarfile
|
|
tar -c -z -f $HERE/$PREFIX.$tarname system assets hardware.yaml
|
|
|
|
# create device specific manifest to track kernel dpkg version
|
|
cp assets/dpkg.list $HERE/$PREFIX.$manifestname
|
|
|
|
# show size of initrd and kernel in the log
|
|
ls -lh assets/
|
|
|
|
# dump the content list into the log
|
|
echo "I: device tarball contents for $PREFIX.$tarname:"
|
|
find . -type f
|
|
|
|
# azure wants its own device tarball
|
|
if [ "$ARCH" = "amd64" ]; then
|
|
cp $HERE/$PREFIX.$tarname $HERE/$PREFIX.azure.$tarname
|
|
fi
|
|
|
|
# create snap
|
|
snapname="kernel.snap"
|
|
metaname=canonical-pc-linux
|
|
|
|
if [ "$devarch" = "raspi2" ];then
|
|
metaname=canonical-pi2-linux
|
|
snapname="$devarch.kernel.snap"
|
|
elif [ "$devarch" = "generic" ] && [ "$ARCH" = "armhf" ];then
|
|
metaname=canonical-bbb-linux
|
|
elif [ "$devarch" = "dragonboard" ] && [ "$ARCH" = "arm64" ];then
|
|
metaname=canonical-snapdragon-linux
|
|
snapname="$devarch.kernel.snap"
|
|
fi
|
|
|
|
rm -rf $HERE/snap || true
|
|
mkdir -p $HERE/snap/meta
|
|
cp -a $TMPDIR/assets/* $HERE/snap
|
|
cp -a $TMPDIR/system/* $HERE/snap
|
|
|
|
cd $HERE/snap
|
|
kernel="$(ls vmlinuz-*)"
|
|
initrd="$(ls initrd.img-*)"
|
|
# old kernel spec
|
|
ln -s $kernel vmlinuz
|
|
ln -s $initrd initrd.img
|
|
# new kernel spec
|
|
ln -s $kernel kernel.img
|
|
kvers="$(ls vmlinuz-*|sed 's/^.*vmlinuz-//;s/-[a-z.]*$//')"
|
|
|
|
VERSION=$kvers
|
|
|
|
cat > meta/kernel.yaml <<EOF
|
|
version: $kvers
|
|
EOF
|
|
|
|
cat > meta/snap.yaml <<EOF
|
|
name: $metaname
|
|
version: $VERSION
|
|
architectures: [$ARCH]
|
|
summary: The canonical $devarch $ARCH kernel
|
|
type: kernel
|
|
|
|
kernel: $(ls vmlinuz-*)
|
|
initrd: $(ls initrd.img-*)
|
|
modules: $(ls -d lib/modules/*)
|
|
firmware: lib/firmware
|
|
EOF
|
|
if [ -d dtbs ]; then
|
|
printf "dtbs: dtbs/ \n" >> meta/snap.yaml
|
|
fi
|
|
cd $HERE
|
|
|
|
apt-get -y install snapcraft
|
|
snapcraft snap snap
|
|
|
|
snapfile="$(ls $metaname*.snap)"
|
|
cp -a $snapfile $PREFIX.$snapname
|
|
)
|
|
done
|
|
fi
|
|
|
|
LB_LINUX_FLAVOURS=none
|
|
;;
|
|
esac
|
|
|
|
for FLAVOUR in $LB_LINUX_FLAVOURS; do
|
|
if [ -z "$LB_LINUX_FLAVOURS" ] || [ "$LB_LINUX_FLAVOURS" = "none" ]; then
|
|
continue
|
|
fi
|
|
if [ "$FLAVOUR" = "virtual" ]; then
|
|
# The virtual kernel is named generic in /boot
|
|
FLAVOUR="generic"
|
|
fi
|
|
KVERS="$( (cd "binary/$INITFS"; ls vmlinu?-* 2>/dev/null || true) | (fgrep -v .efi || true) | sed -n "s/^vmlinu.-\\([^-]*-[^-]*-$FLAVOUR\\)$/\\1/p" )"
|
|
if [ -z "$KVERS" ]; then
|
|
if [ -e "binary/$INITFS/vmlinuz" ]; then
|
|
# already renamed by ubuntu-defaults-image
|
|
break
|
|
fi
|
|
echo "No kernel output for $FLAVOUR!" >&2
|
|
exit 1
|
|
fi
|
|
NUMKVERS="$(set -- $KVERS; echo $#)"
|
|
if [ "$NUMKVERS" -gt 1 ]; then
|
|
echo "Cannot handle more than one kernel for $FLAVOUR ($KVERS)!" >&2
|
|
exit 1
|
|
fi
|
|
ln "binary/$INITFS/"vmlinu?-"$KVERS" "$PREFIX.kernel-$FLAVOUR"
|
|
if [ -e "binary/$INITFS/"vmlinu?-"$KVERS.efi.signed" ]; then
|
|
ln "binary/$INITFS/"vmlinu?-"$KVERS.efi.signed" "$PREFIX.kernel-$FLAVOUR.efi.signed"
|
|
chmod 644 "$PREFIX.kernel-$FLAVOUR.efi.signed"
|
|
fi
|
|
chmod 644 "$PREFIX.kernel-$FLAVOUR"
|
|
if [ -e "binary/$INITFS/initrd.img-$KVERS" ]; then
|
|
ln "binary/$INITFS/initrd.img-$KVERS" "$PREFIX.initrd-$FLAVOUR"
|
|
chmod 644 "$PREFIX.initrd-$FLAVOUR"
|
|
fi
|
|
done
|
|
|
|
NUMFLAVOURS="$(set -- $LB_LINUX_FLAVOURS; echo $#)"
|
|
if [ "$NUMFLAVOURS" = 1 ] && [ "$LB_LINUX_FLAVOURS" != "none" ]; then
|
|
# only one kernel flavour
|
|
if [ -f "binary/$INITFS/vmlinuz" ] && ! [ -h "binary/$INITFS/vmlinuz" ]; then
|
|
ln "binary/$INITFS/vmlinuz" "$PREFIX.kernel"
|
|
chmod 644 "$PREFIX.kernel"
|
|
else
|
|
ln -sf "$PREFIX.kernel-$LB_LINUX_FLAVOURS" "$PREFIX.kernel"
|
|
fi
|
|
if [ -f "binary/$INITFS/initrd.lz" ] && ! [ -h "binary/$INITFS/initrd.lz" ]; then
|
|
ln "binary/$INITFS/initrd.lz" "$PREFIX.initrd"
|
|
chmod 644 "$PREFIX.initrd"
|
|
else
|
|
ln -sf "$PREFIX.initrd-$LB_LINUX_FLAVOURS" "$PREFIX.initrd"
|
|
fi
|
|
fi
|
|
|
|
case $SUBARCH in
|
|
ac100)
|
|
# create the md5sum and size files for which we are actually doing all this
|
|
md5sum $PREFIX.rootfs.tar.gz >chroot/installer.md5
|
|
wc -c $PREFIX.rootfs.tar.gz >chroot/installer.size
|
|
|
|
INFO_DESC="$(lsb_release -d -s)"
|
|
INFO_STAMP=$(date +20%y%m%d-%H:%M)
|
|
|
|
echo "$INFO_DESC - $ARCH ($INFO_STAMP)" >chroot/media-info
|
|
|
|
# make sure update-initramfs feels cosy and warm in the environment
|
|
lb chroot_proc install "$@"
|
|
lb chroot_sysfs install "$@"
|
|
lb chroot_devpts install "$@"
|
|
|
|
# re-create initrd to contain the installer.md5 file
|
|
Chroot chroot "env FLASH_KERNEL_SKIP=1 update-initramfs -k all -t -u -v"
|
|
|
|
# create boot.img
|
|
Chroot chroot "abootimg --create /boot/installer-${KVERS}.img -f /boot/bootimg.cfg-$SUBARCH -r /boot/initrd.img-${KVERS} -k /boot/vmlinuz-${KVERS}"
|
|
|
|
# clean up
|
|
lb chroot_devpts remove "$@"
|
|
lb chroot_sysfs remove "$@"
|
|
lb chroot_proc remove "$@"
|
|
|
|
cp "chroot/boot/installer-${KVERS}.img" "$PREFIX.bootimg-$FLAVOUR"
|
|
ln -sf "$PREFIX.bootimg-$FLAVOUR" "$PREFIX.bootimg"
|
|
;;
|
|
|
|
raspi2|raspi3)
|
|
# copy the kernel and initrd to a predictable directory for
|
|
# ubuntu-image consumption. In some cases, like in pi2/3
|
|
# u-boot, the bootloader needs to contain the kernel and initrd,
|
|
# so during rootfs build we copy it over to a directory that
|
|
# ubuntu-image looks for and shoves into the bootloader
|
|
# partition.
|
|
UBOOT_BOOT="image/boot/uboot"
|
|
|
|
mkdir -p $UBOOT_BOOT
|
|
|
|
cp $PREFIX.initrd $UBOOT_BOOT/initrd.img || true
|
|
cp $PREFIX.kernel $UBOOT_BOOT/vmlinuz || true
|
|
;;
|
|
esac
|
|
|
|
if [ "$PROJECT" = "ubuntu-touch" ] || [ "$PROJECT" = "ubuntu-touch-custom" ]; then
|
|
sourceslist="chroot/etc/apt/sources.list"
|
|
|
|
lb chroot_proc install "$@"
|
|
lb chroot_sysfs install "$@"
|
|
lb chroot_devpts install "$@"
|
|
|
|
if [ -e "$PREFIX.manifest" ]; then
|
|
Chroot chroot "click list" | while read line; do
|
|
echo "click:$line" >>"$PREFIX.manifest"
|
|
done
|
|
fi
|
|
|
|
if [ -e chroot/etc/resolv.conf ]; then
|
|
mv chroot/etc/resolv.conf chroot/etc/resolv.conf.orig
|
|
fi
|
|
if [ -e /etc/resolv.conf ]; then
|
|
cp /etc/resolv.conf chroot/etc/resolv.conf
|
|
fi
|
|
|
|
mv "${sourceslist}" "${sourceslist}.orig"
|
|
mv "${sourceslist}.d" "${sourceslist}.d.orig"
|
|
echo "deb $LB_PARENT_MIRROR_CHROOT ${LB_DISTRIBUTION} main universe multiverse restricted" >$sourceslist
|
|
Chroot chroot "apt-get -y update"
|
|
Chroot chroot "apt-get -y install android"
|
|
|
|
if [ "$ARCH" = "armhf" ]; then
|
|
touchsubarches="flo mako generic"
|
|
for subarch in $touchsubarches; do
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-system-armel+${subarch}.img\
|
|
"${PREFIX}.system-armel+${subarch}.img"
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-recovery-armel+${subarch}.img\
|
|
"${PREFIX}.recovery-armel+${subarch}.img"
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-boot-armhf+${subarch}.img\
|
|
"${PREFIX}.boot-armhf+${subarch}.img"
|
|
# drop this following line once cdimage can handle -boot-*.img
|
|
cp -v "${PREFIX}.boot-armhf+${subarch}.img" "${PREFIX}.bootimg-${subarch}"
|
|
done
|
|
fi
|
|
if [ "$ARCH" = "i386" ]; then
|
|
touchsubarches="generic_x86"
|
|
for subarch in $touchsubarches; do
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-system-i386+${subarch}.img\
|
|
"${PREFIX}.system-i386+${subarch}.img"
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-recovery-i386+${subarch}.img\
|
|
"${PREFIX}.recovery-i386+${subarch}.img"
|
|
cp -v chroot/usr/share/android/product/*-preinstalled-boot-i386+${subarch}.img\
|
|
"${PREFIX}.boot-i386+${subarch}.img"
|
|
# drop this following line once cdimage can handle -boot-*.img
|
|
cp -v "${PREFIX}.boot-i386+${subarch}.img" "${PREFIX}.bootimg-${subarch}"
|
|
done
|
|
fi
|
|
|
|
lb chroot_devpts remove "$@"
|
|
lb chroot_sysfs remove "$@"
|
|
lb chroot_proc remove "$@"
|
|
|
|
rm -rf chroot/etc/init/*.override
|
|
fi
|
|
|
|
# LTSP chroot building (only in 32bit and for Edubuntu (DVD))
|
|
case $PROJECT in
|
|
edubuntu-dvd)
|
|
if [ "$ARCH" = i386 ]; then
|
|
echo "Building LTSP chroot"
|
|
ltsp-build-client --base $(pwd) --mirror $LB_PARENT_MIRROR_BOOTSTRAP --arch $ARCH --dist $LB_PARENT_DISTRIBUTION --chroot ltsp-live --late-packages ldm-edubuntu-theme,plymouth-theme-edubuntu --purge-chroot --skipimage
|
|
mkdir -p images
|
|
mksquashfs ltsp-live images/ltsp-live.img -e cdrom
|
|
rm -Rf ltsp-live
|
|
if [ -f images/ltsp-live.img ]; then
|
|
mv images/ltsp-live.img livecd.$PROJECT-ltsp.squashfs
|
|
chmod 0644 livecd.$PROJECT-ltsp.squashfs
|
|
rmdir --ignore-fail-on-non-empty images
|
|
else
|
|
echo "LTSP: Unable to build the chroot, see above for details."
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [ -f "config/magic-proxy.pid" ]; then
|
|
kill -TERM $(cat config/magic-proxy.pid)
|
|
rm -f config/magic-proxy.pid
|
|
|
|
# Remove previously-inserted iptables rule.
|
|
iptables -t nat -D OUTPUT -p tcp --dport 80 -m owner ! --uid-owner daemon \
|
|
-j REDIRECT --to 8080
|
|
fi
|