diff options
Diffstat (limited to 'testing/util-vserver')
-rw-r--r-- | testing/util-vserver/APKBUILD | 7 | ||||
-rw-r--r-- | testing/util-vserver/setup-vs-guest | 258 |
2 files changed, 263 insertions, 2 deletions
diff --git a/testing/util-vserver/APKBUILD b/testing/util-vserver/APKBUILD index bdf49caf41..db7d785b2b 100644 --- a/testing/util-vserver/APKBUILD +++ b/testing/util-vserver/APKBUILD @@ -2,7 +2,7 @@ pkgname=util-vserver pkgver=0.30.216_pre2849 _realver=0.30.216-pre2849 -pkgrel=0 +pkgrel=1 pkgdesc="Linux-VServer admin utilities" url="http://www.nongnu.org/util-vserver/" license="GPL" @@ -17,6 +17,7 @@ source="http://people.linux-vserver.org/~dhozac/t/uv-testing/util-vserver-$_real validate.patch alpine.patch setup-vs-template + setup-vs-guest " subpackages="$pkgname-doc $pkgname-dev" @@ -41,6 +42,7 @@ build() { make || return 1 make DESTDIR="$pkgdir/" install install-distribution install -Dm755 ../setup-vs-template "$pkgdir"/usr/sbin/setup-vs-template + install -Dm755 ../setup-vs-guest "$pkgdir"/usr/sbin/setup-vs-guest } md5sums="af4c22b420320bdd94a1756f3c90de20 util-vserver-0.30.216-pre2849.tar.bz2 @@ -48,4 +50,5 @@ md5sums="af4c22b420320bdd94a1756f3c90de20 util-vserver-0.30.216-pre2849.tar.bz2 ff8f561f672524eb46fe633f584ef60e ensc_pathprog.patch da8b70c4fd40e68894b3903ffd121397 validate.patch 04000261fd990a3963b0e98260b481bd alpine.patch -4504f4a97eba4a4ab21feff1b121c7bd setup-vs-template" +4504f4a97eba4a4ab21feff1b121c7bd setup-vs-template +b7a30afd4ba87968cb58137d59d8e8f8 setup-vs-guest" diff --git a/testing/util-vserver/setup-vs-guest b/testing/util-vserver/setup-vs-guest new file mode 100644 index 0000000000..a1e6959e23 --- /dev/null +++ b/testing/util-vserver/setup-vs-guest @@ -0,0 +1,258 @@ +#!/bin/sh + +# simple script to set up a new vserver guest + +# test the first argument against the remaining ones, return success on a match +isin() { + local _a=$1 _b + + shift + for _b; do + [ "$_a" = "$_b" ] && return 0 + done + return 1 +} + +# remove all occurrences of first argument from list formed by +# the remaining arguments +rmel() { + local _a=$1 _b + + shift + for _b; do + [ "$_a" != "$_b" ] && echo -n "$_b " + done +} + +# Issue a read into the global variable $resp. +_ask() { + local _redo=0 + + read resp + case "$resp" in + !) echo "Type 'exit' to return to setup." + sh + _redo=1 + ;; + !*) eval "${resp#?}" + _redo=1 + ;; + esac + return $_redo +} + +# Ask for user input. +# +# $1 = the question to ask the user +# $2 = the default answer +# +# Save the user input (or the default) in $resp. +# +# Allow the user to escape to shells ('!') or execute commands +# ('!foo') before entering the input. +ask() { + local _question=$1 _default=$2 + + while :; do + echo -n "$_question " + [ -z "$_default" ] || echo -n "[$_default] " + _ask && : ${resp:=$_default} && break + done +} + +# Ask for user input until a non-empty reply is entered. +# +# $1 = the question to ask the user +# $2 = the default answer +# +# Save the user input (or the default) in $resp. +ask_until() { + resp= + while [ -z "$resp" ] ; do + ask "$1" "$2" + done +} + +# Ask for the user to select one value from a list, or 'done'. +# +# $1 = name of the list items (disk, cd, etc.) +# $2 = question to ask +# $3 = list of valid choices +# $4 = default choice, if it is not specified use the first item in $3 +# +# N.B.! $3 and $4 will be "expanded" using eval, so be sure to escape them +# if they contain spooky stuff +# +# At exit $resp holds selected item, or 'done' +ask_which() { + local _name=$1 _query=$2 _list=$3 _def=$4 _dynlist _dyndef + + while :; do + # Put both lines in ask prompt, rather than use a + # separate 'echo' to ensure the entire question is + # re-ask'ed after a '!' or '!foo' shell escape. + eval "_dynlist=\"$_list\"" + eval "_dyndef=\"$_def\"" + + # Clean away whitespace and determine the default + set -o noglob + set -- $_dyndef; _dyndef="$1" + set -- $_dynlist; _dynlist="$*" + set +o noglob + [ $# -lt 1 ] && resp=done && return + + : ${_dyndef:=$1} + echo "Available ${_name}s are: $_dynlist." + echo -n "Which one $_query? (or 'done') " + [ -n "$_dyndef" ] && echo -n "[$_dyndef] " + _ask || continue + [ -z "$resp" ] && resp="$_dyndef" + + # Quote $resp to prevent user from confusing isin() by + # entering something like 'a a'. + isin "$resp" $_dynlist done && break + echo "'$resp' is not a valid choice." + done +} + +# Ask for user input until a non-empty reply is entered. +# +# $1 = the question to ask the user +# $2 = the default answer +# +# Save the user input (or the default) in $resp. +ask_until() { + resp= + while [ -z "$resp" ] ; do + ask "$1" "$2" + done +} + +# http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names +valid_hostname() { + # check length + if [ $(echo "$1" | wc -c) -gt 63 ]; then + echo "Hostname '$1' is too long." + return 1 + fi + # check that it only contains valid chars + if ! [ -z "$(echo $1 | sed 's/[0-9a-z-]//g')" ]; then + echo "Hostname must only contain letters (a-z), digits (0-9) or -" + return 1 + fi + # must not start with - + case "$1" in + -*) echo "Hostname must not start with a '-'"; return 1;; + esac + return 0 +} + +# return last ipv4 address and mask +# +# $1 = interface +# +last_ipv4_addr_mask() { + local _iface=$1 + ip addr show dev $_iface | awk '$1 == "inet" {print $2}' | tail -n1 +} + +valid_ip() { + [ "$1" ] || return 0 + ipcalc -s $1 +} + +if [ "$(whoami)" != "root" ]; then + echo "Need to be root. Sorry." + exit 1 +fi + +ifaces=$(ip addr | awk -F: '$1 ~ /^[0-9]/ {printf "%s" $2} END {printf "\n"}') +last_iface=$(echo $ifaces | sed 's/.* //') + +while true; do + ask "Hostname for new vserver:" + if [ -d /etc/vservers/$resp ]; then + echo "/etc/vservers/$resp already exist" + continue + fi + if [ -d /vservers/$resp ]; then + echo "/vservers/$resp already exist" + continue + fi + valid_hostname $resp && break +done +_hostname=$resp + +# get ip address(es) +resp= +ifaceopts= +while [ "$resp" != "done" ]; do + if [ -z "$ifaces" ] || [ "$ifaces" = "lo " ]; then + _def="done" + else + _def=$(echo $ifaces | sed 's/.* //') + fi + ask_which "network interface" "to use for $_hostname" "$ifaces" $_def + [ "$resp" = "done" ] && break + + _iface=$resp + ifaces=$(rmel $_iface $ifaces) + # suggested ip by last digit + 1 + _last_ip_mask=$(last_ipv4_addr_mask $_iface) + _last_ip=${_last_ip_mask%/*} + _last_ip_digit=${_last_ip##*.} + _ip=${_last_ip%.*}.$((($_last_ip_digit + 1) % 256)) + _mask=${_last_ip_mask#*/} + while true; do + ask "Enter IP address/mask for $_iface:" $_ip/$_mask + valid_ip $resp && break + echo "$resp is not a valid IPv4 address/mask" + done + _ip_mask=$resp + ifaceopts="$ifaceopts --interface $_iface:$_ip_mask" + + # suggest context from last digit in first ip address + if [ -z "$_context" ]; then + _ip=${_ip_mask%/*} + _last_digit=${_ip##*.} + _context=$((10000 + $_last_digit)) + fi +done + +# get context id +while true; do + ask "Enter context id for $_hostname:" $_context + if echo "$resp" | egrep -q "[0-9]+"; then + [ $resp -ge 0 ] && [ $resp -lt 65535 ] && break + fi + echo "Context id must be a 0-65534 number" +done +_context=$resp + +# get template +while true; do + ask "Enter template file (or empty for generate a new):" + if [ -z "$resp" ] || [ -r "$resp" ]; then + break + fi + echo "Can not read $resp" +done +_template=$resp + +if [ -z "$_template" ]; then + _template=/vservers/template.tar.gz + echo -n "Generating template..." + if setup-vs-template -q -o $_template; then + echo "ok" + else + echo "Failed to create template" + exit 1 + fi +fi + +vserver $_hostname build \ + --hostname $_hostname \ + $ifaceopts \ + --context $_context \ + -m template -- -t "$_template" -d alpine + |