#!/bin/bash # # Copyright 2006-2009 (C) Canonical Ltd. # Author: Kees Cook # # ################################################################## # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # See file /usr/share/common-licenses/GPL for more details. # # ################################################################## # # This script creates LVM snapshot chroots via schroot and sbuild. # Much love to "man sbuild-setup", https://wiki.ubuntu.com/PbuilderHowto, # and https://help.ubuntu.com/community/SbuildLVMHowto. # # It will deal with sbuild having not be installed and configured before. set -e # For when schroot enters the chroot, we cannot be in a directory that # will not exist in the chroot. cd / # Make sure we've got a regular user if [ -w /etc/passwd ]; then echo "Please run this script as a regular user, not root." >&2 exit 1 fi # Perform once-only things to initially set up for using sbuild+schroot+lvm if [ ! -w /var/lib/sbuild ]; then # Load all the packages you'll need to do work sudo apt-get install sbuild schroot debootstrap lvm2 # Add self to the sbuild group sudo adduser "$USER" sbuild # Prepare a usable default .sbuildrc if [ ! -e ~/.sbuildrc ]; then cat > ~/.sbuildrc <&2 exit 1 fi # Set up configurable defaults (loaded after option processing) LV_SIZE="5G" SNAPSHOT_SIZE="4G" SOURCE_CHROOTS_DIR=/srv/chroot function usage() { echo "Usage: $0 [OPTIONS] Release" >&2 echo "Options:" echo " --arch=ARCH What architecture to select" echo " --name=NAME Base name for the schroot (arch is appended)" echo " --personality=PERSONALITY What personality to use (defaults to match --arch)" echo " --debug Turn on script debugging" echo " --skip-updates Do not include -updates pocket in sources.list" echo " --source-template=FILE Use FILE as the sources.list template" echo " --debootstrap-mirror=URL Use URL as the debootstrap source" echo " --distro=DISTRO Install specific distro (defaults to 'ubuntu')" echo " --volume-group=VG use LVM snapshots, with group VG" echo "" echo "Configuration (via ~/.mk-sbuild.rc)" echo " SOURCE_CHROOTS_DIR directory to put source chroots in" echo " LV_SIZE Size of source LVs (default ${LV_SIZE})" echo " SNAPSHOT_SIZE Size of snapshot LVs (default ${SNAPSHOT_SIZE})" echo " SCHROOT_CONF_SUFFIX Lines to append to schroot.conf entries" echo " SKIP_UPDATES Enable --skip-updates" echo " TEMPLATE_SOURCES A template for sources.list" echo " TEMPLATE_SCHROOTCONF A template for schroot.conf stanza" exit 1 } if [ -z "$1" ]; then usage fi OPTS=`getopt -o '' --long "help,debug,skip-updates,arch:,name:,source-template:,debootstrap-mirror:,personality:,distro:,volume-group" -- "$@"` eval set -- "$OPTS" VG="" DISTRO="ubuntu" name="" while :; do case "$1" in --debug) set -x shift ;; --arch) # By default, use the native architecture. arch_opt="--arch=$2" arch_suffix="-$2" CHROOT_ARCH="$2" if [ "$2" = "i386" ] || [ "$2" = "lpia" ] && [ -z "$personality" ]; then personality="linux32" fi shift 2 ;; --personality) personality="$2" shift 2 ;; --skip-updates) SKIP_UPDATES="1" shift ;; --name) name="$2" shift 2 ;; --source-template) TEMPLATE_SOURCES="$2" shift 2 if [ ! -r $TEMPLATE_SOURCES ]; then echo "W: Template file $TEMPLATE_SOURCES is not readable" echo "W: Continuing with default sources!" fi ;; --debootstrap-mirror) DEBOOTSTRAP_MIRROR="$2" shift 2 ;; --distro) DISTRO="$2" shift 2 ;; --volume-group) VG="$2" shift 2 ;; --) shift break ;; --help|*) usage ;; esac done # To build the LV, we need to know which volume group to use, and which # release of Ubuntu to debootstrap RELEASE="$1" if [ -z "$RELEASE" ]; then usage fi # By default, name the schroot the same as the release if [ -z "$name" ]; then name="$RELEASE" fi SRC_TYPE="union" SCHROOT_CONF_TYPE="directory" CHROOT_NAME="${name}${arch_suffix}" HOST_ARCH=$(dpkg --print-architecture) if [ -z "$CHROOT_ARCH" ]; then CHROOT_ARCH=$HOST_ARCH fi # Load customizations if [ -r ~/.mk-sbuild.rc ]; then . ~/.mk-sbuild.rc fi [ -n "${VG}" ] && { SRC_TYPE="lvm"; SCHROOT_CONF_TYPE="lvm-snapshot"; } case "$SRC_TYPE" in "lvm") # Make sure LVM tools that operate on the snapshots have needed module if ! sudo dmsetup targets | grep -q ^snapshot; then sudo modprobe dm_snapshot echo dm_snapshot | sudo tee -a /etc/modules >/dev/null fi # Set up some variables for use in the paths and names CHROOT_LV="${name}_chroot${arch_suffix}" CHROOT_PATH="/dev/$VG/$CHROOT_LV" # Does the specified VG exist? (vgdisplay doesn't set error codes...) if [ `sudo vgdisplay -c "$VG" | wc -l` -eq 0 ]; then exit 1 fi ;; "union") if [ ! -d "${SOURCE_CHROOTS_DIR}" ]; then sudo mkdir "${SOURCE_CHROOTS_DIR}" fi ;; *) echo "unknown source type" >&2; exit 1;; esac # Is the specified release known to debootstrap? if [ ! -r "/usr/share/debootstrap/scripts/$RELEASE" ]; then echo "Specified release not known to debootstrap" >&2 exit 1 else variant_opt="--variant=buildd" fi BUILD_PKGS="build-essential fakeroot devscripts apt-utils" # Handle distro-specific logic, unknown to debootstrap case "$DISTRO" in ubuntu) if [ -z "$DEBOOTSTRAP_MIRROR" ]; then case "$CHROOT_ARCH" in amd64 | i386) DEBOOTSTRAP_MIRROR="http://archive.ubuntu.com/ubuntu" ;; armel | hppa | ia64 | lpia | sparc) DEBOOTSTRAP_MIRROR="http://ports.ubuntu.com/ubuntu-ports" ;; powerpc) if [ "$RELEASE" != "dapper" ]; then DEBOOTSTRAP_MIRROR="http://ports.ubuntu.com/ubuntu-ports" else DEBOOTSTRAP_MIRROR="http://archive.ubuntu.com/ubuntu" fi ;; esac fi if [ -z "$COMPONENTS" ]; then COMPONENTS="main restricted universe multiverse" fi if [ -z "$SOURCES_SECURITY_SUITE" ]; then SOURCES_SECURITY_SUITE="RELEASE-security" fi if [ -z "$SOURCES_SECURITY_URL" ]; then case "$CHROOT_ARCH" in amd64 | i386) SOURCES_SECURITY_URL="http://security.ubuntu.com/ubuntu" ;; armel | hppa | ia64 | lpia | sparc) SOURCES_SECURITY_URL="http://ports.ubuntu.com/ubuntu-ports" ;; powerpc) if [ "$RELEASE" != "dapper" ]; then SOURCES_SECURITY_URL="http://ports.ubuntu.com/ubuntu-ports" else SOURCES_SECURITY_URL="http://security.ubuntu.com/ubuntu" fi ;; esac fi # Add edgy+ buildd tools if [ "$RELEASE" != "breezy" ] && [ "$RELEASE" != "dapper" ]; then # Disable recommends for a smaller chroot (gutsy and later only) BUILD_PKGS="--no-install-recommends $BUILD_PKGS" # Add buildd tools BUILD_PKGS="$BUILD_PKGS pkg-create-dbgsym pkgbinarymangler" fi ;; debian) if [ -z "$DEBOOTSTRAP_MIRROR" ]; then DEBOOTSTRAP_MIRROR="http://ftp.debian.org/debian" fi if [ -z "$COMPONENTS" ]; then COMPONENTS="main non-free contrib" fi # Debian only performs security updates SKIP_UPDATES=1 if [ -z "$SOURCES_SECURITY_SUITE" ]; then SOURCES_SECURITY_SUITE="RELEASE/updates" fi if [ -z "$SOURCES_SECURITY_URL" ]; then SOURCES_SECURITY_URL="http://security.debian.org/" fi # Unstable (aka "sid") does not have a security repository if [ "$RELEASE" = 'unstable' ] || [ "$RELEASE" = 'sid' ]; then SKIP_SECURITY=1 fi ;; *) echo "Unknown --distro '$DISTRO': aborting" >&2 exit 1 ;; esac DEBOOTSTRAP_COMMAND=debootstrap # Use qemu-arm-static / build-arm-chroot for foreign armel chroots if [ "$CHROOT_ARCH" = 'armel' ] && [ ! "$HOST_ARCH" = 'armel' ] ; then if [ -f "/usr/bin/build-arm-chroot" ]; then DEBOOTSTRAP_COMMAND=build-arm-chroot else echo Please install qemu-arm-static to use foreign armel chroots fi fi case "$SRC_TYPE" in "lvm") # Allocate the "golden" chroot LV sudo lvcreate -n "$CHROOT_LV" -L "$LV_SIZE" "$VG" sudo mkfs -t ext4 "$CHROOT_PATH" # Mount MNT=`mktemp -d -t schroot-XXXXXX` sudo mount "$CHROOT_PATH" "$MNT" ;; "union") CHROOT_PATH="${SOURCE_CHROOTS_DIR}/${CHROOT_NAME}" MNT="${CHROOT_PATH}" if [ -d "${MNT}" ]; then echo "${MNT} exists. exiting"; exit 1; fi sudo mkdir -p "${MNT}" ;; esac # debootstrap the chroot sudo $DEBOOTSTRAP_COMMAND $arch_opt $variant_opt "$RELEASE" "$MNT" "${DEBOOTSTRAP_MIRROR:-http://archive.ubuntu.com/ubuntu}" # Update the package sources TEMP_SOURCES=`mktemp -t sources-XXXXXX` if [ -z "$TEMPLATE_SOURCES" ]; then TEMPLATE_SOURCES=~/.mk-sbuild.sources fi if [ -r "$TEMPLATE_SOURCES" ]; then cat "$TEMPLATE_SOURCES" > "$TEMP_SOURCES" else cat > "$TEMP_SOURCES" <> "$TEMP_SOURCES" <> "$TEMP_SOURCES" < $MNT/etc/apt/sources.list" rm -f "$TEMP_SOURCES" # Copy the timezone (comment this out if you want to leave the chroot at UTC) sudo cp /etc/localtime /etc/timezone "$MNT"/etc/ # Create an LVM-snapshot-based schroot entry for this LV TEMP_SCHROOTCONF=`mktemp -t schrootconf-XXXXXX` TEMPLATE_SCHROOTCONF=~/.mk-sbuild.schroot.conf TYPED_TEMPLATE_SCHROOTCONF="${TEMPLATE_SCHROOTCONF}.${SCHROOT_CONF_TYPE}" if [ -r "${TEMPLATE_SCHROOT}" ]; then cat "$TEMPLATE_SCHROOTCONF" > "$TEMP_SCHROOTCONF" elif [ -r "${TYPED_TEMPLATE_SCHROOTCONF}" ]; then cat "${TYPED_TEMPLATE_SCHROOTCONF}" > "$TEMP_SCHROOTCONF" else if [ "${SRC_TYPE}" = "lvm" ]; then cat > "$TEMP_SCHROOTCONF" < "${TEMP_SCHROOTCONF}" <> "$TEMP_SCHROOTCONF" fi if [ ! -z "$SCHROOT_CONF_SUFFIX" ]; then echo "$SCHROOT_CONF_SUFFIX" >> "$TEMP_SCHROOTCONF" fi cat "$TEMP_SCHROOTCONF" | sed \ -e "s|CHROOT_NAME|$CHROOT_NAME|g" \ -e "s|CHROOT_PATH|$CHROOT_PATH|g" \ -e "s|SNAPSHOT_SIZE|$SNAPSHOT_SIZE|g" \ | \ sudo bash -c "cat >> /etc/schroot/schroot.conf" rm -f "$TEMP_SCHROOTCONF" # Create image finalization script sudo bash -c "cat >> $MNT/finish.sh" <