MODE="system"
COMPAT_LEVEL=5
+EXCLUDES=""
+TEMPLATE_FILES="${LXC_PATH}/config"
+
+
# Make sure the usual locations are in PATH
export PATH="$PATH:/usr/sbin:/usr/bin:/sbin:/bin"
fi
relevant_file() {
+ # Reads the supplied file name from LOCAL_TEMP..
+ # If the file exists in $LOCAL_TEMP/$FILENAME.$COMPAT_LEVEL, it will be used.
+ # The default COMPAT_LEVEL is 5.
+ # If the file exists in $LOCAL_TEMP/$FILENAME-$MODE, it will be used.
+ # The default MODE is "system".
+ # If a mode or compatibility level specific file does not exist, the
+ # passed file name will be used.
FILE_PATH="${LOCAL_TEMP}/$1"
if [ -e "${FILE_PATH}-${MODE}" ]; then
echo "${FILE_PATH}"
}
+create_build_dir() {
+ # Create temporary build directory.
+ # If mktemp is not available, use /tmp/lxc-local.$$
+ 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 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_METADATA}" -C "${LOCAL_TEMP}"; then
- echo "ERROR: Invalid metadata file" 2>&1
- exit 1
-fi
+ echo "Using local temporary directory ${LOCAL_TEMP}"
+}
-EXCLUDES=""
-excludelist=$(relevant_file excludes)
-if [ -f "${excludelist}" ]; then
+process_excludes() {
+ # If the file ${LXC_PATH}/excludes exists, it will be used as a list of
+ # files to exclude from the tarball.
+ excludelist=$(relevant_file excludes)
+ if [ -f "${excludelist}" ]; then
while read -r line; do
- EXCLUDES="${EXCLUDES} --exclude=${line}"
+ EXCLUDES="${EXCLUDES} --exclude=${line}"
done < "${excludelist}"
-fi
+ 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}"
+extract_config() {
+ # lxc-create will automatically create a config file at ${LXC_PATH}/config.
+ # This function extracts the network config, and any remaining lxc config
+ # The extracted config is stored in ${LXC_PATH}/config-network and ${LXC_PATH}/config-extra
+ # The config will be merged later.
-mkdir -p "${LXC_ROOTFS}/dev/pts/"
+ # Extract all the network config entries
+ sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" "${LXC_PATH}/config"
-# 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
+ if [ -e "${LXC_PATH}/config-network" ]; then
+ echo "Extracted network config to: ${LXC_PATH}/config-network"
+ cat "${LXC_PATH}/config-network"
+ fi
+
+ # Extract any other config entry
+ sed -i -e "/lxc./{w ${LXC_PATH}/config-extra" -e "d}" "${LXC_PATH}/config"
-## 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"
+ if [ -e "${LXC_PATH}/config-extra" ]; then
+ echo "Extracted additional config to: ${LXC_PATH}/config-extra"
+ cat "${LXC_PATH}/config-extra"
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"
+add_container_config() {
+ # Adds the contents of the supplied metadata config to the container config
+ {
+ echo ""
+ echo "# Distribution configuration"
+ cat "$configfile"
+ } >> "${LXC_PATH}/config"
+}
-## Re-add the previously removed network config
-if [ -e "${LXC_PATH}/config-network" ]; then
+add_extra_config() {
+ # Add the container-specific config
{
echo ""
- echo "# Network configuration"
- cat "${LXC_PATH}/config-network"
- rm "${LXC_PATH}/config-network"
+ echo "# Container specific configuration"
+ if [ -e "${LXC_PATH}/config-extra" ]; then
+ cat "${LXC_PATH}/config-extra"
+ rm "${LXC_PATH}/config-extra"
+ fi
} >> "${LXC_PATH}/config"
-fi
+}
-TEMPLATE_FILES="${LXC_PATH}/config"
+add_network_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
+}
-# Setup the fstab
-if [ -e "${fstab}" ]; then
- cp "${fstab}" "${LXC_PATH}/fstab"
- TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab"
-fi
+process_config() {
+ # Process the supplied config file if it exists.
+ configfile="$(relevant_file config)"
+ if [ ! -e "${configfile}" ]; then
+ echo "ERROR: metadata tarball is missing the configuration file" 1>&2
+ return
+ 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
+ extract_config
+ add_container_config
+ add_extra_config
+ add_network_config
+}
+process_fstab() {
+ # Process the supplied fstab file if it exists.
+ # Add the fstab file to template files so substitions can be made.
+ fstab="$(relevant_file fstab)"
+ if [ -e "${fstab}" ]; then
+ echo "lxc.mount.fstab = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config"
+ cp "${fstab}" "${LXC_PATH}/fstab"
+ TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab"
+ fi
+}
-# Replace variables in all templates
-OLD_IFS=${IFS}
-IFS=";"
-for file in ${TEMPLATE_FILES}; do
- [ ! -f "${file}" ] && continue
+process_templates() {
+ # Look for extra templates
+ template="$(relevant_file template)"
+ if [ -e "${template}" ]; then
+ while read -r line; do
+ fullpath="${LXC_ROOTFS}/${line}"
+ [ ! -e "${fullpath}" ] && continue
+ TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}"
+ done < "${template}"
+ fi
+}
- 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}
+unpack_metadata() {
+ # Unpack file that contains the container metadata
+ # If the file does not exist, just warn and continue.
+ if [ -n "${LXC_METADATA}" ] && [ -f "${LXC_METADATA}" ]; then
+ if tar Jxf "${LXC_METADATA}" -C "${LOCAL_TEMP}"; then
+ echo "Unpacked metadata file: ${LXC_METADATA}"
+ process_excludes
+ process_config
+ process_fstab
+ process_templates
+ else
+ echo "Unable to unpack metadata file: ${LXC_METADATA}" 2>&1
+ exit 1
+ fi
+ fi
+}
-# 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
+set_utsname() {
+ # Set the container's hostname
+ echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_PATH}/config"
+}
+
+prepare_rootfs() {
+ # Additional configuration that must be done on the rootfs.
+ # Always add /dev/pts as /dev may be excluded.
+ mkdir -p "${LXC_ROOTFS}/dev/pts/"
+}
+unpack_rootfs() {
+ # Unpack the rootfs
+ echo "Unpacking the rootfs to: ${LXC_ROOTFS}"
-if [ -e "$(relevant_file create-message)" ]; then
- echo ""
- echo "---"
- cat "$(relevant_file create-message)"
-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}"
+
+ prepare_rootfs
+}
+
+replace_template_vars() {
+ # 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}
+}
+
+fix_tty() {
+ # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle
+ if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then
+ echo "Patching ${LXC_ROOTFS}/etc/init/tty.conf to prevent mingetty from calling vhangup."
+ sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf"
+ fi
+}
+
+display_creation_message() {
+ if [ -e "$(relevant_file create-message)" ]; then
+ echo ""
+ echo "---"
+ cat "$(relevant_file create-message)"
+ fi
+}
+
+
+create_build_dir
+unpack_metadata
+unpack_rootfs
+
+set_utsname
+replace_template_vars
+fix_tty
+
+display_creation_message
exit 0