From: Christian Brauner Date: Mon, 26 Feb 2018 11:49:10 +0000 (+0100) Subject: templates: add lxc-local template X-Git-Tag: lxc-3.0.0.beta1~10^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2190%2Fhead;p=thirdparty%2Flxc.git templates: add lxc-local template Closes #2184. Signed-off-by: Christian Brauner --- diff --git a/configure.ac b/configure.ac index 224e1f15e..a4b1c93dd 100644 --- a/configure.ac +++ b/configure.ac @@ -877,6 +877,7 @@ AC_CONFIG_FILES([ templates/lxc-fedora templates/lxc-fedora-legacy templates/lxc-gentoo + templates/lxc-local templates/lxc-oci templates/lxc-openmandriva templates/lxc-opensuse diff --git a/templates/Makefile.am b/templates/Makefile.am index c4a5b9555..63abdf6fb 100644 --- a/templates/Makefile.am +++ b/templates/Makefile.am @@ -12,6 +12,7 @@ templates_SCRIPTS = \ lxc-fedora \ lxc-fedora-legacy \ lxc-gentoo \ + lxc-local \ lxc-oci \ lxc-openmandriva \ lxc-opensuse \ diff --git a/templates/lxc-local.in b/templates/lxc-local.in new file mode 100644 index 000000000..6c6caf814 --- /dev/null +++ b/templates/lxc-local.in @@ -0,0 +1,266 @@ +#!/bin/sh + +# Client script for LXC container images. +# +# Copyright © 2018 Stéphane Graber +# Copyright © 2018 Christian Brauner +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA + +set -eu + +LXC_HOOK_DIR="@LXCHOOKDIR@" +LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" + +LXC_NAME= +LXC_PATH= +LXC_ROOTFS= +LXC_CONFIG= +MODE="system" +COMPAT_LEVEL=4 + +# Make sure the usual locations are in PATH +export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin + +in_userns() { + [ -e /proc/self/uid_map ] || { echo no; return; } + + while read -r line; do + fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" + if [ "${fields}" = "0 0 4294967295" ]; then + echo no; + return; + fi + + if echo "${fields}" | grep -q " 0 1$"; then + echo userns-root; + return; + fi + done < /proc/self/uid_map + + [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; } + echo yes +} + +usage() { + cat < ]: The container name +[ --path ]: The path to the container +[ --rootfs ]: The path to the container's rootfs + +EOF + return 0 +} + +if ! options=$(getopt -o hm:f: -l help,metadata:,fstree:,name:,path:,rootfs:,mapped-uid:,mapped-gid: -- "$@"); then + usage + exit 1 +fi +eval set -- "$options" + +while :; do + case "$1" in + -h|--help) usage && exit 1;; + --name) LXC_NAME="$2"; shift 2;; + --path) LXC_PATH="$2"; shift 2;; + --rootfs) LXC_ROOTFS="$2"; shift 2;; + -m|--metadata) LXC_CONFIG="$2"; shift 2;; + -f|--fstree) LXC_FSTREE="$2"; shift 2;; + *) break;; + esac +done + +# Check for required binaries +for bin in tar xz; do + if ! command -V "${bin}" >/dev/null 2>&1; then + echo "ERROR: Missing required tool: ${bin}" 1>&2 + exit 1 + fi +done + +cleanup() { + if [ -d "${LOCAL_TEMP}" ]; then + rm -Rf "${LOCAL_TEMP}" + fi +} + +# Trap all exit signals +trap cleanup EXIT HUP INT TERM + +USERNS="$(in_userns)" + +if [ "${USERNS}" != "no" ]; then + if [ "${USERNS}" = "yes" ]; then + if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then + echo "ERROR: In a user namespace without a map." 1>&2 + exit 1 + fi + MODE="user" + else + MODE="user" + fi +fi + +relevant_file() { + FILE_PATH="${LOCAL_TEMP}/$1" + + if [ -e "${FILE_PATH}-${MODE}" ]; then + FILE_PATH="${FILE_PATH}-${MODE}" + fi + + if [ -e "${FILE_PATH}.${COMPAT_LEVEL}" ]; then + FILE_PATH="${FILE_PATH}.${COMPAT_LEVEL}" + fi + + echo "${FILE_PATH}" +} + + +# Unpack the rootfs +echo "Unpacking the rootfs" + +# Create temporary directory to +if ! command -V mktemp >/dev/null 2>&1; then + LOCAL_TEMP=/tmp/lxc-local.$$ + mkdir -p "${LOCAL_TEMP}" +else + LOCAL_TEMP=$(mktemp -d) +fi + +# Unpack file that contains meta.tar.xz +if ! tar Jxf "${LXC_CONFIG}" -C "${LOCAL_TEMP}"; then + echo "ERROR: Invalid metadata file" 2>&1 + exit 1 +fi + +EXCLUDES="" +excludelist=$(relevant_file excludes) +if [ -f "${excludelist}" ]; then + while read -r line; do + EXCLUDES="${EXCLUDES} --exclude=${line}" + done < "${excludelist}" +fi + +# Do not surround ${EXCLUDES} by quotes. This does not work. The solution could +# use array but this is not POSIX compliant. The only POSIX compliant solution +# is to use a function wrapper, but the latter can't be used here as the args +# are dynamic. We thus need to ignore the warning brought by shellcheck. +# shellcheck disable=SC2086 +tar --anchored ${EXCLUDES} --numeric-owner -xpJf "${LXC_FSTREE}" -C "${LXC_ROOTFS}" + +mkdir -p "${LXC_ROOTFS}/dev/pts/" + +# Setup the configuration +# Setup the configuration +configfile="$(relevant_file config)" +if [ ! -e "${configfile}" ]; then + echo "ERROR: meta tarball is missing the configuration file" 1>&2 + exit 1 +fi + +## Extract all the network config entries +sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" "${LXC_PATH}/config" + +## Extract any other config entry +sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config" + +## Append the defaults +{ + echo "" + echo "# Distribution configuration" + cat "$configfile" +} >> "${LXC_PATH}/config" + +## Add the container-specific config +{ + echo "" + echo "# Container specific configuration" + if [ -e "${LXC_PATH}/config-auto" ]; then + cat "${LXC_PATH}/config-auto" + rm "${LXC_PATH}/config-auto" + fi +} >> "${LXC_PATH}/config" + +fstab="$(relevant_file fstab)" +if [ -e "${fstab}" ]; then + echo "lxc.mount.fstab = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config" +fi +echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_PATH}/config" + +## Re-add the previously removed network config +if [ -e "${LXC_PATH}/config-network" ]; then + { + echo "" + echo "# Network configuration" + cat "${LXC_PATH}/config-network" + rm "${LXC_PATH}/config-network" + } >> "${LXC_PATH}/config" +fi + +TEMPLATE_FILES="${LXC_PATH}/config" + +# Setup the fstab +if [ -e "${fstab}" ]; then + cp "${fstab}" "${LXC_PATH}/fstab" + TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab" +fi + +# Look for extra templates +if [ -e "$(relevant_file templates)" ]; then + while read -r line; do + fullpath="${LXC_ROOTFS}/${line}" + [ ! -e "${fullpath}" ] && continue + TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}" + done < "$(relevant_file templates)" +fi + + +# Replace variables in all templates +OLD_IFS=${IFS} +IFS=";" +for file in ${TEMPLATE_FILES}; do + [ ! -f "${file}" ] && continue + + sed -i "s#LXC_NAME#${LXC_NAME}#g" "${file}" + sed -i "s#LXC_PATH#${LXC_PATH}#g" "${file}" + sed -i "s#LXC_ROOTFS#${LXC_ROOTFS}#g" "${file}" + sed -i "s#LXC_TEMPLATE_CONFIG#${LXC_TEMPLATE_CONFIG}#g" "${file}" + sed -i "s#LXC_HOOK_DIR#${LXC_HOOK_DIR}#g" "${file}" +done +IFS=${OLD_IFS} + +# prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle +if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then + sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf" +fi + + +if [ -e "$(relevant_file create-message)" ]; then + echo "" + echo "---" + cat "$(relevant_file create-message)" +fi + +exit 0