From 37c135f2cec6113aa2baaf1b52fe46fd64265975 Mon Sep 17 00:00:00 2001 From: Markus Heiser Date: Thu, 27 Feb 2020 19:13:03 +0100 Subject: [PATCH] LXC: improved UX when working with a bunch of containers Signed-off-by: Markus Heiser --- utils/filtron.sh | 2 +- utils/lib.sh | 32 +++++++++---- utils/lxc.sh | 120 ++++++++++++++++++++++++++++++----------------- utils/morty.sh | 2 +- utils/searx.sh | 21 +++++++-- 5 files changed, 122 insertions(+), 55 deletions(-) diff --git a/utils/filtron.sh b/utils/filtron.sh index 56b27dc7..663c2b1d 100755 --- a/utils/filtron.sh +++ b/utils/filtron.sh @@ -257,7 +257,7 @@ filtron_is_installed() { [[ -f $SERVICE_HOME/go-apps/bin/filtron ]] } -_svcpr=" |${SERVICE_USER}| " +_svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} " install_filtron() { rst_title "Install filtron in user's ~/go-apps" section diff --git a/utils/lib.sh b/utils/lib.sh index aeb38e15..47e9e803 100755 --- a/utils/lib.sh +++ b/utils/lib.sh @@ -117,9 +117,9 @@ rst_title() { # usage: rst_title [part|chapter|section] case ${2-chapter} in - part) printf "\n${_BGreen}${1//?/=}\n${_BCyan}${1}${_BGreen}\n${1//?/=}${_creset}\n";; - chapter) printf "\n${_BCyan}${1}\n${_BGreen}${1//?/=}${_creset}\n";; - section) printf "\n${_BCyan}${1}\n${_BGreen}${1//?/-}${_creset}\n";; + part) printf "\n${_BGreen}${1//?/=}${_creset}\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/=}${_creset}\n";; + chapter) printf "\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/=}${_creset}\n";; + section) printf "\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/-}${_creset}\n";; *) err_msg "invalid argument '${2}' in line $(caller)" return 42 @@ -238,7 +238,7 @@ prefix_stdout () { local prefix="${_BYellow}-->|${_creset}" - if [[ -n $1 ]] ; then prefix="${_BYellow}$1${_creset}"; fi + if [[ -n $1 ]] ; then prefix="$1"; fi # shellcheck disable=SC2162 (while IFS= read line; do @@ -294,7 +294,8 @@ backup_file() { # usage: backup_file /path/to/file.foo - local stamp=$(date +"_%Y%m%d_%H%M%S") + local stamp + stamp=$(date +"_%Y%m%d_%H%M%S") info_msg "create backup: ${1}${stamp}" cp -a "${1}" "${1}${stamp}" } @@ -503,7 +504,7 @@ install_go() { # usage: install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}" - local _svcpr=" |${3}| " + local _svcpr=" ${_Yellow}|${3}|${_creset} " rst_title "Install Go in user's HOME" section @@ -1034,17 +1035,32 @@ git_clone() { if [[ -d "${dest}" ]] ; then info_msg "already cloned: $dest" - tee_stderr 0.1 <&1 | prefix_stdout " |$user| " + tee_stderr 0.1 <&1 | prefix_stdout " ${_Yellow}|$user|${_creset} " cd "${dest}" git checkout -m -B "$branch" --track "$remote/$branch" git pull --all EOF else info_msg "clone into: $dest" - tee_stderr 0.1 <&1 | prefix_stdout " |$user| " + tee_stderr 0.1 <&1 | prefix_stdout " ${_Yellow}|$user|${_creset} " mkdir -p "$(dirname "$dest")" cd "$(dirname "$dest")" git clone --branch "$branch" --origin "$remote" "$url" "$(basename "$dest")" EOF fi } + +# containers +# ---------- + +is_container() { + sudo_or_exit + + # usage: is_container && echo "process running inside a LXC container" + # is_container || echo "process is not running inside a LXC container" + # + # hint: Reads init process environment, therefore root access is required! + + # to be safe, take a look at the environment of process 1 (/sbin/init) + grep -qa 'container=lxc' /proc/1/environ +} diff --git a/utils/lxc.sh b/utils/lxc.sh index 58528d59..ab9afcbb 100755 --- a/utils/lxc.sh +++ b/utils/lxc.sh @@ -63,6 +63,12 @@ HOST_USER="${SUDO_USER:-$USER}" HOST_USER_ID=$(id -u "${HOST_USER}") HOST_GROUP_ID=$(id -g "${HOST_USER}") +searx_suite_set_env() { + export FILTRON_API="0.0.0.0:4005" + export FILTRON_LISTEN="0.0.0.0:4004" + export MORTY_LISTEN="0.0.0.0:3000" +} + # ---------------------------------------------------------------------------- usage() { # ---------------------------------------------------------------------------- @@ -74,8 +80,8 @@ usage:: $(basename "$0") build [containers] $(basename "$0") install [searx-suite] $(basename "$0") remove [containers|subordinate] - $(basename "$0") [start|stop] [containers] - $(basename "$0") inspect [info|config] + $(basename "$0") [start|stop] [containers|] + $(basename "$0") show [info|config|searx-suite] $(basename "$0") cmd ... build / remove @@ -83,10 +89,11 @@ build / remove add / remove :subordinate: lxd permission to map ${HOST_USER}'s user/group id through start/stop - :containers: start/stop of all containers -inspect - :info: show info of all containers - :config: show config of all containers + :containers: start/stop of all 'containers' or only +show + :info: show info of all containers + :config: show config of all containers + :searx-suite: show searx-suite services of all containers cmd ... run commandline ... in all containers install @@ -116,22 +123,10 @@ main() { local exit_val local _usage="unknown or missing $1 command $2" - case $1 in - __install) - sudo_or_exit - case $2 in - searx-suite) install_searx_suite ;; - esac - exit - ;; - *) - if ! required_commands lxc; then - lxd_info - exit 42 - fi - ;; - esac - + if [[ ! $1 == __* ]] && ! required_commands lxc; then + lxd_info + exit 42 + fi case $1 in --source-only) ;; -h|--help) usage; exit 0;; @@ -141,20 +136,23 @@ main() { case $2 in containers) build_instances ;; *) usage "$_usage"; exit 42;; - esac ;; + esac + ;; remove) sudo_or_exit case $2 in containers) remove_instances ;; subordinate) echo; del_subordinate_ids ;; *) usage "$_usage"; exit 42;; - esac ;; + esac + ;; add) sudo_or_exit case $2 in subordinate) echo; add_subordinate_ids ;; *) usage "$_usage"; exit 42;; - esac ;; + esac + ;; start|stop) sudo_or_exit case $2 in @@ -163,14 +161,27 @@ main() { info_msg "lxc $1 $2" lxc "$1" "$2" | prefix_stdout "[${_BBlue}${i}${_creset}] " ;; - esac ;; - inspect) + esac + ;; + show) sudo_or_exit case $2 in config) lxc_cmd config show;; info) lxc_cmd info;; + searx-suite) + for i in "${LOCAL_IMAGES[@]}"; do + info_msg "[${_BBlue}${i}${_creset}] ${_BGreen}${LXC_REPO_ROOT}/utils/lxc.sh install $2${_creset}" + lxc exec -t "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __show "$2" | prefix_stdout "[${i}] " + done + ;; *) usage "$_usage"; exit 42;; - esac ;; + esac + ;; + __show) + case $2 in + searx-suite) searx_suite_info ;; + esac + ;; cmd) sudo_or_exit shift @@ -192,30 +203,55 @@ main() { searx-suite) for i in "${LOCAL_IMAGES[@]}"; do info_msg "[${_BBlue}${i}${_creset}] ${_BGreen}${LXC_REPO_ROOT}/utils/lxc.sh install $2${_creset}" - lxc exec "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __install "$2" + lxc exec -t "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __install "$2" | prefix_stdout "[${i}] " done ;; *) usage "$_usage"; exit 42;; - esac ;; + esac + ;; + __install) + case $2 in + searx-suite) searx_suite_install ;; + esac + ;; *) usage "unknown or missing command $1"; exit 42;; esac } -install_searx_suite() { - export FILTRON_API="0.0.0.0:4005" - export FILTRON_LISTEN="0.0.0.0:4004" - export MORTY_LISTEN="0.0.0.0:3000" - FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/searx.sh" install all - FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/morty.sh" install all - FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/filtron.sh" install all - rst_title "[$(hostname)] searx-suite installation finished" part - rst_para "IPs of the container ..." - echo - ip addr show | grep "inet\s*[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" - echo +searx_suite_install() { + ( + searx_suite_set_env + export FORCE_TIMEOUT=0 + "${LXC_REPO_ROOT}/utils/searx.sh" install all + "${LXC_REPO_ROOT}/utils/morty.sh" install all + "${LXC_REPO_ROOT}/utils/filtron.sh" install all + + rst_title "searx-suite installation finished ($(hostname))" part + searx_suite_info + echo + ) } +searx_suite_info() { + ( + searx_suite_set_env + rst_para "Services of the container $(hostname)" + for ip in $(hostname -I); do + echo + if [[ $ip =~ .*:.* ]]; then + : + # IPv6: not yet implemented / tested + # echo " searx (filtron) --> http://[$ip]:4004/" + # echo " morty --> http://[$ip]:3000/" + else + # IPv4: + echo " searx (filtron) --> http://$ip:4004/" + echo " morty --> http://$ip:3000/" + fi + done + ) +} build_instances() { rst_title "Build LXC instances" diff --git a/utils/morty.sh b/utils/morty.sh index fcc9dc72..e7e2f865 100755 --- a/utils/morty.sh +++ b/utils/morty.sh @@ -255,7 +255,7 @@ morty_is_installed() { [[ -f $SERVICE_HOME/go-apps/bin/morty ]] } -_svcpr=" |${SERVICE_USER}| " +_svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} " install_morty() { rst_title "Install morty in user's ~/go-apps" section diff --git a/utils/searx.sh b/utils/searx.sh index 270c30ac..c435b5c0 100755 --- a/utils/searx.sh +++ b/utils/searx.sh @@ -210,7 +210,7 @@ main() { esac } -_service_prefix=" |$SERVICE_USER| " +_service_prefix=" ${_Yellow}|$SERVICE_USER|${_creset} " install_all() { rst_title "Install $SEARX_INSTANCE_NAME (service)" @@ -352,7 +352,7 @@ install_settings() { sudo -H -i rst_para 'Diff between new setting file (-) and current (+):' echo - $DIFF_CMD "${SEARX_SRC}/searx/settings.yml" "${SEARX_SETTINGS_PATH}" + $DIFF_CMD "${SEARX_SRC}/searx/settings.yml" "${SEARX_SETTINGS_PATH}" wait_key ;; esac @@ -440,7 +440,7 @@ test_local_searx() { fi sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH" tee_stderr 0.1 <&1 | prefix_stdout "$_service_prefix" -export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}" +export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}" cd ${SEARX_SRC} timeout 10 python3 searx/webapp.py & sleep 3 @@ -537,6 +537,18 @@ EOF uWSGI_app_available "$SEARX_UWSGI_APP" \ || err_msg "uWSGI app $SEARX_UWSGI_APP not available!" + if is_container; then + warn_msg "runnning inside container ..." + for ip in $(hostname -I); do + if [[ $ip =~ .*:.* ]]; then + info_msg " public HTTP service (IPv6) --> http://[$ip]" + else + info_msg " public HTTP service (IPv4) --> http://$ip" + fi + done + warn_msg "SEARX_INTERNAL_URL not available from outside" + fi + if ! service_is_available "http://${SEARX_INTERNAL_URL}"; then err_msg "uWSGI app (service) at http://${SEARX_INTERNAL_URL} is not available!" echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .." @@ -545,6 +557,9 @@ EOF if ! service_is_available "${PUBLIC_URL}"; then warn_msg "Public service at ${PUBLIC_URL} is not available!" + if is_container; then + warn_msg "Check if public name is correct and routed or use the public IP from above." + fi fi local _debug_on