diff options
Diffstat (limited to 'libexec/container')
-rwxr-xr-x | libexec/container/build | 284 | ||||
-rwxr-xr-x | libexec/container/get (renamed from libexec/container/create) | 10 | ||||
-rwxr-xr-x | libexec/container/key | 26 | ||||
-rwxr-xr-x | libexec/container/list | 11 |
4 files changed, 322 insertions, 9 deletions
diff --git a/libexec/container/build b/libexec/container/build new file mode 100755 index 0000000..b64af48 --- /dev/null +++ b/libexec/container/build @@ -0,0 +1,284 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann <daniel.baumann@open-infrastructure.net> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# 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 <https://www.gnu.org/licenses/>. + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +CONFIG="/etc/${SOFTWARE}/config" +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" +SCRIPTS="/usr/share/${SOFTWARE}/build-scripts" +CONFIG_TEMPLATE="/usr/share/${SOFTWARE}/config/container.conf.in" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:,cnt.container-server:,cnt.overlay:,cnt.overlay-options:,start:,bind:,bind-ro:,capability:,drop-capability:,script:,verbose," + GETOPT_OPTIONS="n:,b:,c:,d:,s:,v," + + PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})" + + if [ "${?}" != "0" ] + then + echo "'${COMMAND}': getopt exit" >&2 + exit 1 + fi + + eval set -- "${PARAMETERS}" + + while true + do + case "${1}" in + -n|--name) + NAME="${2}" + shift 2 + ;; + + --cnt.auto) + CNT_AUTO="${2}" + shift 2 + ;; + + --cnt.container-server) + CNT_CONTAINER_SERVER="${2}" + shift 2 + ;; + + --cnt.overlay) + CNT_OVERLAY="${2}" + shift 2 + ;; + + --cnt.overlay-options) + CNT_OVERLAY_OPTIONS="${2}" + shift 2 + ;; + + --cnt.start) + CNT_START="${2}" + shift 2 + ;; + + -b|--bind) + BIND="${2}" + shift 2 + ;; + + --bind-ro) + BIND_RO="${2}" + shift 2 + ;; + + -c|--capability) + CAPABILITY="${2}" + shift 2 + ;; + + -d|--drop-capability) + DROP_CAPABILITY="${2}" + shift 2 + ;; + + -s|--script) + SCRIPT="${2}" + shift 2 + ;; + + -v|--verbose) + VERBOSE="true" + shift 1 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--cnt.container-server=true|false|FQDN] [--cnt.overlay=DIRECTORY_LOWER:DIRECTORY_UPPER:DIRECTORY_WORK:DIRECTORY_MERGED] [--cnt.overlay-options=OPTION[,OPTION]] [--cnt.start=OPTION[,OPTION]] [-b|--bind DIRECTORY:DIRECTORY[:OPTIONS]] [--bind-ro DIRECTORY:DIRECTORY[:OPTIONS]] [-c|--capability CAPABILITY[,CAPABILITY]] [-d|--drop-capability DROP_CAPABILITY[,DROP_CAPABILITY]] [-s|--script SCRIPT] [-v|--verbose] [-- SCRIPT_OPTIONS]" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +case "${NAME}" in + ALL) + echo "'${NAME}': name 'ALL' is reserved to expand to all available container" >&2 + exit 1 + ;; +esac + +if [ -e "${CONFIG}/${NAME}.conf" ] +then + echo "'${NAME}': container already exists or ${CONFIG}/${NAME}.conf has not been removed" >&2 + exit 1 +fi + +if [ -z "${SCRIPT}" ] +then + if [ -e "${SCRIPTS}/default" ] + then + TARGET="$(basename $(readlink ${SCRIPTS}/default))" + + case "${TARGET}" in + container_build-script) + TARGET="$(basename $(readlink /etc/alternatives/container_build-script))" + ;; + esac + + if [ -e "${SCRIPTS}/${TARGET}" ] + then + SCRIPT="${TARGET}" + else + echo "default -> '${TARGET}': no such script" >&2 + exit 1 + fi + else + SCRIPT="debian" + fi +else + if [ ! -e "${SCRIPTS}/${SCRIPT}" ] + then + echo "'${SCRIPT}': no such script" >&2 + exit 1 + fi +fi + +case "${VERBOSE}" in + true) + +cat << EOF +################################################################################ +Building container: ${NAME} +################################################################################ +EOF + + ;; +esac + +CNT_CONTAINER_SERVER="${CNT_CONTAINER_SERVER:-$(hostname -f 2> /dev/null || hostname)}" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Creating rw bind mounts +if [ -n "${BIND}" ] +then + BINDS="$(echo ${BIND} | sed -e 's|;| |g')" + + for ENTRY in ${BINDS} + do + DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')" + + mkdir -p "${DIRECTORY}" + done +fi + +# Creating ro bind mounts +if [ -n "${BIND_RO}" ] +then + BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" + + for ENTRY in ${BINDS_RO} + do + DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')" + + mkdir -p "${DIRECTORY}" + done +fi + +# Creating overlay mounts +if [ -n "${CNT_OVERLAY}" ] +then + CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')" + + for ENTRY in ${CNT_OVERLAYS} + do + DIRECTORY_LOWER="$(echo ${ENTRY} | awk -F: '{ print $1 }')" + DIRECTORY_UPPER="$(echo ${ENTRY} | awk -F: '{ print $2 }')" + DIRECTORY_WORK="$(echo ${ENTRY} | awk -F: '{ print $3 }')" + DIRECTORY_MERGED="$(echo ${ENTRY} | awk -F: '{ print $4 }')" + + for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}" + do + mkdir -p "${DIRECTORY}" + done + done +fi + +# config +mkdir -p "${CONFIG}" + +sed -e "s|@CNT_AUTO@|${CNT_AUTO}|g" \ + -e "s|@CNT_CONTAINER_SERVER@|${CNT_CONTAINER_SERVER}|g" \ + -e "s|@CNT_NETWORK_BRIDGE@|${CNT_NETWORK_BRIDGE}|g" \ + -e "s|@CNT_OVERLAY@|${CNT_OVERLAY}|g" \ + -e "s|@CNT_OVERLAY_OPTIONS@|${CNT_OVERLAY_OPTIONS}|g" \ + -e "s|@CNT_START@|${CNT_START}|g" \ + -e "s|@NAME@|${NAME}|g" \ + -e "s|@BIND@|${BIND}|g" \ + -e "s|@BIND_RO@|${BIND_RO}|g" \ + -e "s|@BOOT@|yes|g" \ + -e "s|@CAPABILITY@|${CAPABILITY}|g" \ + -e "s|@DIRECTORY@|${MACHINES}/${NAME}|g" \ + -e "s|@DROP_CAPABILITY@|${DROP_CAPABILITY}|g" \ + -e "s|@LINK_JOURNAL@|no|g" \ + -e "s|@MACHINE@|${NAME}|g" \ + -e "s|@NETWORK_VETH_EXTRA@|${NETWORK_VETH_EXTRA}|g" \ + -e "s|@PRIVATE_USERS@|no|g" \ + -e "s|@REGISTER@|yes|g" \ +"${CONFIG_TEMPLATE}" > "${CONFIG}/${NAME}.conf" + +# Run +"${SCRIPTS}/${SCRIPT}" $(echo "${@}" | sed -e 's| -- | |') + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# done +echo "'${NAME}': container built." diff --git a/libexec/container/create b/libexec/container/get index af85007..1005f89 100755 --- a/libexec/container/create +++ b/libexec/container/get @@ -27,7 +27,7 @@ COMMAND="$(basename ${0})" CONFIG="/etc/${SOFTWARE}/config" HOOKS="/etc/${SOFTWARE}/hooks" MACHINES="/var/lib/machines" -SCRIPTS="/usr/share/${SOFTWARE}/scripts" +SCRIPTS="/usr/share/${SOFTWARE}/get-scripts" CONFIG_TEMPLATE="/usr/share/${SOFTWARE}/config/container.conf.in" Parameters () @@ -154,8 +154,8 @@ then TARGET="$(basename $(readlink ${SCRIPTS}/default))" case "${TARGET}" in - container_script) - TARGET="$(basename $(readlink /etc/alternatives/container_script))" + container_get-script) + TARGET="$(basename $(readlink /etc/alternatives/container_get-script))" ;; esac @@ -167,7 +167,7 @@ then exit 1 fi else - SCRIPT="debian" + SCRIPT="curl" fi else if [ ! -e "${SCRIPTS}/${SCRIPT}" ] @@ -182,7 +182,7 @@ case "${VERBOSE}" in cat << EOF ################################################################################ -Creating container: ${NAME} +Building container: ${NAME} ################################################################################ EOF diff --git a/libexec/container/key b/libexec/container/key index 5f76fb2..19b7fa9 100755 --- a/libexec/container/key +++ b/libexec/container/key @@ -76,7 +76,7 @@ Parameters () Usage () { - echo "Usage: ${PROGRAM} ${COMMAND} [-a|--add KEY] [-l|--list] [-r|--remove KEY]" >&2 + echo "Usage: ${PROGRAM} ${COMMAND} [-a|--add KEY_FILE|KEY_ID] [-l|--list] [-r|--remove KEY|KEY_ID]" >&2 exit 1 } @@ -87,6 +87,15 @@ then Usage fi +if [ ! -w "${KEYS}" ] +then + if [ "$(id -u)" -ne 0 ] + then + echo "'${COMMAND}': need root privileges (or write permissions to '${KEYS}')" >&2 + exit 1 + fi +fi + # Pre hooks for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" do @@ -105,7 +114,7 @@ then chmod 0700 "${KEYS}" cat > "${KEYS}/gnupg.conf" << EOF -keyserver hkps://hkps.pool.sks-keyservers.net +keyserver hkps://keys.openpgp.org keyserver-options include-revoked keyserver-options no-honor-keyserver-url @@ -131,7 +140,18 @@ fi case "${ACTION}" in add) - gpg --homedir "${KEYS}" --import "${ADD}" + if [ -e "${ADD}" ] + then + gpg --homedir "${KEYS}" --import "${ADD}" + elif [ -e "/usr/share/compute-tools/keys/${ADD}" ] + then + gpg --homedir "${KEYS}" --import "/usr/share/compute-tools/keys/${ADD}" + elif [ -e "/usr/share/compute-tools/keys/${ADD}.pub" ] + then + gpg --homedir "${KEYS}" --import "/usr/share/compute-tools/keys/${ADD}.pub" + else + gpg --homedir "${KEYS}" --recv "${ADD}" + fi ;; list) diff --git a/libexec/container/list b/libexec/container/list index 3ef6e49..6567afb 100755 --- a/libexec/container/list +++ b/libexec/container/list @@ -368,7 +368,16 @@ do case "${STATE}" in started) - ADDRESS="$(cnt run -n ${CONTAINER} -- hostname -I | sed -e 's|\r$||' | awk '{ print $1 }')" + case "${FORMAT}" in + shell|sh) + ;; + + *) + LEADER="$(machinectl status ${CONTAINER} | awk '/Leader: / { print $2 }')" + ADDRESS="$(nsenter --all --target "${LEADER}" /bin/hostname -I | sed -e 's|\r$||' | awk '{ print $1 }')" + ;; + esac + ADDRESS="${ADDRESS:-none}" ;; |