555c8a1bf1
This change creates a simple LXC create template for machinectl. This will allow out container create process to use less storage and more efficently build containers which will speed up operations and deployments. This also begins to leverage common tools already on the systems we support there by simplifing how cache is stored, containers are built and the general management of images within a host. The new lxc container create template, and the features it provides, will only impact new containers created allowing deployers to safely adopt this change in any existing environment. Change-Id: I70d53cabd0888954f31def924e9f4436398cdebf Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
213 lines
6.6 KiB
Django/Jinja
213 lines
6.6 KiB
Django/Jinja
#!/usr/bin/env bash
|
|
|
|
# Copyright 2017, Rackspace US, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
set -eu
|
|
|
|
|
|
## Vars ----------------------------------------------------------------------
|
|
LXC_CACHE_BASE="/var/cache/lxc/"
|
|
LXC_CACHE_PATH="${LXC_CACHE_PATH:-$LXC_CACHE_BASE}"
|
|
LXC_HOOK_DIR="/usr/share/lxc/hooks"
|
|
LXC_TEMPLATE_CONFIG="/usr/share/lxc/config"
|
|
|
|
# Default variables
|
|
DOWNLOAD_VARIANT=
|
|
DOWNLOAD_DIST=
|
|
DOWNLOAD_RELEASE=
|
|
DOWNLOAD_ARCH=
|
|
|
|
# NOTE(cloudnull): These variables are created magically through the
|
|
# `lxc-create` command and must exist at the top of the file.
|
|
LXC_NAME=
|
|
LXC_PATH=
|
|
LXC_ROOTFS=
|
|
|
|
## Functions ------------------------------------------------------------------
|
|
usage() {
|
|
# Return usage information
|
|
cat <<EOF
|
|
LXC container image in machinectl
|
|
|
|
Special arguments:
|
|
[ -h | --help ]: Print this help message and exit.
|
|
|
|
Required arguments:
|
|
[ --name <name> ]: The container name
|
|
[ -d | --dist <distribution> ]: The name of the distribution
|
|
[ -r | --release <release> ]: Release name/version
|
|
[ -a | --arch <architecture> ]: Architecture of the container
|
|
|
|
Optional arguments:
|
|
[ --variant <variant> ]: Variant of the image (default: "default")
|
|
[ -b | --base <base-image> ]: Set the image base name to ANY existing machine image
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
# Trap all exit signals
|
|
trap EXIT HUP INT TERM
|
|
|
|
## Exports --------------------------------------------------------------------
|
|
# Make sure the usual locations are in PATH
|
|
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin
|
|
|
|
|
|
## Main -----------------------------------------------------------------------
|
|
if ! options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,name:,path:,rootfs: -- "$@"); then
|
|
usage
|
|
exit 1
|
|
fi
|
|
eval set -- "$options"
|
|
|
|
while :; do
|
|
case "$1" in
|
|
-h|--help) usage && exit 1;;
|
|
-l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;;
|
|
-d|--dist) DOWNLOAD_DIST="$2"; shift 2;;
|
|
-r|--release) DOWNLOAD_RELEASE="$2"; shift 2;;
|
|
-a|--arch) DOWNLOAD_ARCH="$2"; shift 2;;
|
|
--variant) DOWNLOAD_VARIANT="$2"; shift 2;;
|
|
--name) LXC_NAME="$2"; shift 2;;
|
|
--path) LXC_PATH="$2"; shift 2;;
|
|
--rootfs) LXC_ROOTFS="$2"; shift 2;;
|
|
*) break;;
|
|
esac
|
|
done
|
|
|
|
# Setup the basic information used for machine images
|
|
if [ -z "${LXC_MACHINE_IMAGE:-}" ]; then
|
|
export LXC_MACHINE_IMAGE="${DOWNLOAD_DIST}-${DOWNLOAD_RELEASE}-${DOWNLOAD_ARCH}"
|
|
fi
|
|
|
|
# NOTE(cloudnull): If a variant name has not been defined, set it as "default".
|
|
# If a variant is set, amend the machine image name
|
|
if [ -z "${DOWNLOAD_VARIANT:-}" ]; then
|
|
export DOWNLOAD_VARIANT="default"
|
|
fi
|
|
|
|
# Setup the basic pathing pointing at the known LXC cache
|
|
LXC_CACHE_PATH="${LXC_CACHE_PATH}/download/${DOWNLOAD_DIST}"
|
|
LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_RELEASE}/${DOWNLOAD_ARCH}/"
|
|
export LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_VARIANT}"
|
|
|
|
# Check for required binaries
|
|
for bin in machinectl; do
|
|
if ! command -V "${bin}" >/dev/null 2>&1; then
|
|
echo "ERROR: Missing required tool: ${bin}" 1>&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Check for the lxc base image
|
|
if ! btrfs subvolume show "/var/lib/machines/${LXC_MACHINE_IMAGE}" 2>&1 > /dev/null; then
|
|
echo "[FAILURE] Base image does not exist."
|
|
exit 99
|
|
fi
|
|
|
|
if btrfs subvolume show "/var/lib/machines/${LXC_NAME}" 2>&1 > /dev/null; then
|
|
echo "[NOTICE] Contianer volume already exists"
|
|
else
|
|
btrfs subvolume snapshot \
|
|
"/var/lib/machines/${LXC_MACHINE_IMAGE}" \
|
|
"/var/lib/machines/${LXC_NAME}"
|
|
echo "[NOTICE] New machine volume created"
|
|
fi
|
|
|
|
# Set the LXC_ROOTFS to the machines path
|
|
export LXC_ROOTFS="/var/lib/machines/${LXC_NAME}"
|
|
|
|
# Ensuing the container path exists
|
|
mkdir -p "${LXC_ROOTFS}/${LXC_NAME}/dev/pts/"
|
|
mkdir -p "${LXC_PATH}/rootfs"
|
|
|
|
cat <<EOF
|
|
=== CONTAINER DETAILS ===
|
|
machine image: ${LXC_MACHINE_IMAGE}
|
|
lxc cache path: ${LXC_CACHE_PATH}
|
|
container path: ${LXC_PATH}
|
|
rootfs path: ${LXC_ROOTFS}
|
|
container name: ${LXC_NAME}
|
|
=== CONTAINER DETAILS ===
|
|
EOF
|
|
|
|
if [ ! -e "${LXC_CACHE_PATH}/config" ]; then
|
|
echo "ERROR: meta tarball is missing the configuration file" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Build container specific configurations
|
|
echo -e "\n# Distribution configuration" >> "${LXC_PATH}/config"
|
|
cat "${LXC_CACHE_PATH}/config" >> "${LXC_PATH}/config"
|
|
|
|
echo -e "\n# Container specific configuration" >> "${LXC_PATH}/config"
|
|
|
|
# If an older fstab file exists in the template, extend the lxc config.
|
|
if [ -e "${LXC_CACHE_PATH}/fstab" ]; then
|
|
echo "lxc.mount.fstab = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config"
|
|
fi
|
|
|
|
# Set the uts name
|
|
echo "lxc.utsname = ${LXC_NAME}" >> "${LXC_PATH}/config"
|
|
|
|
# Look for extra templates
|
|
TEMPLATE_FILES="${LXC_PATH}/config"
|
|
if [ -e "${LXC_CACHE_PATH}/templates" ]; then
|
|
while read -r line; do
|
|
fullpath="${LXC_ROOTFS}/${line}"
|
|
[ ! -e "${fullpath}" ] && continue
|
|
TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}"
|
|
done < "${LXC_CACHE_PATH}/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}
|
|
|
|
# Add the machinectl backend store for the new containe
|
|
if grep -q '^lxc\.rootfs =' "${LXC_PATH}/config"; then
|
|
sed -i "s|^lxc\.rootfs =.*|lxc.rootfs = ${LXC_ROOTFS}|" "${LXC_PATH}/config"
|
|
else
|
|
echo "lxc.rootfs = ${LXC_ROOTFS}" >> "${LXC_PATH}/config"
|
|
fi
|
|
if grep -q '^lxc\.rootfs\.backend =' "${LXC_PATH}/config"; then
|
|
sed -i "s|^lxc\.rootfs\.backend =.*|lxc.rootfs.backend = btrfs|" "${LXC_PATH}/config"
|
|
else
|
|
echo "lxc.rootfs.backend = btrfs" >> "${LXC_PATH}/config"
|
|
fi
|
|
|
|
# Prevent mingetty from calling vhangup(2)
|
|
if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then
|
|
sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf"
|
|
fi
|
|
|
|
# Display exit message
|
|
if [ -e "${LXC_CACHE_PATH}/create-message" ]; then
|
|
echo -e "\n---"
|
|
cat "${LXC_CACHE_PATH}/create-message"
|
|
fi
|
|
|
|
exit 0
|