#!/bin/sh
# adt-build-lxc is part of autopkgtest
# autopkgtest is a tool for testing Debian binary packages
#
# autopkgtest is Copyright (C) 2006-2014 Canonical Ltd.
#
# Build or update a container with the debian or ubuntu LXC template
#
# 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 2 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# See the file CREDITS for a full list of credits information (often
# installed as /usr/share/doc/autopkgtest/CREDITS).
set -e

DISTRO="$1"
RELEASE="$2"
if [ -z "$1" ] || [ -z "$2" ]; then
    echo "Usage: $0 debian|ubuntu <release> [arch]" >&2
    exit 1
fi

# check that LXC config has networking
if grep -q 'lxc.network.type *= *empty' /etc/lxc/default.conf; then
    cat <<EOF >&2
ERROR: autopkgtest containers need networking; please set it up and adjust
lxc.network.type in /etc/lxc/default.conf
EOF
    exit 1
fi

ARCH=${3:-}
NAME="adt-${RELEASE}${ARCH:+-$ARCH}"

# fall back for older LXC option name
LXCDIR=`lxc-config lxc.lxcpath` || LXCDIR=`lxc-config lxcpath` || LXCDIR=/var/lib/lxc

LXC_ARGS="-t $DISTRO -- -r $RELEASE ${ARCH:+-a $ARCH}"

# auto-detect apt-cacher-ng
proxy_detect() {
    if [ -z "$ADT_APT_PROXY" ]; then
        RES=`apt-config shell proxy Acquire::http::Proxy`
        eval $RES
        if echo "$proxy" | egrep -q '(localhost|127\.0\.0\.[0-9]*):3142'; then
            # set http_proxy for the initial debootstrap
            export http_proxy="$proxy"
            local bridge_ip=$(ip -4 a show dev lxcbr0 | awk '/ inet / {sub(/\/.*$/, "", $2); print $2}') || true
            if [ -n "$bridge_ip" ]; then
                ADT_APT_PROXY="http://$bridge_ip:3142"
            fi
            echo "Detected apt-cacher-ng. Using local proxy $http_proxy, container proxy $ADT_APT_PROXY"
        fi
    fi
}

setup() {
    # add deb-src
    sed -i '/^deb/ { p; s/^deb/deb-src/}' $LXCDIR/$1/rootfs/etc/apt/sources.list

    # a host's http_proxy for localhost does not work in the guest, apt proxy
    # needs to be set up separately there
    if [ "$http_proxy" != "${http_proxy#*localhost*}" ] || \
       [ "$http_proxy" != "${http_proxy#*127.0.0.*}" ]; then
       unset http_proxy
       unset https_proxy
    fi

    # set up apt proxy for the container
    if [ -n "$ADT_APT_PROXY" ]; then
        echo "Acquire::http { Proxy \"$ADT_APT_PROXY\"; };" > $LXCDIR/$1/rootfs/etc/apt/apt.conf.d/01proxy
    fi

    lxc-start --daemon --name=$1
    # wait until it is booted: lxc-attach works and we get a numeric runlevel
    timeout=60
    while [ $timeout -ge 0 ]; do
        timeout=$((timeout - 1))
        sleep 1
        O=`lxc-attach --name=$1 runlevel 2>/dev/null` || continue
        [ "$O" = "${O%[0-9]}" ] || break
    done
    [ $timeout -ge 0 ] || {
        echo "Timed out waiting for container to boot" >&2
        lxc-stop --kill --name=$1 || true
        lxc-destroy --name=$1 || true
        exit 1
    }

    lxc-attach --name=$1 apt-get update
    lxc-stop --name=$1
}

proxy_detect

if [ ! -e $LXCDIR/$NAME ]; then
    # first-time run: just create the container
    lxc-create --name=$NAME $LXC_ARGS
    setup $NAME
else
    # remove LXC rootfs caches; on btrfs this might be a subvolume, otherwise
    # rm it
    subvols=$(btrfs subvolume list / 2>/dev/null | awk "/cache\/lxc.*utopic/ {print \$(NF)}") || true
    if [ -n "$subvols" ]; then
        for vol in $subvols; do
            btrfs subvolume delete /$vol
        done
    else
        rm -rf /var/cache/lxc/$RELEASE /var/cache/lxc/$DISTRO/rootfs-$RELEASE*
    fi
    # create a new rootfs in a temp container
    lxc-create --name=${NAME}.new $LXC_ARGS
    setup ${NAME}.new
    # replace the original rootfs; can't make this more atomic unfortunately
    mv $LXCDIR/${NAME}.new/rootfs $LXCDIR/${NAME}/rootfs.new
    mv $LXCDIR/${NAME}/rootfs $LXCDIR/${NAME}/rootfs.old
    mv $LXCDIR/${NAME}/rootfs.new $LXCDIR/${NAME}/rootfs
    rm -rf $LXCDIR/${NAME}/rootfs.old
    mkdir $LXCDIR/${NAME}.new/rootfs
    lxc-destroy --name=${NAME}.new
fi
