From 50d4e91c572290cb1447795f2b1e09c3bf0458c2 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 28 Jun 2023 14:22:55 +0300 Subject: [PATCH] added more scripts + cleanup... Signed-off-by: Alex A. Naanou --- .pct-helpers | 84 ++++++++++++++++++++++++++++++++++++++++ check-status | 18 +++++++-- make-shares | 51 ++++++++++++++++++++++++ pct-mclone | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ update-status | 59 ++++++++++++++++------------ 5 files changed, 289 insertions(+), 28 deletions(-) create mode 100644 .pct-helpers create mode 100644 make-shares create mode 100644 pct-mclone diff --git a/.pct-helpers b/.pct-helpers new file mode 100644 index 0000000..b74b04d --- /dev/null +++ b/.pct-helpers @@ -0,0 +1,84 @@ +#!/usr/bin/bash +#---------------------------------------------------------------------- + +#---------------------------------------------------------------------- +#QUIET= +#DRY_RUN= +@(){ + if [ -z $DRY_RUN ] ; then + ! [ $QUIET ] \ + && echo "### $@" + $@ + else + echo $@ + fi +} + + +#---------------------------------------------------------------------- +# get CT hostname... +cthostname(){ + local ct=${CT_DIR}/${id}.conf + local host=$(cat $ct | grep hostname | head -1) + echo ${host/hostname: /} +} + + +#---------------------------------------------------------------------- +fillsection(){ ( + usage(){ + echo "Usage:" + echo " ${FUNCNAME[0]} [-h]" + echo " ${FUNCNAME[0]} [-r] NAME FILE [CONTENT]" + echo + } + while true ; do + case $1 in + -h|--help) + usage + echo "Options:" + # . . . + echo " -h | --help print this help message and exit." + echo " -r | --return replace section markers with CONTENT." + echo + return 0 + ;; + -r|--replace) + local replace=1 + shift + ;; + + *) + break + ;; + esac + done + if [[ $# < 2 ]] ; then + usage + return 1 + fi + + name=$1 + file=$2 + content=$3 + content=${content:=/dev/stdin} + + # print file upto section marker... + if [ $replace ] ; then + sed "/${name^^} BEGIN/q" "$file" | sed '$d' + else + sed "/${name^^} BEGIN/q" "$file" + fi + # print content... + cat $content + # print file from section end marker... + if [ $replace ] ; then + sed -ne "/${name^^} END/,$ p" "$file" | sed '1d' + else + sed -ne "/${name^^} END/,$ p" "$file" + fi +) } + + +#---------------------------------------------------------------------- +# vim:set ts=4 sw=4 nowrap : diff --git a/check-status b/check-status index 0a485f5..3863bd9 100644 --- a/check-status +++ b/check-status @@ -3,6 +3,12 @@ IFS=$'\n' SITES=("$@") +TIMEOUT=${TIMEOUT:=10} +TRIES=${TRIES:=2}3 +SAFE=${SAFE:=1} + +OK_STATUS='2[0-9][0-9]|30[1-9]|401|501' + check(){ local comment=`sed \ -e 's/^\(.*\)https\?:\/\/.*$/\1/' \ @@ -17,9 +23,13 @@ check(){ # nmap $target -Pn -p ssh | grep open # http/https - local safe=--no-check-certificate + if [ $SAFE ] ; then + local safe=--no-check-certificate + else + local safe + fi local response=$(\ - wget -S --spider $safe $target 2>&1 \ + wget -S --spider -T $TIMEOUT --tries=$TRIES $safe $target 2>&1 \ | awk '/HTTP\// {print $2}' ) echo "COMMENT=$comment" @@ -28,6 +38,7 @@ check(){ } problems= +status_pattern="\(${OK_STATUS//|/\\|}\)" for site in ${SITES[@]} ; do IFS=$'\n' \ res=($(check "$site")) @@ -39,7 +50,8 @@ for site in ${SITES[@]} ; do ! [ -z $comment ] \ && comment="$comment " - if [ $(grep '\(2[0-9][0-9]\|30[1-9]\|401\|501\)' <<<$res) ] ; then + #if [ $(grep '\(2[0-9][0-9]\|30[1-9]\|401\|501\)' <<<$res) ] ; then + if [ $(grep "$status_pattern" <<<$res) ] ; then state=OK else state="ERROR ($res)" diff --git a/make-shares b/make-shares new file mode 100644 index 0000000..84321dd --- /dev/null +++ b/make-shares @@ -0,0 +1,51 @@ +#!/usr/bin/bash + +source ./.pct-helpers + +# config... +CT_DIR=/etc/pve/lxc/ +SHARE_ROOT=/media/shared/ + +SYNCTHING=syncthing +SYNCTHING_DIR=/home/syncthing/Proxmox + +# normalize... +SHARE_ROOT=${SHARE_ROOT%/} + + +# create base shared directory... +if ! [ -d "${SHARE_ROOT}/$(hostname)" ] ; then + @ mkdir -p "${SHARE_ROOT}/$(hostname)" + @ chmod 777 "${SHARE_ROOT}" +fi + +# mount ct shares... +for ct in $CT_DIR/*.conf ; do + id=$(basename ${ct/.conf/}) + + host=$(cat $ct | grep hostname | head -1) + host=${host/hostname: /} + + # skip templates... + if [ "$(cat $ct | grep 'template: 1')" != "" ] ; then + continue + fi + + # mount... + # NOTE: we are not taking care of the actual mount numbers here... + if [[ "$(cat $ct | grep "mp[0-9]:.*${SHARE_ROOT}/${host}" | wc -l)" = 0 ]] ; then + if ! [ -e ${SHARE_ROOT}/${host} ] ; then + @ mkdir -p ${SHARE_ROOT}/${host} + fi + @ pct set $id -mp0 ${SHARE_ROOT}/${host},mp=/mnt/shared,backup=0 + fi + + # special case: syncthing... + if [ -n $SYNCTHING ] && [ "$host" = "$SYNCTHING" ] ; then + if [[ "$(cat $ct | grep "mp[0-9]:.*mp=$SYNCTHING_DIR" | wc -l)" = 0 ]] ; then + @ pct set $id -mp1 ${SHARE_ROOT},mp=$SYNCTHING_DIR,backup=0 + fi + fi +done + +# vim:set ts=4 sw=4 nowrap : diff --git a/pct-mclone b/pct-mclone new file mode 100644 index 0000000..711d931 --- /dev/null +++ b/pct-mclone @@ -0,0 +1,105 @@ +#!/usr/bin/bash +#---------------------------------------------------------------------- +# +#---------------------------------------------------------------------- + +source ./.pct-helpers + + +# config... +CT_DIR=/etc/pve/lxc/ +SHARE_ROOT=/media/shared/ + + +# XXX better argument handling / help... +id=$1 +to=$2 +tpl=$3 + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +ct=${CT_DIR}/${id}.conf +host=$(cthostname $id) +running=$(pct list | grep "running\s*$host\s*$") + + +#---------------------------------------------------------------------- +# checks... + +# error checking... +if [ -z $id ] || [ -z $to ] ; then + echo ERR need both id and target id + exit 1 +fi +if [ $id = $to ] ; then + echo ERR need id and target id must be different + exit 1 +fi + +if ! [ -e $ct ] ; then + echo ERR $ct does not exist. + exit 1 +fi +if [ -e ${CT_DIR}/${to}.conf ] ; then + echo ERR $to already exists. + exit 1 +fi +if ! [ -z $tpl ] && [ -e ${CT_DIR}/${tpl}.conf ] ; then + echo ERR $to already exists. + exit 1 +fi + +# check mount points... +IFS=$'\n' mounts=($(cat $ct | grep 'mp[0-9]*:')) +# check... +for mp in ${mounts[@]} ; do + if ! [ $(grep ": $SHARE_ROOT" <<< $mp) ] ; then + echo "ERR mountpoint: \"$mp\" heeds to handled manually." + exit 1 + fi +done + + +#---------------------------------------------------------------------- +# after this point we are making changes... + +# need to shutdown to clone... +# XXX might be a good idea to also do this with a snapshot... +if ! [ -z $running ] ; then + @ pct shutdown $id +fi + + +# delete mount points... +for mp in ${mounts[@]} ; do + @ pct set ${id} -delete ${mp/: */} +done + + +# clone... +@ pct clone ${id} ${to} --hostname ${host} +@ pct set ${to} -onboot 0 +@ ./make-shares + + +# startup if we stopped... +if ! [ -z $running ] ; then + @ pct start $id +fi + + +#---------------------------------------------------------------------- +# after this point are are not affecting uptime... + +# make template... +if ! [ -z $tpl ] ; then + @ pct clone ${to} ${tpl} --hostname ${host} + @ pct template ${tpl} +fi + +@ ./make-shares + + +#---------------------------------------------------------------------- +# vim:set ts=4 sw=4 nowrap : diff --git a/update-status b/update-status index 41d152e..48ffed2 100644 --- a/update-status +++ b/update-status @@ -1,63 +1,72 @@ #!/usr/bin/bash - -TEXT_TARGET=/media/shared/status - -CONFIG=/etc/pve/nodes/pve/config - -TMP_TARGET=${CONFIG}.new-status - -TARGET=${TARGET:=${TMP_TARGET}} +source .pct-helpers +TEXT_STATUS=${TEXT_STATUS:=/media/shared/status} -DATE=``date +'%Y-%m-%d %H:%M'` +CONFIG=${CONFIG:=/etc/pve/nodes/pve/config} -if [ -e $TMP_TARGET ] ; then - rm -f $TMP_TARGET +# NOTE: since proxmox monitors files, it is better modify the file in +# one go but since checking can not be done in an instant we write +# the check results to $TMP_RESULTS and when done will swap it with +# $CONFIG... +# XXX move this to /tmp??? +TMP_RESULTS=${TMP_RESULTS:=${CONFIG}.live} + + + +DATE=`date +'%Y-%m-%d %H:%M'` + + +if [ -e $TMP_RESULTS ] ; then + rm -f $TMP_RESULTS fi -if [ -e $TEXT_TARGET ] ; then - mv -f $TEXT_TARGET{,.old} - echo $DATE > $TEXT_TARGET +if [ -e $TEXT_STATUS ] ; then + mv -f $TEXT_STATUS{,.old} + echo $DATE > $TEXT_STATUS else - TEXT_TARGET=/dev/null + TEXT_STATUS=/dev/null fi + +# read the sites from the status section in $CONFIG... IFS=$'\n' \ SITES=($(\ sed -n '/STATUS BEGIN/,/STATUS END/p' "$CONFIG" \ | sed \ -e '1d;$d' \ -e 's/^#//' \ - -e 's/^- //' \ -e 's/^\**//' \ -e 's/%3A/:/g' \ -e 's/ : .*//' \ | grep 'http')) + +# fill the status section -> $TMP_RESULTS... cp -f "$CONFIG" "$CONFIG".bak { - sed '/STATUS BEGIN/q' "$CONFIG" | sed '$d' echo '#' - for site in "${SITES[@]}" ; do ./check-status "$site" \ - | tee -a $TEXT_TARGET \ + | tee -a $TEXT_STATUS \ | sed \ -e 's/^\s*\(.*ERROR.*$\)/**\1**/' \ - -e 's/^/#- /' \ + -e 's/^/#/' \ -e 's/$/\n#/' done echo "#_(checked on: ${DATE})_" - echo '#' - sed -ne '/STATUS END/,$ p' "$CONFIG" | sed '1d' -} > "$TARGET" +} \ + | fillsection -r STATUS ${CONFIG} \ + > "$TMP_RESULTS" -if [ -e $TMP_TARGET ] ; then - mv -f "$TMP_TARGET" "$CONFIG" + +# replace $TMP_RESULTS -> $CONFIG +if [ -e $TMP_RESULTS ] ; then + mv -f "$TMP_RESULTS" "$CONFIG" fi