static usb ethnet addresses
[automated-distro-installer] / pxe-server
index c46c72eb34c1141433f9e8c3c177ab448f034d14..1e99b03a004447eb1124f1d1585b5aa33a919a5a 100755 (executable)
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
 
 
-x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace"
+readonly this_file="$(readlink -f -- "${BASH_SOURCE[0]}")"
+script_dir="${this_file%/*}"
+# shellcheck source=./bash-trace
+source "${script_dir}/bash-trace"
+cd $script_dir
+PATH="$PATH:$PWD"
 
 
 usage() {
 
 
 usage() {
@@ -29,7 +35,10 @@ not general purpose, it has code specific to dhcp servers I run.
 Without TYPE, disable  server and fai server. In that case, HOST is only
 needed for fsf office network.
 
 Without TYPE, disable  server and fai server. In that case, HOST is only
 needed for fsf office network.
 
-HOST       A hostname known to the dhcp server, or default for all.
+HOST       Only do dhcp pxe for HOST. The hostname must be known to the dhcp
+           server to target its mac. Use "default" for all hosts.
+           Required in fsf office environment.
+
 TYPE       One of arch, parabola, plain, fai.
 
 -a         Don't setup pxe, just Wait for 2 dhcp acks, then disable the pxe
 TYPE       One of arch, parabola, plain, fai.
 
 -a         Don't setup pxe, just Wait for 2 dhcp acks, then disable the pxe
@@ -38,8 +47,9 @@ TYPE       One of arch, parabola, plain, fai.
            after the 2nd. I can't remember exactly why this caused a
            problem, but I'm hoping the sleep will take care of it.
 -d         Don't alter dhcp config. Only make sense for fai type, and on network
            after the 2nd. I can't remember exactly why this caused a
            problem, but I'm hoping the sleep will take care of it.
 -d         Don't alter dhcp config. Only make sense for fai type, and on network
-           other than home or fsf.
+           other than home or fsf, when using fai-cd, or pxe-kexec.
 -k         Pass -k to myfai-chboot.
 -k         Pass -k to myfai-chboot.
+--no-r     Pass --no-r to myfai-chboot.
 -r         Don't redeploy fai config. For example, if there is a different host
            that is mid-install.
 
 -r         Don't redeploy fai config. For example, if there is a different host
            that is mid-install.
 
@@ -56,31 +66,54 @@ rm tftpboot
 ln -s <arch/parabola/debian iso dir> tftpboot
 
 
 ln -s <arch/parabola/debian iso dir> tftpboot
 
 
+Notes on debugging pxe dhcp tftp:
+
+For debugging dhcp, add to /etc/dnsmasq.conf: log-dhcp
+
+Newer openwrt runs dnsmasq with a whitelist of readable files and dirs:
+
+ps ww :
+/sbin/ujail -t 5 -n dnsmasq -u -l -r /bin/ubus -r /etc/TZ -r /etc/dnsmasq.conf -r /etc/ethers -r /etc/group -r /etc/hosts -r /etc/passwd -w /tmp/dhcp.leases -r /tmp/dnsmasq.d -r /tmp/hosts -r /tmp/resolv.conf.d -r /usr/bin/jshn -r /usr/lib/dnsmasq/dhcp-script.sh -r /usr/share/dnsmasq/dhcpbogushostname.conf -r /usr/share/dnsmasq/rfc6761.conf -r /usr/share/dnsmasq/trust-anchors.conf -r /usr/share/libubox/jshn.sh -r /var/etc/dnsmasq.conf.cfg01411c -w /var/run/dnsmasq/ -- /usr/sbin/dnsmasq -C /var/etc/dnsmasq.conf.cfg01411c -k -x /var/run/dnsmasq/dnsmasq.cfg01411c.pid
+
+logging tftp requests:
+/etc/default/tftpd-hpa:
+add -vv:
+TFTP_OPTIONS="--secure -vv"
+jr -u tftpd-hpa -f
+
 Note: Uses GNU getopt options parsing style
 EOF
   exit $1
 }
 
 Note: Uses GNU getopt options parsing style
 EOF
   exit $1
 }
 
