#!/usr/bin/env bash

# Copyright (C) 2014-2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2015-2016 Robin Schneider <ypid@riseup.net>
# Copyright (C) 2014-2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only

# A simple script to create na uprivileged LXC container based on current LXC
# host distribution, release and architecture. The script uses the
# 'lxc-hwaddr-static' and 'lxc-prepare-ssh' commands to further configure the
# created LXC container.

# Usage: lxc-new-unprivileged <container> [config-file]


set -o nounset -o pipefail -o errexit

SCRIPT="$(basename "${0}")"
readonly SCRIPT
readonly CONTAINER="${1:-}"
CONFIG_FILE="$(grep 'lxc.default_unprivileged_config' /etc/lxc/lxc.conf | awk '{print $3}')"
readonly CONFIG_FILE

DISTRIBUTION="$(lsb_release -i | awk '{print $NF}' | tr '[:upper:]' '[:lower:]')"
readonly DISTRIBUTION
RELEASE="$(lsb_release -c | awk '{print $NF}' | tr '[:upper:]' '[:lower:]')"
readonly RELEASE
ARCHITECTURE="$(dpkg --print-architecture)"
readonly ARCHITECTURE

# The SKS keyservers are deprecated, so we need to provide an alternative
readonly DOWNLOAD_KEYSERVER="${DOWNLOAD_KEYSERVER:-hkp://keyserver.ubuntu.com}"
export DOWNLOAD_KEYSERVER

container_exists () {
    local container
    container="${1}"

    if lxc-ls -1 | grep -q -E "^${container}$" ; then
        return 0
    else
        return 1
    fi
}

print_usage () {
    cat <<EOF
${SCRIPT}: create new unprivileged LXC container based on LXC host

Usage: ${SCRIPT} <container-name>
EOF
}

error_msg () {
    printf "%s\\n" "${*}" >&2
}

main () {
    local container
    container="${CONTAINER}"

    local config_file
    config_file="${CONFIG_FILE}"

    local distribution
    distribution="${DISTRIBUTION}"

    local release
    release="${RELEASE}"

    local architecture
    architecture="${ARCHITECTURE}"

    if [ -n "${container}" ] ; then
        if ! container_exists "${container}" ; then

            printf "Container '%s' doesn't exist, creating...\\n" "${container}"

            lxc-create --name "${container}" \
                       --config "${config_file}" \
                       --template "download" \
                       -- --dist "${distribution}" \
                          --release "${release}" \
                          --arch "${architecture}"

            if grep -qE '^lxc\.uts\.name\s+=' "/var/lib/lxc/${container}/config" ; then
                iface_count="$(grep -cE '^lxc\.net\.[0-9]+\.type\s+=' "/var/lib/lxc/${container}/config")"
            elif grep -qE '^lxc\.utsname\s+=' "/var/lib/lxc/${container}/config" ; then
                iface_count="$(grep -cE '^lxc\.network\.type\s+=' "/var/lib/lxc/${container}/config")"
            fi
            iface_count="$(( iface_count - 1 ))"

            if [ -f "/var/lib/lxc/${container}/rootfs/etc/network/interfaces" ] ; then
                if [ "${iface_count}" -gt 0 ] ; then
                    for (( i=1 ; i<=iface_count ; i++ )) ; do
                        printf "Adding eth%s interface to network configuration\\n" "${i}"
                        cat <<EOF >> "/var/lib/lxc/${container}/rootfs/etc/network/interfaces"

auto eth${i}
iface eth${i} inet dhcp
EOF
                    done
                fi
            fi

            lxc-hwaddr-static "${container}"

            if pidof systemd > /dev/null 2>&1 ; then
                systemctl enable "lxc@${container}.service"
                systemctl start "lxc@${container}.service"
            else
                lxc-start -n "${container}" -d
            fi
            lxc-wait -n "${container}" -s RUNNING

            # During container creation, a static hostname is added into
            # '/etc/hosts' which breaks proper DNS domain resolution of the
            # container. Because we are using DHCP/DNS server to manage
            # containers, remove the static host entry to fix the issue.
            if lxc-attach -n "${container}" -- grep -q '127.0.1.1' /etc/hosts ; then
                printf "Removing static host entry from /etc/hosts...\\n"
                lxc-attach -n "${container}" -- sed -i "/127\\.0\\.1\\.1/d" /etc/hosts > /dev/null
            fi

            c=0
            until lxc-prepare-ssh "${container}" ; do
                ((c++)) && ((c==4)) && break
                printf "Waiting for network inside container to settle...\\n"
                sleep 5
            done

        else
            error_msg "Error: container '${container}' already exists"
            return 1
        fi
    else
        print_usage
        return 1
    fi
}

main
