#!/bin/sh # container-tools - Manage systemd-nspawn containers # Copyright (C) 2014-2017 Daniel Baumann # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set -e SCRIPT="${0}" HOOKS="/etc/container-tools/hooks" MACHINES="/var/lib/machines" CACHE="/var/cache/container-tools/images" Parameters () { GETOPT_LONGOPTIONS="bind:,bind-ro:,script:,name:,clean,image:,server:,password:" GETOPT_OPTIONS="b:,s:,n:,p:" PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${SCRIPT} --options ${GETOPT_OPTIONS} --shell sh -- ${@})" if [ "${?}" != "0" ] then echo "'${SCRIPT}': getopt exit" >&2 exit 1 fi eval set -- "${PARAMETERS}" while true do case "${1}" in -b|--bind) # ignore shift 2 ;; --bind-ro) # ignore shift 2 ;; --cnt.auto) # ignore shift 2 ;; --cnt.container-server) # ignore shift 2 ;; -s|--script) # ignore shift 2 ;; -n|--name) NAME="${2}" shift 2 ;; --clean) CLEAN="true" shift 1 ;; --image) IMAGE="${2}" shift 2 ;; --server) SERVER="${2}" shift 2 ;; -p|--password) PASSWORD="${2}" shift 2 ;; --) shift 1 break ;; *) echo "'${SCRIPT}': getopt error" >&2 exit 1 ;; esac done } Usage () { echo "Usage: container create -n|--name NAME -s|--script ${SCRIPT} -- [--clean] [--image IMAGE] [--server SERVER] [-p|--password PASSWORD}" >&2 exit 1 } Parameters "${@}" if [ -z "${NAME}" ] then Usage fi if [ -e "${MACHINES}/${NAME}" ] then echo "'${NAME}': container already exists" >&2 exit 1 fi if [ ! -x /usr/bin/curl ] then echo "'${NAME}': /usr/bin/curl - no such file." >&2 exit 1 fi if [ "$(id -u)" -ne 0 ] then echo "'${NAME}': need root privileges" >&2 exit 1 fi if [ -x /usr/bin/lzip ] then COMPRESSION="lz" elif [ -x /usr/bin/xz ] then COMPRESSION="xz" else COMPRESSION="gz" fi ARCHITECTURE="${ARCHITECTURE:-$(dpkg --print-architecture)}" IMAGE="${IMAGE:-debian-stretch-${ARCHITECTURE}.tar.${COMPRESSION}}" SERVER="${SERVER:-https://files.open-infrastructure.net/system/container/debian}" PASSWORD="${PASSWORD:-$(dd if=/dev/urandom bs=12 count=1 2> /dev/null | base64)}" VERSION="$(container version)" # Pre hooks for FILE in "${HOOKS}/pre-${SCRIPT}".* "${HOOKS}/${NAME}.pre-${SCRIPT}" do if [ -x "${FILE}" ] then "${FILE}" fi done # Run # FIXME: Show available image directories on server # FIXME: Fetch debconf-choices.txt to show debconf select # FIXME: gpg verification against debian-keyring or local keyring # FIXME: default server via configuration file echo "Downloading ${IMAGE}" mkdir -p "${CACHE}" if [ -e "${CACHE}/${IMAGE}" ] then CURL_OPTIONS="--time-cond ${CACHE}/${IMAGE}" fi if curl -V | grep -qs http2 then CURL_OPTIONS="${CURL_OPTIONS} --http2" fi for FILE in "${SERVER}/${IMAGE}" "${SERVER}/${IMAGE}.sha512" do if curl --fail --head --output /dev/null --silent "${FILE}" then curl --fail --location --progress-bar --user-agent container-tools/${VERSION} ${CURL_OPTIONS} \ "${FILE}" -o "${CACHE}/$(basename ${FILE})" fi done if [ -e "${CACHE}/${IMAGE}.sha512" ] && [ -e "${CACHE}/${IMAGE}" ] then echo -n "Verifying ${IMAGE}.sha512" cd "${CACHE}" set +e sha512sum --check "${IMAGE}.sha512" --status SHA512SUM="${?}" case "${SHA512SUM}" in 0) echo " ok." ;; *) echo " failed." exit 1 ;; esac set -e cd "${OLDPWD}" fi echo "Unpacking ${IMAGE}" mkdir -p "${MACHINES}/${NAME}" case "${IMAGE}" in *.gz) TAR_OPTIONS="--gzip" ;; *.lz) TAR_OPTIONS="--lzip" if [ ! -e /usr/bin/lzip ] then echo "'${NAME}': /usr/bin/lzip - no such file." >&2 exit 1 fi ;; *.xz) TAR_OPTIONS="--xz" if [ ! -e /usr/bin/xz ] then echo "'${NAME}': /usr/bin/xz - no such file." >&2 exit 1 fi ;; *) TAR_OPTIONS="" ;; esac if [ -e /usr/bin/pv ] then pv --format '%p' --width 77 "${CACHE}/${IMAGE}" | tar xf - ${TAR_OPTIONS} -C "${MACHINES}/${NAME}" --strip 1 else tar xf "${CACHE}/${IMAGE}" ${TAR_OPTIONS} -C "${MACHINES}/${NAME}" --strip 1 fi # Creating machine-id chroot "${MACHINES}/${NAME}" systemd-machine-id-setup > /dev/null 2>&1 # Setting hostname echo "${NAME}" > "${MACHINES}/${NAME}/etc/hostname" # Copying resolv.conf cp -L /etc/resolv.conf "${MACHINES}/${NAME}/etc/resolv.conf" # Setting root password echo root:${PASSWORD} | chroot "${MACHINES}/${NAME}" chpasswd echo "${NAME}: root password set to '${PASSWORD}'." # Remove cache case "${CLEAN}" in true) rm -f "${CACHE}/${IMAGE}" rm -f "${CACHE}/${IMAGE}.sha512" ;; esac # Post hooks for FILE in "${HOOKS}/post-${SCRIPT}".* "${HOOKS}/${NAME}.post-${SCRIPT}" do if [ -x "${FILE}" ] then "${FILE}" fi done