+pre="${0##*/}:"
+m() { printf "$pre %s\n"  "$*"; "$@"; }
+e() { printf "$pre %s\n"  "$*"; }
+err() { echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: $pre: $*" >&2; }
+
+PATH="/a/exe:$PATH"
+
 ##### begin command line parsing ########
 
 dhcp=true
 redep=true
 acks=2
 wait=false
 ##### begin command line parsing ########
 
 dhcp=true
 redep=true
 acks=2
 wait=false
-fsf=false
+fsf_office=false
 
 case $HOSTNAME in
 
 case $HOSTNAME in
-  x3|kw) fsf=true ;;
+  x3|kw) fsf_office=true ;;
 esac
 
 chboot_args=()
 esac
 
 chboot_args=()
-temp=$(getopt -l help adkrSwh "$@") || usage 1
+temp=$(getopt -l no-r,help adkrSwh "$@") || usage 1
 eval set -- "$temp"
 while true; do
   case $1 in
     -a) wait=true; set=false; shift ;;
     -d) dhcp=false; shift ;;
     -k) chboot_args+=(-k); shift ;;
 eval set -- "$temp"
 while true; do
   case $1 in
     -a) wait=true; set=false; shift ;;
     -d) dhcp=false; shift ;;
     -k) chboot_args+=(-k); shift ;;
+    --no-r) chboot_args+=(--no-r); shift ;;
     -r) redep=false; shift ;;
     -S) chboot_args+=(-S); shift ;;
     -w) wait=true; set=true; shift ;;
     -r) redep=false; shift ;;
     -S) chboot_args+=(-S); shift ;;
     -w) wait=true; set=true; shift ;;
@@ -114,10 +147,14 @@ esac
 
 
 if $wait && ! $dhcp; then
 
 
 if $wait && ! $dhcp; then
-  echo "$0: error -w conflicts with -d, choose one or other"
+  echo "$0: error -w conflicts with -d, choose one or other" >&2
   exit 1
 fi
 
   exit 1
 fi
 
+if $fsf_office && [[ ! $host ]]; then
+  echo "$0: at fsf_office, provide HOST arg" >&2
+  exit 1
+  fi
 
 if [[ $host && $host != default ]]; then
   host_tag="tag:$host,"
 
 if [[ $host && $host != default ]]; then
   host_tag="tag:$host,"
@@ -125,16 +162,11 @@ fi
 
 ##### end command line parsing ########
 
 
 ##### end command line parsing ########
 
-e() {
-  echo "$@"
-  "$@"
-}
-
 archlike() {
   cat <<EOF
 archlike() {
   cat <<EOF
-dhcp-option-force=209,boot/syslinux/${type}iso.cfg
-dhcp-option-force=210,/${type}/
-dhcp-boot=${host_tag}/${type}/boot/syslinux/lpxelinux.0
+${host_tag}209,boot/syslinux/${type}iso.cfg
+${host_tag}210,/${type}/
+${host_tag}option:bootfile-name,/${type}/boot/syslinux/lpxelinux.0
 EOF
 }
 
 EOF
 }
 
