lxc-download: make POSIX shellcheck clean

parent b80f86f2
...@@ -55,12 +55,12 @@ LXC_PATH= ...@@ -55,12 +55,12 @@ LXC_PATH=
LXC_ROOTFS= LXC_ROOTFS=
if [ -z "${DOWNLOAD_KEYSERVER:-}" ]; then if [ -z "${DOWNLOAD_KEYSERVER:-}" ]; then
DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net" DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net"
# Deal with GPG over http proxy # Deal with GPG over http proxy
if [ -n "${http_proxy:-}" ]; then if [ -n "${http_proxy:-}" ]; then
DOWNLOAD_KEYSERVER="hkp://p80.pool.sks-keyservers.net:80" DOWNLOAD_KEYSERVER="hkp://p80.pool.sks-keyservers.net:80"
fi fi
fi fi
# Make sure the usual locations are in PATH # Make sure the usual locations are in PATH
...@@ -68,140 +68,141 @@ export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin ...@@ -68,140 +68,141 @@ export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
# Some useful functions # Some useful functions
cleanup() { cleanup() {
if [ -d "${DOWNLOAD_TEMP}" ]; then if [ -d "${DOWNLOAD_TEMP}" ]; then
rm -Rf "${DOWNLOAD_TEMP}" rm -Rf "${DOWNLOAD_TEMP}"
fi fi
} }
wget_wrapper() { wget_wrapper() {
for i in $(seq 3); do for _ in $(seq 3); do
if wget "$@"; then if wget "$@"; then
return 0 return 0
fi fi
done done
return 1 return 1
} }
download_file() { download_file() {
if ! wget_wrapper -T 30 -q "https://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then if ! wget_wrapper -T 30 -q "https://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then
if ! wget_wrapper -T 30 -q "http://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then if ! wget_wrapper -T 30 -q "http://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then
if [ "$3" = "noexit" ]; then if [ "$3" = "noexit" ]; then
return 1 return 1
else else
echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2
exit 1 exit 1
fi fi
elif [ "${DOWNLOAD_SHOW_HTTP_WARNING}" = "true" ]; then elif [ "${DOWNLOAD_SHOW_HTTP_WARNING}" = "true" ]; then
DOWNLOAD_SHOW_HTTP_WARNING="false" DOWNLOAD_SHOW_HTTP_WARNING="false"
echo "WARNING: Failed to download the file over HTTPs." 1>&2 echo "WARNING: Failed to download the file over HTTPs" 1>&2
echo " The file was instead download over HTTP. " 1>&2 echo " The file was instead download over HTTP " 1>&2
echo "A server replay attack may be possible!" 1>&2 echo "A server replay attack may be possible!" 1>&2
fi
fi fi
fi
} }
download_sig() { download_sig() {
if ! download_file "$1" "$2" noexit; then if ! download_file "$1" "$2" noexit; then
if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then
if [ "$3" = "normal" ]; then if [ "$3" = "normal" ]; then
echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2
exit 1 exit 1
else else
return 1 return 1
fi fi
else else
return 0 return 0
fi
fi fi
fi
} }
gpg_setup() { gpg_setup() {
if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then
return return
fi
if [ "${DOWNLOAD_READY_GPG}" = "true" ]; then
return
fi
echo "Setting up the GPG keyring"
mkdir -p "${DOWNLOAD_TEMP}/gpg"
chmod 700 "${DOWNLOAD_TEMP}/gpg"
export GNUPGHOME="${DOWNLOAD_TEMP}/gpg"
success=
for _ in $(seq 3); do
if gpg --keyserver "${DOWNLOAD_KEYSERVER}" \
--recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then
success=1
break
fi fi
break
done
if [ "${DOWNLOAD_READY_GPG}" = "true" ]; then if [ -z "${success}" ]; then
return echo "ERROR: Unable to fetch GPG key from keyserver"
fi exit 1
fi
echo "Setting up the GPG keyring"
mkdir -p "${DOWNLOAD_TEMP}/gpg"
chmod 700 "${DOWNLOAD_TEMP}/gpg"
export GNUPGHOME="${DOWNLOAD_TEMP}/gpg"
success=
for i in $(seq 3); do
if gpg --keyserver "${DOWNLOAD_KEYSERVER}" \
--recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then
success=1
break
fi
break
done
if [ -z "${success}" ]; then
echo "ERROR: Unable to fetch GPG key from keyserver."
exit 1
fi
DOWNLOAD_READY_GPG="true" DOWNLOAD_READY_GPG="true"
} }
gpg_validate() { gpg_validate() {
if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then
if [ "${DOWNLOAD_SHOW_GPG_WARNING}" = "true" ]; then if [ "${DOWNLOAD_SHOW_GPG_WARNING}" = "true" ]; then
echo "WARNING: Running without gpg validation!" 1>&2 echo "WARNING: Running without gpg validation!" 1>&2
fi
DOWNLOAD_SHOW_GPG_WARNING="false"
return 0
fi fi
DOWNLOAD_SHOW_GPG_WARNING="false"
return 0
fi
if ! gpg --verify "$1" >/dev/null 2>&1; then if ! gpg --verify "$1" >/dev/null 2>&1; then
echo "ERROR: Invalid signature for $1" 1>&2 echo "ERROR: Invalid signature for $1" 1>&2
exit 1 exit 1
fi fi
} }
in_userns() { in_userns() {
[ -e /proc/self/uid_map ] || { echo no; return; } [ -e /proc/self/uid_map ] || { echo no; return; }
while read -r line; do while read -r line; do
fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')"
if [ "${fields}" = "0 0 4294967295" ]; then if [ "${fields}" = "0 0 4294967295" ]; then
echo no; echo no;
return; return;
fi fi
if echo "${fields}" | grep -q " 0 1$"; then if echo "${fields}" | grep -q " 0 1$"; then
echo userns-root; echo userns-root;
return; return;
fi fi
done < /proc/self/uid_map done < /proc/self/uid_map
[ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \ [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; }
{ echo userns-root; return; } echo yes
echo yes
} }
relevant_file() { relevant_file() {
FILE_PATH="${LXC_CACHE_PATH}/$1" FILE_PATH="${LXC_CACHE_PATH}/$1"
if [ -e "${FILE_PATH}-${DOWNLOAD_MODE}" ]; then
FILE_PATH="${FILE_PATH}-${DOWNLOAD_MODE}" if [ -e "${FILE_PATH}-${DOWNLOAD_MODE}" ]; then
fi FILE_PATH="${FILE_PATH}-${DOWNLOAD_MODE}"
if [ -e "${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" ]; then fi
FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}"
fi
echo "${FILE_PATH}" if [ -e "${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" ]; then
FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}"
fi
echo "${FILE_PATH}"
} }
usage() { usage() {
cat <<EOF cat <<EOF
LXC container image downloader LXC container image downloader
Special arguments: Special arguments:
[ -h | --help ]: Print this help message and exit. [ -h | --help ]: Print this help message and exit
[ -l | --list ]: List all available images and exit. [ -l | --list ]: List all available images and exit
Required arguments: Required arguments:
[ -d | --dist <distribution> ]: The name of the distribution [ -d | --dist <distribution> ]: The name of the distribution
...@@ -229,84 +230,83 @@ DOWNLOAD_KEYSERVER : The URL of the key server to use, instead of the default. ...@@ -229,84 +230,83 @@ DOWNLOAD_KEYSERVER : The URL of the key server to use, instead of the default.
Can be further overridden by using optional argument --keyserver Can be further overridden by using optional argument --keyserver
EOF EOF
return 0 return 0
} }
if ! options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\ if ! options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\
server:,keyid:,keyserver:,no-validate,flush-cache,force-cache,name:,path:,\ server:,keyid:,keyserver:,no-validate,flush-cache,force-cache,name:,path:,\
rootfs:,mapped-uid:,mapped-gid: -- "$@"); then rootfs:,mapped-uid:,mapped-gid: -- "$@"); then
usage usage
exit 1 exit 1
fi fi
eval set -- "$options" eval set -- "$options"
while :; do while :; do
case "$1" in case "$1" in
-h|--help) usage && exit 1;; -h|--help) usage && exit 1;;
-l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;; -l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;;
-d|--dist) DOWNLOAD_DIST="$2"; shift 2;; -d|--dist) DOWNLOAD_DIST="$2"; shift 2;;
-r|--release) DOWNLOAD_RELEASE="$2"; shift 2;; -r|--release) DOWNLOAD_RELEASE="$2"; shift 2;;
-a|--arch) DOWNLOAD_ARCH="$2"; shift 2;; -a|--arch) DOWNLOAD_ARCH="$2"; shift 2;;
--variant) DOWNLOAD_VARIANT="$2"; shift 2;; --variant) DOWNLOAD_VARIANT="$2"; shift 2;;
--server) DOWNLOAD_SERVER="$2"; shift 2;; --server) DOWNLOAD_SERVER="$2"; shift 2;;
--keyid) DOWNLOAD_KEYID="$2"; shift 2;; --keyid) DOWNLOAD_KEYID="$2"; shift 2;;
--keyserver) DOWNLOAD_KEYSERVER="$2"; shift 2;; --keyserver) DOWNLOAD_KEYSERVER="$2"; shift 2;;
--no-validate) DOWNLOAD_VALIDATE="false"; shift 1;; --no-validate) DOWNLOAD_VALIDATE="false"; shift 1;;
--flush-cache) DOWNLOAD_FLUSH_CACHE="true"; shift 1;; --flush-cache) DOWNLOAD_FLUSH_CACHE="true"; shift 1;;
--force-cache) DOWNLOAD_FORCE_CACHE="true"; shift 1;; --force-cache) DOWNLOAD_FORCE_CACHE="true"; shift 1;;
--name) LXC_NAME="$2"; shift 2;; --name) LXC_NAME="$2"; shift 2;;
--path) LXC_PATH="$2"; shift 2;; --path) LXC_PATH="$2"; shift 2;;
--rootfs) LXC_ROOTFS="$2"; shift 2;; --rootfs) LXC_ROOTFS="$2"; shift 2;;
--mapped-uid) LXC_MAPPED_UID="$2"; shift 2;; --mapped-uid) LXC_MAPPED_UID="$2"; shift 2;;
--mapped-gid) LXC_MAPPED_GID="$2"; shift 2;; --mapped-gid) LXC_MAPPED_GID="$2"; shift 2;;
*) break;; *) break;;
esac esac
done done
# Check for required binaries # Check for required binaries
for bin in tar xz wget; do for bin in tar xz wget; do
if ! command -V "${bin}" >/dev/null 2>&1; then if ! command -V "${bin}" >/dev/null 2>&1; then
echo "ERROR: Missing required tool: ${bin}" 1>&2 echo "ERROR: Missing required tool: ${bin}" 1>&2
exit 1 exit 1
fi fi
done done
# Check for GPG # Check for GPG
if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then
if ! command -V gpg >/dev/null 2>&1; then if ! command -V gpg >/dev/null 2>&1; then
echo "ERROR: Missing recommended tool: gpg" 1>&2 echo "ERROR: Missing recommended tool: gpg" 1>&2
echo "You can workaround this by using --no-validate." 1>&2 echo "You can workaround this by using --no-validate" 1>&2
exit 1 exit 1
fi fi
fi fi
# Check that we have all variables we need # Check that we have all variables we need
if [ -z "${LXC_NAME}" ] || [ -z "${LXC_PATH}" ] || [ -z "${LXC_ROOTFS}" ]; then if [ -z "${LXC_NAME}" ] || [ -z "${LXC_PATH}" ] || [ -z "${LXC_ROOTFS}" ]; then
if [ "${DOWNLOAD_LIST_IMAGES}" != "true" ]; then if [ "${DOWNLOAD_LIST_IMAGES}" != "true" ]; then
echo "ERROR: Not running through LXC." 1>&2 echo "ERROR: Please pass the name, path, and rootfs for the container" 1>&2
exit 1 exit 1
fi fi
fi fi
USERNS="$(in_userns)" USERNS="$(in_userns)"
if [ "${USERNS}" != "no" ]; then if [ "${USERNS}" != "no" ]; then
if [ "${USERNS}" = "yes" ]; then if [ "${USERNS}" = "yes" ]; then
if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then
echo "ERROR: In a user namespace without a map." 1>&2 echo "ERROR: In a user namespace without a map" 1>&2
exit 1 exit 1
fi
DOWNLOAD_MODE="user"
DOWNLOAD_TARGET="user"
else
DOWNLOAD_MODE="user"
DOWNLOAD_TARGET="system"
fi fi
DOWNLOAD_MODE="user"
DOWNLOAD_TARGET="user"
else
DOWNLOAD_MODE="user"
DOWNLOAD_TARGET="system"
fi
fi fi
if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || \ if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || [ -z "${DOWNLOAD_ARCH}" ]; then
[ -z "${DOWNLOAD_ARCH}" ]; then DOWNLOAD_INTERACTIVE="true"
DOWNLOAD_INTERACTIVE="true"
fi fi
# Trap all exit signals # Trap all exit signals
...@@ -314,84 +314,79 @@ trap cleanup EXIT HUP INT TERM ...@@ -314,84 +314,79 @@ trap cleanup EXIT HUP INT TERM
# /tmp may be mounted in tmpfs or noexec # /tmp may be mounted in tmpfs or noexec
if mountpoint -q /tmp; then if mountpoint -q /tmp; then
DOWNLOAD_TEMP="${LXC_PATH}" DOWNLOAD_TEMP="${LXC_PATH}"
fi fi
if ! command -V mktemp >/dev/null 2>&1; then if ! command -V mktemp >/dev/null 2>&1; then
DOWNLOAD_TEMP="${DOWNLOAD_TEMP}/tmp/lxc-download.$$" DOWNLOAD_TEMP="${DOWNLOAD_TEMP}/tmp/lxc-download.$$"
else else
DOWNLOAD_TEMP="${DOWNLOAD_TEMP}$(mktemp -d)" DOWNLOAD_TEMP="${DOWNLOAD_TEMP}$(mktemp -d)"
fi fi
# Simply list images # Simply list images
if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || \ if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || [ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then
[ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then # Initialize GPG
# Initialize GPG gpg_setup
gpg_setup
# Grab the index
# Grab the index DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}"
DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}"
echo "Downloading the image index"
echo "Downloading the image index" if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" "${DOWNLOAD_TEMP}/index" noexit ||
if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \ ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" "${DOWNLOAD_TEMP}/index.asc" noexit; then
"${DOWNLOAD_TEMP}/index" noexit || download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal
! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \ download_sig "${DOWNLOAD_INDEX_PATH}.asc" "${DOWNLOAD_TEMP}/index.asc" normal
"${DOWNLOAD_TEMP}/index.asc" noexit; then fi
download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal
download_sig "${DOWNLOAD_INDEX_PATH}.asc" \ gpg_validate "${DOWNLOAD_TEMP}/index.asc"
"${DOWNLOAD_TEMP}/index.asc" normal
fi # Parse it
echo ""
gpg_validate "${DOWNLOAD_TEMP}/index.asc" echo "---"
printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n"
# Parse it echo "---"
echo "" while IFS=';' read -r f1 f2 f3 f4 f5 f6; do
echo "---" [ -n "${DOWNLOAD_DIST}" ] && [ "$f1" != "${DOWNLOAD_DIST}" ] && continue
printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n" [ -n "${DOWNLOAD_RELEASE}" ] && [ "$f2" != "${DOWNLOAD_RELEASE}" ] && continue
echo "---" [ -n "${DOWNLOAD_ARCH}" ] && [ "$f3" != "${DOWNLOAD_ARCH}" ] && continue
while IFS=';' read -r f1 f2 f3 f4 f5 f6; do [ -n "${DOWNLOAD_VARIANT}" ] && [ "$f4" != "${DOWNLOAD_VARIANT}" ] && continue
[ -z "${f5}" ] || [ -z "${f6}" ] && continue
[ -n "${DOWNLOAD_DIST}" ] && [ "$f1" != "${DOWNLOAD_DIST}" ] && continue
[ -n "${DOWNLOAD_RELEASE}" ] && [ "$f2" != "${DOWNLOAD_RELEASE}" ] && continue printf "%s\t%s\t%s\t%s\t%s\n" "${f1}" "${f2}" "${f3}" "${f4}" "${f5}"
[ -n "${DOWNLOAD_ARCH}" ] && [ "$f3" != "${DOWNLOAD_ARCH}" ] && continue unset f1 f2 f3 f4 f5 f6
[ -n "${DOWNLOAD_VARIANT}" ] && [ "$f4" != "${DOWNLOAD_VARIANT}" ] && continue done < "${DOWNLOAD_TEMP}/index"
[ -z "${f5}" ] || [ -z "${f6}" ] && continue echo "---"
printf "%s\t%s\t%s\t%s\t%s\n" "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ]; then
unset f1 f2 f3 f4 f5 f6 exit 1
done < "${DOWNLOAD_TEMP}/index" fi
echo "---"
if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ]; then
exit 1
fi
# Interactive mode # Interactive mode
echo "" echo ""
if [ -z "${DOWNLOAD_DIST}" ]; then if [ -z "${DOWNLOAD_DIST}" ]; then
echo "Distribution: " echo "Distribution: "
read -r DOWNLOAD_DIST read -r DOWNLOAD_DIST
fi fi
if [ -z "${DOWNLOAD_RELEASE}" ]; then if [ -z "${DOWNLOAD_RELEASE}" ]; then
echo "Release: " echo "Release: "
read -r DOWNLOAD_RELEASE read -r DOWNLOAD_RELEASE
fi fi
if [ -z "${DOWNLOAD_ARCH}" ]; then if [ -z "${DOWNLOAD_ARCH}" ]; then
echo "Architecture: " echo "Architecture: "
read -r DOWNLOAD_ARCH read -r DOWNLOAD_ARCH
fi fi
echo "" echo ""
fi fi
# Setup the cache # Setup the cache
if [ "${DOWNLOAD_TARGET}" = "system" ]; then if [ "${DOWNLOAD_TARGET}" = "system" ]; then
LXC_CACHE_BASE="${LOCALSTATEDIR}/cache/lxc/" LXC_CACHE_BASE="${LOCALSTATEDIR}/cache/lxc/"
else else
LXC_CACHE_BASE="${HOME}/.cache/lxc/" LXC_CACHE_BASE="${HOME}/.cache/lxc/"
fi fi
# Allow the setting of the LXC_CACHE_PATH with the usage of environment variables. # Allow the setting of the LXC_CACHE_PATH with the usage of environment variables.
...@@ -401,110 +396,102 @@ LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_RELEASE}/${DOWNLOAD_ARCH}/" ...@@ -401,110 +396,102 @@ LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_RELEASE}/${DOWNLOAD_ARCH}/"
LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_VARIANT}" LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_VARIANT}"
if [ -d "${LXC_CACHE_PATH}" ]; then if [ -d "${LXC_CACHE_PATH}" ]; then
if [ "${DOWNLOAD_FLUSH_CACHE}" = "true" ]; then if [ "${DOWNLOAD_FLUSH_CACHE}" = "true" ]; then
echo "Flushing the cache..." echo "Flushing the cache..."
rm -Rf "${LXC_CACHE_PATH}" rm -Rf "${LXC_CACHE_PATH}"
elif [ "${DOWNLOAD_FORCE_CACHE}" = "true" ]; then elif [ "${DOWNLOAD_FORCE_CACHE}" = "true" ]; then
DOWNLOAD_USE_CACHE="true" DOWNLOAD_USE_CACHE="true"
else else
DOWNLOAD_USE_CACHE="true" DOWNLOAD_USE_CACHE="true"
if [ -e "$(relevant_file expiry)" ]; then if [ -e "$(relevant_file expiry)" ]; then
if [ "$(cat "$(relevant_file expiry)")" -lt "$(date +%s)" ]; then if [ "$(cat "$(relevant_file expiry)")" -lt "$(date +%s)" ]; then
echo "The cached copy has expired, re-downloading..." echo "The cached copy has expired, re-downloading..."
DOWNLOAD_USE_CACHE="false" DOWNLOAD_USE_CACHE="false"
fi fi
fi
fi fi
fi
fi fi
# Download what's needed # Download what's needed
if [ "${DOWNLOAD_USE_CACHE}" = "false" ]; then if [ "${DOWNLOAD_USE_CACHE}" = "false" ]; then
# Initialize GPG # Initialize GPG
gpg_setup gpg_setup
# Grab the index # Grab the index
DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}" DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}"
echo "Downloading the image index" echo "Downloading the image index"
if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \ if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" "${DOWNLOAD_TEMP}/index" noexit ||
"${DOWNLOAD_TEMP}/index" noexit || ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" "${DOWNLOAD_TEMP}/index.asc" noexit; then
! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \ download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal
"${DOWNLOAD_TEMP}/index.asc" noexit; then download_sig "${DOWNLOAD_INDEX_PATH}.asc" "${DOWNLOAD_TEMP}/index.asc" normal
download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal fi
download_sig "${DOWNLOAD_INDEX_PATH}.asc" \
"${DOWNLOAD_TEMP}/index.asc" normal gpg_validate "${DOWNLOAD_TEMP}/index.asc"
# Parse it
while IFS=';' read -r f1 f2 f3 f4 f5 f6; do
if [ "${f1}" != "${DOWNLOAD_DIST}" ] || \
[ "${f2}" != "${DOWNLOAD_RELEASE}" ] || \
[ "${f3}" != "${DOWNLOAD_ARCH}" ] || \
[ "${f4}" != "${DOWNLOAD_VARIANT}" ] || \
[ -z "${f6}" ]; then
continue
fi fi
gpg_validate "${DOWNLOAD_TEMP}/index.asc" DOWNLOAD_BUILD="${f5}"
DOWNLOAD_URL="${f6}"
# Parse it unset f1 f2 f3 f4 f5 f6
while IFS=';' read -r f1 f2 f3 f4 f5 f6; do break
done < "${DOWNLOAD_TEMP}/index"
if [ "${f1}" != "${DOWNLOAD_DIST}" ] || \ if [ -z "${DOWNLOAD_URL}" ]; then
[ "${f2}" != "${DOWNLOAD_RELEASE}" ] || \ echo "ERROR: Couldn't find a matching image" 1>&1
[ "${f3}" != "${DOWNLOAD_ARCH}" ] || \ exit 1
[ "${f4}" != "${DOWNLOAD_VARIANT}" ] || \ fi
[ -z "${f6}" ]; then
continue
fi
DOWNLOAD_BUILD="${f5}" if [ -d "${LXC_CACHE_PATH}" ] && [ -f "${LXC_CACHE_PATH}/build_id" ] && \
DOWNLOAD_URL="${f6}" [ "$(cat "${LXC_CACHE_PATH}/build_id")" = "${DOWNLOAD_BUILD}" ]; then
echo "The cache is already up to date"
echo "Using image from local cache"
else
# Download the actual files
echo "Downloading the rootfs"
download_file "${DOWNLOAD_URL}/rootfs.tar.xz" "${DOWNLOAD_TEMP}/rootfs.tar.xz" normal
download_sig "${DOWNLOAD_URL}/rootfs.tar.xz.asc" "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" normal
gpg_validate "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc"
echo "Downloading the metadata"
download_file "${DOWNLOAD_URL}/meta.tar.xz" "${DOWNLOAD_TEMP}/meta.tar.xz" normal
download_sig "$DOWNLOAD_URL/meta.tar.xz.asc" "${DOWNLOAD_TEMP}/meta.tar.xz.asc" normal
gpg_validate "${DOWNLOAD_TEMP}/meta.tar.xz.asc"
if [ -d "${LXC_CACHE_PATH}" ]; then
rm -Rf "${LXC_CACHE_PATH}"
fi
mkdir -p "${LXC_CACHE_PATH}"
mv "${DOWNLOAD_TEMP}/rootfs.tar.xz" "${LXC_CACHE_PATH}"
if ! tar Jxf "${DOWNLOAD_TEMP}/meta.tar.xz" -C "${LXC_CACHE_PATH}"; then
echo "ERROR: Invalid rootfs tarball." 2>&1
exit 1
fi
unset f1 f2 f3 f4 f5 f6 echo "${DOWNLOAD_BUILD}" > "${LXC_CACHE_PATH}/build_id"
break
done < "${DOWNLOAD_TEMP}/index"
if [ -z "${DOWNLOAD_URL}" ]; then if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then
echo "ERROR: Couldn't find a matching image." 1>&1 # As the script is run in strict mode (set -eu), all commands
exit 1 # exiting with non 0 would make the script stop.
# || true or || : (more portable) prevents that.
chown -R "${LXC_MAPPED_UID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || :
fi fi
if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then
if [ -d "${LXC_CACHE_PATH}" ] && [ -f "${LXC_CACHE_PATH}/build_id" ] && \ chgrp -R "${LXC_MAPPED_GID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || :
[ "$(cat "${LXC_CACHE_PATH}/build_id")" = "${DOWNLOAD_BUILD}" ]; then
echo "The cache is already up to date."
echo "Using image from local cache"
else
# Download the actual files
echo "Downloading the rootfs"
download_file "${DOWNLOAD_URL}/rootfs.tar.xz" \
"${DOWNLOAD_TEMP}/rootfs.tar.xz" normal
download_sig "${DOWNLOAD_URL}/rootfs.tar.xz.asc" \
"${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" normal
gpg_validate "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc"
echo "Downloading the metadata"
download_file "${DOWNLOAD_URL}/meta.tar.xz" \
"${DOWNLOAD_TEMP}/meta.tar.xz" normal
download_sig "$DOWNLOAD_URL/meta.tar.xz.asc" \
"${DOWNLOAD_TEMP}/meta.tar.xz.asc" normal
gpg_validate "${DOWNLOAD_TEMP}/meta.tar.xz.asc"
if [ -d "${LXC_CACHE_PATH}" ]; then
rm -Rf "${LXC_CACHE_PATH}"
fi
mkdir -p "${LXC_CACHE_PATH}"
mv "${DOWNLOAD_TEMP}/rootfs.tar.xz" "${LXC_CACHE_PATH}"
if ! tar Jxf "${DOWNLOAD_TEMP}/meta.tar.xz" -C "${LXC_CACHE_PATH}"; then
echo "ERROR: Invalid rootfs tarball." 2>&1
exit 1
fi
echo "${DOWNLOAD_BUILD}" > "${LXC_CACHE_PATH}/build_id"
if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then
# As the script is run in strict mode (set -eu), all commands
# exiting with non 0 would make the script stop.
# || true or || : (more portable) prevents that.
chown -R "${LXC_MAPPED_UID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || :
fi
if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then
chgrp -R "${LXC_MAPPED_GID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || :
fi
echo "The image cache is now ready"
fi fi
echo "The image cache is now ready"
fi
else else
echo "Using image from local cache" echo "Using image from local cache"
fi fi
# Unpack the rootfs # Unpack the rootfs
...@@ -513,9 +500,9 @@ echo "Unpacking the rootfs" ...@@ -513,9 +500,9 @@ echo "Unpacking the rootfs"
EXCLUDES="" EXCLUDES=""
excludelist=$(relevant_file excludes) excludelist=$(relevant_file excludes)
if [ -f "${excludelist}" ]; then if [ -f "${excludelist}" ]; then
while read -r line; do while read -r line; do
EXCLUDES="${EXCLUDES} --exclude=${line}" EXCLUDES="${EXCLUDES} --exclude=${line}"
done < "${excludelist}" done < "${excludelist}"
fi fi
# Do not surround ${EXCLUDES} by quotes. This does not work. The solution could # Do not surround ${EXCLUDES} by quotes. This does not work. The solution could
...@@ -523,8 +510,7 @@ fi ...@@ -523,8 +510,7 @@ fi
# is to use a function wrapper, but the latter can't be used here as the args # 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. # are dynamic. We thus need to ignore the warning brought by shellcheck.
# shellcheck disable=SC2086 # shellcheck disable=SC2086
tar --anchored ${EXCLUDES} --numeric-owner -xpJf \ tar --anchored ${EXCLUDES} --numeric-owner -xpJf "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}"
"${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}"
mkdir -p "${LXC_ROOTFS}/dev/pts/" mkdir -p "${LXC_ROOTFS}/dev/pts/"
...@@ -532,57 +518,62 @@ mkdir -p "${LXC_ROOTFS}/dev/pts/" ...@@ -532,57 +518,62 @@ mkdir -p "${LXC_ROOTFS}/dev/pts/"
configfile="$(relevant_file config)" configfile="$(relevant_file config)"
fstab="$(relevant_file fstab)" fstab="$(relevant_file fstab)"
if [ ! -e "${configfile}" ]; then if [ ! -e "${configfile}" ]; then
echo "ERROR: meta tarball is missing the configuration file" 1>&2 echo "ERROR: meta tarball is missing the configuration file" 1>&2
exit 1 exit 1
fi fi
## Extract all the network config entries ## Extract all the network config entries
sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" \ sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" "${LXC_PATH}/config"
"${LXC_PATH}/config"
## Extract any other config entry ## Extract any other config entry
sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config" sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
## Append the defaults ## Append the defaults
echo "" >> "${LXC_PATH}/config" {
echo "# Distribution configuration" >> "${LXC_PATH}/config" echo ""
cat "$configfile" >> "${LXC_PATH}/config" echo "# Distribution configuration"
cat "$configfile"
} >> "${LXC_PATH}/config"
## Add the container-specific config ## Add the container-specific config
echo "" >> "${LXC_PATH}/config" {
echo "# Container specific configuration" >> "${LXC_PATH}/config" echo ""
if [ -e "${LXC_PATH}/config-auto" ]; then echo "# Container specific configuration"
cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config" if [ -e "${LXC_PATH}/config-auto" ]; then
cat "${LXC_PATH}/config-auto"
rm "${LXC_PATH}/config-auto" rm "${LXC_PATH}/config-auto"
fi fi
if [ -e "${fstab}" ]; then if [ -e "${fstab}" ]; then
echo "lxc.mount.fstab = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config" echo "lxc.mount.fstab = ${LXC_PATH}/fstab"
fi fi
echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_PATH}/config" echo "lxc.uts.name = ${LXC_NAME}"
} >> "${LXC_PATH}/config"
## Re-add the previously removed network config ## Re-add the previously removed network config
if [ -e "${LXC_PATH}/config-network" ]; then if [ -e "${LXC_PATH}/config-network" ]; then
echo "" >> "${LXC_PATH}/config" {
echo "# Network configuration" >> "${LXC_PATH}/config" echo ""
cat "${LXC_PATH}/config-network" >> "${LXC_PATH}/config" echo "# Network configuration"
cat "${LXC_PATH}/config-network"
rm "${LXC_PATH}/config-network" rm "${LXC_PATH}/config-network"
} >> "${LXC_PATH}/config"
fi fi
TEMPLATE_FILES="${LXC_PATH}/config" TEMPLATE_FILES="${LXC_PATH}/config"
# Setup the fstab # Setup the fstab
if [ -e "${fstab}" ]; then if [ -e "${fstab}" ]; then
cp "${fstab}" "${LXC_PATH}/fstab" cp "${fstab}" "${LXC_PATH}/fstab"
TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab" TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab"
fi fi
# Look for extra templates # Look for extra templates
if [ -e "$(relevant_file templates)" ]; then if [ -e "$(relevant_file templates)" ]; then
while read -r line; do while read -r line; do
fullpath="${LXC_ROOTFS}/${line}" fullpath="${LXC_ROOTFS}/${line}"
[ ! -e "${fullpath}" ] && continue [ ! -e "${fullpath}" ] && continue
TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}" TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}"
done < "$(relevant_file templates)" done < "$(relevant_file templates)"
fi fi
# Replace variables in all templates # Replace variables in all templates
...@@ -590,31 +581,31 @@ OLD_IFS=${IFS} ...@@ -590,31 +581,31 @@ OLD_IFS=${IFS}
IFS=";" IFS=";"
for file in ${TEMPLATE_FILES}; do for file in ${TEMPLATE_FILES}; do
[ ! -f "${file}" ] && continue [ ! -f "${file}" ] && continue
sed -i "s#LXC_NAME#${LXC_NAME}#g" "${file}"
sed -i "s#LXC_NAME#${LXC_NAME}#g" "${file}" sed -i "s#LXC_PATH#${LXC_PATH}#g" "${file}"
sed -i "s#LXC_PATH#${LXC_PATH}#g" "${file}" sed -i "s#LXC_ROOTFS#${LXC_ROOTFS}#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_TEMPLATE_CONFIG#${LXC_TEMPLATE_CONFIG}#g" "${file}" sed -i "s#LXC_HOOK_DIR#${LXC_HOOK_DIR}#g" "${file}"
sed -i "s#LXC_HOOK_DIR#${LXC_HOOK_DIR}#g" "${file}"
done done
IFS=${OLD_IFS} IFS=${OLD_IFS}
# prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle
if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then
sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf" sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf"
fi fi
if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then
chown "${LXC_MAPPED_UID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : chown "${LXC_MAPPED_UID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || :
fi fi
if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then
chgrp "${LXC_MAPPED_GID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : chgrp "${LXC_MAPPED_GID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || :
fi fi
if [ -e "$(relevant_file create-message)" ]; then if [ -e "$(relevant_file create-message)" ]; then
echo "" echo ""
echo "---" echo "---"
cat "$(relevant_file create-message)" cat "$(relevant_file create-message)"
fi fi
exit 0 exit 0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment