mirror of
				https://github.com/flynx/proxmox-utils.git
				synced 2025-11-03 21:50:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			621 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			621 lines
		
	
	
		
			11 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 $?
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#----------------------------------------------------------------------
 | 
						|
 | 
						|
#
 | 
						|
#	check MSG COMMAND ..
 | 
						|
#
 | 
						|
check(){
 | 
						|
	local MSG=$1
 | 
						|
	shift
 | 
						|
	for cmd in "$@" ; do
 | 
						|
		which $cmd > /dev/null 2>&1 \
 | 
						|
			|| eval "echo \"$MSG\"" >&2
 | 
						|
	done
 | 
						|
}
 | 
						|
 | 
						|
need(){
 | 
						|
	check 'ERROR: "$cmd": needed by this script but not in path.' "$@"
 | 
						|
}
 | 
						|
would-like(){
 | 
						|
	check 'WARNING: "$cmd": is not in path.' "$@"
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#----------------------------------------------------------------------
 | 
						|
# 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(){
 | 
						|
	if [ $DRY_RUN ] ; then
 | 
						|
		[ -z $2 ] \
 | 
						|
			|| eval "$2=${CT_TEMPLATE:-\\\$CT_TEMPLATE}"
 | 
						|
		return
 | 
						|
	fi
 | 
						|
 | 
						|
	#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
 | 
						|
#
 | 
						|
# This saves all user input variables to the $XREAD_VARS array.
 | 
						|
#
 | 
						|
# XXX add support for keywords like SKIP and DISABLE
 | 
						|
xread(){
 | 
						|
	local non_empty=
 | 
						|
	if [[ $1 == '-n' ]] ; then
 | 
						|
		shift
 | 
						|
		local non_empty=1
 | 
						|
	fi
 | 
						|
	if [[ "${!2}" == "SKIP" ]] ; then
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	if [ -z ${!2} ] ; then
 | 
						|
		eval 'read -ep "'$1'" -i "$DFL_'$2'" '${2}''
 | 
						|
		XREAD_VARS+=(${2})
 | 
						|
	fi
 | 
						|
	if [ -z $non_empty ] ; then
 | 
						|
		eval ''$2'=${'$2':=$DFL_'$2'}'
 | 
						|
	fi
 | 
						|
	[ $SCRIPTING ] \
 | 
						|
		&& echo "$2=${!2}"
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
#	xreadYes MSG VAR
 | 
						|
#
 | 
						|
xreadYes(){
 | 
						|
	if [[ "${!2}" == "SKIP" ]] ; then
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	if [ -z ${!2} ] ; then
 | 
						|
		if [ -z $(eval "echo \$DFL_${2}") ] ; then
 | 
						|
			local yes=y
 | 
						|
			local no=N
 | 
						|
			local dfl=
 | 
						|
		else
 | 
						|
			local yes=Y
 | 
						|
			local no=n
 | 
						|
			local dfl=1
 | 
						|
		fi
 | 
						|
		eval 'read -ep "'$1' ('$yes'/'$no') " '${2}''
 | 
						|
		XREAD_VARS+=(${2})
 | 
						|
		# normalize...
 | 
						|
		eval "${2}=${!2,,}"
 | 
						|
		if [[ "${!2}" == 'y' ]] ; then
 | 
						|
			eval "${2}=1"
 | 
						|
		elif [[ ${!2} == 'n' ]] ; then
 | 
						|
			eval "${2}="
 | 
						|
		# set default if empty...
 | 
						|
		else
 | 
						|
			eval "${2}=\${${2}:-$dfl}"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	[ $SCRIPTING ] \
 | 
						|
		&& echo "$2=${!2}"
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
#	xreadpass VAR
 | 
						|
#
 | 
						|
xreadpass(){
 | 
						|
	if [[ ${!1} == 'SKIP' ]] ; then
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	local PASS1
 | 
						|
	local PASS2
 | 
						|
	for attempt in 1 2 3 ; do
 | 
						|
		read -sep "password (Enter to skip): " PASS1
 | 
						|
		echo
 | 
						|
		if [ -z $PASS1 ] ; then
 | 
						|
			return
 | 
						|
		fi
 | 
						|
		read -sep "retype password: " PASS2
 | 
						|
		echo
 | 
						|
		if [[ $PASS1 != $PASS2 ]] ; then
 | 
						|
			echo "ERR: passwords do not match."
 | 
						|
			continue
 | 
						|
		fi
 | 
						|
		eval ''$1'='${PASS1}''
 | 
						|
		return
 | 
						|
	done
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Wait for /etc/inithooks.conf to be generated then cleared
 | 
						|
#
 | 
						|
# 	tklWaitForSetup ID
 | 
						|
#
 | 
						|
# for tkl inithooks doc see:
 | 
						|
# 	https://www.turnkeylinux.org/docs/inithooks
 | 
						|
tklWaitForSetup(){
 | 
						|
	printf "# TKL setup, this may take a while"
 | 
						|
	if [ -z $DRY_RUN ] ; then
 | 
						|
		while ! $(lxc-attach $1 -- test -e /etc/inithooks.conf) ; do
 | 
						|
			printf '.'
 | 
						|
			sleep ${TIMEOUT:=5}
 | 
						|
		done
 | 
						|
		printf '+'
 | 
						|
		sleep ${TIMEOUT:=5}
 | 
						|
		while ! [[ $(lxc-attach $1 -- cat /etc/inithooks.conf | wc -c) < 2 ]] ; do
 | 
						|
			printf '.'
 | 
						|
			sleep ${TIMEOUT:=5}
 | 
						|
		done
 | 
						|
	else
 | 
						|
		printf '.+..'
 | 
						|
	fi
 | 
						|
	printf 'ready.\n'
 | 
						|
	sleep ${TIMEOUT:=5}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# 
 | 
						|
# 	readConfig
 | 
						|
#
 | 
						|
# Envioronment variables:
 | 
						|
#	CLEAN_RUN	- if set ignore ./config.last-run
 | 
						|
#	CONFIG		- config file to load last
 | 
						|
#
 | 
						|
readConfig(){
 | 
						|
	if [ -z $NO_DEFAULTS ] ; then
 | 
						|
		[ -e ../config.global ] \
 | 
						|
			&& source ../config.global
 | 
						|
		[ -e ./config ] \
 | 
						|
			&& source ./config
 | 
						|
		# XXX is this the right priority for this???
 | 
						|
		[ -e ./config.last-run ] \
 | 
						|
			&& [ -z $CLEAN_RUN ] \
 | 
						|
			&& source ./config.last-run
 | 
						|
		[ -e "$CONFIG" ] \
 | 
						|
			&& source $CONFIG
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
#	saveConfig [-d|-a] CONFIG VAR ..
 | 
						|
#
 | 
						|
saveConfig(){
 | 
						|
	local prefix=
 | 
						|
	local append=
 | 
						|
	while true ; do
 | 
						|
		case $1 in
 | 
						|
			-d|--default)
 | 
						|
				prefix=DFL_
 | 
						|
				shift
 | 
						|
				;;
 | 
						|
			-a|--append)
 | 
						|
				append=1
 | 
						|
				shift
 | 
						|
				;;
 | 
						|
			*)
 | 
						|
				break
 | 
						|
				;;
 | 
						|
		esac
 | 
						|
	done
 | 
						|
	local cfg=$1
 | 
						|
	shift
 | 
						|
 | 
						|
	if [ -z $append ] ; then
 | 
						|
		printf '' > "$cfg"
 | 
						|
	fi
 | 
						|
	{
 | 
						|
		for var in $@ ; do
 | 
						|
			echo "${prefix}${var}=${!var}"
 | 
						|
		done
 | 
						|
		echo
 | 
						|
	} >> "$cfg"
 | 
						|
}
 | 
						|
 | 
						|
saveLastRunConfig(){
 | 
						|
	local cfg=config.last-run
 | 
						|
	echo "# Saving config to: config.last-run"
 | 
						|
	{
 | 
						|
		echo "#"
 | 
						|
		echo "# This file is auto-generated, any changes here will be overwritten." 
 | 
						|
		echo "#"
 | 
						|
	} > "$cfg"
 | 
						|
	saveConfig -d -a "$cfg" ${XREAD_VARS[@]}
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
#	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 [VAR ..]
 | 
						|
#
 | 
						|
# XXX revise: SKIP handling...
 | 
						|
buildAssets(){
 | 
						|
	local template_dir=${TEMPLATE_DIR:-templates}
 | 
						|
	local assets_dir=${ASSETS_DIR:-assets}
 | 
						|
 | 
						|
	if ! [ -e $template_dir ] ; then
 | 
						|
		return
 | 
						|
	fi
 | 
						|
 | 
						|
	local PATTERNS=()
 | 
						|
	local DFL_VARS=(
 | 
						|
		EMAIL
 | 
						|
		DOMAIN
 | 
						|
		CTHOSTNAME
 | 
						|
		GATE_HOSTNAME
 | 
						|
		NS_HOSTNAME
 | 
						|
		GATE_LAN_IP
 | 
						|
		GATE_ADMIN_IP
 | 
						|
		NS_LAN_IP
 | 
						|
		NS_ADMIN_IP
 | 
						|
		WAN_IP
 | 
						|
		WAN_GATE
 | 
						|
		LAN_IP
 | 
						|
		LAN_GATE
 | 
						|
		ADMIN_IP
 | 
						|
		ADMIN_GATE
 | 
						|
	)
 | 
						|
	for var in ${DFL_VARS[@]} ; do
 | 
						|
		local val=${!var}
 | 
						|
		if [[ $val == SKIP ]] ; then
 | 
						|
			val=
 | 
						|
		fi
 | 
						|
		PATTERNS+=("-e 's/\\\${${var}}/${val//\//\\/}/g'")
 | 
						|
	done
 | 
						|
	local IP_VARS=(
 | 
						|
		GATE_LAN_IPn
 | 
						|
		GATE_ADMIN_IPn
 | 
						|
		NS_LAN_IPn
 | 
						|
		NS_ADMIN_IPn
 | 
						|
		WAN_IPn
 | 
						|
		LAN_IPn
 | 
						|
		ADMIN_IPn
 | 
						|
	)
 | 
						|
	for var in ${IP_VARS[@]} ; do
 | 
						|
		var=${var%n}
 | 
						|
		local val=${!var}
 | 
						|
		if [[ $val == SKIP ]] ; then
 | 
						|
			val=
 | 
						|
		fi
 | 
						|
		PATTERNS+=("-e 's/\\\${${var}n}/${val/\/*}/g'")
 | 
						|
	done
 | 
						|
	# args...
 | 
						|
	for var in $@ ; do
 | 
						|
		local val=${!var}
 | 
						|
		if [[ $val == SKIP ]] ; then
 | 
						|
			val=
 | 
						|
		fi
 | 
						|
		PATTERNS+=("-e 's/\\\${${var}}/${val//\//\\/}/g'")
 | 
						|
	done
 | 
						|
 | 
						|
	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}" \
 | 
						|
			| eval "sed ${PATTERNS[@]}" \
 | 
						|
			> "${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
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
#	pctCreateTurnkey APP ID ARGS [PASS]
 | 
						|
#
 | 
						|
pctCreateTurnkey(){
 | 
						|
	local app=$1
 | 
						|
	shift
 | 
						|
	local TEMPLATE
 | 
						|
	getLatestTemplate '.*-turnkey-'$app TEMPLATE
 | 
						|
 | 
						|
	pctCreate $1 "$TEMPLATE" "$2" "$3"
 | 
						|
 | 
						|
	tklWaitForSetup $1
 | 
						|
 | 
						|
	sleep ${TIMEOUT:=5}
 | 
						|
}
 | 
						|
#
 | 
						|
#	pctUpdateTurnkey ID
 | 
						|
#
 | 
						|
pctUpdateTurnkey(){
 | 
						|
	@ 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 :
 |