@@ -142,28 +174,35 @@ plain() {
   # if arch based was used before, this additionally needs
   # the tftp link in /mnt/usb to be changed.
   cat <<EOF
   # if arch based was used before, this additionally needs
   # the tftp link in /mnt/usb to be changed.
   cat <<EOF
-dhcp-boot=${host_tag}pxelinux.0
+${host_tag}option:bootfile-name,pxelinux.0
 EOF
 }
 
 fai() {
   cat <<EOF
 EOF
 }
 
 fai() {
   cat <<EOF
-dhcp-boot=${host_tag}pxelinux.0,faiserver.b8.nz,faiserver.b8.nz
+${host_tag}option:bootfile-name,pxelinux.0
+${host_tag}option:server-ip-address,$faiserverip
+${host_tag}option:tftp-server,$faiserverip
 EOF
 EOF
+  # Note, previously used normal dnsmasq option, but it requires dnsmasq
+  # restart, which causes momentary dns failures, which can bork an
+  # install.
+  #
+  # dhcp-boot=${host_tag}pxelinux.0,faiserver.b8.nz,faiserver.b8.nz
 }
 
 ack-wait() {
 }
 
 ack-wait() {
-  if $fsf; then
-    wait_cmd="ssh tarantula tail -n0 -f /var/log/syslog"
+  if $fsf_office; then
+    wait_cmd="ssh tarantula.office.fsf.org tail -n0 -f /var/log/syslog"
   else
   else
-    wait_cmd="ssh wrt logread -f"
+    wait_cmd="ssh cmc logread -f"
   fi
   wait_count=$1
   if [[ $host ]]; then
   fi
   wait_count=$1
   if [[ $host ]]; then
-    if $fsf; then
+    if $fsf_office; then
       host_regex=" $(getent hosts kw | awk '{print $1}' | sed 's/\./\\./g')"
       host_regex=" $(getent hosts kw | awk '{print $1}' | sed 's/\./\\./g')"
-      else
-    host_regex=" $host"
+    else
+      host_regex=" $host"
     fi
   fi
   regex=".*DHCPACK.*$host_regex\b"
     fi
   fi
   regex=".*DHCPACK.*$host_regex\b"
@@ -174,45 +213,52 @@ ack-wait() {
       echo $line
     fi
   done < <($wait_cmd ||:) # tail returns 2 it seems
       echo $line
     fi
   done < <($wait_cmd ||:) # tail returns 2 it seems
-  e sleep 20
+  m sleep 20
 }
 
 set-pxe() {
   $dhcp || return 0
 }
 
 set-pxe() {
   $dhcp || return 0
-  if $fsf; then
+  if $fsf_office; then
     if [[ ! $cmd ]]; then
     if [[ ! $cmd ]]; then
-      echo "$0: removing pxe for $host on tarantula"
-      ssh tarantula bash -e <<EOF
-sed -ri 's/^( *host +$host *\{).*/\1/' /etc/dhcp3/dhcpd.conf
-/etc/init.d/dhcp3-server restart
+      e "removing pxe for $host on tarantula"
+      ssh tarantula.office.fsf.org bash -e <<EOF
+sed -ri 's/^( *host +$host *\{).*/\1/' /etc/dhcp/dhcpd.conf
+systemctl restart isc-dhcp-server
 EOF
     elif [[ $cmd == fai ]]; then
 EOF
     elif [[ $cmd == fai ]]; then
-      echo "$0: adding pxe for $host on tarantula"
-      ssh tarantula bash -e <<EOF
-sed -ri 's/^( *host +$host *\{).*/\1 next-server faiserver.office.fsf.org; filename "pxelinux.0";/' /etc/dhcp3/dhcpd.conf
-/etc/init.d/dhcp3-server restart
+      e "adding pxe for $host on tarantula"
+      ssh tarantula.office.fsf.org bash -e <<EOF
+sed -ri 's/^( *host +$host *\{).*/\1 next-server faiserver.office.fsf.org; filename "pxelinux.0";/' /etc/dhcp/dhcpd.conf
+systemctl restart isc-dhcp-server
 EOF
     fi
   else
 EOF
     fi
   else
-    echo "$0: updating dnsmasq.conf:"
-    $cmd
-    ${cmd:-:}|ssh wrt "cedit pxe /etc/dnsmasq.conf || /etc/init.d/dnsmasq restart
+    e "updating dnsmasq.conf:"
+    $cmd
+    ${cmd:-:}|ssh cmc "dd of=/var/run/dnsmasq/dhcpopts.conf; /etc/init.d/dnsmasq reload
 $([[ $type == arch || $type == parabola ]] && echo archlike-pxe-mount)"
   fi
 }
 
 $([[ $type == arch || $type == parabola ]] && echo archlike-pxe-mount)"
   fi
 }
 
+type -t host &>/dev/null || sudo apt-get -y install dnsutils
+faiserverip=$(host faiserver | sed -rn 's/^\S+ has address //p;T;q' ||:)
+if [[ ! $faiserverip || $faiserverip =~ [[:space:]] ]]; then
+  echo "$0: error: failed to get \$faiserverip, got: $faiserverip"
+  exit 1
+fi
+
 
 if $set; then
   set-pxe
   if [[ $type == fai ]]; then
 
 if $set; then
   set-pxe
   if [[ $type == fai ]]; then
-    e myfai-chboot ${chboot_args[@]} $host
     if $redep; then
     if $redep; then
-      e fai-redep
+      m fai-redep
     fi
     fi
+    m myfai-chboot ${chboot_args[@]} $host
   else
     # This will fail if faiserver is not setup, so ignore any
     # failure and don't bother us about it.
   else
     # This will fail if faiserver is not setup, so ignore any
     # failure and don't bother us about it.
-    myfai-chboot &>/dev/null ||:
+    m myfai-chboot &>/dev/null ||:
   fi
 fi
 
   fi
 fi