proxmox-utils/.pct-helpers
Alex A. Naanou f45338142f tweaks...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-07 16:34:47 +03:00

404 lines
7.7 KiB
Bash

#!/usr/bin/bash
#----------------------------------------------------------------------
CT_DIR=${CT_DIR:=/etc/pve/lxc/}
#----------------------------------------------------------------------
# XXX this is quite generic, might be a good idea to move this to a
# seporate lib/file...
# Execute (optionally) and print a command.
#
#QUIET=
#DRY_RUN=
ECHO_PREFIX="### "
@(){
if [ -z $DRY_RUN ] ; then
! [ $QUIET ] \
&& echo "${ECHO_PREFIX}$@"
$@
else
echo $@
fi
return $?
}
#----------------------------------------------------------------------
# Fill section...
#
# XXX this is quite generic -- move to a more logical place...
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
) }
#----------------------------------------------------------------------
# CT hostname <-> CT id...
ct2hostname(){
local ct=${CT_DIR}/${1}.conf
local host=$(cat $ct | grep hostname | head -1)
echo ${host/hostname: /}
}
hostname2ct(){
if [ -e "${CT_DIR}/${1}.conf" ] ; then
echo $1
fi
local running=$2
running=${running:=any}
local ct
local host
for ct in "${CT_DIR}"/*.conf ; do
host=$(cat $ct | grep hostname | head -1)
host=${host/hostname: /}
if [ "$host" = $1 ] ; then
ct=${ct#${CT_DIR}}
ct=${ct%.conf}
ct=${ct#\/}
# filter results if needed...
if [ $running = "any" ] ; then
echo $ct
else
local status=`pct status $ct`
if [ "$running" = "${status/status: /}" ] ; then
echo $ct
fi
fi
fi
done
}
#----------------------------------------------------------------------
normpath(){
echo $1 \
| sed \
-e 's/\/\+/\//g' \
-e 's/\/.\//\//g' \
-e 's/[^\/]\+\/\.\.//g' \
-e 's/\/\+/\//g' \
-e 's/\/\.$/\//g'
}
#----------------------------------------------------------------------
#
# getLatestTemplate PATTERN [VAR]
#
# see:
# https://pve.proxmox.com/wiki/Linux_Container
getLatestTemplate(){
#IFS=$'\n'
@ pveam update
local templates=($(pveam available | grep -o ''${1}'.*$'))
local latest=${templates[-1]}
@ pveam download local ${latest}
latest=$(pveam list local | grep -o "^.*$latest")
#latest=($(ls /var/lib/vz/template/cache/${1}*))
[ -z $2 ] \
|| eval "$2=${latest}"
}
#
# xread [-n] MSG VAR
#
xread(){
local non_empty=
if [[ $1 == '-n' ]] ; then
shift
local non_empty=1
fi
[ -z ${!2} ] \
&& eval 'read -ep "'$1'" -i "$DFL_'$2'" '${2}''
if [ -z $non_empty ] ; then
eval ''$2'=${'$2':=$DFL_'$2'}'
fi
[ $SCRIPTING ] \
&& echo "$2=${!2}"
}
#
# xreadpass VAR
#
xreadpass(){
local PASS1
local PASS2
read -sep "password (Enter to skip): " PASS1
echo
if [ $PASS1 ] ; then
read -sep "retype password: " PASS2
echo
if [[ $PASS1 != $PASS2 ]] ; then
echo "ERR: passwords do not match."
return 1
fi
eval ''$1'='${PASS1}''
fi
}
#
# readConfig
#
readConfig(){
if [ -z $NO_DEFAULTS ] ; then
[ -e ../config.global ] \
&& source ../config.global
[ -e ./config ] \
&& source ./config
fi
}
#
# readVars
#
# Variables this handles:
# EMAIL
# DOMAIN
# ID
# CTHOSTNAME
# WAN_BRIDGE
# LAN_BRIDGE
# ADMIN_BRIDGE
# WAN_IP
# WAN_GATE
# LAN_IP
# LAN_GATE
# ADMIN_IP
# ADMIN_GATE
# ROOTPASS
# PCT_EXTRA
#
# Variables this sets:
# PASS
#
# Variables used:
# TMP_PASS_LEN
# ROOTPASS
#
readVars(){
xread -n "Email: " EMAIL
xread -n "Domain: " DOMAIN
xread "ID: " ID
xread "Hostname: " CTHOSTNAME
# hardware...
xread "CPU cores: " CORES
xread "RAM (MB): " RAM
xread "SWAP (MB): " SWAP
xread "DRIVE (GB): " DRIVE
# bridge config...
xread "WAN bridge: vmbr" WAN_BRIDGE
xread "LAN bridge: vmbr" LAN_BRIDGE
xread "ADMIN bridge: vmbr" ADMIN_BRIDGE
# gateway...
# IPs can be:
# <empty>
# <IP>/<mask>
# dhcp
# Gateways can be:
# <empty>
# <IP>
xread "WAN ip: " WAN_IP
xread "WAN gateway: " WAN_GATE
xread "LAN ip: " LAN_IP
xread "LAN gateway: " LAN_GATE
xread "ADMIN ip: " ADMIN_IP
xread "ADMIN gateway: " ADMIN_GATE
# root password...
if [ -z $ROOTPASS ] ; then
xreadpass PASS \
|| exit 1
else
PASS=$ROOTPASS
fi
# extra stuff...
xread "pct extra options: " PCT_EXTRA
}
#
# buildAssets [TEMPLATES [ASSETS]]
#
buildAssets(){
local TEMPLATE_DIR=$1
TEMPLATE_DIR=${TEMPLATE_DIR:=templates}
local ASSETS_DIR=$2
ASSETS_DIR=${ASSETS_DIR:=assets}
local TEMPLATES=($(find "$TEMPLATE_DIR" -type f))
for file in "${TEMPLATES[@]}" ; do
file=${file#${TEMPLATE_DIR}}
echo Generating: ${file}...
[ $DRY_RUN ] \
&& continue
# ensure the directory exists...
mkdir -p "$(dirname "${ASSETS_DIR}/${file}")"
cat "${TEMPLATE_DIR}/${file}" \
| sed \
-e 's/\${EMAIL}/'${EMAIL/\//\\/}'/g' \
-e 's/\${DOMAIN}/'${DOMAIN/\//\\/}'/g' \
-e 's/\${CTHOSTNAME}/'${CTHOSTNAME/\//\\/}'/g' \
-e 's/\${GATE_HOSTNAME}/'${GATE_HOSTNAME/\//\\/}'/g' \
-e 's/\${NS_HOSTNAME}/'${NS_HOSTNAME/\//\\/}'/g' \
-e 's/\${GATE_LAN_IP}/'${GATE_LAN_IP/\//\\/}'/g' \
-e 's/\${GATE_LAN_IPn}/'${GATE_LAN_IP/\/*}'/g' \
-e 's/\${GATE_ADMIN_IP}/'${GATE_ADMIN_IP/\//\\/}'/g' \
-e 's/\${GATE_ADMIN_IPn}/'${GATE_ADMIN_IP/\/*}'/g' \
-e 's/\${NS_LAN_IP}/'${NS_LAN_IP/\//\\/}'/g' \
-e 's/\${NS_LAN_IPn}/'${NS_LAN_IP/\/*}'/g' \
-e 's/\${NS_ADMIN_IP}/'${NS_ADMIN_IP/\//\\/}'/g' \
-e 's/\${NS_ADMIN_IPn}/'${NS_ADMIN_IP/\/*}'/g' \
-e 's/\${WAN_IP}/'${WAN_IP/\//\\/}'/g' \
-e 's/\${WAN_IPn}/'${WAN_IP/\/*}'/g' \
-e 's/\${WAN_GATE}/'${WAN_GATE/\//\\/}'/g' \
-e 's/\${LAN_IP}/'${LAN_IP/\//\\/}'/g' \
-e 's/\${LAN_IPn}/'${LAN_IP/\/*}'/g' \
-e 's/\${LAN_GATE}/'${LAN_GATE/\//\\/}'/' \
-e 's/\${ADMIN_IP}/'${ADMIN_IP/\//\\/}'/g' \
-e 's/\${ADMIN_IPn}/'${ADMIN_IP/\/*}'/g' \
-e 's/\${ADMIN_GATE}/'${ADMIN_GATE/\//\\/}'/g' \
> "${ASSETS_DIR}/${file}"
done
}
#
# pctCreate ID TEMPLATE ARGS [PASS]
#
pctCreate(){
local TMP_PASS=$(cat /dev/urandom | base64 | head -c ${TMP_PASS_LEN:=32})
# NOTE: we are not setting the password here to avoid printing it to the terminal...
@ pct create $1 \
${2} \
${3} \
--password="$TMP_PASS" \
--start 1 \
|| exit 1
# set actual root password...
if [ "$4" ] ; then
echo "root:$4" \
| @ lxc-attach $1 chpasswd
fi
}
#
# pctCreate<distro> ID ARGS [PASS]
#
pctCreateAlpine(){
local TEMPLATE
getLatestTemplate alpine TEMPLATE
pctCreate $1 "$TEMPLATE" "$2" "$3"
sleep ${TIMEOUT:=5}
@ lxc-attach $1 apk update
@ lxc-attach $1 apk upgrade
}
pctCreateDebian(){
local TEMPLATE
getLatestTemplate 'debian-12-standard' TEMPLATE
pctCreate $1 "$TEMPLATE" "$2" "$3"
sleep ${TIMEOUT:=5}
@ lxc-attach $1 apt update
@ lxc-attach $1 -- apt upgrade -y
}
pctCreateUbuntu(){
local TEMPLATE
getLatestTemplate ubuntu TEMPLATE
pctCreate $1 "$TEMPLATE" "$2" "$3"
sleep ${TIMEOUT:=5}
@ lxc-attach $1 apt update
@ lxc-attach $1 -- apt upgrade -y
}
#
# pctSet ID [ARGS [REBOOT]]
#
pctSet(){
[ "$2" ] \
&& @ pct set $1 \
${2}
[ "$3" ] \
&& @ pct reboot $1
}
#----------------------------------------------------------------------
# vim:set ts=4 sw=4 nowrap :