#!/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: # # / # dhcp # Gateways can be: # # 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} if ! [ -e $TEMPLATE_DIR ] ; then return fi 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 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 :