#!/bin/bash
LXCBASE=stella-volatile
DEFCLONE=$(mktemp -u $LXCBASE-XXXXXX)
CLONE=
DELAY=5
ROOTFS=
BUILDSTAMP=
PROJECT=stella-datong150206
CODENAME="trusty"
REPO="-devel"
TASK="server-chroottask earlytask task"
DATECODE=$(date +%Y%m%d)
CLEANUP=false
#DEPEND="ubuntu-desktop,apt-transport-https,linux-headers-generic,linux-image-generic,build-essential,debhelper,dh-modaliases,xserver-xorg-dev,execstack"
DEPEND="ubuntu-desktop,apt-transport-https,ca-certificates"

export LANG=C

usage()
{
    [ -n "$1" ] && echo "ERROR: $1"
    echo "USAGE: ${0##*/} COMMAND [OPTIONS]"
    echo "  Command:"
    echo "    build-lxc     Build base Linux container"
    echo "        --name        Specify container's name (default: $LXCBASE)"
    echo "        --package     Specify additional packages (use ',' for seperator)"
    echo
    echo "    update-lxc    Update base Linux container"
    echo "        --name        Specify container for update (default: $LXCBASE)"
    echo "        --package     Specify addiotionl package to install (use ',' for seperator)"
    echo 
    echo "    dryrun <volatile-task package>"
    echo "                  Run dryrun test on the volatile-task package"
    echo "        --project     Specify prject and series name (e.g. stella-datong)"
    echo "        --codename    Specify Ubuntu codename (e.g. trusty)"
    echo "        --devel       Using developer archive"
    echo "        --lxc-base    Specify base Linux container (default: $LXCBASE)"
    echo "        --run-name    Specify runtime Linux container name (default:$CLONE)"
    echo "        --clean       Cleanup the runtime Linux container in the end"
    echo "        --task        Specify dryrun tasks (default: $TASK)"
    echo "                      Be careful, it will be execute in order"
    exit 0
}

delay()
{
    local count=$1 msg=${2:-'Waiting for stable'}
    for ((i=$((count-1));i>=0;i--))
    do
        echo -en "\e[1K\r$msg: $i"
        sleep 1
    done
    echo
}

start_container()
{
    local container=$1
    if ! lxc-ls | grep -q $container; then
        return
    fi

    case $(lxc-info -n $container | awk /State/'{print $2}') in
        STOPPED)
            lxc-start -d -n $container ;;
        FOZEN)
            lxc-unfreeze -n $container ;;
    esac
    lxc-wait -n $container -s RUNNING
    delay $DELAY "Waiting for network is stable"
}

stop_container()
{
    local container=$1
    if ! lxc-ls | grep -q $container; then
        return 1
    fi

    if lxc-info -n $container | grep -qE 'State.*STOPPED$'; then
        return 0
    fi

    lxc-stop -n $container
    lxc-wait -n $container -s STOPPED
}

buildlxc()
{
    local _packages=$DEPEND
    while true; do
        case "$1" in
            --name)
                shift && LXCBASE=${1:$LXCBASE}      ;;
            --package)
                shift && _package="$_packages,$2"   ;;
        esac
        shift || break
    done

    if sudo lxc-ls | grep -q $LXCBASE; then
        stop_container "$LXCBASE"
        lxc-destroy -n $LXCBASE
    fi

    lxc-create -n $LXCBASE -t ubuntu -- --packages "$_packages"
}

updatelxc()
{
    local _packages
    while true; do
        case "$1" in
            --name)
                shift && LXCBASE=${1:$LXCBASE} ;;
            --package)
                shift && _packages="$_packages ${1//,/ }" ;;
        esac
        shift || break
    done

    if ! sudo lxc-ls | grep -q $LXCBASE; then
        echo "Container $LXCBASE is not found"
        exit 0
    fi

    start_container "$LXCBASE"
    lxc-attach -n $LXCBASE -- apt-get update --qq
    [ -n "$_packages" ] && \
        lxc-attach -n $LXCBASE -- apt-get install --yes $_packages
    lxc-attach -n $LXCBASE -- apt-get dist-upgrade --yes
    stop_container "$LXCBASE"
}

