[lxc-devel] [PATCH] gentoo template (updated network management, master rebase)

Stéphane Graber stgraber at ubuntu.com
Tue Jan 14 21:42:39 UTC 2014


On Tue, Jan 14, 2014 at 12:06:26AM +0100, lxc at zitta.fr wrote:
> Gentoo template
> 
> Signed-off-by: gza <lxc at zitta.fr>

Hi,

I must admit having only very briefly gone through the code as I'm not
familiar with Gentoo and it's a rather massive template to do a full
review of.

I just noticed you're missing a .gitignore entry which I'll add and it's
also unfortunate that a new template isn't using the new common config
includes instead of hardcoding the whole config into every single
container, but that's something you'll obviously fix in the near future.


In the meant time:
Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  configure.ac            |   1 +
>  templates/Makefile.am   |   1 +
>  templates/lxc-gentoo.in | 828 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 830 insertions(+)
>  create mode 100644 templates/lxc-gentoo.in
> 
> diff --git a/configure.ac b/configure.ac
> index 8514267..d69afe7 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -648,6 +648,7 @@ AC_CONFIG_FILES([
>      templates/lxc-archlinux
>      templates/lxc-alpine
>      templates/lxc-plamo
> +    templates/lxc-gentoo
>  
>      src/Makefile
>      src/lxc/Makefile
> diff --git a/templates/Makefile.am b/templates/Makefile.am
> index ff0a603..ac870a1 100644
> --- a/templates/Makefile.am
> +++ b/templates/Makefile.am
> @@ -10,6 +10,7 @@ templates_SCRIPTS = \
>      lxc-debian \
>      lxc-download \
>      lxc-fedora \
> +    lxc-gentoo \
>      lxc-openmandriva \
>      lxc-opensuse \
>      lxc-oracle \
> diff --git a/templates/lxc-gentoo.in b/templates/lxc-gentoo.in
> new file mode 100644
> index 0000000..2bc13fd
> --- /dev/null
> +++ b/templates/lxc-gentoo.in
> @@ -0,0 +1,828 @@
> +#!/bin/bash
> +
> +#
> +# LXC template for gentoo
> +#
> +# Author: Guillaume Zitta <lxc at zitta.fr>
> +#
> +# Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo
> +#
> +# this version is reworked with :
> +# - out of the lxc-create compat
> +# - vanilla gentoo config
> +# - ready to use cache
> +#
> +
> +# Ensure strict root's umask doesen't render the VM unusable
> +umask 022
> +
> +################################################################################
> +#                        Various helper functions
> +################################################################################
> +
> +# param: $1: the name of the lock
> +# param: $2: the timeout for the lock
> +# The rest contain the command to execute and its parameters
> +execute_exclusively()
> +{
> +    mkdir -p @LOCALSTATEDIR@/lock/subsys/
> +
> +    local lock_name="$1"
> +    local timeout="$2"
> +    shift 2
> +
> +    {
> +        printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name"
> +
> +        flock -x -w "${timeout}" 50
> +
> +        if [[ $? -ne 0 ]]; then
> +            printf " => unable to obtain lock, aborting.\n"
> +            return 2
> +        else
> +            printf " => done.\n"
> +        fi
> +
> +        printf " => Executing \"%s\"\n" "$*"
> +        "$@"
> +        retval=$?
> +    } 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}"
> +    return $retval
> +}
> +
> +# a die function is always a good idea
> +die()
> +{
> +    printf "\n[the last exit code leading to this death was: %s ]\n" "$?"
> +    local retval="$1"
> +    shift 1
> +    printf "$@"
> +    exit "$retval"
> +}
> +
> +# gentoo arch/variant detection
> +set_default_arch()
> +{
> +    printf "### set_default_arch: default arch/variant autodetect...\n"
> +    arch=$(arch)
> +    if [[ $arch =~ i.86 ]]; then
> +        arch="x86"
> +        variant="x86"
> +    elif [[ $arch == "x86_64" ]]; then
> +        arch="amd64"
> +        variant="amd64"
> +    elif [[ $arch =~ arm.* ]]; then
> +        arch="arm"
> +        variant="armv7a"
> +    else
> +        #who knows, it may work...
> +        printf " => warn: unexpected arch:${arch} let me knows if it works :)\n"
> +        variant="${arch}"
> +    fi
> +    printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}"
> +}
> +
> +store_user_message()
> +{
> +    user_message="${user_message}=> $@\n"
> +}
> +
> +################################################################################
> +#                    CACHE Preparation
> +################################################################################
> +# during setup cachedir is $cacheroot/partial-$arch-$variant
> +# at the end, it will be   $cacheroot/rootfs-$arch-$variant
> +
> +cache_setup(){
> +    partialfs="${cacheroot}/partial-${arch}-${variant}"
> +
> +    #if cache exists and flush not needed, return
> +    [[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0
> +
> +    printf "###### cache_setup(): doing cache preparation\n"
> +    local retval=1
> +
> +    #clean from failed previous run
> +    rm -rf "${partialfs}"
> +    mkdir -p "${partialfs}"
> +
> +    #let's go
> +    cache_precheck && \
> +    cache_stage3 && \
> +    cache_portage && \
> +    cache_inittab && \
> +    cache_net && \
> +    cache_dev && \
> +    cache_openrc && \
> +    rm -rf "${cachefs}" && \
> +    mv "${partialfs}" "${cachefs}" && \
> +    printf "###### cache_setup: Cache should be ready\n"
> +
> +    return $?
> +}
> +
> +cache_precheck()
> +{
> +    printf "### cache_precheck(): doing some pre-start checks ...\n"
> +    # never hurts to have a fail-safe.
> +    [[ -n "${cacheroot//\/}" ]] \
> +        || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
> +}
> +
> +#get latest stage3 tarball
> +cache_stage3()
> +{
> +    printf "### cache_stage3(): stage3 cache deployment...\n"
> +
> +    if [ -z "${tarball}" ]; then
> +        #variables init
> +        local stage3_baseurl="${mirror}/releases/${arch}/autobuilds"
> +
> +        # get latest-stage3....txt file for subpath
> +        local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt"
> +
> +        printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}"
> +        printf " => downloading and processing %s\n" "${stage3_pointer}"
> +
> +        local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 ) \
> +            || die 6 "Error: unable to fetch\n"
> +
> +        printf " => Got: %s\n" "${stage3_latest_tarball}"
> +
> +        printf "Downloading/untarring the actual stage3 tarball...\n"
> +        wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" | tar -xjpf - -C "${partialfs}" \
> +            || die 6 "Error: unable to fetch or untar\n"
> +        printf " => extracted to: %s\n" "${partialfs}"
> +    else
> +        printf "Extracting the stage3 tarball...\n"
> +        tar -xpf "${tarball}" -C "${partialfs}" || die 6 "unable to untar ${tarball} to ${partialfs}"
> +    fi
> +
> +    #check if it chroots
> +    printf "chroot test..."
> +    chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}"
> +    printf " OK\n"
> +    printf " => stage3 cache extracted in : %s\n" "${partialfs}"
> +    return 0
> +}
> +
> +cache_portage()
> +{
> +    printf "### cache_portage: caching portage tree tarball...\n"
> +    [[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0
> +
> +    rm -f ${portage_cache}
> +
> +    printf "Downloading Gentoo portage (software build database) snapshot...\n"
> +    execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \
> +    || die 6 "Error: unable to fetch\n"
> +    printf " => done.\n"
> +}
> +
> +# custom inittab
> +cache_inittab()
> +{
> +    printf "### cache_inittab: tuning inittab...\n"
> +
> +    INITTAB="${partialfs}/etc/inittab"
> +
> +    [[ -w "$INITTAB" ]] || die 1 "Error: $INITTAB is not writeable"
> +
> +    # create console
> +    echo "# Lxc main console" >> "$INITTAB"
> +    echo "1:12345:respawn:/sbin/agetty -a root --noclear 115200 console linux" >> "$INITTAB"
> +
> +    # finally we add a pf line to enable clean shutdown on SIGPWR (issue 60)
> +    echo "# clean container shutdown on SIGPWR" >> "$INITTAB"
> +    echo "pf:12345:powerwait:/sbin/halt" >> "$INITTAB"
> +
> +    # we also blank out /etc/issue here in order to prevent delays spawning login
> +    # caused by attempts to determine domainname on disconnected containers
> +    sed -i 's/[\][Oo]//g' "${partialfs}/etc/issue"
> +}
> +
> +cache_net()
> +{
> +    printf "### cache_net: doing some useful net tuning...\n"
> +    # useful for chroot
> +    # /etc/resolv.conf
> +    grep -i 'search ' /etc/resolv.conf > "${partialfs}/etc/resolv.conf"
> +    grep -i 'nameserver ' /etc/resolv.conf >> "${partialfs}/etc/resolv.conf"
> +
> +    # fix boot-time interface config wipe under aggressive cap drop
> +    # (openrc 0.9.8.4 ~sep 2012 - https://bugs.gentoo.org/show_bug.cgi?id=436266)
> +    # initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf"
> +    # but this one does not depends on interfaces names
> +    echo 'rc_keyword="-stop"' >> "${partialfs}/etc/conf.d/net"
> +}
> +
> +cache_dev()
> +{
> +    printf "### cache_dev(): /dev tuning...\n"
> +
> +    #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
> +    mkdir "${partialfs}/dev/pts"
> +
> +    if [ -n "${nettun}" ]; then
> +        mkdir -m 755 "${partialfs}/net"
> +        mknod -m 666 "${partialfs}/net/tun"        c 10 200
> +    fi
> +
> +    return 0
> +}
> +
> +# fix openrc system
> +cache_openrc()
> +{
> +    printf "### cache_openrc(): doing openrc tuning\n"
> +
> +    #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
> +    chroot "${partialfs}" sed s/-lxc//g -i "/etc/init.d/devfs"
> +
> +    return 0
> +}
> +
> +################################################################################
> +#                    CONTAINER Preparation
> +################################################################################
> +
> +container_setup() {
> +    printf "##### container_setup(): starting container setup\n"
> +
> +    #in most cases lxc-create should have provided a copy of default lxc.conf
> +    #let's tag where template starts, or just create the files
> +    echo '### lxc-gentoo template stuff starts here' >> "$path/config"
> +
> +    #Determine rootfs
> +    #If backingstore was specified, lxc.rootfs should be present or --rootfs did the rootfs var creation
> +    if [ -z "${rootfs}" ]; then
> +        rootfs=`awk -F= '$1 ~ /^lxc.rootfs/ { print $2 }' "$path/config" 2>/dev/null`
> +        if [ -z "${rootfs}" ]; then
> +            #OK it's default
> +            rootfs="${path}/rootfs"
> +        fi
> +    fi
> +    store_user_message "rootfs of container is : ${rootfs}"
> +    store_user_message "config of container is : ${path}/config"
> +
> +    container_precheck && \
> +    container_rootfs && \
> +    container_consoles && \
> +    container_tz && \
> +    container_portage && \
> +    container_net && \
> +    container_hostname && \
> +    container_auth && \
> +    container_conf
> +    if [ $? -ne 0 ]; then
> +        die 1 "container_setup(): one step didn't complete, sorry\n"
> +    fi
> +
> +    printf "###### container_setup(): container should be ready to start!\n"
> +    printf "\n\n"
> +    printf "You could now use you container with: lxc-start -n %s\n" "${name}"
> +    printf "little things you should know about your container:\n"
> +    printf "${user_message}"
> +    return 0
> +}
> +
> +container_precheck()
> +{
> +    printf "### container_precheck(): doing some pre-start checks ...\n"
> +    # never hurts to have a fail-safe.
> +    [[ -n "${name//\/}" ]] \
> +        || die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${name}"
> +
> +    [[ -n "${rootfs//\/}" ]] \
> +        || die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
> +
> +    [[ -n "${cachefs//\/}" ]] \
> +        || die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
> +
> +    # check if the rootfs already exists
> +    [[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}"
> +
> +    # check cache
> +    [[ ! -d "${cachefs}/etc" ]] && die 1 "Error: \$cachefs (%s) not found!" "${cachefs}"
> +
> +    return 0
> +}
> +
> +container_rootfs()
> +{
> +    printf "#### container_rootfs(): copying rootfs %s from cache %s ...\n" "${rootfs}" "${cachefs}"
> +    tar -c -f - -C "${cachefs}" . | tar -x -p -f - -C "${rootfs}" || die 1 "Error: cache copy to rootfs failed"
> +
> +    printf "chroot test..."
> +    chroot "${rootfs}" /bin/true || die 1 "Error: 'chroot %s /bin/true' failed"
> +    printf " OK\n"
> +
> +    printf " => done\n"
> +    return 0
> +}
> +
> +container_consoles() {
> +    printf "#### container_consoles(): setting container consoles ...\n"
> +
> +    # disable unwanted ttys
> +    if [[ ${tty} < 6 ]]; then
> +        local mindis=$(( ${tty} + 1 ))
> +        sed -i "s/^c[${mindis}-6]/#&/" "${rootfs}/etc/inittab"
> +    fi
> +    printf " => main console + ${tty} ttys\n"
> +
> +    if [[ -z "${autologin}" ]]; then
> +        sed 's/agetty -a root/agetty/' -i "${rootfs}/etc/inittab"
> +    elif [[ "${user}" != "root" ]]; then
> +        sed "s/agetty -a root/agetty -a ${user}/" -i "${rootfs}/etc/inittab"
> +        printf " => Autologin on main console for %s enabled\n" "${user}"
> +        [[ -z "${forced_password}" ]] && unset password
> +        store_user_message "${user} has autologin on main console"
> +    else
> +        printf " => Autologin on main console for root enabled\n"
> +        [[ -z "${forced_password}" ]] && unset password
> +        store_user_message "${user} has autologin on main console"
> +    fi
> +    printf " => done\n"
> +}
> +
> +container_tz()
> +{
> +    printf "#### container_tz(): setting container timezone ...\n"
> +
> +    #let's try to copy it from host
> +    if [ -L "/etc/localtime" ]; then
> +        #host has a symlink
> +        #let see if we can reproduct symlink
> +        target=$(readlink /etc/localtime)
> +        if [[ "$target" != "" ]]; then
> +            if [ -f "${rootfs}/${target}" ]; then
> +                #same target exists in container
> +                chroot "${rootfs}" ln -sf "${target}" "/etc/localtime"
> +                printf " => host symlink reproducted in container : %s\n" "${target}"
> +                store_user_message "timezone copyed from host"
> +                return 0
> +            fi
> +        fi
> +    fi
> +
> +    if [ -e /etc/localtime ]; then
> +        # duplicate host timezone
> +        cat /etc/localtime > "${rootfs}/etc/localtime"
> +        printf " => host localtime copyed to container\n"
> +        store_user_message "timezone was staticly copyed from host"
> +    else
> +        # otherwise set up UTC
> +        chroot "${rootfs}" ln -sf /usr/share/zoneinfo/UTC /etc/localtime
> +        printf " => fallback: fixed to UTC\n"
> +        store_user_message "timezone was fixed to UTC"
> +    fi
> +}
> +
> +
> +container_portage()
> +{
> +    printf "#### container_portage(): setting container portage... \n"
> +
> +    #default entry for conf
> +    portage_mount="#container set with private portage tree, no mount here"
> +
> +    printf "Warnings are normal here, don't worry\n"
> +    #container repos detection
> +    if chroot ${rootfs} portageq get_repo_path / gentoo > /dev/null ; then
> +        portage_container="$(chroot ${rootfs} portageq get_repo_path / gentoo)"
> +    else
> +        die 1 "Failed to figure out container portage tree location with portageq get_repo_path / gentoo\n"
> +    fi
> +
> +    if [[ -n "${private_portage}" ]]; then
> +        container_private_portage
> +        return 0
> +    fi
> +
> +    if [ -z "${portage_dir}" ]; then
> +        #gentoo host detection
> +        printf "trying to guess portage_dir from host...\n"
> +        portage_dir="$(portageq get_repo_path / gentoo 2>/dev/null)"
> +        if [ ! -d "${portage_dir}/profiles" ]; then
> +            printf " => host portage detection failed (not gentoo host), fallback to private portage tree\n"
> +            container_private_portage
> +            return 0
> +        fi
> +    else
> +        if [ ! -d "${portage_dir}/profiles" ]; then
> +            die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}"
> +        fi
> +    fi
> +
> +    # if we are here, we have shared portage_dir
> +    #ensure dir exists
> +    chroot "${rootfs}" mkdir ${portage_container}
> +        portage_mount="#container set with shared portage
> +    lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0"
> +    store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}"
> +        #Let's propose binary packages
> +    cat <<- EOF >> "${rootfs}/etc/portage/make.conf"
> +    # enable this to store built binary packages
> +    #FEATURES="\$FEATURES buildpkg"
> +
> +    # enable this to use built binary packages
> +    #EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --usepkg"
> +
> +    # enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants
> +    #PKGDIR="\${PKGDIR}/amd64
> +    #or PKGDIR="\${PKGDIR}/hardened"
> +EOF
> +    printf " => portage stuff done, see /etc/portage/make.conf for additionnal tricks\n"
> +
> +}
> +
> +container_private_portage()
> +{
> +    #called from container_portage() do not call directly from container_setup
> +    printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}"
> +    mkdir -p "${rootfs}/${portage_container}"
> +    execute_exclusively portage 60 tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" -f "${portage_cache}" \
> +        || die 2 "Error: unable to extract the portage tree.\n"
> +    store_user_message "container has its own portage tree at ${portage_container}"
> +    printf "=> done\n"
> +}
> +
> +#helper func for container_genconf_net()
> +nic_write()
> +{
> +    #display with gentoo's confd.net format
> +    echo "config_${nic_name}=\"${nic_conf}\""
> +    #add to managed list
> +    [[ "${nic_conf}" == "dhcp" ]] && nic_managed="${nic_managed} ${nic_name}"
> +    [[ "${nic_conf}" == "null" ]] && nic_unmanaged="${nic_unmanaged} ${nic_name}"
> +    [[ -z "${nic_hwaddr}" && ${nic_type} == "veth" ]] && nic_wo_hwaddr="${nic_wo_hwaddr} ${nic_name}"
> +    nic_writed=1
> +}
> +
> +#Analyse lxc.conf and print conf.d/net content
> +container_conf_net()
> +{
> +    local file=${1}
> +    [[ -z "${nic_last}" ]] && nic_last=-1
> +    [[ -z "${nic_named}" ]] && nic_named=0
> +    OLDIFS=$IFS
> +    IFS="
> +"
> +    #I'll drink champagne the day we do templates in python
> +    #let's do some drity bash things
> +    for line in $( sed -r "s/[ ]*=[ ]*/_real_ugly_sep_42_/" "${file}" ); do
> +        key=$(echo "${line}" | sed 's/_real_ugly_sep_42_.*$//')
> +        value=$(echo "${line}" | sed 's/^.*_real_ugly_sep_42_//')
> +
> +        #new nic !
> +        if [[ "${key}" == "lxc.network.type" ]]; then
> +            #we don't know what to do with it.
> +            [[ "${value}" == "empty" ]] && continue
> +
> +            #write conf from previous loops
> +            [[ "${nic_writed}" == "0" ]] && nic_write
> +
> +            #init defaults
> +            let nic_last=nic_last+1
> +
> +            nic_writed=0
> +            #if 1 named between 2 not named: last is eth1
> +            #=> Number is ID munis number of named NIC before
> +            nic_name="eth$(( ${nic_last} - ${nic_named} ))"
> +            nic_conf="dhcp"
> +            nic_type="${value}"
> +        fi
> +
> +                if [[ "${key}" == "lxc.network.hwaddr" ]]; then
> +                nic_hwaddr=1
> +        fi
> +
> +        if [[ "${key}" =~ ^lxc.network.ipv(4|6) ]]; then
> +            #tell openrc to not manage this NIC as LXC set there address
> +            nic_conf="null"
> +        fi
> +        if [[ "${key}" =~ ^lxc.network.name ]]; then
> +            nic_name="${value}"
> +            let nic_named=nic_named+1
> +        fi
> +        if [[ "${key}" == "lxc.include" ]]; then
> +            #recursive into include
> +            container_conf_net "${value}"
> +        fi
> +    done
> +    #write conf from previous loops
> +    [[ "${nic_writed}" == "0" ]] && nic_write
> +    IFS=$OLDIFS
> +}
> +
> +container_net()
> +{
> +    printf "container_net(): setting container network conf... \n"
> +
> +    #Analyse network configuration in config
> +    container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net"
> +
> +        # found how much nic finaly have
> +    nic_count=$(( ${nic_last} + 1 ))
> +
> +        # unless openrc manage a nic, we now have to force openrc to automatic
> +    # provision of the 'net' dep. If we do not, network dependent services
> +    # will fail to load
> +    if [[ -z "${nic_managed}" ]]; then
> +        #tell openrc that lxc already did the work
> +        echo 'rc_provide="net"' >> "$CACHE/etc/rc.conf"
> +    fi
> +
> +    #No NIC ?
> +    if [[ ${nic_count} == 0 ]]; then
> +        #If no Nic, no need to continue
> +        bridge=$(brctl show | awk 'NR==2 {print $1}')
> +        if [[ "${bridge}" != "" ]]; then
> +                        store_user_message "No network interface for this container
> +It's a pitty, you have bridge, ${bridge}.
> +If it is for Lxc, use it next time by adding this to your default.conf :
> +lxc.network.type = veth
> +lxc.network.link = ${bridge}
> +lxc.network.flags = up
> +lxc.network.hwaddr = fe:xx:xx:xx:xx:xx"
> +                        return 0
> +        else
> +                store_user_message "No network interface for this container"
> +                        return 0
> +        fi
> +    fi
> +
> +    #For each openrc managed nic, activate
> +    for nic in ${nic_managed}
> +    do
> +        chroot "${rootfs}" ln -s net.lo "/etc/init.d/net.${nic}"
> +        chroot "${rootfs}" rc-update add net.${nic} default
> +    done
> +
> +        #Warn about dynamic hwaddr
> +    if [[ -n "${nic_wo_hwaddr}" ]]; then
> +                store_user_message "Warning, these veth NIC don't have fixed hwaddr :
> +${nic_wo_hwaddr}
> +
> +see http://lists.linuxcontainers.org/pipermail/lxc-devel/2013-December/006736.html
> +and man lxc.conf"
> +    fi
> +
> +    printf " => network conf done.\n"
> +}
> +
> +# custom hostname
> +container_hostname()
> +{
> +    printf "#### container_hostname(): setting hostname... \n"
> +    printf "hostnale=%s\n" "${name}" > "${rootfs}/etc/conf.d/hostname"
> +    printf " => done.\n"
> +}
> +
> +container_auth()
> +{
> +    printf "#### container_auth(): setting authentification... \n"
> +    if [[ "${user}" != "root" ]]; then
> +        printf " non root user requested, creating... \n"
> +        chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}"
> +        printf "  => user %s created\n" "${user}"
> +    fi
> +    store_user_message "Connection user is ${user}"
> +    #Home of user
> +    auth_home=$(chroot "${rootfs}" getent passwd "${user}" | cut -d : -f 6)
> +    if [[ -r "${auth_key}" ]]; then
> +        printf " deploying auth_key %s for user %s ...\n" "${auth_key}" "${user}"
> +        mkdir -p "${rootfs}/${auth_home}/.ssh"
> +        cat >> "${rootfs}/${auth_home}/.ssh/authorized_keys"
> +        chroot "${rootfs}" chown "${user}:" "${auth_home}/.ssh/authorized_keys"
> +        printf "  => inserted public key in %s/.ssh/authorized_keys\n" "${auth_home}"
> +        [[ -z "${forced_password}" ]] && unset password
> +        store_user_message "${user} has the ssh key you gived us"
> +    fi
> +
> +    if [[ -n "${password}" ]]; then
> +        printf " setting password for %s ...\n" "${user}"
> +        echo "${user}:${password}" | chroot "${rootfs}" chpasswd || die 1 "failed to change password"
> +        printf "  => done. if you didn't specify , default is 'toor'\n"
> +        if [[ -n "${forced_password}" ]]; then
> +            store_user_message "${user} has the password you give for him"
> +        else
> +            store_user_message "${user} has the default password 'toor', please change it ASAP"
> +        fi
> +    fi
> +
> +    printf " => done.\n"
> +}
> +
> +################################################################################
> +#                        lxc configuration files
> +################################################################################
> +
> +container_conf()
> +{
> +    printf "container_configuration(): making lxc configuration file... \n"
> +
> +    #at this point if there
> +    conf_file="${path}/config"
> +
> +    if grep -q "^lxc.rootfs" "${conf_file}" ; then
> +        #lxc-create already provided one
> +        conf_rootfs_line=""
> +    else
> +        conf_rootfs_line="lxc.rootfs = $(readlink -f "${rootfs}")"
> +    fi
> +    if [[ "${arch}" == "x86" || "${arch}" == "amd64" ]]; then
> +        local conf_arch_line="lxc.arch = ${arch}"
> +    else
> +        local conf_arch_line="# lxc.arch = ${arch}"
> +    fi
> +
> +    conf_lxc_cap_drop="sys_module mac_admin mac_override mknod sys_time"
> +    conf_sysfs="lxc.mount.entry=sys sys sysfs defaults 0 0"
> +
> +    #more aggressive configuration, for your safety. But less things may work
> +    if [ -n "${more_secure}" ]; then
> +        conf_lxc_cap_drop="${conf_lxc_cap_drop} audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable setfcap sys_admin sys_boot sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog"
> +        conf_sysfs="# disabled for security, see http://blog.bofh.it/debian/id_413
> +#lxc.mount.entry=sys sys sysfs defaults 0 0"
> +    fi
> +
> +        cat <<- EOF >> "${conf_file}"
> +# sets container architecture
> +# If desired architecture != amd64 or x86, then we leave it unset as
> +# LXC does not oficially support anything other than x86 or amd64.
> +${conf_arch_line}
> +
> +# console access
> +lxc.tty = ${tty}
> +lxc.pts = 1024
> +
> +# set the hostname
> +lxc.utsname = ${name}
> +
> +${conf_rootfs_line}
> +${portage_mount}
> +${conf_sysfs}
> +
> +# this part is based on 'linux capabilities', see: man 7 capabilities
> +#  eg: you may also wish to drop 'cap_net_raw' (though it breaks ping)
> +#
> +# WARNING: the security vulnerability reported for 'cap_net_admin' at
> +# http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html
> +# via JIT spraying (the BPF JIT module disabled on most systems was used
> +# in the example, but others are suggested vulnerable) meant that users
> +# with root in a container, that capability and kernel module may escape
> +# the container. ALWAYS be extremely careful granting any process root
> +# within a container, use a minimal configuration at all levels -
> +# including the kernel - and multiple layers of security on any system
> +# where security is a priority.  note that not only LXC but PAX (and
> +# others?) were vulnerable to this issue.
> +#
> +# conservative: lxc.cap.drop = sys_module mknod mac_override sys_boot
> +# aggressive follows. (leaves open: chown dac_override fowner ipc_lock kill lease net_admin net_bind_service net_broadcast net_raw setgid setuid sys_chroot)
> +# lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mac_admin mac_override mknod setfcap sys_admin sys_boot sys_module sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config syslog
> +
> +lxc.cap.drop = ${conf_lxc_cap_drop}
> +
> +${conf_mounts}
> +
> +# deny access to all devices by default, explicitly grant some permissions
> +#
> +# format is [c|b] [major|*]:[minor|*] [r][w][m]
> +#            ^     ^                   ^
> +# char/block -'     \`- device number    \`-- read, write, mknod
> +#
> +# first deny all...
> +lxc.cgroup.devices.deny = a
> +# /dev/null and zero
> +lxc.cgroup.devices.allow = c 1:3 rw
> +lxc.cgroup.devices.allow = c 1:5 rw
> +# /dev/{,u}random
> +lxc.cgroup.devices.allow = c 1:9 rw
> +lxc.cgroup.devices.allow = c 1:8 r
> +# /dev/pts/*
> +lxc.cgroup.devices.allow = c 136:* rw
> +lxc.cgroup.devices.allow = c 5:2 rw
> +# /dev/tty{0,1}
> +lxc.cgroup.devices.allow = c 4:1 rwm
> +lxc.cgroup.devices.allow = c 4:0 rwm
> +# /dev/tty
> +lxc.cgroup.devices.allow = c 5:0 rwm
> +# /dev/console
> +lxc.cgroup.devices.allow = c 5:1 rwm
> +EOF
> +    if [ -n "${nettun}" ]; then
> +        cat <<- EOF >> "${conf_file}"
> +# /dev/net/tun
> +lxc.cgroup.devices.allow = c 10:200 rwm
> +EOF
> +    fi
> +    printf  " => done.\n"
> +}
> +
> +usage()
> +{
> +    cat <<EOF
> +$1 -h|--help [-a|--arch <arch>] [-v|--variant <variant>] [-P|--private-portage] [--portage-dir <protagedir>] [-t|--tarball <stage3file>]
> + [-F|--flush-cache] [-c|--cache-only] [-u|--user <username>] [-w|--password <password>] [-S|--auth-key <keyfile>]
> + [-s|--more-secure] [-m|--mirror <gentoomirror>] [--tty <number>] [--nettun]
> +
> +arch: the container architecture (e.g. amd64): defaults to host arch (currently: '${arch}')
> +    If you choose one that needs emulation
> +    tested: amd64, x86
> +    You could try any other gentoo arch, why not...
> +
> +variant: gentoo's Architecture variant as of dec 2013 : (currently: '${variant}')
> +    for amd64 arch: amd64 (default), amd64-hardened+nomultilib, amd64-hardened, amd64-nomultilib, x32
> +    for x86 arch: i686 (default), i486, i686-hardened
> +    for arm arch: armv7a (default), armv7a_hardfp, armv6j, armv6j_hardfp, armv5tel, armv4tl
> +
> +private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}')
> +    this force container to have his own copy
> +
> +portage-dir: portage dir used for shared portage
> +    by default the host on if any (currently: '${portage_dir}')
> +
> +tarball: force usage of local stage3 archive (currently: '${arch}')
> +    If empty, latest will be downloaded
> +
> +flush-cache: do like there is no previous cache
> +
> +cache-only: just ensure cache is present
> +    if cache exists and "flush-cache" not specified, does nothing
> +
> +user: user used in auth oriented options (currently: '${user}')
> +
> +password: password for user (currently: '${password}')
> +    if default, usage of auth-key will disable password setting
> +
> +autologin: enable autologin for user (currently: '${autologin}')
> +    This unset default password setting
> +
> +auth-key: SSH Public key file to inject into container for user (currently: '${auth_key}')
> +    This unset default password setting
> +
> +more-secure: does some additional security agressive settings (may prevent things to run) (currently: '${more_secure}')
> +
> +mirror: gentoo mirror for download (currently: '${mirror}')
> +
> +tty: number of tty (6 max) (currently: '${tty}')
> +
> +nettun: enable creation of /dev/net/tun (for private container VPN) (currently: '${nettun}')
> +EOF
> +    exit 0
> +}
> +
> +#some overridable defaults
> +set_default_arch
> +
> +mirror="http://distfiles.gentoo.org"
> +user="root"
> +password="toor"
> +tty=0
> +options=$(getopt -o hp:n:a:FcPv:t:S:u:w:sm: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth_key:,user:,autologin,password:,more-secure,mirror:,tty:,nettun -- "$@")
> +
> +eval set -- "$options"
> +
> +while true
> +do
> +    case "$1" in
> +    -h|--help)             usage $0 && exit 0;;
> +    --rootfs)              rootfs=$2; shift 2;;
> +    -p|--path)             path=$2; shift 2;;
> +    -n|--name)             name=$2; shift 2;;
> +    -a|--arch)             arch=$2; shift 2;;
> +    -F|--flush-cache)      flush_cache=1; shift 1;;
> +    -c|--cache-only)       cache_only=1; shitf 1;;
> +    -P|--private-portage)  private_portage=1; shift 1;;
> +    -v|--variant)          variant=$2; shift 2;;
> +    --portage-dir)         portage_dir=$2; shift 2;;
> +    -t|--tarball)          tarball=$2; shift 2;;
> +    -S|--auth-key)         auth_key=$2; shift 2;;
> +    -u|--user)             user=$2; shift 2;;
> +    -w|--password)         forced_password=1; password=$2; shift 2;;
> +    -s|--more-secure)      more_secure=1; shift 1;;
> +    -m|--mirror)           mirror=$2; shift 2;;
> +    --nettun)              nettun=1; shift 1;;
> +    --tty)                 [[ $2 -lt 6 ]] && tty=$2; shift 2;;
> +    --autologin)            autologin=1; shift 1;;
> +    --) shift 1; break ;;
> +    *)           break ;;
> +    esac
> +done
> +
> +cacheroot="@LOCALSTATEDIR@/cache/lxc/gentoo"
> +portage_cache="${cacheroot}/portage.tbz"
> +cachefs="${cacheroot}/rootfs-${arch}-${variant}"
> +
> +alias wget="wget --timeout=8 --read-timeout=15 -c -t10 -nd"
> +
> +do_all() {
> +    cache_setup
> +    if [ -z "${cache_only}" ]; then
> +        container_setup
> +    fi
> +}
> +
> +execute_exclusively "cache-${arch}-${variant}" 60 do_all
> -- 
> 1.8.3.2
> 
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140114/0a08c211/attachment.pgp>


More information about the lxc-devel mailing list