on master help sign in
LXC: improved UX when working with a bunch of containers

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>

commit37c135f2cec6113aa2baaf1b52fe46fd64265975 authorMarkus Heiser <markus.heiser@darmarit.de> dateThu 27 Feb 2020, 19:13 (7 years ago) parentaf6acd3
5 files changed+122−55
utils/filtron.sh+1−1 utils/lib.sh+24−8 utils/lxc.sh+78−42 utils/morty.sh+1−1 utils/searx.sh+18−3
utils/filtron.sh+1−1
@@ -257,7 +257,7 @@ filtron_is_installed() {
257257 [[ -f $SERVICE_HOME/go-apps/bin/filtron ]]
258258}
259259
260−_svcpr=" |${SERVICE_USER}| "
260+_svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} "
261261
262262install_filtron() {
263263 rst_title "Install filtron in user's ~/go-apps" section
utils/lib.sh+24−8
@@ -117,9 +117,9 @@ rst_title() {
117117 # usage: rst_title <header-text> [part|chapter|section]
118118
119119 case ${2-chapter} in
120− part) printf "\n${_BGreen}${1//?/=}\n${_BCyan}${1}${_BGreen}\n${1//?/=}${_creset}\n";;
121− chapter) printf "\n${_BCyan}${1}\n${_BGreen}${1//?/=}${_creset}\n";;
122− section) printf "\n${_BCyan}${1}\n${_BGreen}${1//?/-}${_creset}\n";;
120+ part) printf "\n${_BGreen}${1//?/=}${_creset}\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/=}${_creset}\n";;
121+ chapter) printf "\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/=}${_creset}\n";;
122+ section) printf "\n${_BCyan}${1}${_creset}\n${_BGreen}${1//?/-}${_creset}\n";;
123123 *)
124124 err_msg "invalid argument '${2}' in line $(caller)"
125125 return 42
@@ -238,7 +238,7 @@ prefix_stdout () {
238238
239239 local prefix="${_BYellow}-->|${_creset}"
240240
241− if [[ -n $1 ]] ; then prefix="${_BYellow}$1${_creset}"; fi
241+ if [[ -n $1 ]] ; then prefix="$1"; fi
242242
243243 # shellcheck disable=SC2162
244244 (while IFS= read line; do
@@ -294,7 +294,8 @@ backup_file() {
294294
295295 # usage: backup_file /path/to/file.foo
296296
297− local stamp=$(date +"_%Y%m%d_%H%M%S")
297+ local stamp
298+ stamp=$(date +"_%Y%m%d_%H%M%S")
298299 info_msg "create backup: ${1}${stamp}"
299300 cp -a "${1}" "${1}${stamp}"
300301}
@@ -503,7 +504,7 @@ install_go() {
503504
504505 # usage: install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}"
505506
506− local _svcpr=" |${3}| "
507+ local _svcpr=" ${_Yellow}|${3}|${_creset} "
507508
508509 rst_title "Install Go in user's HOME" section
509510
@@ -1034,17 +1035,32 @@ git_clone() {
10341035
10351036 if [[ -d "${dest}" ]] ; then
10361037 info_msg "already cloned: $dest"
1037− tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 | prefix_stdout " |$user| "
1038+ tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 | prefix_stdout " ${_Yellow}|$user|${_creset} "
10381039cd "${dest}"
10391040git checkout -m -B "$branch" --track "$remote/$branch"
10401041git pull --all
10411042EOF
10421043 else
10431044 info_msg "clone into: $dest"
1044− tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 | prefix_stdout " |$user| "
1045+ tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 | prefix_stdout " ${_Yellow}|$user|${_creset} "
10451046mkdir -p "$(dirname "$dest")"
10461047cd "$(dirname "$dest")"
10471048git clone --branch "$branch" --origin "$remote" "$url" "$(basename "$dest")"
10481049EOF
10491050 fi
10501051}
1052+
1053+# containers
1054+# ----------
1055+
1056+is_container() {
1057+ sudo_or_exit
1058+
1059+ # usage: is_container && echo "process running inside a LXC container"
1060+ # is_container || echo "process is not running inside a LXC container"
1061+ #
1062+ # hint: Reads init process environment, therefore root access is required!
1063+
1064+ # to be safe, take a look at the environment of process 1 (/sbin/init)
1065+ grep -qa 'container=lxc' /proc/1/environ
1066+}
utils/lxc.sh+78−42
@@ -63,6 +63,12 @@ HOST_USER="${SUDO_USER:-$USER}"
6363HOST_USER_ID=$(id -u "${HOST_USER}")
6464HOST_GROUP_ID=$(id -g "${HOST_USER}")
6565
66+searx_suite_set_env() {
67+ export FILTRON_API="0.0.0.0:4005"
68+ export FILTRON_LISTEN="0.0.0.0:4004"
69+ export MORTY_LISTEN="0.0.0.0:3000"
70+}
71+
6672# ----------------------------------------------------------------------------
6773usage() {
6874# ----------------------------------------------------------------------------
@@ -74,8 +80,8 @@ usage::
7480 $(basename "$0") build [containers]
7581 $(basename "$0") install [searx-suite]
7682 $(basename "$0") remove [containers|subordinate]
77− $(basename "$0") [start|stop] [containers]
78− $(basename "$0") inspect [info|config]
83+ $(basename "$0") [start|stop] [containers|<container-name>]
84+ $(basename "$0") show [info|config|searx-suite]
7985 $(basename "$0") cmd ...
8086
8187build / remove
@@ -83,10 +89,11 @@ build / remove
8389add / remove
8490 :subordinate: lxd permission to map ${HOST_USER}'s user/group id through
8591start/stop
86− :containers: start/stop of all containers
87−inspect
88− :info: show info of all containers
89− :config: show config of all containers
92+ :containers: start/stop of all 'containers' or only <container-name>
93+show
94+ :info: show info of all containers
95+ :config: show config of all containers
96+ :searx-suite: show searx-suite services of all containers
9097cmd ...
9198 run commandline ... in all containers
9299install
@@ -116,22 +123,10 @@ main() {
116123 local exit_val
117124 local _usage="unknown or missing $1 command $2"
118125
119− case $1 in
120− __install)
121− sudo_or_exit
122− case $2 in
123− searx-suite) install_searx_suite ;;
124− esac
125− exit
126− ;;
127− *)
128− if ! required_commands lxc; then
129− lxd_info
130− exit 42
131− fi
132− ;;
133− esac
134−
126+ if [[ ! $1 == __* ]] && ! required_commands lxc; then
127+ lxd_info
128+ exit 42
129+ fi
135130 case $1 in
136131 --source-only) ;;
137132 -h|--help) usage; exit 0;;
@@ -141,20 +136,23 @@ main() {
141136 case $2 in
142137 containers) build_instances ;;
143138 *) usage "$_usage"; exit 42;;
144− esac ;;
139+ esac
140+ ;;
145141 remove)
146142 sudo_or_exit
147143 case $2 in
148144 containers) remove_instances ;;
149145 subordinate) echo; del_subordinate_ids ;;
150146 *) usage "$_usage"; exit 42;;
151− esac ;;
147+ esac
148+ ;;
152149 add)
153150 sudo_or_exit
154151 case $2 in
155152 subordinate) echo; add_subordinate_ids ;;
156153 *) usage "$_usage"; exit 42;;
157− esac ;;
154+ esac
155+ ;;
158156 start|stop)
159157 sudo_or_exit
160158 case $2 in
@@ -163,14 +161,27 @@ main() {
163161 info_msg "lxc $1 $2"
164162 lxc "$1" "$2" | prefix_stdout "[${_BBlue}${i}${_creset}] "
165163 ;;
166− esac ;;
167− inspect)
164+ esac
165+ ;;
166+ show)
168167 sudo_or_exit
169168 case $2 in
170169 config) lxc_cmd config show;;
171170 info) lxc_cmd info;;
171+ searx-suite)
172+ for i in "${LOCAL_IMAGES[@]}"; do
173+ info_msg "[${_BBlue}${i}${_creset}] ${_BGreen}${LXC_REPO_ROOT}/utils/lxc.sh install $2${_creset}"
174+ lxc exec -t "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __show "$2" | prefix_stdout "[${i}] "
175+ done
176+ ;;
172177 *) usage "$_usage"; exit 42;;
173− esac ;;
178+ esac
179+ ;;
180+ __show)
181+ case $2 in
182+ searx-suite) searx_suite_info ;;
183+ esac
184+ ;;
174185 cmd)
175186 sudo_or_exit
176187 shift
@@ -192,30 +203,55 @@ main() {
192203 searx-suite)
193204 for i in "${LOCAL_IMAGES[@]}"; do
194205 info_msg "[${_BBlue}${i}${_creset}] ${_BGreen}${LXC_REPO_ROOT}/utils/lxc.sh install $2${_creset}"
195− lxc exec "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __install "$2"
206+ lxc exec -t "${i}" -- "${LXC_REPO_ROOT}/utils/lxc.sh" __install "$2" | prefix_stdout "[${i}] "
196207 done
197208 ;;
198209 *) usage "$_usage"; exit 42;;
199− esac ;;
210+ esac
211+ ;;
212+ __install)
213+ case $2 in
214+ searx-suite) searx_suite_install ;;
215+ esac
216+ ;;
200217 *)
201218 usage "unknown or missing command $1"; exit 42;;
202219 esac
203220}
204221
205−install_searx_suite() {
206− export FILTRON_API="0.0.0.0:4005"
207− export FILTRON_LISTEN="0.0.0.0:4004"
208− export MORTY_LISTEN="0.0.0.0:3000"
209− FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/searx.sh" install all
210− FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/morty.sh" install all
211− FORCE_TIMEOUT=0 "${LXC_REPO_ROOT}/utils/filtron.sh" install all
212− rst_title "[$(hostname)] searx-suite installation finished" part
213− rst_para "IPs of the container ..."
214− echo
215− ip addr show | grep "inet\s*[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"
216− echo
222+searx_suite_install() {
223+ (
224+ searx_suite_set_env
225+ export FORCE_TIMEOUT=0
226+ "${LXC_REPO_ROOT}/utils/searx.sh" install all
227+ "${LXC_REPO_ROOT}/utils/morty.sh" install all
228+ "${LXC_REPO_ROOT}/utils/filtron.sh" install all
229+
230+ rst_title "searx-suite installation finished ($(hostname))" part
231+ searx_suite_info
232+ echo
233+ )
217234}
218235
236+searx_suite_info() {
237+ (
238+ searx_suite_set_env
239+ rst_para "Services of the container $(hostname)"
240+ for ip in $(hostname -I); do
241+ echo
242+ if [[ $ip =~ .*:.* ]]; then
243+ :
244+ # IPv6: not yet implemented / tested
245+ # echo " searx (filtron) --> http://[$ip]:4004/"
246+ # echo " morty --> http://[$ip]:3000/"
247+ else
248+ # IPv4:
249+ echo " searx (filtron) --> http://$ip:4004/"
250+ echo " morty --> http://$ip:3000/"
251+ fi
252+ done
253+ )
254+}
219255
220256build_instances() {
221257 rst_title "Build LXC instances"
utils/morty.sh+1−1
@@ -255,7 +255,7 @@ morty_is_installed() {
255255 [[ -f $SERVICE_HOME/go-apps/bin/morty ]]
256256}
257257
258−_svcpr=" |${SERVICE_USER}| "
258+_svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} "
259259
260260install_morty() {
261261 rst_title "Install morty in user's ~/go-apps" section
utils/searx.sh+18−3
@@ -210,7 +210,7 @@ main() {
210210 esac
211211}
212212
213−_service_prefix=" |$SERVICE_USER| "
213+_service_prefix=" ${_Yellow}|$SERVICE_USER|${_creset} "
214214
215215install_all() {
216216 rst_title "Install $SEARX_INSTANCE_NAME (service)"
@@ -352,7 +352,7 @@ install_settings() {
352352 sudo -H -i
353353 rst_para 'Diff between new setting file (-) and current (+):'
354354 echo
355− $DIFF_CMD "${SEARX_SRC}/searx/settings.yml" "${SEARX_SETTINGS_PATH}"
355+ $DIFF_CMD "${SEARX_SRC}/searx/settings.yml" "${SEARX_SETTINGS_PATH}"
356356 wait_key
357357 ;;
358358 esac
@@ -440,7 +440,7 @@ test_local_searx() {
440440 fi
441441 sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"
442442 tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
443−export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}"
443+export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}"
444444cd ${SEARX_SRC}
445445timeout 10 python3 searx/webapp.py &
446446sleep 3
@@ -537,6 +537,18 @@ EOF
537537 uWSGI_app_available "$SEARX_UWSGI_APP" \
538538 || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"
539539
540+ if is_container; then
541+ warn_msg "runnning inside container ..."
542+ for ip in $(hostname -I); do
543+ if [[ $ip =~ .*:.* ]]; then
544+ info_msg " public HTTP service (IPv6) --> http://[$ip]"
545+ else
546+ info_msg " public HTTP service (IPv4) --> http://$ip"
547+ fi
548+ done
549+ warn_msg "SEARX_INTERNAL_URL not available from outside"
550+ fi
551+
540552 if ! service_is_available "http://${SEARX_INTERNAL_URL}"; then
541553 err_msg "uWSGI app (service) at http://${SEARX_INTERNAL_URL} is not available!"
542554 echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .."
@@ -545,6 +557,9 @@ EOF
545557
546558 if ! service_is_available "${PUBLIC_URL}"; then
547559 warn_msg "Public service at ${PUBLIC_URL} is not available!"
560+ if is_container; then
561+ warn_msg "Check if public name is correct and routed or use the public IP from above."
562+ fi
548563 fi
549564
550565 local _debug_on