diff --git a/bin/pot b/bin/pot index b3afcde..d85e437 100755 --- a/bin/pot +++ b/bin/pot @@ -118,6 +118,7 @@ usage() { mount-in -- Mount directory, ZFS dataset, or fscomp into a pot mount-out -- Unmount directory, ZFS dataset, or fscomp from a pot add-dep -- Add a dependency + set-aliases -- Set alias hostname for the pot's addr in /etc/hosts set-rss -- Set a resource constraint get-rss -- Get the current resource usage set-cmd -- Set the command to start the pot @@ -190,7 +191,7 @@ case "${CMD}" in create-base|create-fscomp|create|\ create-private-bridge|\ copy-in|copy-out|mount-in|mount-out|prune|set-hook|\ - destroy|add-dep|set-rss|get-rss|set-cmd|set-env|set-hosts|\ + destroy|add-dep|set-aliases|set-rss|get-rss|set-cmd|set-env|set-hosts|\ export|import|prepare|\ export-ports|set-attribute|get-attribute|\ start|stop|term|\ diff --git a/share/pot/common.sh b/share/pot/common.sh index a3e8fcb..5cbbfde 100644 --- a/share/pot/common.sh +++ b/share/pot/common.sh @@ -5,14 +5,14 @@ : "${ECHO:=echo}" : "${SED:=sed}" -_POT_RW_ATTRIBUTES="start-at-boot early-start-at-boot persistent no-rc-script prunable localhost-tunnel no-tmpfs no-etc-hosts" +_POT_RW_ATTRIBUTES="start-at-boot early-start-at-boot persistent no-rc-script prunable localhost-tunnel no-tmpfs no-etc-hosts dynamic-etc-hosts" _POT_RO_ATTRIBUTES="to-be-pruned" _POT_NETWORK_TYPES="inherit alias public-bridge private-bridge" # not devfs handles separately _POT_JAIL_RW_ATTRIBUTES='enforce_statfs mount fdescfs linprocfs nullfs procfs tmpfs zfs raw_sockets sysvshm sysvsem sysvmsg children mlock devfs_ruleset exec_stop stop_timeout' -# N: arg name jail command, T: type of data, D: deafult value +# N: arg name jail command, T: type of data, D: default value # devfs is always mounted _POT_DEFAULT_mount_N='allow.mount' _POT_DEFAULT_mount_T='bool' diff --git a/share/pot/prepare.sh b/share/pot/prepare.sh index e383412..fca2029 100644 --- a/share/pot/prepare.sh +++ b/share/pot/prepare.sh @@ -234,6 +234,9 @@ pot-prepare() if ! pot-cmd set-attribute -A no-etc-hosts -V YES -p "$_new_pname" ; then _error "Couldn't disable the enrichment of /etc/hosts - ignoring" fi + if ! pot-cmd set-attribute -A dynamic-etc-hosts -V NO -p "$_new_pname" ; then + _error "Couldn't disable the enrichment of dynamic /etc/hosts - ignoring" + fi if ! pot-cmd set-attribute -A no-tmpfs -V YES -p "$_new_pname" ; then _error "Couldn't disable tmpfs for /tmp - ignoring" fi diff --git a/share/pot/set-aliases.sh b/share/pot/set-aliases.sh new file mode 100644 index 0000000..17c0b5c --- /dev/null +++ b/share/pot/set-aliases.sh @@ -0,0 +1,92 @@ +#!/bin/sh +# shellcheck disable=SC3033,SC3040,SC3043 +: + +set-aliases-help() { + cat <<-"EOH" + pot set-aliases [-hv] -p pot -A alias_A[ alias_B alias_C ...] + -h print this help + -v verbose + -p pot : the working pot + -A alias_A[ alias_B alias_C ...] : adding alias for an alternative name resolution + via /etc/hosts file + EOH +} + +# $1 pot +# $2 hostfile +_set_aliases() +{ + local _pname _tmpfile _cfile + _pname="$1" + _tmpfile="$2" + _cfile=$POT_FS_ROOT/jails/$_pname/conf/pot.conf + ${SED} -i '' -e "/^pot.aliases=.*/d" "$_cfile" + sed 's/.*/pot.aliases=&/g' "$_tmpfile" >> "$_cfile" +} + + +pot-set-aliases() +{ + local _pname _tmpfile _aliases _alias + _pname= + if ! _is_pot_tmp_dir ; then + _error "Failed to create the POT_TMP directory" + return 1 + fi + _tmpfile="$(mktemp "${POT_TMP:-/tmp}/pot-set-aliases${POT_MKTMP_SUFFIX}")" || exit 1 + OPTIND=1 + while getopts "hvp:A:" _o ; do + case "$_o" in + h) + set-aliases-help + rm -f "$_tmpfile" + return 0 + ;; + v) + _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) + ;; + A) + # validate IP address + _alias=$OPTARG + if [ -z "$_alias" ] ; then + _error "Submitted alias is empty" + set-aliases-help + rm -f "$_tmpfile" + return 1 + fi + echo "alias=$_alias" + _aliases=$(echo "$_aliases $_alias" | sed -e "s/^ *//g") + echo "aliases $_aliases " + ;; + p) + _pname="$OPTARG" + ;; + ?) + set-aliases-help + rm -f "$_tmpfile" + return 1 + esac + done + + if [ -z "$_pname" ]; then + _error "A pot name is mandatory" + set-aliases-help + rm -f "$_tmpfile" + return 1 + fi + if ! _is_pot "$_pname" ; then + _error "pot $_pname is not valid" + set-aliases-help + rm -f "$_tmpfile" + return 1 + fi + if ! _is_uid0 ; then + rm -f "$_tmpfile" + return 1 + fi + cat $_tmpfile + echo "$_aliases " >> "$_tmpfile" + _set_aliases "$_pname" "$_tmpfile" + rm -f "$_tmpfile" +} diff --git a/share/pot/set-attribute.sh b/share/pot/set-attribute.sh index 6d276f4..cff5c5f 100644 --- a/share/pot/set-attribute.sh +++ b/share/pot/set-attribute.sh @@ -165,6 +165,7 @@ pot-set-attribute() "persistent"|\ "no-rc-script"|\ "no-etc-hosts"|\ + "dynamic-etc-hosts"|\ "prunable"|\ "localhost-tunnel") _cmd=_set_boolean_attribute diff --git a/share/pot/start.sh b/share/pot/start.sh index 159fb87..cd2299a 100644 --- a/share/pot/start.sh +++ b/share/pot/start.sh @@ -113,27 +113,41 @@ _js_resolv() # $1 pot name _js_etc_hosts() { - local _pname _phosts _hostname _bridge_name _cfile + local _pname _phosts _hostname _bridge_name _cfile _dynamics _pname="$1" _phosts="${POT_FS_ROOT}/jails/$_pname/m/etc/hosts" _hostname="$( _get_conf_var "$_pname" host.hostname )" + _dynamics="$( _get_conf_var "$_pname" pot.attr.dynamic-etc-hosts )" + [ "$_dynamics" = "YES" ] && aopt="--aliases-included" || aopt="" printf "::1 localhost %s\n" "$_hostname" > "$_phosts" printf "127.0.0.1 localhost %s\n" "$_hostname" >> "$_phosts" + _cfile="${POT_FS_ROOT}/jails/$_pname/conf/pot.conf" + grep '^pot.hosts=' "$_cfile" | sed 's/^pot.hosts=//g' >> "$_phosts" if [ "$(_get_conf_var "$_pname" "pot.attr.no-etc-hosts")" = "YES" ]; then _debug "Attribute no-etchosts: no additional /etc/hosts entries injected" else case "$( _get_conf_var "$_pname" network_type )" in "public-bridge") - potnet etc-hosts >> "$_phosts" + potnet etc-hosts $aopt >> "$_phosts" ;; "private-bridge") _bridge_name="$( _get_conf_var "$_pname" bridge )" - potnet etc-hosts -b "$_bridge_name" >> "$_phosts" + potnet etc-hosts -b "$_bridge_name" $aopt >> "$_phosts" ;; esac fi - _cfile="${POT_FS_ROOT}/jails/$_pname/conf/pot.conf" - grep '^pot.hosts=' "$_cfile" | sed 's/^pot.hosts=//g' >> "$_phosts" +} + +_update_dynamic_hosts() { + local _pots _pot _dynamic + _pots=$( _get_pot_list ) + for _pot in $_pots ; do + _dynamic="$( _get_conf_var "$_pot" pot.attr.dynamic-etc-hosts)" + if [ "$_dynamic" = "YES" ]; then + _debug "updating etc-hosts for ${_pot}" + _js_etc_hosts $_pot + fi + done } # returns interface names of epaira and epairb @@ -864,5 +878,6 @@ pot-start() _error "$_pname failed to start" return 1 fi + _update_dynamic_hosts return 0 } diff --git a/share/pot/stop.sh b/share/pot/stop.sh index cdddc04..198c671 100644 --- a/share/pot/stop.sh +++ b/share/pot/stop.sh @@ -234,7 +234,10 @@ pot-stop() ${EXIT} 1 fi _js_rm_resolv "$_pname" + . "${_POT_INCLUDE}/start.sh" + _update_dynamic_hosts _pot_umount "$_pname" + lockf "${POT_TMP:-/tmp}/pot-lock-$_pname" "${_POT_PATHNAME}" set-status -p "$_pname" -s stopped _set_pot_status "$_pname" stopped rc=$? if [ $rc -eq 2 ]; then diff --git a/share/pot/update-config.sh b/share/pot/update-config.sh index 9aacecc..8bd56a3 100644 --- a/share/pot/update-config.sh +++ b/share/pot/update-config.sh @@ -83,10 +83,18 @@ _update_one_pot() _debug "pot.attr.no-tmpfs=NO" echo "pot.attr.no-tmpfs=NO" >> "$_conf" fi + if [ -z "$(_get_conf_var "$_pname" "pot.attr.aliases")" ]; then + _debug "updating extra hosts in $_pname" + echo "pot.attr.aliases=NO" >> "$_conf" + fi if [ -z "$(_get_conf_var "$_pname" "pot.attr.no-etc-hosts")" ]; then _debug "pot.attr.no-etc-hosts=NO" echo "pot.attr.no-etc-hosts=NO" >> "$_conf" fi + if [ -z "$(_get_conf_var "$_pname" "pot.attr.dynamic-etc-hosts")" ]; then + _debug "pot.attr.dynamic-etc-hosts=NO" + echo "pot.attr.dynamic-etc-hosts=NO" >> "$_conf" + fi # convert pot.export.static.ports=80 to the new format pot.export.ports=80:80 # being aware that pot.export.ports may already exist