runtest()
{
    while true; do
        case $1 in
            --project)
                shift && PROJECT=$1     ;;
            --codename)
                shift && CODENAME=$1    ;;
            --task)
                shift && TASK=$1        ;;
            --lxc-base)
                shift && LXCBASE=$1     ;;
            --run-name)
                shift && CLONE=$1       ;;
            --config)
                shift && CONFIG=$1      ;;
            --devel)
                REPO=""                 ;;
            --clean)
                CLEANUP=true            ;;
            *volatile-task*)
                VOLATILEPKG=$1          ;;
        esac
        shift || break
    done

    [ ! -f "$VOLATILEPKG" ] && \
        usage "Cannot find volatile-task package"

    if ! lxc-ls | grep -q $LXCBASE; then
        usage "The $LXCBASE container is not exist, use build-lxc to create it"
    fi

    [[ -z "$CLONE" ]] && \
        CLONE=$DEFCLONE || \
        CLEANUP=false

    ROOTFS=/var/lib/lxc/$CLONE/delta0

    stop_container "$LXCBASE"

    if lxc-ls | grep -q $CLONE; then
        stop_container "$CLONE"
        lxc-destroy -n $CLONE
    fi

    lxc-clone -s -B aufs $LXCBASE $CLONE
    cp -f $VOLATILEPKG $ROOTFS

    cat > $ROOTFS/run-volatile-task-test << EOF
#!/bin/bash

set -x

# add buildstamp
cat > /etc/buildstamp << END
${PROJECT}-${CODENAME}-amd64-iso-${DATECODE}-0
END

# add source list
mkdir -p /etc/apt/sources.list.d
cat > /etc/apt/sources.list.d/${PROJECT}-${CODENAME}.list << END
deb https://warthogs:eB+uZWXE7@cesg.canonical.com/canonical ${PROJECT}-${CODENAME}${REPO} public private
deb-src https://warthogs:eB+uZWXE7@cesg.canonical.com/canonical ${PROJECT}-${CODENAME}${REPO} public private
END
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 95829CE3 --yes

# patch update-grub
cat > /usr/sbin/update-grub << END
#!/bin/sh
set -e
if \\\`type running-in-container > /dev/null 2>&1\\\` && running-in-container; then
    echo "\$0 not running since it is in a container"
    exit 0
fi
exec grub-mkconfig -o /boot/grub/grub.cfg "\\\$@"
END

# apt-get debugging
mv /usr/bin/apt-get /usr/bin/apt-get.bin
cat > /usr/bin/apt-get << END
#!/bin/sh
set -x
/usr/bin/apt-get.bin \\\$@
END
chmod 755 /usr/bin/apt-get

TASK=\$@
VPATH=/usr/share/volatile

dpkg -i /${VOLATILEPKG##*/}

set +x

while read line
do
    sed "s,http://cesg-mirror.buildd/cesg-mirror,https://warthogs:eB+uZWXE7@cesg.canonical.com/canonical,g" -i \$line
done < <(grep -rnH cesg \$VPATH/* | awk -F: '{print \$1}')

for t in \$TASK; do
    exec > >(tee /run-\$t.log)
    exec 2>&1
    set -x
    run-parts --report \$VPATH/\$t 2>&1 | ts %s-%.S
    set +x
done
EOF

    start_container "$CLONE"

    lxc-attach -n $CLONE -- locale-gen $LC_TIME         # fix locale warning
    lxc-attach -n $CLONE -- dpkg --add-architecture i386
    lxc-attach -n $CLONE -- apt-get update -qq
    lxc-attach -n $CLONE -- apt-get install --yes $(dpkg-deb -f $VOLATILEPKG Depends | tr -d [:space:] | sed -e 's/(.*)//g' -e 's/|/ /g' -e 's/,/ /g')
    lxc-attach -n $CLONE -- bash /run-volatile-task-test $TASK

    stop_container "$CLONE"

    cp -f $ROOTFS/run-*.log .
    if $CLEANUP; then
        lxc-destroy -n $CLONE
    fi
}

# parse command
_command=
_param=${@:2}
case $1 in
    build-lxc)
        _command=buildlxc ;;
    update-lxc)
        _command=updatelxc ;;
    dryrun)
        _command=runtest ;;
    *)
        usage ;;
esac
shift

[ -z "$_command" ] &&
    usage

# parse global parameters
while true; do
    case $1 in
        --delay)
            shift && DELAY=${1:-5} ;;
        -x)
            set -x ;;
    esac
    shift || break
done

if [ $(id -u) -ne 0 ]; then
    echo "ERROR: This script must run in root privilege"
    exit 1
fi

# generate log
exec > >(tee ${0##*/}.log)

if ! dpkg -l | grep -q lxc; then
    apt-get install lxc --yes
fi

$_command $_param
