diff options
Diffstat (limited to 'libexec/container/list')
-rwxr-xr-x | libexec/container/list | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/libexec/container/list b/libexec/container/list new file mode 100755 index 0000000..ba794ab --- /dev/null +++ b/libexec/container/list @@ -0,0 +1,439 @@ +#!/bin/sh + +# Copyright (C) 2014-2021 Daniel Baumann <daniel.baumann@open-infrastructure.net> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +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> + <name>${CONTAINER}</name> + <address>${ADDRESS}</address> + </container> +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 +<compute-tools> + <version>${VERSION}</version> +</compute-tools> +<host> + <name>${HOST}</name> +</host> +<containers> +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 +</containers> +EOF + + ;; +esac + +# Post hooks +for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}" +do + if [ -x "${FILE}" ] + then + "${FILE}" + fi +done |