diff options
Diffstat (limited to 'lib/container')
-rwxr-xr-x | lib/container/auto | 90 | ||||
-rwxr-xr-x | lib/container/create | 16 | ||||
-rwxr-xr-x | lib/container/list | 54 | ||||
-rwxr-xr-x | lib/container/start | 102 | ||||
-rwxr-xr-x | lib/container/stop | 41 |
5 files changed, 268 insertions, 35 deletions
diff --git a/lib/container/auto b/lib/container/auto new file mode 100755 index 0000000..247b667 --- /dev/null +++ b/lib/container/auto @@ -0,0 +1,90 @@ +#!/bin/sh + +# container-tools - Manage systemd-nspawn containers +# Copyright (C) 2014-2016 Daniel Baumann <daniel.baumann@open-infrastructure.net> +# +# 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 <http://www.gnu.org/licenses/>. + +set -e + +COMMAND="$(basename ${0})" + +CONFIG="/etc/container-tools/config" + +Parameters () +{ + LONG_OPTIONS="start,stop" + OPTIONS="s,t" + + PARAMETERS="$(getopt --longoptions ${LONG_OPTIONS} --name=${COMMAND} --options ${OPTIONS} --shell sh -- ${@})" + + if [ "${?}" != "0" ] + then + echo "'${COMMAND}': getopt exit" >&2 + exit 1 + fi + + eval set -- "${PARAMETERS}" + + while true + do + case "${1}" in + -s|--start) + ACTION="start" + shift 1 + ;; + + -t|--stop) + ACTION="stop" + shift 1 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: container ${COMMAND} -s|--start -t|--stop" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${ACTION}" ] +then + Usage +fi + +HOST="$(hostname -f)" + +# Run +for FILE in "${CONFIG}"/*.conf +do + if grep -Eqs "^ *cnt.auto=true" "${FILE}" || grep -Eqs "^ *cnt.auto=${HOST}" "${FILE}" + then + CONTAINER="$(basename ${FILE} .conf)" + + cnt ${ACTION} -n ${CONTAINER} || true + fi +done diff --git a/lib/container/create b/lib/container/create index fab9f5b..0b0aa3a 100755 --- a/lib/container/create +++ b/lib/container/create @@ -25,7 +25,7 @@ MACHINES="/var/lib/machines" Parameters () { - LONG_OPTIONS="name:,cnt.autostart:,bind:,capability:,drop-capability:script:" + LONG_OPTIONS="name:,cnt.auto:,bind:,capability:,drop-capability:script:" OPTIONS="n:,b:,c:,d:,s:" PARAMETERS="$(getopt --longoptions ${LONG_OPTIONS} --name=${COMMAND} --options ${OPTIONS} --shell sh -- ${@})" @@ -46,8 +46,8 @@ Parameters () shift 2 ;; - --cnt.autostart) - CNT_AUTOSTART="${2}" + --cnt.auto) + CNT_AUTO="${2}" shift 2 ;; @@ -86,7 +86,7 @@ Parameters () Usage () { - echo "Usage: container ${COMMAND} -n|--name NAME [--cnt.autostart=true|false|FQDN] [-b|--bind DIRECTORY:DIRECTORY[:OPTIONS]] [-c|--capability CAPABILITY[,CAPABILITY]] [-d|--drop-capability DROP_CAPABILITY[,DROP_CAPABILITY]] [-s|--script SCRIPT] [-- SCRIPT_OPTIONS]" >&2 + echo "Usage: container ${COMMAND} -n|--name NAME [--cnt.auto=true|false|FQDN] [-b|--bind DIRECTORY:DIRECTORY[:OPTIONS]] [-c|--capability CAPABILITY[,CAPABILITY]] [-d|--drop-capability DROP_CAPABILITY[,DROP_CAPABILITY]] [-s|--script SCRIPT] [-- SCRIPT_OPTIONS]" >&2 exit 1 } @@ -110,7 +110,7 @@ then echo "'${SCRIPT}': no such script" >&2 fi -CNT_AUTOSTART="${CNT_AUTOSTART:-$(hostname -f)}" +CNT_AUTO="${CNT_AUTO:-$(hostname -f)}" BINDS="$(echo ${BIND} | sed -e 's|;| |g')" @@ -127,7 +127,8 @@ done # config mkdir -p "${CONFIG}" -sed -e "s|@CNT_AUTOSTART@|${CNT_AUTOSTART}|g" \ +sed -e "s|@CNT_AUTO@|${CNT_AUTO}|g" \ + -e "s|@CNT_NETWORK_BRIDGE@|${CNT_NETWORK_BRIDGE}|g" \ -e "s|@NAME@|${NAME}|g" \ -e "s|@BIND@|${BIND}|g" \ -e "s|@BOOT@|yes|g" \ @@ -135,8 +136,7 @@ sed -e "s|@CNT_AUTOSTART@|${CNT_AUTOSTART}|g" \ -e "s|@DIRECTORY@|${MACHINES}/${NAME}|g" \ -e "s|@DROP_CAPABILITY@|${DROP_CAPABILITY}|g" \ -e "s|@MACHINE@|${NAME}|g" \ - -e "s|@NETWORK_VETH@|yes|g" \ - -e "s|@NETWORK_BRIDGE@|br0|g" \ + -e "s|@NETWORK_VETH_EXTRA@|${NETWORK_VETH_EXTRA}|g" \ -e "s|@LINK_JOURNAL@|no|g" \ -e "s|@REGISTER@|yes|g" \ /usr/share/container-tools/config/container.conf.in > "${CONFIG}/${NAME}.conf" diff --git a/lib/container/list b/lib/container/list index 5ab5755..8b55e09 100755 --- a/lib/container/list +++ b/lib/container/list @@ -94,7 +94,7 @@ case "${FORMAT}" in NORMAL="$(tput sgr0)" cat << EOF -Container IPv4 Address Status +Container IPv4 Address(es) Status -------------------------------------------------------------------------------- EOF @@ -118,9 +118,9 @@ do if [ -e "${MACHINES}/${CONTAINER}/etc/network/interfaces" ] then - ADDRESS="$(awk '/address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/network/interfaces)" + ADDRESSES="$(awk '/address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/network/interfaces)" else - ADDRESS="n/a" + ADDRESSES="n/a" fi case "${STATE}" in @@ -142,7 +142,21 @@ do ;; full) - printf "%-72s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" "${STATUS}" + FIRST_LINE="true" + + for ADDRESS in ${ADDRESSES} + do + case "${FIRST_LINE}" in + true) + FIRST_LINE="false" + printf "%-69s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" " ${STATUS}" + ;; + + *) + printf "%-54s %-29s\n" "" "${ADDRESS}" + ;; + esac + done ;; esac ;; @@ -156,7 +170,21 @@ do ;; full) - printf "%-72s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" "${STATUS}" + FIRST_LINE="true" + + for ADDRESS in ${ADDRESSES} + do + case "${FIRST_LINE}" in + true) + FIRST_LINE="false" + printf "%-69s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" " ${STATUS}" + ;; + + *) + printf "%-54s %-29s\n" "" "${ADDRESS}" + ;; + esac + done ;; esac ;; @@ -175,7 +203,21 @@ do ;; full) - printf "%-72s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" "${STATUS}" + FIRST_LINE="true" + + for ADDRESS in ${ADDRESSES} + do + case "${FIRST_LINE}" in + true) + FIRST_LINE="false" + printf "%-69s %-29s %-7s\n" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" " ${STATUS}" + ;; + + *) + printf "%-54s %-29s\n" "" "${ADDRESS}" + ;; + esac + done ;; esac ;; diff --git a/lib/container/start b/lib/container/start index 8d5429b..d026bf1 100755 --- a/lib/container/start +++ b/lib/container/start @@ -23,9 +23,12 @@ COMMAND="$(basename ${0})" CONFIG="/etc/container-tools/config" MACHINES="/var/lib/machines" +START="false" +SYSTEMCTL="true" + Parameters () { - LONG_OPTIONS="name:" + LONG_OPTIONS="name:,nspawn,start" OPTIONS="n:" PARAMETERS="$(getopt --longoptions ${LONG_OPTIONS} --name=${COMMAND} --options ${OPTIONS} --shell sh -- ${@})" @@ -46,6 +49,19 @@ Parameters () shift 2 ;; + --nspawn) + # internal option + SYSTEMCTL="false" + shift 1 + ;; + + --start) + # internal option + START="true" + SYSTEMCTL="false" + shift 1 + ;; + --) shift 1 break @@ -78,12 +94,16 @@ then exit 1 fi -STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')" +case "${START}" in + false) + STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')" -case "${STATE}" in - running) - echo "'${NAME}': container is already started" >&2 - exit 1 + case "${STATE}" in + running) + echo "'${NAME}': container is already started" >&2 + exit 1 + ;; + esac ;; esac @@ -185,27 +205,58 @@ then MACHINE="--machine=${NAME}" - NETWORK_BRIDGE="$(awk -F= '/^network-bridge=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + NETWORK_VETH_EXTRA_CONF="$(awk -F= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + NETWORK_VETH_EXTRA="" - case "${NETWORK_BRIDGE}" in + case "${NETWORK_VETH_EXTRA_CONF}" in "") - NETWORK_BRIDGE="" ;; *) - NETWORK_BRIDGE="--network-bridge=${NETWORK_BRIDGE}" + for VETH in ${NETWORK_VETH_EXTRA_CONF} + do + NETWORK_VETH_EXTRA="${NETWORK_VETH_EXTRA} --network-veth-extra=${VETH}" + INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')" + +cat > "/etc/network/interfaces.d/${INTERFACE}" << EOF +allow-hotplug ${INTERFACE} +iface ${INTERFACE} inet manual + pre-up ifconfig ${INTERFACE} up + post-down ifconfig ${INTERFACE} down +EOF + + done ;; esac - NETWORK_VETH="$(awk -F= '/^network-veth=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)" + NETWORK_BRIDGES="$(awk -F= '/^cnt.network-bridge=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - case "${NETWORK_VETH}" in - yes) - NETWORK_VETH="--network-veth" + case "${NETWORK_BRIDGES}" in + "") ;; *) - NETWORK_VETH="" + for BRIDGE_DEFINITION in ${NETWORK_BRIDGES} + do + INTERFACE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $1 }')" + BRIDGE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $2 }')" + + if [ -n "${BRIDGE}" ] && [ -n "${INTERFACE}" ] + then + +cat > "/etc/network/interfaces.d/${INTERFACE}" << EOF +allow-hotplug ${INTERFACE} +iface ${INTERFACE} inet manual + pre-up ifconfig ${INTERFACE} up + post-up brctl addif ${BRIDGE} ${INTERFACE} + pre-down brctl delif ${BRIDGE} ${INTERFACE} + post-down ifconfig ${INTERFACE} down +EOF + + else + echo "Warning bridge definition '${BRIDGE_DEFINITION}' not recognized (expected <bridge>:<interface>): Ignoring" + fi + done ;; esac @@ -298,14 +349,25 @@ then fi fi -# Run -case "${SET_PROPERTY}" in +case "${SYSTEMCTL}" in true) - ${SETARCH} systemd-nspawn ${BIND} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_BRIDGE} ${NETWORK_VETH} ${LINK_JOURNAL} ${REGISTER} & \ - systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWITH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWITH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} + systemctl start container@${NAME}.service + # FIXME start console .. after sleep? + configuration option + exit 0 + ;; +esac + +case "${START}" in + true) + case "${SET_PROPERTY}" in + true) + systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWITH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWITH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} + ;; + esac ;; *) - ${SETARCH} systemd-nspawn ${BIND} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_BRIDGE} ${NETWORK_VETH} ${LINK_JOURNAL} ${REGISTER} + # Run + ${SETARCH} systemd-nspawn --keep-unit ${BIND} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_VETH_EXTRA} ${LINK_JOURNAL} ${REGISTER} ;; esac diff --git a/lib/container/stop b/lib/container/stop index cd3de10..67cc403 100755 --- a/lib/container/stop +++ b/lib/container/stop @@ -20,11 +20,14 @@ set -e COMMAND="$(basename ${0})" +CONFIG="/etc/container-tools/config" MACHINES="/var/lib/machines" +CLEAN="false" + Parameters () { - LONG_OPTIONS="name:,force" + LONG_OPTIONS="name:,force,clean" OPTIONS="n:,f" PARAMETERS="$(getopt --longoptions ${LONG_OPTIONS} --name=${COMMAND} --options ${OPTIONS} --shell sh -- ${@})" @@ -49,6 +52,12 @@ Parameters () FORCE="true" ;; + --clean) + # internal option + CLEAN="true" + shift 1 + ;; + --) shift 1 break @@ -83,6 +92,36 @@ fi STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')" +# Removing network configuration +case "${CLEAN}" in + true) + NETWORK_VETH_EXTRA_CONF="$(awk -F= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${NETWORK_VETH_EXTRA_CONF}" in + "") + ;; + + *) + for VETH in ${NETWORK_VETH_EXTRA_CONF} + do + INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')" + FILE="/etc/network/interfaces.d/${INTERFACE}" + + if [ -f "${FILE}" ] + then + rm -f "${FILE}" + fi + done + ;; + esac + + exit 0 + ;; + + *) + ;; +esac + case "${STATE}" in running) ;; |