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

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


On Tue, Jan 14, 2014 at 11:34:19PM +0100, lxc at zitta.fr wrote:
> 
> Le 14/01/2014 22:42, Stéphane Graber a écrit :
> > 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>
> Hi, I'll try to apply best practices during next days.
> 
> BTW, What about common "bash functions" for templates ?
> Perhaps for Lxc 1.1 ...

It's been mentioned a few times but apparently nobody actually did that yet.
Adding a new lxc-templates.functions with standard shell functions for
template to use would make a lot of sense to me.

Btw, I forgot to comment on that earlier, you say:
> >> +    #I'll drink champagne the day we do templates in python
> >> +    #let's do some drity bash things

Well, there's actually no reason why you couldn't have written your
template in python. It's just a coincidence that everyone so far has
been using either POSIX shell or bash for their templates. LXC simply
expects a standard set of arguments to be accepted by the template and
have it exit 1 on error and 0 on success.


> >> ---
> >>  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
> >
> >
> > _______________________________________________
> > lxc-devel mailing list
> > lxc-devel at lists.linuxcontainers.org
> > http://lists.linuxcontainers.org/listinfo/lxc-devel
> 
> _______________________________________________
> 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/872e32f9/attachment-0001.pgp>


More information about the lxc-devel mailing list