From 9c47a33c9a0896eda85b22a1c0f16e96a27b6450 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 11 Apr 2021 15:52:48 +0200 Subject: Merging upstream version 20210411. Signed-off-by: Daniel Baumann --- CHANGELOG.txt | 38 +- Makefile | 85 +++-- VERSION.txt | 2 +- bin/container | 14 +- bin/container-shell | 6 +- lib/container/auto | 130 ------- lib/container/console | 115 ------ lib/container/create | 277 -------------- lib/container/enter | 125 ------- lib/container/key | 152 -------- lib/container/limit | 208 ----------- lib/container/list | 439 ---------------------- lib/container/log | 143 ------- lib/container/move | 211 ----------- lib/container/remove | 257 ------------- lib/container/restart | 137 ------- lib/container/run | 127 ------- lib/container/start | 531 -------------------------- lib/container/status | 104 ------ lib/container/stop | 289 --------------- lib/container/top | 118 ------ lib/container/version | 48 --- libexec/container/auto | 131 +++++++ libexec/container/console | 116 ++++++ libexec/container/create | 278 ++++++++++++++ libexec/container/enter | 126 +++++++ libexec/container/key | 153 ++++++++ libexec/container/limit | 209 +++++++++++ libexec/container/list | 440 ++++++++++++++++++++++ libexec/container/log | 164 +++++++++ libexec/container/move | 212 +++++++++++ libexec/container/remove | 258 +++++++++++++ libexec/container/restart | 138 +++++++ libexec/container/run | 128 +++++++ libexec/container/start | 532 +++++++++++++++++++++++++++ libexec/container/status | 105 ++++++ libexec/container/stop | 290 +++++++++++++++ libexec/container/top | 119 ++++++ libexec/container/version | 49 +++ share/bash-completion/container | 27 +- share/doc/examples/bullseye.cfg | 35 ++ share/doc/examples/buster.cfg | 35 -- share/doc/examples/container-images.sh | 2 +- share/doc/examples/engywuck-backports.cfg | 70 ---- share/doc/examples/fuchur-backports.cfg | 70 ++++ share/hooks/post-start.chown-nvidia.sh | 2 +- share/hooks/pre-create.git-pull.sh | 9 +- share/hooks/pre-start.unlink-console.sh | 5 +- share/logrotate/container | 2 +- share/man/Makefile | 2 +- share/man/compute-tools.7.txt | 2 +- share/man/container-auto.1.txt | 2 +- share/man/container-console.1.txt | 2 +- share/man/container-create-curl.1.txt | 8 +- share/man/container-create-debconf.1.txt | 8 +- share/man/container-create-debootstrap.1.txt | 2 +- share/man/container-create.1.txt | 2 +- share/man/container-enter.1.txt | 2 +- share/man/container-key.1.txt | 2 +- share/man/container-limit.1.txt | 2 +- share/man/container-list.1.txt | 2 +- share/man/container-log.1.txt | 2 +- share/man/container-move.1.txt | 2 +- share/man/container-remove.1.txt | 2 +- share/man/container-restart.1.txt | 2 +- share/man/container-run.1.txt | 2 +- share/man/container-shell.1.txt | 2 +- share/man/container-start.1.txt | 2 +- share/man/container-status.1.txt | 2 +- share/man/container-stop.1.txt | 2 +- share/man/container-top.1.txt | 2 +- share/man/container-version.1.txt | 2 +- share/man/container.1.txt | 12 +- share/scripts/curl | 14 +- share/scripts/curl.d/0001-debconf | 2 +- share/scripts/debconf | 60 +-- share/scripts/debconf.d/0001-preseed-file | 7 +- share/scripts/debconf.d/0002-preseed-debconf | 2 +- share/scripts/debconf.d/0003-debconf | 16 +- share/scripts/debootstrap | 4 +- 80 files changed, 3741 insertions(+), 3695 deletions(-) delete mode 100755 lib/container/auto delete mode 100755 lib/container/console delete mode 100755 lib/container/create delete mode 100755 lib/container/enter delete mode 100755 lib/container/key delete mode 100755 lib/container/limit delete mode 100755 lib/container/list delete mode 100755 lib/container/log delete mode 100755 lib/container/move delete mode 100755 lib/container/remove delete mode 100755 lib/container/restart delete mode 100755 lib/container/run delete mode 100755 lib/container/start delete mode 100755 lib/container/status delete mode 100755 lib/container/stop delete mode 100755 lib/container/top delete mode 100755 lib/container/version create mode 100755 libexec/container/auto create mode 100755 libexec/container/console create mode 100755 libexec/container/create create mode 100755 libexec/container/enter create mode 100755 libexec/container/key create mode 100755 libexec/container/limit create mode 100755 libexec/container/list create mode 100755 libexec/container/log create mode 100755 libexec/container/move create mode 100755 libexec/container/remove create mode 100755 libexec/container/restart create mode 100755 libexec/container/run create mode 100755 libexec/container/start create mode 100755 libexec/container/status create mode 100755 libexec/container/stop create mode 100755 libexec/container/top create mode 100755 libexec/container/version create mode 100644 share/doc/examples/bullseye.cfg delete mode 100644 share/doc/examples/buster.cfg delete mode 100644 share/doc/examples/engywuck-backports.cfg create mode 100644 share/doc/examples/fuchur-backports.cfg diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 171ca3c..e76a584 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,9 +1,45 @@ +2021-04-11 Daniel Baumann + + * Releasing version 20210411. + + * Backward incompatible changes: + - all path have been shortened in preparation for additional + backends alongside systemd-nspawn: The only user visible is the + configuration directory: + + new: /etc/open-infrastructure/container + old: /etc/compute-tools + + [ Daniel Baumann ] + * Moving command files from /usr/lib to /usr/libexec. + * Moving config files from /etc/open-infrastructure to /etc/compute-tools. + * Using /usr/libexec/container instead of /usr/libexec/open-infrastructure/container. + * Using /usr/share/compute-tools instead of /usr/share/open-infrastructure/container. + * Using /var/log/compute-tools instead of /var/log/open-infrastructure. + * Using /var/cache/container instead of /var/cache/open-infrastructure/container. + * Making hook to git-pull debconf files work recursively. + * Harmonizing initial variables in curl and debconf container create scripts for consistency. + * Updating copyright in bash-completion, it got re-written from scratch years ago. + * Adding hook support to container log command for consistency. + * Cosmetically improving output of test target. + * Adding shellcheck in test target (but not failing yet on it). + * Removing superfluous whitespace in changelog. + * Removing dpkg hack for progress-linux in debconf container create script, not needed for buster and newer anymore. + * Removing base-files hack for progress-linux in debconf container create script, not needed for buster and newer anymore. + * Removing readline hack for progress-linux in debconf container create script, not needed for buster and newer anymore. + * Removing sysvinit hack for progress-linux in debconf container create script, not needed for buster and newer anymore. + * Removing stretch support from debconf container create script. + * Using https for security.debian.org in container create related items. + * Using https instead of http in all comments. + * Adding support for Debian bookworm in container debconf create script. + * Synchronising versioning number for progress-linux releases in debconf container create script. + * Updating preseed examples for debconf container scripts to bullseye. + 2021-01-01 Daniel Baumann * Releasing version 20210101. [ Daniel Baumann ] - * Adding container run command to execute programs within containers. * Cleaning up and harmonizing verbose output for container remove, restart, start, and stop commands. * Expanding host-setup documentation about ipv4/ipv6 dual-stack bridge configuration. diff --git a/Makefile b/Makefile index 2b1fb37..538c2ac 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ # 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 . +# along with this program. If not, see . SHELL := sh -e @@ -21,23 +21,20 @@ PROJECT = open-infrastructure SOFTWARE = compute-tools PROGRAM = container -SCRIPTS = bin/* lib/*/* +SCRIPTS = bin/* libexec/*/* all: build test: - @echo -n "Checking for syntax errors" - + @echo -n "Checking for syntax errors with sh... " @for SCRIPT in $(SCRIPTS); \ do \ sh -n $${SCRIPT}; \ echo -n "."; \ done - @echo " done." - @echo -n "Checking for bashisms" - + @echo -n "Checking for bashisms... " @if [ -x /usr/bin/checkbashisms ]; \ then \ for SCRIPT in $(SCRIPTS); \ @@ -48,7 +45,20 @@ test: else \ echo "Note: devscripts not installed, skipping checkbashisms."; \ fi + @echo " done." + # FIXME: fail hard on shellcheck once all issues are fixed + @echo -n "Checking with shellcheck... " + @if [ -x /usr/bin/checkbashisms ]; \ + then \ + for SCRIPT in $(SCRIPTS); \ + do \ + shellcheck $${SCRIPT} || true; \ + echo -n "."; \ + done; \ + else \ + echo "Note: shellcheck not installed, skipping shellcheck."; \ + fi @echo " done." build: share/man/*.txt @@ -57,19 +67,19 @@ build: share/man/*.txt sed -n '/^NAME/,$$p' share/man/$(SOFTWARE).7.txt > README.txt install: build - mkdir -p $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/config - mkdir -p $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/debconf - mkdir -p $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/hooks + mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/config + mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/debconf + mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/hooks mkdir -p $(DESTDIR)/usr/bin cp -r bin/* $(DESTDIR)/usr/bin - mkdir -p $(DESTDIR)/usr/lib/$(PROJECT) - cp -r lib/* $(DESTDIR)/usr/lib/$(PROJECT) + mkdir -p $(DESTDIR)/usr/libexec + cp -r libexec/* $(DESTDIR)/usr/libexec - mkdir -p $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM) - cp -r VERSION.txt $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM) - cp -r share/config share/hooks share/scripts $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM) + mkdir -p $(DESTDIR)/usr/share/$(SOFTWARE) + cp -r VERSION.txt $(DESTDIR)/usr/share/$(SOFTWARE) + cp -r share/config share/hooks share/scripts $(DESTDIR)/usr/share/$(SOFTWARE) mkdir -p $(DESTDIR)/usr/share/bash-completion/completions cp -r share/bash-completion/* $(DESTDIR)/usr/share/bash-completion/completions @@ -102,31 +112,31 @@ install: build ln -sf container-shell.1 $(DESTDIR)/usr/share/man/man1/cntsh.1 ln -sf container $(DESTDIR)/usr/share/bash-completion/completions/cnt - ln -sf debconf $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM)/scripts/debian - ln -sf debconf.d $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM)/scripts/debian.d + ln -sf debconf $(DESTDIR)/usr/share/$(SOFTWARE)/scripts/debian + ln -sf debconf.d $(DESTDIR)/usr/share/$(SOFTWARE)/scripts/debian.d ln -sf container-create-debconf.1 $(DESTDIR)/usr/share/man/man1/container-create-debian.1 - ln -sf debconf $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM)/scripts/progress-linux - ln -sf debconf.d $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM)/scripts/progress-linux.d + ln -sf debconf $(DESTDIR)/usr/share/$(SOFTWARE)/scripts/progress-linux + ln -sf debconf.d $(DESTDIR)/usr/share/$(SOFTWARE)/scripts/progress-linux.d ln -sf container-create-debconf.1 $(DESTDIR)/usr/share/man/man1/container-create-progress-linux.1 - ln -sf debootstrap $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM)/scripts/mmdebstrap + ln -sf debootstrap $(DESTDIR)/usr/share/$(SOFTWARE)/scripts/mmdebstrap ln -sf container-create-debootstrap.1 $(DESTDIR)/usr/share/man/man1/container-create-mmdebstrap.1 - ln -sf create $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/cr - ln -sf list $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/ls - ln -sf move $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/mv - ln -sf remove $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/rm - ln -sf restart $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/rs - ln -sf start $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/s - ln -sf status $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/st - ln -sf stop $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM)/t + ln -sf create $(DESTDIR)/usr/libexec/$(PROGRAM)/cr + ln -sf list $(DESTDIR)/usr/libexec/$(PROGRAM)/ls + ln -sf move $(DESTDIR)/usr/libexec/$(PROGRAM)/mv + ln -sf remove $(DESTDIR)/usr/libexec/$(PROGRAM)/rm + ln -sf restart $(DESTDIR)/usr/libexec/$(PROGRAM)/rs + ln -sf start $(DESTDIR)/usr/libexec/$(PROGRAM)/s + ln -sf status $(DESTDIR)/usr/libexec/$(PROGRAM)/st + ln -sf stop $(DESTDIR)/usr/libexec/$(PROGRAM)/t mkdir -p $(DESTDIR)/lib/systemd/system cp -r share/systemd/* $(DESTDIR)/lib/systemd/system - mkdir -p $(DESTDIR)/var/log/$(PROJECT) + mkdir -p $(DESTDIR)/var/log/$(SOFTWARE) uninstall: - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/var/log/$(PROJECT) || true + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/var/log/$(SOFTWARE) || true for FILE in share/systemd/*; \ do \ @@ -174,11 +184,11 @@ uninstall: rm -rf $(DESTDIR)/usr/share/doc/$(SOFTWARE) rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/share/doc || true - rm -rf $(DESTDIR)/usr/share/$(PROJECT)/$(PROGRAM) + rm -rf $(DESTDIR)/usr/share/$(SOFTWARE) rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/share || true - rm -rf $(DESTDIR)/usr/lib/$(PROJECT)/$(PROGRAM) - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/lib || true + rm -rf $(DESTDIR)/usr/libexec/$(PROGRAM) + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/libexec || true for FILE in bin/*; \ do \ @@ -186,11 +196,10 @@ uninstall: done rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/bin || true - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/config || true - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/debconf || true - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM)/hooks || true - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(PROJECT)/$(PROGRAM) || true - rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(PROJECT) || true + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/config || true + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/debconf || true + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/hooks || true + rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE) || true rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc || true rmdir --ignore-fail-on-non-empty --parents $(DESTDIR) || true diff --git a/VERSION.txt b/VERSION.txt index 71bc3f4..4320a50 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -20210101 +20210411 diff --git a/bin/container b/bin/container index 4570dc3..c3748d9 100755 --- a/bin/container +++ b/bin/container @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e @@ -23,7 +23,7 @@ PROJECT="open-infrastructure" SOFTWARE="compute-tools" PROGRAM="container" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" +HOOKS="/etc/${SOFTWARE}/hooks" # Parameter PARAMETER="${1}" @@ -44,7 +44,7 @@ OPTIONS="${@}" for COMMAND in $(echo ${COMMANDS} | sed -e 's|,| |g') do - if [ ! -e "/usr/lib/${PROJECT}/${PROGRAM}/${COMMAND}" ] + if [ ! -e "/usr/libexec/${PROGRAM}/${COMMAND}" ] then echo "'${COMMAND}': no such ${PROGRAM} command" >&2 exit 1 @@ -71,12 +71,12 @@ do HOST="$(hostname -f 2> /dev/null || hostname)" # logfile - echo "${DATE} ${HOST} ${USER} ${PROGRAM} ${COMMAND} ${OPTIONS}" >> "/var/log/${PROJECT}/${PROGRAM}.log" + echo "${DATE} ${HOST} ${USER} ${PROGRAM} ${COMMAND} ${OPTIONS}" >> "/var/log/${SOFTWARE}/${PROGRAM}.log" # irc - if [ -e /usr/bin/irk ] && [ -e "/etc/${PROJECT}/${PROGRAM}.conf" ] + if [ -e /usr/bin/irk ] && [ -e "/etc/${SOFTWARE}.conf" ] then - . "/etc/${PROJECT}/${PROGRAM}.conf" + . "/etc/${SOFTWARE}.conf" if [ -n "${IRK_TARGETS}" ] then @@ -91,7 +91,7 @@ do fi # Run - "/usr/lib/${PROJECT}/${PROGRAM}/${COMMAND}" "${OPTIONS}" + "/usr/libexec/${PROGRAM}/${COMMAND}" "${OPTIONS}" # Post hooks for FILE in "${HOOKS}/post-${PROGRAM}".* "${HOOKS}/${NAME}.post-${PROGRAM}" diff --git a/bin/container-shell b/bin/container-shell index 016724f..98ece06 100755 --- a/bin/container-shell +++ b/bin/container-shell @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e @@ -64,7 +64,7 @@ Shell () echo "The following ${PROGRAM} commands are available:" echo - cd "/usr/lib/${PROJECT}/${PROGRAM}" + cd "/usr/libexec/${PROGRAM}" find . -type f -printf " %f\n" | sort cd "${OLDPWD}" @@ -97,7 +97,7 @@ Shell () ;; esac - if [ ! -e "/usr/lib/${PROJECT}/${PROGRAM}/${COMMAND}" ] + if [ ! -e "/usr/libexec/${PROGRAM}/${COMMAND}" ] then echo "'${COMMAND}': no such ${PROGRAM} command" >&2 return diff --git a/lib/container/auto b/lib/container/auto deleted file mode 100755 index 6c1d47b..0000000 --- a/lib/container/auto +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" - -Parameters () -{ - GETOPT_LONGOPTIONS="force,start,stop," - GETOPT_OPTIONS="f,s,t," - - 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 - -f|--force) - FORCE="true" - shift 1 - ;; - - -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: ${PROGRAM} ${COMMAND} -f|--force -s|--start -t|--stop" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${ACTION}" ] -then - Usage -fi - -HOST="$(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 - -# Run -OPTIONS="" - -case "${FORCE}" in - true) - OPTIONS="${OPTIONS} -f" - ;; -esac - -for FILE in "${CONFIG}"/*.conf -do - if grep -Eqs "^ *cnt.auto=force-true" "${FILE}" - then - OPTIONS="${OPTIONS} -f" - fi - - if grep -Eqs "^ *cnt.auto=(force-true|true)" "${FILE}" && grep -Eqs "^ *cnt.container-server=${HOST}" "${FILE}" - then - CONTAINER="$(basename ${FILE} .conf)" - - cnt ${ACTION} -n ${CONTAINER} ${OPTIONS} || true - fi -done - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/console b/lib/container/console deleted file mode 100755 index 2dc6546..0000000 --- a/lib/container/console +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:," - GETOPT_OPTIONS="n:," - - 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 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - ;; - - *) - echo "'${NAME}': container is not started" >&2 - exit 1 - ;; -esac - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -machinectl login ${NAME} - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/create b/lib/container/create deleted file mode 100755 index bdf9fb4..0000000 --- a/lib/container/create +++ /dev/null @@ -1,277 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" -SCRIPTS="/usr/share/${PROJECT}/${PROGRAM}/scripts" -CONFIG_TEMPLATE="/usr/share/${PROJECT}/${PROGRAM}/config/container.conf.in" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:,cnt.container-server:,cnt.overlay:,cnt.overlay-options:,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 - ;; - - -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]] [-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_script) - TARGET="$(basename $(readlink /etc/alternatives/container_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 -################################################################################ -Creating 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|@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 created." diff --git a/lib/container/enter b/lib/container/enter deleted file mode 100755 index fed1193..0000000 --- a/lib/container/enter +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:," - GETOPT_OPTIONS="n:," - - 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 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - ;; - - *) - echo "'${NAME}': container is not running" >&2 - exit 1 - ;; -esac - -LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')" - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}" - -# Run -nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 /bin/bash -l" -q /dev/null - -case "${SSH_CLIENT}" in - 127.0.0.1*) - unset SSH_CLIENT - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/key b/lib/container/key deleted file mode 100755 index 4cbdaa0..0000000 --- a/lib/container/key +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -KEYS="/etc/${PROJECT}/${PROGRAM}/keys" - -Parameters () -{ - GETOPT_LONGOPTIONS="add:,list,remove:," - GETOPT_OPTIONS="a:,l,r:," - - 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 - -a|--add) - ADD="${2}" - ACTION="add" - shift 2 - ;; - - -l|--list) - ACTION="list" - shift 1 - ;; - - -r|--remove) - REMOVE="${2}" - ACTION="remove" - shift 2 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} [-a|--add KEY] [-l|--list] [-r|--remove KEY]" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${ACTION}" ] -then - Usage -fi - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -if [ ! -e "${KEYS}" ] -then - mkdir -p "${KEYS}" - - chown root:root "${KEYS}" - chmod 0700 "${KEYS}" - -cat > "${KEYS}/gnupg.conf" << EOF -keyserver hkps://hkps.pool.sks-keyservers.net -keyserver-options include-revoked -keyserver-options no-honor-keyserver-url - -cert-digest-algo SHA512 -default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB ZIP Uncompressed -personal-cipher-preferences AES256 AES192 AES -personal-compress-preferences ZLIB ZIP Uncompressed -personal-digest-preferences SHA512 SHA384 SHA256 SHA224 - -no-comments -no-emit-version -no-greeting -keyid-format 0xlong -list-options show-keyring -list-options show-uid-validity -verify-options show-uid-validity -with-fingerprint - -charset utf-8 -EOF - -fi - -case "${ACTION}" in - add) - gpg --homedir "${KEYS}" --import "${ADD}" - ;; - - list) - gpg --homedir "${KEYS}" --list-keys - ;; - - remove) - gpg --homedir "${KEYS}" --delete-keys "${REMOVE}" - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/limit b/lib/container/limit deleted file mode 100755 index 99ef03a..0000000 --- a/lib/container/limit +++ /dev/null @@ -1,208 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:,blockio-device-weight:,blockio-read-bandwidth:,blockio-weight:,blockio-write-bandwidth:,cpu-quota:,cpu-shares:,memory-limit:,tasks-max:," - GETOPT_OPTIONS="n:b:c:m:t:," - - 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 - ;; - - -c|--cpu-quota) - CPU_QUOTA="${2}" - shift 2 - ;; - - --cpu-shares) - CPU_SHARES="${2}" - shift 2 - ;; - - -m|--memory-limit) - MEMORY_LIMIT="${2}" - shift 2 - ;; - - -t|--tasks-max) - TASKS_MAX="${2}" - shift 2 - ;; - - --blockio-device-weight) - BLOCK_IO_DEVICE_WEIGHT="${2}" - shift 2 - ;; - - --blockio-read-bandwidth) - BLOCK_IO_READ_BANDWIDTH="${2}" - shift 2 - ;; - - -b|--blockio-weight) - BLOCK_IO_WEIGHT="${2}" - shift 2 - ;; - - --blockio-write-bandwidth) - BLOCK_IO_WRITE_BANDWIDTH="${2}" - shift 2 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--blockio-device-weight \"DEVICE WEIGHT\"] [--blockio-read-bandwidth \"DEVICE BYTES\"] [-b|--blockio-weight WEIGHT] [--blockio-write-bandwidth \"DEVICE BYTES\"] [-c|--cpu-quota QUOTA] [--cpu-shares SHARES] [-m|--memory-limit BYTES] [-t|--tasks-max NUMBER]" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - ;; - - *) - echo "'${NAME}': container is not running" >&2 - exit 1 - ;; -esac - -if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ] -then - BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}" - SET_PROPERTY="true" -fi - -if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ] -then - BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}" - SET_PROPERTY="true" -fi - -if [ -n "${BLOCK_IO_WEIGHT}" ] -then - BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}" - SET_PROPERTY="true" -fi - -if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ] -then - BLOCK_IO_WRITE_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}" - SET_PROPERTY="true" -fi - -if [ -n "${CPU_QUOTA}" ] -then - CPU_QUOTA="CPUQuota=${CPU_QUOTA}" - SET_PROPERTY="true" -fi - -if [ -n "${CPU_SHARES}" ] -then - CPU_SHARES="CPUShares=${CPU_SHARES}" - SET_PROPERTY="true" -fi - -if [ -n "${MEMORY_LIMIT}" ] -then - MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}" - SET_PROPERTY="true" -fi - -if [ -n "${TASKS_MAX}" ] -then - TASKS_MAX="TasksMax=${TASKS_MAX}" - SET_PROPERTY="true" -fi - -if [ "${SET_PROPERTY}" != "true" ] -then - Usage -fi - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/list b/lib/container/list deleted file mode 100755 index ba794ab..0000000 --- a/lib/container/list +++ /dev/null @@ -1,439 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -VERSION="$(${PROGRAM} version)" - -Parameters () -{ - GETOPT_LONGOPTIONS="all,csv-separator:,format:,host:,nwdiag-color:,nwdiag-label:,other,started,stopped," - GETOPT_OPTIONS="a,f:,h:,o,s,t," - - 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 - -a|--all) - LIST="${LIST} all" - shift 1 - ;; - - --csv-separator) - CSV_SEPARATOR="${2}" - shift 2 - ;; - - -f|--format) - FORMAT="${2}" - shift 2 - ;; - - -h|--host) - HOST="${2}" - shift 2 - ;; - - --nwdiag-color) - NWDIAG_COLOR="${2}" - shift 2 - ;; - - --nwdiag-label) - NWDIAG_LABEL="${2}" - shift 2 - ;; - - -o|--other) - LIST="${LIST} other" - shift 1 - ;; - - -s|--started) - LIST="${LIST} started" - shift 1 - ;; - - -t|--stopped) - LIST="${LIST} stopped" - shift 1 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} [-a|--all] [--csv-separator SEPARATOR] [--format FORMAT] [-h|--host HOSTNAME] [--nwdiag-color COLOR] [--nwdiag-label LABEL] [-o|--other] [-s|--started] [-t|--stopped]" >&2 - exit 1 -} - -Parameters "${@}" - -LIST="${LIST:-started stopped}" -FORMAT="${FORMAT:-cli}" -HOST="${HOST:-$(hostname -f 2> /dev/null || hostname)}" - -CSV_SEPARATOR="${CSV_SEPARATOR:-,}" - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -List () -{ - case "${FORMAT}" in - cli) - printf "%1s %-74s %-19s\n" "${STATUS}" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" - ;; - - csv) - echo "${HOST}${CSV_SEPARATOR}${CONTAINER}${CSV_SEPARATOR}${STATE}${CSV_SEPARATOR}${ADDRESS}" - ;; - - json) - -cat << EOF - { - "name": "${CONTAINER}", - "status": "${STATE}", - "address": "${ADDRESS}", - }, -EOF - - ;; - - nwdiag) - Nwdiag_width "${CONTAINER}" - - case "${STATE}" in - started) - COLOR="#73d216" - ;; - - stopped) - COLOR="#cc0000" - ;; - - other) - COLOR="#d3d7cf" - ;; - esac - - echo " ${CONTAINER} [address = \"${ADDRESS}\", color = \"${COLOR}\", shape = \"flowchart.terminator\", width = \"${WIDTH}\"];" - ;; - - shell|sh) - echo "${CONTAINER}" - ;; - - yaml) - -cat << EOF - - name: ${CONTAINER} - address: ${ADDRESS} -EOF - - ;; - - xml) - -cat << EOF - - ${CONTAINER} -
${ADDRESS}
-
-EOF - - ;; - esac -} - -Nwdiag_width () -{ - NAME="${1}" - - CHARACTERS="$(echo "${NAME}" | wc -c)" - - if [ "${CHARACTERS}" -gt 13 ] - then - # default width is 128 fitting 13 characters - WIDTH="$(( ${CHARACTERS} - 13 ))" - WIDTH="$(( ${WIDTH} * 5 ))" - WIDTH="$(( ${WIDTH} + 128 ))" - else - WIDTH="128" - fi -} - -case "${FORMAT}" in - cli) - RED="$(tput setaf 1)$(tput bold)" - GREEN="$(tput setaf 2)$(tput bold)" - YELLOW="$(tput setaf 3)$(tput bold)" - BLUE="$(tput setaf 4)$(tput bold)" - WHITE="$(tput setaf 7)$(tput bold)" - NORMAL="$(tput sgr0)" - -cat << EOF -${WHITE} ${NORMAL} Container IP Address --------------------------------------------------------------------------------- -EOF - - ;; - - csv) - -cat << EOF -# compute-tools ${VERSION} -Host${CSV_SEPARATOR}Container${CSV_SEPARATOR}Status${CSV_SEPARATOR}IPv4-Address -EOF - - ;; - - json) - -cat << EOF -{ - "compute-tools": { - "version": "${VERSION}", - }, - "host": { - "name": "${HOST}", - }, - "container": [ -EOF - - ;; - - nwdiag) - NETWORK="$(echo ${HOST} | sed -e 's|\.|_|g')" - -cat << EOF -# compute-tools ${VERSION} -nwdiag { - external_connector = none; - network ${NETWORK} { -EOF - - if [ -n "${NWDIAG_LABEL}" ] - then - echo " label = \"${NWDIAG_LABEL}\"" - else - echo " label = \"\"" - fi - - NUMBER="$(${0} --format=short | wc -l)" - - if [ -n "${NWDIAG_COLOR}" ] - then - COLOR="${NWDIAG_COLOR}" - else - COLOR="#3465a4" - fi - - Nwdiag_width "${HOST}" - -cat << EOF - # host - ${HOST} [color = "${COLOR}", shape = "box", numbered = "${NUMBER}", width = "${WIDTH}"]; - # container -EOF - - ;; - - yaml) - -cat << EOF ---- -compute_tools: - version: ${VERSION} - -host: - name: ${HOST} - -container: -EOF - - ;; - - xml) - -cat << EOF - - ${VERSION} - - - ${HOST} - - -EOF - - ;; -esac - -if ls "${MACHINES}"/* > /dev/null 2>&1 -then - CONTAINERS="$(cd "${MACHINES}" 2>/dev/null && find -maxdepth 1 \( -type d -or -type l \) -and -not -name 'lost+found' -printf '%P\n' | sort)" -fi - -for CONTAINER in ${CONTAINERS} -do - STATE="$(machinectl show ${CONTAINER} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - - if [ -e "${CONFIG}/${CONTAINER}.conf" ] - then - CONTAINER_SERVER="$(awk -Fcnt.container-server= '/^cnt.container-server=/ { print $2 }' ${CONFIG}/${CONTAINER}.conf)" - CONTAINER_SERVER="${CONTAINER_SERVER:-false}" - - case "${CONTAINER_SERVER}" in - ${HOST}|true) - ;; - - *) - STATE="other" - ;; - esac - else - STATE="other" - fi - - case "${STATE}" in - running) - STATE="started" - STATUS="${GREEN}●${NORMAL}" - ;; - - other) - STATUS="${WHITE}○${NORMAL}" - ;; - - *) - STATE="stopped" - STATUS="${RED}●${NORMAL}" - ;; - esac - - ADDRESS="" - - if ls "${MACHINES}/${CONTAINER}/etc/systemd/network"/*.network > /dev/null 2>&1 - then - ADDRESS="$(awk -FAddress= '/^Address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/systemd/network/*.network | head -n1)" - elif [ -e "${MACHINES}/${CONTAINER}/etc/network/interfaces" ] - then - ADDRESS="$(awk '/address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/network/interfaces | head -n1)" - fi - - ADDRESS="${ADDRESS:-n/a}" - - if echo ${LIST} | grep -qs all - then - List - fi - - for ITEM in other started stopped - do - if echo ${LIST} | grep -qs ${ITEM} - then - case "${STATE}" in - ${ITEM}) - List - ;; - esac - fi - done -done - -case "${FORMAT}" in - cli) - -cat << EOF --------------------------------------------------------------------------------- -EOF - - ;; - - json) - -cat << EOF - ], -} -EOF - - ;; - - nwdiag) - -cat << EOF - } -} -EOF - - ;; - - xml) - -cat << EOF - -EOF - - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/log b/lib/container/log deleted file mode 100755 index a18c421..0000000 --- a/lib/container/log +++ /dev/null @@ -1,143 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -LOG="/var/log/${PROJECT}/${PROGRAM}.log" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:,date:," - GETOPT_OPTIONS="n:,d:," - - 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 - -d|--date) - DATE="${2}" - shift 2 - ;; - - -n|--name) - NAME="${2}" - shift 2 - ;; - - -u|--user) - USER="${2}" - shift 2 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} [-n|--name NAME] [-d|--date DATE|today|today-N|yesterday] [-u|--user USER]" >&2 - exit 1 -} - -Parameters "${@}" - -case "${DATE}" in - today-*) - DAYS="$(echo ${DATE} | awk -F- '{ print $2 }')" - - START="$(date -d "${DAYS} day ago" '+%Y-%m-%d')" - END="$(date +%Y-%m-%d)" - - DATE="(${START}" - - while true - do - DATE="${DATE}|${START}" - - if [ "${START}" = "${END}" ] - then - break - fi - - START="$(date +%Y-%m-%d --date "${START} +1 day")" - done - - DATE="${DATE})" - ;; - - today) - DATE="$(date +%Y-%m-%d)" - ;; - - yesterday) - DATE="$(date -d '1 day ago' '+%Y-%m-%d')" - ;; -esac - -if ls "${LOG}"-*.gz > /dev/null 2>&1 -then - LOGS="$(ls ${LOG}-*.gz) ${LOG}" -else - LOGS="${LOG}" -fi - -for LOG in ${LOGS} -do - case "${LOG}" in - *.gz) - GREP="zgrep" - ;; - - *) - GREP="grep" - ;; - esac - - case "${NAME}" in - "") - ${GREP} -E "^${DATE}" "${LOG}" || true - ;; - - *) - ${GREP} -E "^${DATE}" "${LOG}" | grep " ${NAME}" || true - ;; - esac -done diff --git a/lib/container/move b/lib/container/move deleted file mode 100755 index e20d8a8..0000000 --- a/lib/container/move +++ /dev/null @@ -1,211 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="force,new:,old:," - GETOPT_OPTIONS="f,n:,o:," - - 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 - -f|--force) - FORCE="true" - shift 1 - ;; - - -n|--new) - NEW="${2}" - shift 2 - ;; - - -o|--old) - OLD="${2}" - shift 2 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} [-f|--force] -n|--new NAME -o|--old NAME" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${OLD}" ] || [ -z "${NEW}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${OLD}" ] -then - echo "'${OLD}': no such container" >&2 - exit 1 -fi - -if [ -e "${MACHINES}/${NEW}" ] -then - echo "'${NEW}': container already exists" >&2 - exit 1 -fi - -STATE="$(machinectl show ${OLD} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - echo "'${OLD}': container is started" >&2 - exit 1 - ;; -esac - -case "${FORCE}" in - true) - ;; - - *) - if ${PROGRAM} list --other | grep -qs "^${OLD}$" - then - echo -n "'${OLD}': rename container to '${NEW}' [y|N]? " - read FORCE - - FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')" - - case "${FORCE}" in - y|yes) - ;; - - *) - exit 1 - ;; - esac - fi - ;; -esac - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${OLD}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -mv "${CONFIG}/${OLD}.conf" "${CONFIG}/${NEW}.conf" -mv "${MACHINES}/${OLD}" "${MACHINES}/${NEW}" - -# rw bind mounts -BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NEW}.conf)" - -if [ -n "${BIND}" ] -then - BINDS="$(echo ${BIND} | sed -e 's|;| |g')" - - for BIND in ${BINDS} - do - SOURCE_OLD="$(echo ${BIND} | awk -F: '{ print $1 }')" - SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")" - - if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ] - then - mv "${SOURCE_OLD}" "${SOURCE_NEW}" - fi - - TARGET_OLD="$(echo ${BIND} | awk -F: '{ print $2 }')" - TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")" - - if [ "${TARGET_OLD}" != "${TARGET_NEW}" ] - then - mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}" - fi - done -fi - -# ro bind mounts -BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NEW}.conf)" - -if [ -n "${BIND_RO}" ] -then - BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" - - for BIND_RO in ${BINDS_RO} - do - SOURCE_OLD="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" - SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")" - - if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ] - then - mv "${SOURCE_OLD}" "${SOURCE_NEW}" - fi - - TARGET_OLD="$(echo ${BIND_RO} | awk -F: '{ print $2 }')" - TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")" - - if [ "${TARGET_OLD}" != "${TARGET_NEW}" ] - then - mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}" - fi - done -fi - -# config -sed -i -e "s|${OLD}|${NEW}|g" "${CONFIG}/${NEW}.conf" - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NEW}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/remove b/lib/container/remove deleted file mode 100755 index 75ebd60..0000000 --- a/lib/container/remove +++ /dev/null @@ -1,257 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - OPTIONS_ALL="" - - GETOPT_LONGOPTIONS="name:,allow-stop,force,verbose," - GETOPT_OPTIONS="n:,f,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 - ;; - - --allow-stop) - ALLOW_STOP="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --allow-stop" - ;; - - -f|--force) - FORCE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --force" - ;; - - -v|--verbose) - VERBOSE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --verbose" - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--allow-stop] [-f|--force] [-v|--verbose]" >&2 - exit 1 -} - -Rmdir () -{ - DIRECTORIES="${@}" - - for DIRECTORY in ${DIRECTORIES} - do - PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)" - - if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ] - then - # the directory is at least two levels down from / - cd "${PARENT_DIRECTORY}" - - CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)" - rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true - - cd "${OLDPWD}" - fi - done -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -case "${NAME}" in - ALL) - NAMES="$(${PROGRAM} list --format shell --stopped)" - - for NAME in ${NAMES} - do - ${PROGRAM} remove --name ${NAME} ${OPTIONS_ALL} || true - done - - exit 0 - ;; -esac - -if [ ! -e "${MACHINES}/${NAME}" ] && [ ! -e "${CONFIG}/${NAME}.conf" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - case "${ALLOW_STOP}" in - true) - echo "'${NAME}': container is started, stopping it now" >&2 - ${PROGRAM} stop -n ${NAME} - ;; - - *) - echo "'${NAME}': container is started" >&2 - exit 1 - ;; - esac - ;; -esac - -case "${FORCE}" in - true) - ;; - - *) - echo -n "'${NAME}': remove container '${NAME}' [y|N]? " - read FORCE - - FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')" - - case "${FORCE}" in - y|yes) - ;; - - *) - exit 1 - ;; - esac - ;; -esac - -case "${VERBOSE}" in - true) - RM_OPTIONS="--verbose" - ;; - - *) - RM_OPTIONS="" - ;; -esac - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# data -if [ -e "${CONFIG}/${NAME}.conf" ] -then - # Removing rw bind mounts - BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND}" ] - then - BINDS="$(echo ${BIND} | sed -e 's|;| |g')" - - for BIND in ${BINDS} - do - DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" - - Rmdir "${DIRECTORY}" - done - fi - - # Removing ro bind mounts - BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND_RO}" ] - then - BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" - - for BIND_RO in ${BINDS_RO} - do - DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" - - Rmdir "${DIRECTORY}" - done - fi -fi - -# Run -case "${VERBOSE}" in - true) - echo -n "Removing container ${NAME}..." - ;; -esac - -rm --preserve-root --one-file-system -rf ${RM_OPTIONS} "${MACHINES}/${NAME}" -rm -f ${RM_OPTIONS} "${CONFIG}/${NAME}.conf" - -case "${VERBOSE}" in - true) - echo " done." - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/restart b/lib/container/restart deleted file mode 100755 index 3c84f4d..0000000 --- a/lib/container/restart +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - OPTIONS_ALL="" - - GETOPT_LONGOPTIONS="name:,verbose," - GETOPT_OPTIONS="n:,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 - ;; - - -v|--verbose) - VERBOSE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --verbose" - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-v|--verbose]" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -case "${NAME}" in - ALL) - NAMES="$(${PROGRAM} list --format shell --started)" - - for NAME in ${NAMES} - do - ${PROGRAM} restart --name ${NAME} ${OPTIONS_ALL} || true - done - - exit 0 - ;; -esac - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -case "${VERBOSE}" in - true) - echo -n "Restarting container ${NAME}..." - ;; -esac - -machinectl reboot ${NAME} - -case "${VERBOSE}" in - true) - echo " done." - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/run b/lib/container/run deleted file mode 100755 index f6323c0..0000000 --- a/lib/container/run +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2019 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:," - GETOPT_OPTIONS="n:," - - 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 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME -- COMMAND" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')" - -case "${STATE}" in - running) - ;; - - *) - echo "'${NAME}': container is not running" >&2 - exit 1 - ;; -esac - -LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')" - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}" - -RUN="$(echo ${@} | awk -F-- '{ print $2}')" - -# Run -nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 /bin/bash -l -c \"${RUN}\"" -q /dev/null - -case "${SSH_CLIENT}" in - 127.0.0.1*) - unset SSH_CLIENT - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/start b/lib/container/start deleted file mode 100755 index 30aee53..0000000 --- a/lib/container/start +++ /dev/null @@ -1,531 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -START="false" -SYSTEMCTL="true" - -Parameters () -{ - OPTIONS_ALL="" - - GETOPT_LONGOPTIONS="name:,force,nspawn,start,verbose," - GETOPT_OPTIONS="n:,f,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 - ;; - - -f|--force) - FORCE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --force" - ;; - - --nspawn) - # internal option - SYSTEMCTL="false" - shift 1 - ;; - - --start) - # internal option - START="true" - SYSTEMCTL="false" - shift 1 - ;; - - -v|--verbose) - VERBOSE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --verbose" - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force]" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -# hooks -export NAME - -case "${NAME}" in - ALL) - NAMES="$(${PROGRAM} list --format shell --stopped)" - - for NAME in ${NAMES} - do - ${PROGRAM} start --name ${NAME} ${OPTIONS_ALL} || true - done - - exit 0 - ;; -esac - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -case "${START}" in - false) - STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - - case "${STATE}" in - running) - echo "'${NAME}': container is already started" >&2 - exit 1 - ;; - esac - ;; -esac - -if [ -e "${MACHINES}/.#${NAME}.lck" ] -then - case "${FORCE}" in - true) - rm -f "${MACHINES}/.#${NAME}.lck" - - VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')" - - for VETH in ${VETHS} - do - ip link delete ${VETH} > /dev/null 2>&1 || true - done - ;; - - *) - echo "'${NAME}': container is locked" >&2 - exit 1 - ;; - esac -fi - -HOST_ARCHITECTURE="$(dpkg --print-architecture)" -MACHINE_ARCHITECTURE="$(chroot ${MACHINES}/${NAME} dpkg --print-architecture)" - -case "${HOST_ARCHITECTURE}" in - amd64) - case "${MACHINE_ARCHITECTURE}" in - i386) - SETARCH="setarch i686" - ;; - - *) - SETARCH="" - ;; - esac - ;; -esac - -case "${START}" in - start) - ;; - - *) - # Pre hooks - for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" - do - if [ -x "${FILE}" ] - then - "${FILE}" - fi - done - ;; -esac - -# config -if [ -e "${CONFIG}/${NAME}.conf" ] -then - CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - CNT_OVERLAY_OPTIONS="$(awk -Fcnt.overlay-options= '/^cnt.overlay-options=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${CNT_OVERLAY}" ] - then - CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')" - - COUNT="0" - for CNT_OVERLAY in ${CNT_OVERLAYS} - do - DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')" - DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')" - DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')" - DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')" - - COUNT="$((${COUNT} + 1))" - CNT_OVERLAY_OPTION="$(echo ${CNT_OVERLAY_OPTIONS} | awk -F ';' "{ print \$${COUNT} }")" - - for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}" - do - mkdir -p "${DIRECTORY}" - done - - if ! findmnt -n -o SOURCE "${DIRECTORY_MERGED}" | grep -qs '^cnt.overlay-' - then - if [ -n "${CNT_OVERLAY_OPTION}" ] - then - CNT_OVERLAY_OPTION="-o ${CNT_OVERLAY_OPTION}" - fi - - mount cnt.overlay-${NAME} -t overlay ${CNT_OVERLAY_OPTION} -olowerdir="${DIRECTORY_LOWER}",upperdir="${DIRECTORY_UPPER}",workdir="${DIRECTORY_WORK}",default_permissions "${DIRECTORY_MERGED}" - fi - done - fi - - BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND}" ] - then - BINDS="$(echo ${BIND} | sed -e 's|;| |g')" - - for BIND in ${BINDS} - do - DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" - - if [ ! -e "${DIRECTORY}" ] - then - echo "'${DIRECTORY}': creating non-existing directory for bind mounting" - mkdir -p "${DIRECTORY}" - fi - done - - BIND="" - - for DIRECTORIES in ${BINDS} - do - BIND="${BIND} --bind ${DIRECTORIES}" - done - fi - - BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND_RO}" ] - then - BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" - - for BIND_RO in ${BINDS_RO} - do - DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" - - if [ ! -e "${DIRECTORY}" ] - then - echo "'${DIRECTORY}': creating non-existing directory for bind-ro mounting" - mkdir -p "${DIRECTORY}" - fi - done - - BIND_RO="" - - for DIRECTORIES in ${BINDS_RO} - do - BIND_RO="${BIND_RO} --bind-ro ${DIRECTORIES}" - done - fi - - BOOT="$(awk -Fboot= '/^boot=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)" - - case "${BOOT}" in - yes) - BOOT="--boot" - ;; - - *) - BOOT="" - ;; - esac - - CAPABILITY="$(awk -Fcapability= '/^capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - case "${CAPABILITY}" in - "") - CAPABILITY="" - ;; - - *) - CAPABILITY="--capability=${CAPABILITY}" - ;; - esac - - DIRECTORY="$(awk -Fdirectory= '/^directory=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo ${MACHINES}/${NAMES})" - DIRECTORY="--directory ${DIRECTORY}" - - DROP_CAPABILITY="$(awk -Fdrop-capability= '/^drop-capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - case "${DROP_CAPABILITY}" in - "") - DROP_CAPABILITY="" - ;; - - *) - DROP_CAPABILITY="--drop-capability=${DROP_CAPABILITY}" - ;; - esac - - LINK_JOURNAL="$(awk -Flink-journal= '/^link-journal=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)" - - case "${LINK_JOURNAL}" in - yes) - LINK_JOURNAL="--link-journal=yes" - ;; - - *) - LINK_JOURNAL="--link-journal=no" - ;; - esac - - MACHINE="--machine=${NAME}" - - NETWORK_VETH_EXTRA="" - - VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - case "${VETHS}" in - "") - ;; - - *) - for VETH in ${VETHS} - do - NETWORK_VETH_EXTRA="${NETWORK_VETH_EXTRA} --network-veth-extra=${VETH}" - INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')" - - if [ "$(echo ${INTERFACE} | wc -c)" -gt 15 ] - then - echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working." - fi - done - ;; - esac - - NETWORK_BRIDGES="$(awk -Fcnt.network-bridge= '/^cnt.network-bridge=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - case "${NETWORK_BRIDGES}" in - "") - ;; - - *) - for BRIDGE_DEFINITION in ${NETWORK_BRIDGES} - do - INTERFACE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $1 }')" - BRIDGE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $2 }')" - - if [ "$(echo ${INTERFACE} | wc -c)" -gt 15 ] - then - echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working." - fi - - if [ -n "${BRIDGE}" ] && [ -n "${INTERFACE}" ] - then - -cat > "/etc/network/interfaces.d/${INTERFACE}" << EOF -allow-hotplug ${INTERFACE} -iface ${INTERFACE} inet manual - pre-up ip link set ${INTERFACE} up - post-up ip link set ${INTERFACE} master ${BRIDGE} - pre-down ip link set ${INTERFACE} nomaster - post-down ip link set ${INTERFACE} down -EOF - - else - echo "Warning bridge definition '${BRIDGE_DEFINITION}' not recognized (expected :): Ignoring" - fi - done - ;; - esac - - PRIVATE_USERS="$(awk -Fprivate-users= '/^private-users=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)" - - case "${PRIVATE_USERS}" in - yes) - PRIVATE_USERS="--private-users=yes" - ;; - - *) - PRIVATE_USERS="--private-users=no" - ;; - esac - - REGISTER="$(awk -Fregister= '/^register=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)" - - case "${REGISTER}" in - yes) - REGISTER="--register=yes" - ;; - - *) - REGISTER="--register=no" - ;; - esac - - BLOCK_IO_DEVICE_WEIGHT="$(awk -FBlockIODeviceWeight= '/^BlockIODeviceWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ] - then - BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}" - SET_PROPERTY="true" - fi - - BLOCK_IO_READ_BANDWIDTH="$(awk -FBlockIOReadBandwidth= '/^BlockIOReadBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ] - then - BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}" - SET_PROPERTY="true" - fi - - BLOCK_IO_WEIGHT="$(awk -FBlockIOWeight= '/^BlockIOWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BLOCK_IO_WEIGHT}" ] - then - BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}" - SET_PROPERTY="true" - fi - - BLOCK_IO_WRITE_BANDWIDTH="$(awk -FBlockIOWriteBandwidth=/= '/^BlockIOWriteBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ] - then - BLOCK_IO_WRITE_BANDWIDTH="BlockIOWriteBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}" - SET_PROPERTY="true" - fi - - CPU_QUOTA="$(awk -FCPUQuota= '/^CPUQuota=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${CPU_QUOTA}" ] - then - CPU_QUOTA="CPUQuota=${CPU_QUOTA}" - SET_PROPERTY="true" - fi - - CPU_SHARES="$(awk -FCPUShares= '/^CPUShares=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${CPU_SHARES}" ] - then - CPU_SHARES="CPUShares=${CPU_SHARES}" - SET_PROPERTY="true" - fi - - MEMORY_LIMIT="$(awk -FMemoryLimit= '/^MemoryLimit=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${MEMORY_LIMIT}" ] - then - MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}" - SET_PROPERTY="true" - fi - - TASKS_MAX="$(awk -FTasksMax= '/^TasksMax=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${TASKS_MAX}" ] - then - TASKS_MAX="TasksMax=${TASKS_MAX}" - SET_PROPERTY="true" - fi -fi - -case "${SYSTEMCTL}" in - true) - systemctl start ${PROGRAM}@${NAME}.service - - # Post hooks - for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" - do - if [ -x "${FILE}" ] - then - "${FILE}" - fi - done - - exit 0 - ;; -esac - -case "${START}" in - true) - case "${SET_PROPERTY}" in - true) - systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} - ;; - esac - ;; - - *) - # Run - - case "${VERBOSE}" in - true) - echo -n "Starting container ${NAME}..." - ;; - esac - - ${SETARCH} systemd-nspawn --keep-unit ${BIND} ${BIND_RO} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_VETH_EXTRA} ${LINK_JOURNAL} ${REGISTER} - - case "${VERBOSE}" in - true) - echo " done." - ;; - esac - ;; -esac diff --git a/lib/container/status b/lib/container/status deleted file mode 100755 index a4b49e1..0000000 --- a/lib/container/status +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2016 Simon Spöehel -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -Parameters () -{ - GETOPT_LONGOPTIONS="name:," - GETOPT_OPTIONS="n:," - - 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 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 - exit 1 -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -systemctl status ${PROGRAM}@${NAME}.service --full - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/stop b/lib/container/stop deleted file mode 100755 index 6b8caee..0000000 --- a/lib/container/stop +++ /dev/null @@ -1,289 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -MACHINES="/var/lib/machines" - -CLEAN="false" - -Parameters () -{ - OPTIONS_ALL="" - - GETOPT_LONGOPTIONS="name:,force,clean,verbose," - GETOPT_OPTIONS="n:,f,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 - ;; - - -f|--force) - FORCE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --force" - ;; - - --clean) - # internal option - CLEAN="true" - shift 1 - - OPTONS_ALL="${OPTIONS_ALL} --clean" - ;; - - -v|--verbose) - VERBOSE="true" - shift 1 - - OPTIONS_ALL="${OPTIONS_ALL} --verbose" - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force] [-v|--verbose]" >&2 - exit 1 -} - -Rmdir () -{ - DIRECTORIES="${@}" - - for DIRECTORY in ${DIRECTORIES} - do - PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)" - - if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ] - then - # the directory is at least two levels down from / - cd "${PARENT_DIRECTORY}" - - CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)" - rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true - - cd "${OLDPWD}" - fi - done -} - -Parameters "${@}" - -if [ -z "${NAME}" ] -then - Usage -fi - -case "${NAME}" in - ALL) - NAMES="$(${PROGRAM} list --format shell --started)" - - for NAME in ${NAMES} - do - ${PROGRAM} stop --name ${NAME} ${OPTIONS_ALL} || true - done - - exit 0 - ;; -esac - -if [ ! -e "${MACHINES}/${NAME}" ] -then - echo "'${NAME}': no such container" >&2 - exit 1 -fi - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" - -case "${CLEAN}" in - true) - # Removing overlay mounts - CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${CNT_OVERLAY}" ] - then - CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')" - - for CNT_OVERLAY in ${CNT_OVERLAYS} - do - DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')" - DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')" - DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')" - DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')" - - umount -f "${DIRECTORY_MERGED}" - - Rmdir "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}" - done - fi - - # Removing rw bind mounts - BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND}" ] - then - BINDS="$(echo ${BIND} | sed -e 's|;| |g')" - - for BIND in ${BINDS} - do - DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" - - Rmdir "${DIRECTORY}" - done - fi - - # Removing ro bind mounts - BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - if [ -n "${BIND_RO}" ] - then - BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" - - for BIND_RO in ${BINDS_RO} - do - DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" - - Rmdir "${DIRECTORY}" - done - fi - - # Removing network configuration - VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" - - case "${VETHS}" in - "") - ;; - - *) - for VETH in ${VETHS} - 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) - ;; - - *) - echo "'${NAME}': container is already stopped" >&2 - exit 1 - ;; -esac - -case "${FORCE}" in - true) - MODE="terminate" - ;; - - *) - MODE="poweroff" - ;; -esac - -# Run -case "${VERBOSE}" in - true) - echo -n "Stopping container ${NAME}..." - ;; -esac - -machinectl ${MODE} ${NAME} - -case "${FORCE}" in - true) - VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')" - - for VETH in ${VETHS} - do - ip link delete ${VETH} > /dev/null 2>&1 || true - done - ;; -esac - -case "${VERBOSE}" in - true) - echo " done." - ;; -esac - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/top b/lib/container/top deleted file mode 100755 index d9baa1c..0000000 --- a/lib/container/top +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -Parameters () -{ - GETOPT_LONGOPTIONS="delay:," - GETOPT_OPTIONS="d:," - - 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 - -d|--delay) - DELAY="${2}" - shift 2 - ;; - - --) - shift 1 - break - ;; - - *) - echo "'${COMMAND}': getopt error" >&2 - exit 1 - ;; - esac - done -} - -Usage () -{ - echo "Usage: ${PROGRAM} ${COMMAND} [-d|--delay DELAY]" >&2 - exit 1 -} - -Parameters "${@}" - -DELAY="${DELAY:-1}" -HOST="$(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 - -# Run -Top () -{ - HOME="$(tput cup 0 0)" - ED="$(tput ed)" - EL="$(tput el)" - - printf '%s%s' "${HOME}" "${ED}" - - while true - do - ROWS="$(tput lines)" - COLS="$(tput cols)" - CMD="${@}" - - ${SHELL:=sh} -c "${CMD}" | head -n ${ROWS} | while IFS= read LINE - do - printf '%-*.*s%s\n' ${COLS} ${COLS} "${LINE}" "${EL}" - done - - printf '%s%s' "${ED}" "${HOME}" - sleep ${DELAY} - done -} - -trap 'clear' EXIT HUP INT QUIT TERM - -Top "${PROGRAM} list && printf '%-59s %-19s\n' \" Host: ${HOST}\" \"\$(date +%Y-%m-%d\ %H:%M:%S)\"" - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/lib/container/version b/lib/container/version deleted file mode 100755 index c2b7716..0000000 --- a/lib/container/version +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2014-2021 Daniel Baumann -# -# 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 . - -set -e - -PROJECT="open-infrastructure" -PROGRAM="container" -COMMAND="$(basename ${0})" - -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -SHARE="/usr/share/${PROJECT}/${PROGRAM}" - -# Pre hooks -for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done - -# Run -cat "${SHARE}/VERSION.txt" - -# Post hooks -for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" -do - if [ -x "${FILE}" ] - then - "${FILE}" - fi -done diff --git a/libexec/container/auto b/libexec/container/auto new file mode 100755 index 0000000..0c9d136 --- /dev/null +++ b/libexec/container/auto @@ -0,0 +1,131 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +CONFIG="/etc/${SOFTWARE}/config" +HOOKS="/etc/${SOFTWARE}/hooks" + +Parameters () +{ + GETOPT_LONGOPTIONS="force,start,stop," + GETOPT_OPTIONS="f,s,t," + + 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 + -f|--force) + FORCE="true" + shift 1 + ;; + + -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: ${PROGRAM} ${COMMAND} -f|--force -s|--start -t|--stop" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${ACTION}" ] +then + Usage +fi + +HOST="$(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 + +# Run +OPTIONS="" + +case "${FORCE}" in + true) + OPTIONS="${OPTIONS} -f" + ;; +esac + +for FILE in "${CONFIG}"/*.conf +do + if grep -Eqs "^ *cnt.auto=force-true" "${FILE}" + then + OPTIONS="${OPTIONS} -f" + fi + + if grep -Eqs "^ *cnt.auto=(force-true|true)" "${FILE}" && grep -Eqs "^ *cnt.container-server=${HOST}" "${FILE}" + then + CONTAINER="$(basename ${FILE} .conf)" + + cnt ${ACTION} -n ${CONTAINER} ${OPTIONS} || true + fi +done + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/console b/libexec/container/console new file mode 100755 index 0000000..ce53712 --- /dev/null +++ b/libexec/container/console @@ -0,0 +1,116 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:," + GETOPT_OPTIONS="n:," + + 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 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + ;; + + *) + echo "'${NAME}': container is not started" >&2 + exit 1 + ;; +esac + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +machinectl login ${NAME} + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/create b/libexec/container/create new file mode 100755 index 0000000..418bc35 --- /dev/null +++ b/libexec/container/create @@ -0,0 +1,278 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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}/scripts" +CONFIG_TEMPLATE="/usr/share/${SOFTWARE}/config/container.conf.in" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:,cnt.container-server:,cnt.overlay:,cnt.overlay-options:,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 + ;; + + -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]] [-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_script) + TARGET="$(basename $(readlink /etc/alternatives/container_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 +################################################################################ +Creating 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|@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 created." diff --git a/libexec/container/enter b/libexec/container/enter new file mode 100755 index 0000000..2664fdc --- /dev/null +++ b/libexec/container/enter @@ -0,0 +1,126 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:," + GETOPT_OPTIONS="n:," + + 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 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + ;; + + *) + echo "'${NAME}': container is not running" >&2 + exit 1 + ;; +esac + +LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}" + +# Run +nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 /bin/bash -l" -q /dev/null + +case "${SSH_CLIENT}" in + 127.0.0.1*) + unset SSH_CLIENT + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/key b/libexec/container/key new file mode 100755 index 0000000..5f76fb2 --- /dev/null +++ b/libexec/container/key @@ -0,0 +1,153 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +KEYS="/etc/${SOFTWARE}/keys" + +Parameters () +{ + GETOPT_LONGOPTIONS="add:,list,remove:," + GETOPT_OPTIONS="a:,l,r:," + + 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 + -a|--add) + ADD="${2}" + ACTION="add" + shift 2 + ;; + + -l|--list) + ACTION="list" + shift 1 + ;; + + -r|--remove) + REMOVE="${2}" + ACTION="remove" + shift 2 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} [-a|--add KEY] [-l|--list] [-r|--remove KEY]" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${ACTION}" ] +then + Usage +fi + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +if [ ! -e "${KEYS}" ] +then + mkdir -p "${KEYS}" + + chown root:root "${KEYS}" + chmod 0700 "${KEYS}" + +cat > "${KEYS}/gnupg.conf" << EOF +keyserver hkps://hkps.pool.sks-keyservers.net +keyserver-options include-revoked +keyserver-options no-honor-keyserver-url + +cert-digest-algo SHA512 +default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB ZIP Uncompressed +personal-cipher-preferences AES256 AES192 AES +personal-compress-preferences ZLIB ZIP Uncompressed +personal-digest-preferences SHA512 SHA384 SHA256 SHA224 + +no-comments +no-emit-version +no-greeting +keyid-format 0xlong +list-options show-keyring +list-options show-uid-validity +verify-options show-uid-validity +with-fingerprint + +charset utf-8 +EOF + +fi + +case "${ACTION}" in + add) + gpg --homedir "${KEYS}" --import "${ADD}" + ;; + + list) + gpg --homedir "${KEYS}" --list-keys + ;; + + remove) + gpg --homedir "${KEYS}" --delete-keys "${REMOVE}" + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/limit b/libexec/container/limit new file mode 100755 index 0000000..6323a42 --- /dev/null +++ b/libexec/container/limit @@ -0,0 +1,209 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:,blockio-device-weight:,blockio-read-bandwidth:,blockio-weight:,blockio-write-bandwidth:,cpu-quota:,cpu-shares:,memory-limit:,tasks-max:," + GETOPT_OPTIONS="n:b:c:m:t:," + + 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 + ;; + + -c|--cpu-quota) + CPU_QUOTA="${2}" + shift 2 + ;; + + --cpu-shares) + CPU_SHARES="${2}" + shift 2 + ;; + + -m|--memory-limit) + MEMORY_LIMIT="${2}" + shift 2 + ;; + + -t|--tasks-max) + TASKS_MAX="${2}" + shift 2 + ;; + + --blockio-device-weight) + BLOCK_IO_DEVICE_WEIGHT="${2}" + shift 2 + ;; + + --blockio-read-bandwidth) + BLOCK_IO_READ_BANDWIDTH="${2}" + shift 2 + ;; + + -b|--blockio-weight) + BLOCK_IO_WEIGHT="${2}" + shift 2 + ;; + + --blockio-write-bandwidth) + BLOCK_IO_WRITE_BANDWIDTH="${2}" + shift 2 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--blockio-device-weight \"DEVICE WEIGHT\"] [--blockio-read-bandwidth \"DEVICE BYTES\"] [-b|--blockio-weight WEIGHT] [--blockio-write-bandwidth \"DEVICE BYTES\"] [-c|--cpu-quota QUOTA] [--cpu-shares SHARES] [-m|--memory-limit BYTES] [-t|--tasks-max NUMBER]" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + ;; + + *) + echo "'${NAME}': container is not running" >&2 + exit 1 + ;; +esac + +if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ] +then + BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}" + SET_PROPERTY="true" +fi + +if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ] +then + BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}" + SET_PROPERTY="true" +fi + +if [ -n "${BLOCK_IO_WEIGHT}" ] +then + BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}" + SET_PROPERTY="true" +fi + +if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ] +then + BLOCK_IO_WRITE_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}" + SET_PROPERTY="true" +fi + +if [ -n "${CPU_QUOTA}" ] +then + CPU_QUOTA="CPUQuota=${CPU_QUOTA}" + SET_PROPERTY="true" +fi + +if [ -n "${CPU_SHARES}" ] +then + CPU_SHARES="CPUShares=${CPU_SHARES}" + SET_PROPERTY="true" +fi + +if [ -n "${MEMORY_LIMIT}" ] +then + MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}" + SET_PROPERTY="true" +fi + +if [ -n "${TASKS_MAX}" ] +then + TASKS_MAX="TasksMax=${TASKS_MAX}" + SET_PROPERTY="true" +fi + +if [ "${SET_PROPERTY}" != "true" ] +then + Usage +fi + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/list b/libexec/container/list new file mode 100755 index 0000000..30446c0 --- /dev/null +++ b/libexec/container/list @@ -0,0 +1,440 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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" + +VERSION="$(${PROGRAM} version)" + +Parameters () +{ + GETOPT_LONGOPTIONS="all,csv-separator:,format:,host:,nwdiag-color:,nwdiag-label:,other,started,stopped," + GETOPT_OPTIONS="a,f:,h:,o,s,t," + + 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 + -a|--all) + LIST="${LIST} all" + shift 1 + ;; + + --csv-separator) + CSV_SEPARATOR="${2}" + shift 2 + ;; + + -f|--format) + FORMAT="${2}" + shift 2 + ;; + + -h|--host) + HOST="${2}" + shift 2 + ;; + + --nwdiag-color) + NWDIAG_COLOR="${2}" + shift 2 + ;; + + --nwdiag-label) + NWDIAG_LABEL="${2}" + shift 2 + ;; + + -o|--other) + LIST="${LIST} other" + shift 1 + ;; + + -s|--started) + LIST="${LIST} started" + shift 1 + ;; + + -t|--stopped) + LIST="${LIST} stopped" + shift 1 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} [-a|--all] [--csv-separator SEPARATOR] [--format FORMAT] [-h|--host HOSTNAME] [--nwdiag-color COLOR] [--nwdiag-label LABEL] [-o|--other] [-s|--started] [-t|--stopped]" >&2 + exit 1 +} + +Parameters "${@}" + +LIST="${LIST:-started stopped}" +FORMAT="${FORMAT:-cli}" +HOST="${HOST:-$(hostname -f 2> /dev/null || hostname)}" + +CSV_SEPARATOR="${CSV_SEPARATOR:-,}" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +List () +{ + case "${FORMAT}" in + cli) + printf "%1s %-74s %-19s\n" "${STATUS}" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}" + ;; + + csv) + echo "${HOST}${CSV_SEPARATOR}${CONTAINER}${CSV_SEPARATOR}${STATE}${CSV_SEPARATOR}${ADDRESS}" + ;; + + json) + +cat << EOF + { + "name": "${CONTAINER}", + "status": "${STATE}", + "address": "${ADDRESS}", + }, +EOF + + ;; + + nwdiag) + Nwdiag_width "${CONTAINER}" + + case "${STATE}" in + started) + COLOR="#73d216" + ;; + + stopped) + COLOR="#cc0000" + ;; + + other) + COLOR="#d3d7cf" + ;; + esac + + echo " ${CONTAINER} [address = \"${ADDRESS}\", color = \"${COLOR}\", shape = \"flowchart.terminator\", width = \"${WIDTH}\"];" + ;; + + shell|sh) + echo "${CONTAINER}" + ;; + + yaml) + +cat << EOF + - name: ${CONTAINER} + address: ${ADDRESS} +EOF + + ;; + + xml) + +cat << EOF + + ${CONTAINER} +
${ADDRESS}
+
+EOF + + ;; + esac +} + +Nwdiag_width () +{ + NAME="${1}" + + CHARACTERS="$(echo "${NAME}" | wc -c)" + + if [ "${CHARACTERS}" -gt 13 ] + then + # default width is 128 fitting 13 characters + WIDTH="$(( ${CHARACTERS} - 13 ))" + WIDTH="$(( ${WIDTH} * 5 ))" + WIDTH="$(( ${WIDTH} + 128 ))" + else + WIDTH="128" + fi +} + +case "${FORMAT}" in + cli) + RED="$(tput setaf 1)$(tput bold)" + GREEN="$(tput setaf 2)$(tput bold)" + YELLOW="$(tput setaf 3)$(tput bold)" + BLUE="$(tput setaf 4)$(tput bold)" + WHITE="$(tput setaf 7)$(tput bold)" + NORMAL="$(tput sgr0)" + +cat << EOF +${WHITE} ${NORMAL} Container IP Address +-------------------------------------------------------------------------------- +EOF + + ;; + + csv) + +cat << EOF +# compute-tools ${VERSION} +Host${CSV_SEPARATOR}Container${CSV_SEPARATOR}Status${CSV_SEPARATOR}IPv4-Address +EOF + + ;; + + json) + +cat << EOF +{ + "compute-tools": { + "version": "${VERSION}", + }, + "host": { + "name": "${HOST}", + }, + "container": [ +EOF + + ;; + + nwdiag) + NETWORK="$(echo ${HOST} | sed -e 's|\.|_|g')" + +cat << EOF +# compute-tools ${VERSION} +nwdiag { + external_connector = none; + network ${NETWORK} { +EOF + + if [ -n "${NWDIAG_LABEL}" ] + then + echo " label = \"${NWDIAG_LABEL}\"" + else + echo " label = \"\"" + fi + + NUMBER="$(${0} --format=short | wc -l)" + + if [ -n "${NWDIAG_COLOR}" ] + then + COLOR="${NWDIAG_COLOR}" + else + COLOR="#3465a4" + fi + + Nwdiag_width "${HOST}" + +cat << EOF + # host + ${HOST} [color = "${COLOR}", shape = "box", numbered = "${NUMBER}", width = "${WIDTH}"]; + # container +EOF + + ;; + + yaml) + +cat << EOF +--- +compute_tools: + version: ${VERSION} + +host: + name: ${HOST} + +container: +EOF + + ;; + + xml) + +cat << EOF + + ${VERSION} + + + ${HOST} + + +EOF + + ;; +esac + +if ls "${MACHINES}"/* > /dev/null 2>&1 +then + CONTAINERS="$(cd "${MACHINES}" 2>/dev/null && find -maxdepth 1 \( -type d -or -type l \) -and -not -name 'lost+found' -printf '%P\n' | sort)" +fi + +for CONTAINER in ${CONTAINERS} +do + STATE="$(machinectl show ${CONTAINER} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + + if [ -e "${CONFIG}/${CONTAINER}.conf" ] + then + CONTAINER_SERVER="$(awk -Fcnt.container-server= '/^cnt.container-server=/ { print $2 }' ${CONFIG}/${CONTAINER}.conf)" + CONTAINER_SERVER="${CONTAINER_SERVER:-false}" + + case "${CONTAINER_SERVER}" in + ${HOST}|true) + ;; + + *) + STATE="other" + ;; + esac + else + STATE="other" + fi + + case "${STATE}" in + running) + STATE="started" + STATUS="${GREEN}●${NORMAL}" + ;; + + other) + STATUS="${WHITE}○${NORMAL}" + ;; + + *) + STATE="stopped" + STATUS="${RED}●${NORMAL}" + ;; + esac + + ADDRESS="" + + if ls "${MACHINES}/${CONTAINER}/etc/systemd/network"/*.network > /dev/null 2>&1 + then + ADDRESS="$(awk -FAddress= '/^Address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/systemd/network/*.network | head -n1)" + elif [ -e "${MACHINES}/${CONTAINER}/etc/network/interfaces" ] + then + ADDRESS="$(awk '/address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/network/interfaces | head -n1)" + fi + + ADDRESS="${ADDRESS:-n/a}" + + if echo ${LIST} | grep -qs all + then + List + fi + + for ITEM in other started stopped + do + if echo ${LIST} | grep -qs ${ITEM} + then + case "${STATE}" in + ${ITEM}) + List + ;; + esac + fi + done +done + +case "${FORMAT}" in + cli) + +cat << EOF +-------------------------------------------------------------------------------- +EOF + + ;; + + json) + +cat << EOF + ], +} +EOF + + ;; + + nwdiag) + +cat << EOF + } +} +EOF + + ;; + + xml) + +cat << EOF + +EOF + + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/log b/libexec/container/log new file mode 100755 index 0000000..e514391 --- /dev/null +++ b/libexec/container/log @@ -0,0 +1,164 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +LOG="/var/log/${SOFTWARE}/${PROGRAM}.log" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:,date:," + GETOPT_OPTIONS="n:,d:," + + 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 + -d|--date) + DATE="${2}" + shift 2 + ;; + + -n|--name) + NAME="${2}" + shift 2 + ;; + + -u|--user) + USER="${2}" + shift 2 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} [-n|--name NAME] [-d|--date DATE|today|today-N|yesterday] [-u|--user USER]" >&2 + exit 1 +} + +Parameters "${@}" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +case "${DATE}" in + today-*) + DAYS="$(echo ${DATE} | awk -F- '{ print $2 }')" + + START="$(date -d "${DAYS} day ago" '+%Y-%m-%d')" + END="$(date +%Y-%m-%d)" + + DATE="(${START}" + + while true + do + DATE="${DATE}|${START}" + + if [ "${START}" = "${END}" ] + then + break + fi + + START="$(date +%Y-%m-%d --date "${START} +1 day")" + done + + DATE="${DATE})" + ;; + + today) + DATE="$(date +%Y-%m-%d)" + ;; + + yesterday) + DATE="$(date -d '1 day ago' '+%Y-%m-%d')" + ;; +esac + +if ls "${LOG}"-*.gz > /dev/null 2>&1 +then + LOGS="$(ls ${LOG}-*.gz) ${LOG}" +else + LOGS="${LOG}" +fi + +for LOG in ${LOGS} +do + case "${LOG}" in + *.gz) + GREP="zgrep" + ;; + + *) + GREP="grep" + ;; + esac + + case "${NAME}" in + "") + ${GREP} -E "^${DATE}" "${LOG}" || true + ;; + + *) + ${GREP} -E "^${DATE}" "${LOG}" | grep " ${NAME}" || true + ;; + esac +done + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/move b/libexec/container/move new file mode 100755 index 0000000..a76cde1 --- /dev/null +++ b/libexec/container/move @@ -0,0 +1,212 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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" + +Parameters () +{ + GETOPT_LONGOPTIONS="force,new:,old:," + GETOPT_OPTIONS="f,n:,o:," + + 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 + -f|--force) + FORCE="true" + shift 1 + ;; + + -n|--new) + NEW="${2}" + shift 2 + ;; + + -o|--old) + OLD="${2}" + shift 2 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} [-f|--force] -n|--new NAME -o|--old NAME" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${OLD}" ] || [ -z "${NEW}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${OLD}" ] +then + echo "'${OLD}': no such container" >&2 + exit 1 +fi + +if [ -e "${MACHINES}/${NEW}" ] +then + echo "'${NEW}': container already exists" >&2 + exit 1 +fi + +STATE="$(machinectl show ${OLD} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + echo "'${OLD}': container is started" >&2 + exit 1 + ;; +esac + +case "${FORCE}" in + true) + ;; + + *) + if ${PROGRAM} list --other | grep -qs "^${OLD}$" + then + echo -n "'${OLD}': rename container to '${NEW}' [y|N]? " + read FORCE + + FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')" + + case "${FORCE}" in + y|yes) + ;; + + *) + exit 1 + ;; + esac + fi + ;; +esac + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${OLD}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +mv "${CONFIG}/${OLD}.conf" "${CONFIG}/${NEW}.conf" +mv "${MACHINES}/${OLD}" "${MACHINES}/${NEW}" + +# rw bind mounts +BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NEW}.conf)" + +if [ -n "${BIND}" ] +then + BINDS="$(echo ${BIND} | sed -e 's|;| |g')" + + for BIND in ${BINDS} + do + SOURCE_OLD="$(echo ${BIND} | awk -F: '{ print $1 }')" + SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")" + + if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ] + then + mv "${SOURCE_OLD}" "${SOURCE_NEW}" + fi + + TARGET_OLD="$(echo ${BIND} | awk -F: '{ print $2 }')" + TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")" + + if [ "${TARGET_OLD}" != "${TARGET_NEW}" ] + then + mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}" + fi + done +fi + +# ro bind mounts +BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NEW}.conf)" + +if [ -n "${BIND_RO}" ] +then + BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" + + for BIND_RO in ${BINDS_RO} + do + SOURCE_OLD="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" + SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")" + + if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ] + then + mv "${SOURCE_OLD}" "${SOURCE_NEW}" + fi + + TARGET_OLD="$(echo ${BIND_RO} | awk -F: '{ print $2 }')" + TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")" + + if [ "${TARGET_OLD}" != "${TARGET_NEW}" ] + then + mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}" + fi + done +fi + +# config +sed -i -e "s|${OLD}|${NEW}|g" "${CONFIG}/${NEW}.conf" + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NEW}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/remove b/libexec/container/remove new file mode 100755 index 0000000..3205c32 --- /dev/null +++ b/libexec/container/remove @@ -0,0 +1,258 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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" + +Parameters () +{ + OPTIONS_ALL="" + + GETOPT_LONGOPTIONS="name:,allow-stop,force,verbose," + GETOPT_OPTIONS="n:,f,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 + ;; + + --allow-stop) + ALLOW_STOP="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --allow-stop" + ;; + + -f|--force) + FORCE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --force" + ;; + + -v|--verbose) + VERBOSE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --verbose" + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--allow-stop] [-f|--force] [-v|--verbose]" >&2 + exit 1 +} + +Rmdir () +{ + DIRECTORIES="${@}" + + for DIRECTORY in ${DIRECTORIES} + do + PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)" + + if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ] + then + # the directory is at least two levels down from / + cd "${PARENT_DIRECTORY}" + + CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)" + rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true + + cd "${OLDPWD}" + fi + done +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +case "${NAME}" in + ALL) + NAMES="$(${PROGRAM} list --format shell --stopped)" + + for NAME in ${NAMES} + do + ${PROGRAM} remove --name ${NAME} ${OPTIONS_ALL} || true + done + + exit 0 + ;; +esac + +if [ ! -e "${MACHINES}/${NAME}" ] && [ ! -e "${CONFIG}/${NAME}.conf" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + case "${ALLOW_STOP}" in + true) + echo "'${NAME}': container is started, stopping it now" >&2 + ${PROGRAM} stop -n ${NAME} + ;; + + *) + echo "'${NAME}': container is started" >&2 + exit 1 + ;; + esac + ;; +esac + +case "${FORCE}" in + true) + ;; + + *) + echo -n "'${NAME}': remove container '${NAME}' [y|N]? " + read FORCE + + FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')" + + case "${FORCE}" in + y|yes) + ;; + + *) + exit 1 + ;; + esac + ;; +esac + +case "${VERBOSE}" in + true) + RM_OPTIONS="--verbose" + ;; + + *) + RM_OPTIONS="" + ;; +esac + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# data +if [ -e "${CONFIG}/${NAME}.conf" ] +then + # Removing rw bind mounts + BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND}" ] + then + BINDS="$(echo ${BIND} | sed -e 's|;| |g')" + + for BIND in ${BINDS} + do + DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" + + Rmdir "${DIRECTORY}" + done + fi + + # Removing ro bind mounts + BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND_RO}" ] + then + BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" + + for BIND_RO in ${BINDS_RO} + do + DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" + + Rmdir "${DIRECTORY}" + done + fi +fi + +# Run +case "${VERBOSE}" in + true) + echo -n "Removing container ${NAME}..." + ;; +esac + +rm --preserve-root --one-file-system -rf ${RM_OPTIONS} "${MACHINES}/${NAME}" +rm -f ${RM_OPTIONS} "${CONFIG}/${NAME}.conf" + +case "${VERBOSE}" in + true) + echo " done." + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/restart b/libexec/container/restart new file mode 100755 index 0000000..922629d --- /dev/null +++ b/libexec/container/restart @@ -0,0 +1,138 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" + +Parameters () +{ + OPTIONS_ALL="" + + GETOPT_LONGOPTIONS="name:,verbose," + GETOPT_OPTIONS="n:,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 + ;; + + -v|--verbose) + VERBOSE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --verbose" + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-v|--verbose]" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +case "${NAME}" in + ALL) + NAMES="$(${PROGRAM} list --format shell --started)" + + for NAME in ${NAMES} + do + ${PROGRAM} restart --name ${NAME} ${OPTIONS_ALL} || true + done + + exit 0 + ;; +esac + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +case "${VERBOSE}" in + true) + echo -n "Restarting container ${NAME}..." + ;; +esac + +machinectl reboot ${NAME} + +case "${VERBOSE}" in + true) + echo " done." + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/run b/libexec/container/run new file mode 100755 index 0000000..bf8d0a7 --- /dev/null +++ b/libexec/container/run @@ -0,0 +1,128 @@ +#!/bin/sh + +# Copyright (C) 2014-2019 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +MACHINES="/var/lib/machines" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:," + GETOPT_OPTIONS="n:," + + 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 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME -- COMMAND" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')" + +case "${STATE}" in + running) + ;; + + *) + echo "'${NAME}': container is not running" >&2 + exit 1 + ;; +esac + +LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}" + +RUN="$(echo ${@} | awk -F-- '{ print $2}')" + +# Run +nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 /bin/bash -l -c \"${RUN}\"" -q /dev/null + +case "${SSH_CLIENT}" in + 127.0.0.1*) + unset SSH_CLIENT + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/start b/libexec/container/start new file mode 100755 index 0000000..089aa7d --- /dev/null +++ b/libexec/container/start @@ -0,0 +1,532 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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" + +START="false" +SYSTEMCTL="true" + +Parameters () +{ + OPTIONS_ALL="" + + GETOPT_LONGOPTIONS="name:,force,nspawn,start,verbose," + GETOPT_OPTIONS="n:,f,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 + ;; + + -f|--force) + FORCE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --force" + ;; + + --nspawn) + # internal option + SYSTEMCTL="false" + shift 1 + ;; + + --start) + # internal option + START="true" + SYSTEMCTL="false" + shift 1 + ;; + + -v|--verbose) + VERBOSE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --verbose" + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force]" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +# hooks +export NAME + +case "${NAME}" in + ALL) + NAMES="$(${PROGRAM} list --format shell --stopped)" + + for NAME in ${NAMES} + do + ${PROGRAM} start --name ${NAME} ${OPTIONS_ALL} || true + done + + exit 0 + ;; +esac + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +case "${START}" in + false) + STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + + case "${STATE}" in + running) + echo "'${NAME}': container is already started" >&2 + exit 1 + ;; + esac + ;; +esac + +if [ -e "${MACHINES}/.#${NAME}.lck" ] +then + case "${FORCE}" in + true) + rm -f "${MACHINES}/.#${NAME}.lck" + + VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')" + + for VETH in ${VETHS} + do + ip link delete ${VETH} > /dev/null 2>&1 || true + done + ;; + + *) + echo "'${NAME}': container is locked" >&2 + exit 1 + ;; + esac +fi + +HOST_ARCHITECTURE="$(dpkg --print-architecture)" +MACHINE_ARCHITECTURE="$(chroot ${MACHINES}/${NAME} dpkg --print-architecture)" + +case "${HOST_ARCHITECTURE}" in + amd64) + case "${MACHINE_ARCHITECTURE}" in + i386) + SETARCH="setarch i686" + ;; + + *) + SETARCH="" + ;; + esac + ;; +esac + +case "${START}" in + start) + ;; + + *) + # Pre hooks + for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" + do + if [ -x "${FILE}" ] + then + "${FILE}" + fi + done + ;; +esac + +# config +if [ -e "${CONFIG}/${NAME}.conf" ] +then + CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + CNT_OVERLAY_OPTIONS="$(awk -Fcnt.overlay-options= '/^cnt.overlay-options=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${CNT_OVERLAY}" ] + then + CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')" + + COUNT="0" + for CNT_OVERLAY in ${CNT_OVERLAYS} + do + DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')" + DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')" + DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')" + DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')" + + COUNT="$((${COUNT} + 1))" + CNT_OVERLAY_OPTION="$(echo ${CNT_OVERLAY_OPTIONS} | awk -F ';' "{ print \$${COUNT} }")" + + for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}" + do + mkdir -p "${DIRECTORY}" + done + + if ! findmnt -n -o SOURCE "${DIRECTORY_MERGED}" | grep -qs '^cnt.overlay-' + then + if [ -n "${CNT_OVERLAY_OPTION}" ] + then + CNT_OVERLAY_OPTION="-o ${CNT_OVERLAY_OPTION}" + fi + + mount cnt.overlay-${NAME} -t overlay ${CNT_OVERLAY_OPTION} -olowerdir="${DIRECTORY_LOWER}",upperdir="${DIRECTORY_UPPER}",workdir="${DIRECTORY_WORK}",default_permissions "${DIRECTORY_MERGED}" + fi + done + fi + + BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND}" ] + then + BINDS="$(echo ${BIND} | sed -e 's|;| |g')" + + for BIND in ${BINDS} + do + DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" + + if [ ! -e "${DIRECTORY}" ] + then + echo "'${DIRECTORY}': creating non-existing directory for bind mounting" + mkdir -p "${DIRECTORY}" + fi + done + + BIND="" + + for DIRECTORIES in ${BINDS} + do + BIND="${BIND} --bind ${DIRECTORIES}" + done + fi + + BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND_RO}" ] + then + BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" + + for BIND_RO in ${BINDS_RO} + do + DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" + + if [ ! -e "${DIRECTORY}" ] + then + echo "'${DIRECTORY}': creating non-existing directory for bind-ro mounting" + mkdir -p "${DIRECTORY}" + fi + done + + BIND_RO="" + + for DIRECTORIES in ${BINDS_RO} + do + BIND_RO="${BIND_RO} --bind-ro ${DIRECTORIES}" + done + fi + + BOOT="$(awk -Fboot= '/^boot=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)" + + case "${BOOT}" in + yes) + BOOT="--boot" + ;; + + *) + BOOT="" + ;; + esac + + CAPABILITY="$(awk -Fcapability= '/^capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${CAPABILITY}" in + "") + CAPABILITY="" + ;; + + *) + CAPABILITY="--capability=${CAPABILITY}" + ;; + esac + + DIRECTORY="$(awk -Fdirectory= '/^directory=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo ${MACHINES}/${NAMES})" + DIRECTORY="--directory ${DIRECTORY}" + + DROP_CAPABILITY="$(awk -Fdrop-capability= '/^drop-capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${DROP_CAPABILITY}" in + "") + DROP_CAPABILITY="" + ;; + + *) + DROP_CAPABILITY="--drop-capability=${DROP_CAPABILITY}" + ;; + esac + + LINK_JOURNAL="$(awk -Flink-journal= '/^link-journal=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)" + + case "${LINK_JOURNAL}" in + yes) + LINK_JOURNAL="--link-journal=yes" + ;; + + *) + LINK_JOURNAL="--link-journal=no" + ;; + esac + + MACHINE="--machine=${NAME}" + + NETWORK_VETH_EXTRA="" + + VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${VETHS}" in + "") + ;; + + *) + for VETH in ${VETHS} + do + NETWORK_VETH_EXTRA="${NETWORK_VETH_EXTRA} --network-veth-extra=${VETH}" + INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')" + + if [ "$(echo ${INTERFACE} | wc -c)" -gt 15 ] + then + echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working." + fi + done + ;; + esac + + NETWORK_BRIDGES="$(awk -Fcnt.network-bridge= '/^cnt.network-bridge=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${NETWORK_BRIDGES}" in + "") + ;; + + *) + for BRIDGE_DEFINITION in ${NETWORK_BRIDGES} + do + INTERFACE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $1 }')" + BRIDGE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $2 }')" + + if [ "$(echo ${INTERFACE} | wc -c)" -gt 15 ] + then + echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working." + fi + + if [ -n "${BRIDGE}" ] && [ -n "${INTERFACE}" ] + then + +cat > "/etc/network/interfaces.d/${INTERFACE}" << EOF +allow-hotplug ${INTERFACE} +iface ${INTERFACE} inet manual + pre-up ip link set ${INTERFACE} up + post-up ip link set ${INTERFACE} master ${BRIDGE} + pre-down ip link set ${INTERFACE} nomaster + post-down ip link set ${INTERFACE} down +EOF + + else + echo "Warning bridge definition '${BRIDGE_DEFINITION}' not recognized (expected :): Ignoring" + fi + done + ;; + esac + + PRIVATE_USERS="$(awk -Fprivate-users= '/^private-users=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)" + + case "${PRIVATE_USERS}" in + yes) + PRIVATE_USERS="--private-users=yes" + ;; + + *) + PRIVATE_USERS="--private-users=no" + ;; + esac + + REGISTER="$(awk -Fregister= '/^register=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)" + + case "${REGISTER}" in + yes) + REGISTER="--register=yes" + ;; + + *) + REGISTER="--register=no" + ;; + esac + + BLOCK_IO_DEVICE_WEIGHT="$(awk -FBlockIODeviceWeight= '/^BlockIODeviceWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ] + then + BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}" + SET_PROPERTY="true" + fi + + BLOCK_IO_READ_BANDWIDTH="$(awk -FBlockIOReadBandwidth= '/^BlockIOReadBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ] + then + BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}" + SET_PROPERTY="true" + fi + + BLOCK_IO_WEIGHT="$(awk -FBlockIOWeight= '/^BlockIOWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BLOCK_IO_WEIGHT}" ] + then + BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}" + SET_PROPERTY="true" + fi + + BLOCK_IO_WRITE_BANDWIDTH="$(awk -FBlockIOWriteBandwidth=/= '/^BlockIOWriteBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ] + then + BLOCK_IO_WRITE_BANDWIDTH="BlockIOWriteBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}" + SET_PROPERTY="true" + fi + + CPU_QUOTA="$(awk -FCPUQuota= '/^CPUQuota=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${CPU_QUOTA}" ] + then + CPU_QUOTA="CPUQuota=${CPU_QUOTA}" + SET_PROPERTY="true" + fi + + CPU_SHARES="$(awk -FCPUShares= '/^CPUShares=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${CPU_SHARES}" ] + then + CPU_SHARES="CPUShares=${CPU_SHARES}" + SET_PROPERTY="true" + fi + + MEMORY_LIMIT="$(awk -FMemoryLimit= '/^MemoryLimit=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${MEMORY_LIMIT}" ] + then + MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}" + SET_PROPERTY="true" + fi + + TASKS_MAX="$(awk -FTasksMax= '/^TasksMax=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${TASKS_MAX}" ] + then + TASKS_MAX="TasksMax=${TASKS_MAX}" + SET_PROPERTY="true" + fi +fi + +case "${SYSTEMCTL}" in + true) + systemctl start ${PROGRAM}@${NAME}.service + + # Post hooks + for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" + do + if [ -x "${FILE}" ] + then + "${FILE}" + fi + done + + exit 0 + ;; +esac + +case "${START}" in + true) + case "${SET_PROPERTY}" in + true) + systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX} + ;; + esac + ;; + + *) + # Run + + case "${VERBOSE}" in + true) + echo -n "Starting container ${NAME}..." + ;; + esac + + ${SETARCH} systemd-nspawn --keep-unit ${BIND} ${BIND_RO} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_VETH_EXTRA} ${LINK_JOURNAL} ${REGISTER} + + case "${VERBOSE}" in + true) + echo " done." + ;; + esac + ;; +esac diff --git a/libexec/container/status b/libexec/container/status new file mode 100755 index 0000000..9c3a076 --- /dev/null +++ b/libexec/container/status @@ -0,0 +1,105 @@ +#!/bin/sh + +# Copyright (C) 2016 Simon Spöehel +# +# 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 . + +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" + +Parameters () +{ + GETOPT_LONGOPTIONS="name:," + GETOPT_OPTIONS="n:," + + 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 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2 + exit 1 +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +systemctl status ${PROGRAM}@${NAME}.service --full + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/stop b/libexec/container/stop new file mode 100755 index 0000000..58fc0e9 --- /dev/null +++ b/libexec/container/stop @@ -0,0 +1,290 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +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" + +CLEAN="false" + +Parameters () +{ + OPTIONS_ALL="" + + GETOPT_LONGOPTIONS="name:,force,clean,verbose," + GETOPT_OPTIONS="n:,f,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 + ;; + + -f|--force) + FORCE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --force" + ;; + + --clean) + # internal option + CLEAN="true" + shift 1 + + OPTONS_ALL="${OPTIONS_ALL} --clean" + ;; + + -v|--verbose) + VERBOSE="true" + shift 1 + + OPTIONS_ALL="${OPTIONS_ALL} --verbose" + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force] [-v|--verbose]" >&2 + exit 1 +} + +Rmdir () +{ + DIRECTORIES="${@}" + + for DIRECTORY in ${DIRECTORIES} + do + PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)" + + if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ] + then + # the directory is at least two levels down from / + cd "${PARENT_DIRECTORY}" + + CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)" + rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true + + cd "${OLDPWD}" + fi + done +} + +Parameters "${@}" + +if [ -z "${NAME}" ] +then + Usage +fi + +case "${NAME}" in + ALL) + NAMES="$(${PROGRAM} list --format shell --started)" + + for NAME in ${NAMES} + do + ${PROGRAM} stop --name ${NAME} ${OPTIONS_ALL} || true + done + + exit 0 + ;; +esac + +if [ ! -e "${MACHINES}/${NAME}" ] +then + echo "'${NAME}': no such container" >&2 + exit 1 +fi + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')" + +case "${CLEAN}" in + true) + # Removing overlay mounts + CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${CNT_OVERLAY}" ] + then + CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')" + + for CNT_OVERLAY in ${CNT_OVERLAYS} + do + DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')" + DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')" + DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')" + DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')" + + umount -f "${DIRECTORY_MERGED}" + + Rmdir "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}" + done + fi + + # Removing rw bind mounts + BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND}" ] + then + BINDS="$(echo ${BIND} | sed -e 's|;| |g')" + + for BIND in ${BINDS} + do + DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')" + + Rmdir "${DIRECTORY}" + done + fi + + # Removing ro bind mounts + BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + if [ -n "${BIND_RO}" ] + then + BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')" + + for BIND_RO in ${BINDS_RO} + do + DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')" + + Rmdir "${DIRECTORY}" + done + fi + + # Removing network configuration + VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)" + + case "${VETHS}" in + "") + ;; + + *) + for VETH in ${VETHS} + 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) + ;; + + *) + echo "'${NAME}': container is already stopped" >&2 + exit 1 + ;; +esac + +case "${FORCE}" in + true) + MODE="terminate" + ;; + + *) + MODE="poweroff" + ;; +esac + +# Run +case "${VERBOSE}" in + true) + echo -n "Stopping container ${NAME}..." + ;; +esac + +machinectl ${MODE} ${NAME} + +case "${FORCE}" in + true) + VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')" + + for VETH in ${VETHS} + do + ip link delete ${VETH} > /dev/null 2>&1 || true + done + ;; +esac + +case "${VERBOSE}" in + true) + echo " done." + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/top b/libexec/container/top new file mode 100755 index 0000000..c846000 --- /dev/null +++ b/libexec/container/top @@ -0,0 +1,119 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +Parameters () +{ + GETOPT_LONGOPTIONS="delay:," + GETOPT_OPTIONS="d:," + + 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 + -d|--delay) + DELAY="${2}" + shift 2 + ;; + + --) + shift 1 + break + ;; + + *) + echo "'${COMMAND}': getopt error" >&2 + exit 1 + ;; + esac + done +} + +Usage () +{ + echo "Usage: ${PROGRAM} ${COMMAND} [-d|--delay DELAY]" >&2 + exit 1 +} + +Parameters "${@}" + +DELAY="${DELAY:-1}" +HOST="$(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 + +# Run +Top () +{ + HOME="$(tput cup 0 0)" + ED="$(tput ed)" + EL="$(tput el)" + + printf '%s%s' "${HOME}" "${ED}" + + while true + do + ROWS="$(tput lines)" + COLS="$(tput cols)" + CMD="${@}" + + ${SHELL:=sh} -c "${CMD}" | head -n ${ROWS} | while IFS= read LINE + do + printf '%-*.*s%s\n' ${COLS} ${COLS} "${LINE}" "${EL}" + done + + printf '%s%s' "${ED}" "${HOME}" + sleep ${DELAY} + done +} + +trap 'clear' EXIT HUP INT QUIT TERM + +Top "${PROGRAM} list && printf '%-59s %-19s\n' \" Host: ${HOST}\" \"\$(date +%Y-%m-%d\ %H:%M:%S)\"" + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/libexec/container/version b/libexec/container/version new file mode 100755 index 0000000..3b33a4d --- /dev/null +++ b/libexec/container/version @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann +# +# 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 . + +set -e + +PROJECT="open-infrastructure" +SOFTWARE="compute-tools" +PROGRAM="container" +COMMAND="$(basename ${0})" + +HOOKS="/etc/${SOFTWARE}/hooks" +SHARE="/usr/share/${SOFTWARE}" + +# Pre hooks +for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done + +# Run +cat "${SHARE}/VERSION.txt" + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done diff --git a/share/bash-completion/container b/share/bash-completion/container index 4e49cec..540f162 100644 --- a/share/bash-completion/container +++ b/share/bash-completion/container @@ -1,7 +1,6 @@ # bash-completion # -# Copyright (C) 2016 Andreas Kreuzer -# Copyright (C) 2016-2021 Daniel Baumann +# Copyright (C) 2014-2021 Daniel Baumann # # SPDX-License-Identifier: GPL-3.0+ # @@ -16,7 +15,7 @@ # 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 . +# along with this program. If not, see . _container() { @@ -63,13 +62,13 @@ _container() create|cr) case "${prev}" in -n|--name) - opts="$(cd /etc/open-infrastructure/container/debconf 2>/dev/null && ls *.cfg */*.cfg 2>/dev/null | sed -e 's|.*/||g' -e 's|.cfg$||g')" + opts="$(cd /etc/compute-tools/debconf 2>/dev/null && ls *.cfg */*.cfg 2>/dev/null | sed -e 's|.*/||g' -e 's|.cfg$||g')" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; -s|--script) - opts="$(cd /usr/share/open-infrastructure/container/scripts && find -maxdepth 1 -not -type d -and -not -name 'default' -and -not -name 'debconf' -and -not -name '*.d' -printf '%P\n' | sort)" + opts="$(cd /usr/share/compute-tools/scripts && find -maxdepth 1 -not -type d -and -not -name 'default' -and -not -name 'debconf' -and -not -name '*.d' -printf '%P\n' | sort)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; @@ -145,13 +144,13 @@ _container() log) case "${prev}" in -d|--date) - opts="$(if ls /var/log/open-infrastructure/container.log-*.gz > /dev/null 2>&1; + opts="$(if ls /var/log/compute-tools/container.log-*.gz > /dev/null 2>&1; then \ - zcat /var/log/open-infrastructure/container.log-*.gz | awk '{ print $1 }' | sort -u; \ + zcat /var/log/compute-tools/container.log-*.gz | awk '{ print $1 }' | sort -u; \ fi; \ - if [ -e /var/log/open-infrastructure/container.log ]; \ + if [ -e /var/log/compute-tools/container.log ]; \ then \ - awk '{ print $1 }' /var/log/open-infrastructure/container.log | sort -u; \ + awk '{ print $1 }' /var/log/compute-tools/container.log | sort -u; \ fi) \ today yesterday" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) @@ -159,13 +158,13 @@ _container() ;; -n|--name) - opts="$(if ls /var/log/open-infrastructure/container.log-*.gz > /dev/null 2>&1; + opts="$(if ls /var/log/compute-tools/container.log-*.gz > /dev/null 2>&1; then \ - zgrep -E '(\-n|\-\-name) ' /var/log/open-infrastructure/container.log-*.gz | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \ + zgrep -E '(\-n|\-\-name) ' /var/log/compute-tools/container.log-*.gz | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \ fi; \ - if [ -e /var/log/open-infrastructure/container.log ]; \ + if [ -e /var/log/compute-tools/container.log ]; \ then \ - grep -E '(\-n|\-\-name) ' /var/log/open-infrastructure/container.log | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \ + grep -E '(\-n|\-\-name) ' /var/log/compute-tools/container.log | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \ fi)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 @@ -286,7 +285,7 @@ _container() ;; *) - local commands=$(cd /usr/lib/open-infrastructure/container 2>/dev/null && find * -type f -print) + local commands=$(cd /usr/libexec/container 2>/dev/null && find * -type f -print) COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) ) return 0 ;; diff --git a/share/doc/examples/bullseye.cfg b/share/doc/examples/bullseye.cfg new file mode 100644 index 0000000..044504e --- /dev/null +++ b/share/doc/examples/bullseye.cfg @@ -0,0 +1,35 @@ +# example for automated Debian 11 (bullseye) based container creation +# using: sudo container create -s debian + +debconf debconf/priority select critical +debconf debconf/frontend select Noninteractive + +compute-tools container/mode select debian + +#compute-tools container/preseed-files string +#compute-tools container/include-preseed-files string + +compute-tools container/distribution select bullseye +#compute-tools container/parent-distribution select + +compute-tools container/architecture select auto + +compute-tools container/archives multiselect bullseye-security, bullseye-updates +#compute-tools container/parent-archives multiselect + +compute-tools container/mirror string https://deb.debian.org/debian +compute-tools container/mirror-security string https://security.debian.org + +#compute-tools container/parent-mirror string +#compute-tools container/parent-mirror-security string + +compute-tools container/archive-areas multiselect main +#compute-tools container/parent-archive-areas multiselect + +compute-tools container/packages string openssh-server + +compute-tools container/root-password string debian +#compute-tools container/root-password-crypted string + +compute-tools container/network1/bridge string bridge0 +#compute-tools container/network-mac string diff --git a/share/doc/examples/buster.cfg b/share/doc/examples/buster.cfg deleted file mode 100644 index cfc8595..0000000 --- a/share/doc/examples/buster.cfg +++ /dev/null @@ -1,35 +0,0 @@ -# example for automated Debian 10 (buster) based container creation -# using: sudo container create -s debian - -debconf debconf/priority select critical -debconf debconf/frontend select Noninteractive - -compute-tools container/mode select debian - -#compute-tools container/preseed-files string -#compute-tools container/include-preseed-files string - -compute-tools container/distribution select buster -#compute-tools container/parent-distribution select - -compute-tools container/architecture select auto - -compute-tools container/archives multiselect buster-security, buster-updates -#compute-tools container/parent-archives multiselect - -compute-tools container/mirror string https://deb.debian.org/debian -compute-tools container/mirror-security string http://security.debian.org - -#compute-tools container/parent-mirror string -#compute-tools container/parent-mirror-security string - -compute-tools container/archive-areas multiselect main -#compute-tools container/parent-archive-areas multiselect - -compute-tools container/packages string openssh-server - -compute-tools container/root-password string debian -#compute-tools container/root-password-crypted string - -compute-tools container/network1/bridge string bridge0 -#compute-tools container/network-mac string diff --git a/share/doc/examples/container-images.sh b/share/doc/examples/container-images.sh index 7bb40b4..ede68b5 100755 --- a/share/doc/examples/container-images.sh +++ b/share/doc/examples/container-images.sh @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . # Description: example for automated Debian base system container image creation # Requires: debootstrap plzip xz-utils diff --git a/share/doc/examples/engywuck-backports.cfg b/share/doc/examples/engywuck-backports.cfg deleted file mode 100644 index 9ca0288..0000000 --- a/share/doc/examples/engywuck-backports.cfg +++ /dev/null @@ -1,70 +0,0 @@ -# example for automated Progress Linux 5+ (engywuck-backports) container creation -# using: sudo container create -s progress-linux - -debconf debconf/priority select critical -debconf debconf/frontend select Noninteractive - -compute-tools container/mode select progress-linux - -#compute-tools container/preseed-files string -#compute-tools container/include-preseed-files string - -compute-tools container/distribution select engywuck-backports -#compute-tools container/parent-distribution select - -compute-tools container/architecture select auto - -compute-tools container/archives multiselect engywuck-security, engywuck-updates, engywuck-extras, engywuck-backports, engywuck-backports-extras -#compute-tools container/parent-archives multiselect - -compute-tools container/mirror string https://deb.progress-linux.org/packages -compute-tools container/mirror-security string https://deb.progress-linux.org/packages - -compute-tools container/parent-mirror string https://deb.debian.org/debian -compute-tools container/parent-mirror-security string http://security.debian.org - -compute-tools container/archive-areas multiselect main, contrib, non-free -compute-tools container/parent-archive-areas multiselect main, contrib, non-free - -compute-tools container/packages string knot-resolver openssh-server - -compute-tools container/root-password string progress -#compute-tools container/root-password-crypted string - -# Network IP configuration -compute-tools container/network1/bridge string bridge0 -compute-tools container/network1/veth string veth0 -compute-tools container/network1/ipv4-method select static -compute-tools container/network1/ipv4-comment string Primary network interfaces -compute-tools container/network1/ipv4-address string 192.168.0.2 -compute-tools container/network1/ipv4-gateway string 192.168.0.1 -compute-tools container/network1/ipv4-netmask string 255.255.255.0 -#compute-tools container/network1/ipv4-post-up string -#compute-tools container/network1/ipv4-post-down string - -# Network DNS configuration -compute-tools container/nameserver/server string 127.0.0.1 8.8.8.8 8.8.4.4 -compute-tools container/nameserver/domain string example.net -compute-tools container/nameserver/search string example.net -compute-tools container/nameserver/options string timeout:1 attempts:1 - -# Third-Party Repositories -#compute-tools container/archive1/repository string -#compute-tools container/archive1/list string -#compute-tools container/archive1/comment string -#compute-tools container/archive1/source string -#compute-tools container/archive1/key string -#compute-tools container/archive1/preferences-package string -#compute-tools container/archive1/preferences-pin string -#compute-tools container/archive1/preferences-pin-priority - -# Internal Options -#compute-tools container/apt-recommends string -#compute-tools container/debconf-frontend string -#compute-tools container/debconf-priority string -#compute-tools container/container-command string -#compute-tools container/host-command string -compute-tools container/auto string true -#compute-tools container/overlay string -#compute-tools container/bind string -#compute-tools container/bind-ro string diff --git a/share/doc/examples/fuchur-backports.cfg b/share/doc/examples/fuchur-backports.cfg new file mode 100644 index 0000000..20cd127 --- /dev/null +++ b/share/doc/examples/fuchur-backports.cfg @@ -0,0 +1,70 @@ +# example for automated Progress Linux 6.99 (fuchur-backports) container creation +# using: sudo container create -s progress-linux + +debconf debconf/priority select critical +debconf debconf/frontend select Noninteractive + +compute-tools container/mode select progress-linux + +#compute-tools container/preseed-files string +#compute-tools container/include-preseed-files string + +compute-tools container/distribution select fuchur-backports +#compute-tools container/parent-distribution select + +compute-tools container/architecture select auto + +compute-tools container/archives multiselect fuchur-security, fuchur-updates, fuchur-extras, fuchur-backports, fuchur-backports-extras +#compute-tools container/parent-archives multiselect + +compute-tools container/mirror string https://deb.progress-linux.org/packages +compute-tools container/mirror-security string https://deb.progress-linux.org/packages + +compute-tools container/parent-mirror string https://deb.debian.org/debian +compute-tools container/parent-mirror-security string https://security.debian.org + +compute-tools container/archive-areas multiselect main, contrib, non-free +compute-tools container/parent-archive-areas multiselect main, contrib, non-free + +compute-tools container/packages string knot-resolver openssh-server + +compute-tools container/root-password string progress +#compute-tools container/root-password-crypted string + +# Network IP configuration +compute-tools container/network1/bridge string bridge0 +compute-tools container/network1/veth string veth0 +compute-tools container/network1/ipv4-method select static +compute-tools container/network1/ipv4-comment string Primary network interfaces +compute-tools container/network1/ipv4-address string 192.168.0.2 +compute-tools container/network1/ipv4-gateway string 192.168.0.1 +compute-tools container/network1/ipv4-netmask string 255.255.255.0 +#compute-tools container/network1/ipv4-post-up string +#compute-tools container/network1/ipv4-post-down string + +# Network DNS configuration +compute-tools container/nameserver/server string 127.0.0.1 8.8.8.8 8.8.4.4 +compute-tools container/nameserver/domain string example.net +compute-tools container/nameserver/search string example.net +compute-tools container/nameserver/options string timeout:1 attempts:1 + +# Third-Party Repositories +#compute-tools container/archive1/repository string +#compute-tools container/archive1/list string +#compute-tools container/archive1/comment string +#compute-tools container/archive1/source string +#compute-tools container/archive1/key string +#compute-tools container/archive1/preferences-package string +#compute-tools container/archive1/preferences-pin string +#compute-tools container/archive1/preferences-pin-priority + +# Internal Options +#compute-tools container/apt-recommends string +#compute-tools container/debconf-frontend string +#compute-tools container/debconf-priority string +#compute-tools container/container-command string +#compute-tools container/host-command string +compute-tools container/auto string true +#compute-tools container/overlay string +#compute-tools container/bind string +#compute-tools container/bind-ro string diff --git a/share/hooks/post-start.chown-nvidia.sh b/share/hooks/post-start.chown-nvidia.sh index e1ab35b..64c02cc 100755 --- a/share/hooks/post-start.chown-nvidia.sh +++ b/share/hooks/post-start.chown-nvidia.sh @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e diff --git a/share/hooks/pre-create.git-pull.sh b/share/hooks/pre-create.git-pull.sh index 823440f..744f955 100755 --- a/share/hooks/pre-create.git-pull.sh +++ b/share/hooks/pre-create.git-pull.sh @@ -15,14 +15,15 @@ # 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 . +# along with this program. If not, see . set -e PROJECT="open-infrastructure" +SOFTWARE="compute-tools" PROGRAM="container" -DIRECTORIES="/etc/${PROJECT}/${PROGRAM}/debconf /etc/${PROJECT}/${PROGRAM}/debconf/*/" +DIRECTORIES="$(for DIRECTORY in $(find /etc/${SOFTWARE}/debconf/ -type d -name ".git"); do echo $(dirname ${DIRECTORY}); done | sort -uV)" for DIRECTORY in ${DIRECTORIES} do @@ -30,9 +31,9 @@ do then echo "Updating ${DIRECTORY}..." - if [ -e "/etc/${PROJECT}/${PROGRAM}.conf" ] + if [ -e "/etc/${SOFTWARE}.conf" ] then - . "/etc/${PROJECT}/${PROGRAM}.conf" + . "/etc/${SOFTWARE}.conf" fi DEBCONF_ID="${DEBCONF_ID:-HEAD}" diff --git a/share/hooks/pre-start.unlink-console.sh b/share/hooks/pre-start.unlink-console.sh index 3133a19..b44491e 100755 --- a/share/hooks/pre-start.unlink-console.sh +++ b/share/hooks/pre-start.unlink-console.sh @@ -15,14 +15,15 @@ # 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 . +# along with this program. If not, see . set -e PROJECT="open-infrastructure" +SOFTWARE="compute-tools" PROGRAM="container" -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" +CONFIG="/etc/${SOFTWARE}/config" # Run if grep -qs 'bind=.*/dev:/dev;' "${CONFIG}/${NAME}.conf" diff --git a/share/logrotate/container b/share/logrotate/container index 14599be..0722aa5 100644 --- a/share/logrotate/container +++ b/share/logrotate/container @@ -1,4 +1,4 @@ -/var/log/open-infrastructure/container.log { +/var/log/compute-tools/container.log { compress create 0640 root adm dateext diff --git a/share/man/Makefile b/share/man/Makefile index 1500b15..2ef1507 100644 --- a/share/man/Makefile +++ b/share/man/Makefile @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . # Depends: asciidoc dblatex docbook-xsl libxml2-utils source-highlight diff --git a/share/man/compute-tools.7.txt b/share/man/compute-tools.7.txt index f8d9c76..e5f2c54 100644 --- a/share/man/compute-tools.7.txt +++ b/share/man/compute-tools.7.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-TOOLS(7) ================== diff --git a/share/man/container-auto.1.txt b/share/man/container-auto.1.txt index 3ed4c56..ecb84b0 100644 --- a/share/man/container-auto.1.txt +++ b/share/man/container-auto.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-START(1) ================== diff --git a/share/man/container-console.1.txt b/share/man/container-console.1.txt index 8f35a8d..59bb421 100644 --- a/share/man/container-console.1.txt +++ b/share/man/container-console.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CONSOLE(1) ==================== diff --git a/share/man/container-create-curl.1.txt b/share/man/container-create-curl.1.txt index 1095103..e263092 100644 --- a/share/man/container-create-curl.1.txt +++ b/share/man/container-create-curl.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CREATE-CURL(1) ======================== @@ -83,10 +83,10 @@ FILES ----- The following files are used: -*/etc/open-infrastructure/container/config*:: +*/etc/compute-tools/config*:: Container configuration files. -*/usr/share/open-infrastructure/container/scripts*:: +*/usr/share/compute-tools/scripts*:: Container creation scripts. */usr/share/doc/compute-tools*:: @@ -95,7 +95,7 @@ The following files are used: */var/lib/machines*:: Container directory. -*/var/cache/open-infrastructure/container*:: +*/var/cache/container*:: Container cache directory. diff --git a/share/man/container-create-debconf.1.txt b/share/man/container-create-debconf.1.txt index f4092a0..a04dfaf 100644 --- a/share/man/container-create-debconf.1.txt +++ b/share/man/container-create-debconf.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CREATE-DEBOOTSTRAP(1) =============================== @@ -114,10 +114,10 @@ FILES ----- The following files are used: -*/etc/open-infrastructure/container/config*:: +*/etc/compute-tools/config*:: Container configuration files. -*/usr/share/open-infrastructure/container/scripts*:: +*/usr/share/compute-tools/scripts*:: Container creation scripts. */usr/share/doc/compute-tools*:: @@ -126,7 +126,7 @@ The following files are used: */var/lib/machines*:: Container directory. -*/var/cache/open-infrastructure/container*:: +*/var/cache/container*:: Container cache directory. */tmp/compute-tools*:: diff --git a/share/man/container-create-debootstrap.1.txt b/share/man/container-create-debootstrap.1.txt index 60f0a22..37d6414 100644 --- a/share/man/container-create-debootstrap.1.txt +++ b/share/man/container-create-debootstrap.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CREATE-DEBOOTSTRAP(1) =============================== diff --git a/share/man/container-create.1.txt b/share/man/container-create.1.txt index dcb0df4..c49ac9c 100644 --- a/share/man/container-create.1.txt +++ b/share/man/container-create.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CREATE(1) =================== diff --git a/share/man/container-enter.1.txt b/share/man/container-enter.1.txt index c8d7f3c..c7adc1e 100644 --- a/share/man/container-enter.1.txt +++ b/share/man/container-enter.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-CONSOLE(1) ==================== diff --git a/share/man/container-key.1.txt b/share/man/container-key.1.txt index 2b54d78..e6c1553 100644 --- a/share/man/container-key.1.txt +++ b/share/man/container-key.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-KEY(1) ================ diff --git a/share/man/container-limit.1.txt b/share/man/container-limit.1.txt index 5f1ca30..12d76cd 100644 --- a/share/man/container-limit.1.txt +++ b/share/man/container-limit.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-LIMIT(1) ================== diff --git a/share/man/container-list.1.txt b/share/man/container-list.1.txt index 4016b87..4b3df3a 100644 --- a/share/man/container-list.1.txt +++ b/share/man/container-list.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-LIST(1) ================= diff --git a/share/man/container-log.1.txt b/share/man/container-log.1.txt index c30b37a..b503d42 100644 --- a/share/man/container-log.1.txt +++ b/share/man/container-log.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-LOG(1) ================ diff --git a/share/man/container-move.1.txt b/share/man/container-move.1.txt index fef0bce..5c9475c 100644 --- a/share/man/container-move.1.txt +++ b/share/man/container-move.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-REMOVE(1) =================== diff --git a/share/man/container-remove.1.txt b/share/man/container-remove.1.txt index 0975168..50ad861 100644 --- a/share/man/container-remove.1.txt +++ b/share/man/container-remove.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-REMOVE(1) =================== diff --git a/share/man/container-restart.1.txt b/share/man/container-restart.1.txt index 2a4dfa8..afc4581 100644 --- a/share/man/container-restart.1.txt +++ b/share/man/container-restart.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-RESTART(1) ==================== diff --git a/share/man/container-run.1.txt b/share/man/container-run.1.txt index b46ebf8..593e1a7 100644 --- a/share/man/container-run.1.txt +++ b/share/man/container-run.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-RUN(1) ================ diff --git a/share/man/container-shell.1.txt b/share/man/container-shell.1.txt index 03f2185..ce5c13c 100644 --- a/share/man/container-shell.1.txt +++ b/share/man/container-shell.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER(1) ============ diff --git a/share/man/container-start.1.txt b/share/man/container-start.1.txt index 2b7b919..bc0c946 100644 --- a/share/man/container-start.1.txt +++ b/share/man/container-start.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-START(1) ================== diff --git a/share/man/container-status.1.txt b/share/man/container-status.1.txt index 86820df..e74b8e5 100644 --- a/share/man/container-status.1.txt +++ b/share/man/container-status.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-STATUS(1) =================== diff --git a/share/man/container-stop.1.txt b/share/man/container-stop.1.txt index 9eab1c4..dc36bb9 100644 --- a/share/man/container-stop.1.txt +++ b/share/man/container-stop.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-STOP(1) ================= diff --git a/share/man/container-top.1.txt b/share/man/container-top.1.txt index 367be1b..295f51b 100644 --- a/share/man/container-top.1.txt +++ b/share/man/container-top.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-TOP(1) ================ diff --git a/share/man/container-version.1.txt b/share/man/container-version.1.txt index 6549d02..4f625f8 100644 --- a/share/man/container-version.1.txt +++ b/share/man/container-version.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER-VERSION(1) ==================== diff --git a/share/man/container.1.txt b/share/man/container.1.txt index d7ad339..7edc1f4 100644 --- a/share/man/container.1.txt +++ b/share/man/container.1.txt @@ -13,7 +13,7 @@ // 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 . +// along with this program. If not, see . CONTAINER(1) ============ @@ -104,7 +104,7 @@ FILES ----- The following files are used: -*/etc/open-infrastructure/container*:: +*/etc/compute-tools/container*:: Container configuration files. */usr/bin/container*, */usr/bin/cnt*:: @@ -113,22 +113,22 @@ The following files are used: */usr/bin/container-shell*, */usr/bin/cntsh*:: Container shell program. -*/usr/lib/open-infrastructure/container*:: +*/usr/libexec/container*:: Container commands. -*/usr/share/open-infrastructure/container*:: +*/usr/share/compute-tools/*:: Container shared data. */usr/share/doc/compute-tools*:: Container documentation files. -*/var/cache/open-infrastructure/container*:: +*/var/cache/container*:: Container cache directory. */var/lib/machines*:: Container root directory. -*/var/log/open-infrastructure*:: +*/var/log/compute-tools*:: Container log files. diff --git a/share/scripts/curl b/share/scripts/curl index 465ecbe..98c2b82 100755 --- a/share/scripts/curl +++ b/share/scripts/curl @@ -15,19 +15,21 @@ # 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 . +# along with this program. If not, see . set -e PROJECT="open-infrastructure" SOFTWARE="compute-tools" PROGRAM="container" -SCRIPT="${0}" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" -KEYS="/etc/${PROJECT}/${PROGRAM}/keys" +HOOKS="/etc/${SOFTWARE}/hooks" +KEYS="/etc/${SOFTWARE}/keys" MACHINES="/var/lib/machines" -CACHE="/var/cache/${PROJECT}/${PROGRAM}/system" +CACHE="/var/cache/${PROGRAM}/system" + +SCRIPT="${0}" +export SCRIPT Parameters () { @@ -267,7 +269,7 @@ then Debconf # Run debconf parts - for DEBCONF_SCRIPT in /usr/share/${PROJECT}/${PROGRAM}/scripts/curl.d/* + for DEBCONF_SCRIPT in /usr/share/${SOFTWARE}/scripts/curl.d/* do if [ -x "${DEBCONF_SCRIPT}" ] then diff --git a/share/scripts/curl.d/0001-debconf b/share/scripts/curl.d/0001-debconf index 0910480..083d469 100755 --- a/share/scripts/curl.d/0001-debconf +++ b/share/scripts/curl.d/0001-debconf @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e diff --git a/share/scripts/debconf b/share/scripts/debconf index 7f2bf3d..1994926 100755 --- a/share/scripts/debconf +++ b/share/scripts/debconf @@ -15,20 +15,21 @@ # 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 . +# along with this program. If not, see . set -e PROJECT="open-infrastructure" SOFTWARE="compute-tools" PROGRAM="container" -SCRIPT="${0}" -export SCRIPT -CONFIG="/etc/${PROJECT}/${PROGRAM}/config" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" +CONFIG="/etc/${SOFTWARE}/config" +HOOKS="/etc/${SOFTWARE}/hooks" MACHINES="/var/lib/machines" +SCRIPT="${0}" +export SCRIPT + Parameters () { GETOPT_LONGOPTIONS="bind:,bind-ro:,script:,name:,preseed-file:" @@ -448,37 +449,6 @@ EOF rm -f "${DIRECTORY}/etc/mtab" ln -s /proc/self/mounts "${DIRECTORY}/etc/mtab" - # Temporary hack for dpkg - if [ -e "${DIRECTORY}/etc/dpkg/origins/default" ] - then - rm -f "${DIRECTORY}/etc/dpkg/origins/default" - Chroot "${DIRECTORY}" "dpkg-reconfigure base-files" - fi - - # Temporary hack for base-files - for FILE in motd.tail motd profile - do - if [ -e "${DIRECTORY}/usr/share/base-files/${FILE}" ] - then - rm -f "${DIRECTORY}/etc/${FILE}" - cp "${DIRECTORY}/usr/share/base-files/${FILE}" "${DIRECTORY}/etc" - fi - done - - # Temporary hack for readline - if [ -e "${DIRECTORY}/etc/inputrc" ] - then - rm -f "${DIRECTORY}/etc/inputrc" - cp "${DIRECTORY}/usr/share/readline/inputrc" "${DIRECTORY}/etc" - fi - - # Temporary hack for sysvinit - if [ -e "${DIRECTORY}/etc/inittab" ] - then - rm -f "${DIRECTORY}/etc/inittab" - cp "${DIRECTORY}/usr/share/sysvinit/inittab" "${DIRECTORY}/etc/inittab" - fi - # Removing resolv.conf rm -f "${DIRECTORY}/etc/resolv.conf" cp /etc/resolv.conf "${DIRECTORY}/etc" @@ -521,7 +491,7 @@ EOF echo "deb ${PARENT_MIRROR_SECURITY} ${PARENT_DIST}/updates ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list" ;; - bullseye-security) + ${PARENT_DIST}-security) echo "deb ${PARENT_MIRROR_SECURITY} ${PARENT_DIST}-security ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list" ;; @@ -674,16 +644,6 @@ EOF done fi - # Temporary hack for base-files (base-files gets upgraded, so run it second time) - for FILE in motd.tail motd profile - do - if [ -e "${DIRECTORY}/usr/share/base-files/${FILE}" ] - then - rm -f "${DIRECTORY}/etc/${FILE}" - cp "${DIRECTORY}/usr/share/base-files/${FILE}" "${DIRECTORY}/etc" - fi - done - if [ -n "${PACKAGES}" ] then Chroot "${DIRECTORY}" "apt --option Dpkg::Options::=--force-confnew --yes install ${PACKAGES}" @@ -1121,7 +1081,7 @@ do done # Run debconf parts -for DEBCONF_SCRIPT in "/usr/share/${PROJECT}/${PROGRAM}/scripts/debconf.d"/* +for DEBCONF_SCRIPT in "/usr/share/${SOFTWARE}/scripts/debconf.d"/* do if [ -x "${DEBCONF_SCRIPT}" ] then @@ -1132,7 +1092,7 @@ done # Read-in configuration from debconf . "${DEBCONF_TMPDIR}/debconf.default" -CACHE="/var/cache/${PROJECT}/${PROGRAM}/${MODE}" +CACHE="/var/cache/${PROGRAM}/${MODE}" SYSTEM="${MACHINES}/${NAME}" ## Generic parts @@ -1145,7 +1105,7 @@ then mv "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}.tmp" "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" fi -Upgrade_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" || echo "W: If upgrading the system failed, try removing the cache for your distribution in /var/cache/${PROJECT}/${PROGRAM}" +Upgrade_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" || echo "W: If upgrading the system failed, try removing the cache for your distribution in /var/cache/${PROGRAM}" Cleanup_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" ## Specific parts diff --git a/share/scripts/debconf.d/0001-preseed-file b/share/scripts/debconf.d/0001-preseed-file index 4fec6b0..d70e4e1 100755 --- a/share/scripts/debconf.d/0001-preseed-file +++ b/share/scripts/debconf.d/0001-preseed-file @@ -15,14 +15,15 @@ # 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 . +# along with this program. If not, see . set -e PROJECT="open-infrastructure" +SOFTWARE="compute-tools" PROGRAM="container" -CONFIG="/etc/${PROJECT}/${PROGRAM}/debconf" +CONFIG="/etc/${SOFTWARE}/debconf" DEBCONF_NOWARNINGS="true" export DEBCONF_NOWARNINGS @@ -43,7 +44,7 @@ then elif [ "$(ls ${CONFIG}/*/${NAME}.cfg 2>/dev/null | wc -l)" -eq 1 ] then # user did not specify a pressed file, but there is 1 (and only 1) - # matching in a sub-directory of /etc/${PROJECT}/${PROGRAM}/debconf + # matching in a sub-directory of /etc/${SOFTWARE}/debconf FILE="$(ls ${CONFIG}/*/${NAME}.cfg)" diff --git a/share/scripts/debconf.d/0002-preseed-debconf b/share/scripts/debconf.d/0002-preseed-debconf index 9bc9fcf..4bc4da6 100755 --- a/share/scripts/debconf.d/0002-preseed-debconf +++ b/share/scripts/debconf.d/0002-preseed-debconf @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e diff --git a/share/scripts/debconf.d/0003-debconf b/share/scripts/debconf.d/0003-debconf index dda3821..c1c4e79 100755 --- a/share/scripts/debconf.d/0003-debconf +++ b/share/scripts/debconf.d/0003-debconf @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e @@ -53,15 +53,15 @@ Distribution () then case "${MODE}" in debian) - db_subst container/distribution CHOICES "Debian GNU/Linux 9 \"stretch\", Debian GNU/Linux 10 \"buster\", Debian GNU/Linux 11 \"bullseye\", Debian GNU/Linux unstable/sid" - db_subst container/distribution CHOICES_C "stretch, buster, bullseye, sid" + db_subst container/distribution CHOICES "Debian GNU/Linux 10 \"buster\", Debian GNU/Linux 11 \"bullseye\", Debian GNU/Linux testing/bookworm, Debian GNU/Linux unstable/sid" + db_subst container/distribution CHOICES_C "buster, bullseye, bookworm, sid" db_set container/distribution bullseye db_fset container/distribution seen false ;; progress-linux) - db_subst container/distribution CHOICES "Progress Linux 5 (engywuck), Progress Linux 5+ (engywuck-backports), Progress Linux 6 (fuchur), Progress Linux 6+ (fuchur-backports)" + db_subst container/distribution CHOICES "Progress Linux 5 (engywuck), Progress Linux 5.99 (engywuck-backports), Progress Linux 6 (fuchur), Progress Linux 6.99 (fuchur-backports)" db_subst container/distribution CHOICES_C "engywuck, engywuck-backports, fuchur, fuchur-backports" db_set container/distribution fuchur-backports @@ -352,7 +352,7 @@ Mirror_security () then case "${MODE}" in debian) - db_set container/mirror-security http://security.debian.org + db_set container/mirror-security https://security.debian.org db_fset container/mirror-security seen false ;; @@ -373,7 +373,7 @@ Mirror_security () then case "${MODE}" in debian) - MIRROR_SECURITY="http://security.debian.org" + MIRROR_SECURITY="https://security.debian.org" ;; *) @@ -445,7 +445,7 @@ Parent_mirror_security () then case "${MODE}" in progress-linux) - db_set container/parent-mirror-security http://security.debian.org + db_set container/parent-mirror-security https://security.debian.org db_fset container/parent-mirror-security seen false db_settitle container/title @@ -466,7 +466,7 @@ Parent_mirror_security () then case "${MODE}" in progress-linux) - PARENT_MIRROR_SECURITY="http://security.debian.org" + PARENT_MIRROR_SECURITY="https://security.debian.org" ;; *) diff --git a/share/scripts/debootstrap b/share/scripts/debootstrap index 98f202b..f0db7e8 100755 --- a/share/scripts/debootstrap +++ b/share/scripts/debootstrap @@ -15,7 +15,7 @@ # 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 . +# along with this program. If not, see . set -e @@ -25,7 +25,7 @@ PROGRAM="container" SCRIPT="$(basename ${0})" -HOOKS="/etc/${PROJECT}/${PROGRAM}/hooks" +HOOKS="/etc/${SOFTWARE}/hooks" MACHINES="/var/lib/machines" Parameters () -- cgit v1.2.3