#!/bin/bash
# This script configures your backend so that a diskless
# frontend can boot from it.

if [ "$1" == "" ] ; then
  echo "\
Usage: knoppmyth_diskless_frontend.bash <hostname> [nfs_root_dir]
	hostname is the name of your frontend host.
	nfs_root_dir is the dir that contains the frontend root filesystem.
		Defaults to /nfsroot (use /myth/nfsroot if you want it on
		your /myth partition" 
  exit
fi

FRONTEND=$1
if [ -z "$2" ] ; then
  NFSROOT=/nfsroot/$FRONTEND
else
  NFSROOT=$2/$FRONTEND
fi

get_network_interface() {
  NETDEVICES="$(cat /proc/net/dev | awk -F: '/ath.:|wlan.:|eth.:|tr.:/{print $1}')"  
  echo NETDEVICES=$NETDEVICES
  NUM_DEVICES=$(echo $NETDEVICES | wc -w)
  echo NUM_DEVICES=$NUM_DEVICES
  if [ $NUM_DEVICES = 1 ] ; then
    INTERFACE=$NETDEVICES
  else
    DEVICELIST=""
    DEVNUM=0
    for DEVICE in $NETDEVICES
    do 
      DEVNUM=$(($DEVNUM + 1))
      DEVICELIST="$DEVICELIST $DEVICE Interface${DEVNUM} "
    done
    echo DEVICELIST=$DEVICELIST
    TMP=/tmp/interface
    rm -Rf $TMP
    dialog --menu "Which network interface?" 18 70 12 $DEVICELIST 2>$TMP || exit
    INTERFACE=$(cat $TMP)
  fi
  echo INTERFACE=$INTERFACE
}

validip(){
  echo "$1" | egrep -q -e '[0-9]+\.[0-9]+\.[0-9]+.[0-9]+'
  return $?
}

get_network_info() {
  BACKEND_IP=$(echo $(ifconfig $INTERFACE | grep "inet addr" | tr ':' ' ') | 
    cut -d ' ' -f 3)
  echo BACKEND_IP=$BACKEND_IP
  NAMESERVERS="$(awk '/^nameserver/{printf "%s ",$2}' /etc/resolv.conf)"
  echo NAMESERVERS=$NAMESERVERS
  GATEWAY="$(LANG=C LC_ALL=C route -n | awk '/^0\.0\.0\.0/{print $2; exit}')"
  echo GATEWAY=$GATEWAY
  NETWORK="${BACKEND_IP%.*}"
  echo NETWORK=$NETWORK
  HOST="${BACKEND_IP##*.}"
  echo HOST=$HOST
  NETMASK="$(LANG=C LC_ALL=C ifconfig $INTERFACE | awk '/[Mm]ask/{FS="[:   ]*";$0=$0; print $8; exit}')"
  echo NETMASK=$NETMASK

  if [ "$HOST" -lt "201" ] ; then
    START=201
  else
    START=151
  fi

  if [ "$START" = "201" ] ; then
    END=250
  else
    END=200
  fi

  IPRANGE_FROM=""
  IPRANGE_TO=""

  while [ -z "$IPRANGE_FROM" -o -z "$IPRANGE_TO" -o -z "$IPRANGE" ] 
  do
    IPRANGE="$NETWORK.$START $NETWORK.$END"
    rm -f /tmp/iprange
    dialog --clear --inputbox "Please enter the desired IP-Range of \
addresses that should be allocated by clients, separated by a single space." \
      10 75 "$IPRANGE" 2> /tmp/iprange || exit

    IPRANGE=$(cat /tmp/iprange)
    echo IPRANGE=$IPRANGE
    IPRANGE_FROM="${IPRANGE%% *}"
    IPRANGE_TO="${IPRANGE##* }"

    for i in "$IPRANGE_FROM" "$IPRANGE_TO"
    do
      validip "$i" || IPRANGE=""
    done
  done
}

setup_dhcpd() {
  # Generate dhcpd.conf from template

  if [ ! -f /etc/dhcp3/dhcpd.conf.orig ] ; then
    mv -f /etc/dhcp3/dhcpd.conf /etc/dhcp3/dhcpd.conf.orig
  fi

  ALLNAMESERVERS=""
  for i in $NAMESERVERS; do
    ALLNAMESERVERS="${ALLNAMESERVERS:+$ALLNAMESERVERS,} $i"
  done
  echo ALLNAMESERVERS=$ALLNAMESERVERS

  cat >/etc/dhcp3/dhcpd.conf <<EOT
# dhcpd.conf for KNOPPIX terminalserver

# global settings
allow booting;
allow bootp;
default-lease-time 600;
max-lease-time 7200;

subnet ${NETWORK}.0 netmask ${NETMASK} {
  next-server $BACKEND_IP;
  filename "pxelinux.0";
  option subnet-mask ${NETMASK};
  range ${IPRANGE_FROM} ${IPRANGE_TO};
  ${ALLNAMESERVERS:+option domain-name-servers $ALLNAMESERVERS;}
  ${GATEWAY:+option routers $GATEWAY;}
}
EOT

  if [ ! -f /etc/default/dhcp3-server.orig ] 
  then
    mv -f /etc/default/dhcp3-server /etc/default/dhcp3-server.orig
  fi  

  echo "INTERFACES=\"$INTERFACE\"" > /etc/default/dhcp3-server

  update-rc.d dhcp3-server defaults
  /etc/init.d/dhcp3-server restart
}

setup_tftpd() {
  # Check for an uncommented tftp line in /etc/inetd.conf. By default, there
  # will be a commented line, if there is, we will put an uncommented line
  # with the correct details in instead. If there is already an uncommented
  # line, we will just assume that it has already been set up.

  if ! grep -q ^tftp[[:space:]] /etc/inetd.conf ; then
    echo "Inserting tftp details in /etc/inetd.conf"
    cp /etc/inetd.conf /etc/inetd.conf.before_tftp
    cat /etc/inetd.conf.before_tftp |
      awk '/#tftp/{print \
        "tftp dgram udp wait root /usr/sbin/tcpd /usr/sbin/in.tftpd -s /tftpboot"}{print $0}' > \
      /etc/inetd.conf
  else
    echo "Already inserted tftp details in /etc/inetd.conf"
  fi

  # Restart inetd regardless of whether we needed to change inetd.conf
  # because it must be restarted if for example the /tftpboot directory 
  # is re-created.

  /etc/init.d/openbsd-inetd restart
}

check_delete_of_existing_nfsroot() {
  if [ -d $NFSROOT ] ; then
    if dialog --yesno "\
There is already a directory $NFSROOT. Do you want to delete it and \
rebuild it from scratch?" 10 70 ; then
      echo Deleting $NFSROOT
      rm -Rf $NFSROOT
    else
      echo "OK then, bye."
      exit
    fi
  fi
}

enable_mysql_and_backend_networking() {
  # Enable mysql networking on the backend.

  /etc/init.d/mythtv-backend stop

  if grep -q ^bind-address /etc/mysql/my.cnf ; then
    echo "Commenting out bind-address."
    cp /etc/mysql/my.cnf /etc/mysql/my.cnf~
    cat /etc/mysql/my.cnf~ | sed 's/bind-address/#bind-address/g' > \
      /etc/mysql/my.cnf
    /etc/init.d/mysql restart
  else
    echo "Already commented out skip-networking."
  fi

  # Make sure that the backend ip settings in the mythtv mysql database have
  # the actual IP address of the backend rather than the loopback address.
  # Otherwise the frontend will not be able to connect to the backend.

  echo "Setting backend IP in mythtv's mysql settings"
  echo "
UPDATE settings SET data='$BACKEND_IP' WHERE value='BackendServerIP';
UPDATE settings SET data='$BACKEND_IP' WHERE value='MasterServerIP';" |
    mysql mythconverg

  /etc/init.d/mythtv-backend start  
}

export_usr() {
  # Ensure that the /usr directory is read-only exported.

  if ! grep -q ^/usr[[:space:]] /etc/exports ; then
    echo "Adding line for /usr in /etc/exports"
    echo "/usr *(ro,async)" >> /etc/exports
  else
    echo "Already added line for /usr in /etc/exports"
  fi
}

enable_nfs() {
  # Enable NFS.

  if [ ! -e /etc/rc5.d/S20nfs-common ] ; then
    echo "Enabling nfs-common." 
    update-rc.d nfs-common defaults
  else
    echo "Already enabled nfs-common."
  fi 

  if [ ! -e /etc/rc5.d/S20nfs-kernel-server ] ; then
    echo "Enabling nfs-kernel-server." 
    update-rc.d nfs-kernel-server defaults
  else
    echo "Already enabled nfs-kernel-server."
  fi
}

restart_nfs (){
  /etc/init.d/nfs-common restart
  /etc/init.d/nfs-kernel-server restart
}

create_nfsroot() {
  # Create the nfsroot directory that the FE will use as its root filesystem.

  echo "Creating the $NFSROOT directory."
  mkdir -p $NFSROOT
  for DIR in /* ; do
    if [[ "$DIR" != /myth && \
  	  "$DIR" != /mnt && \
	  "$DIR" != /usr && \
	  "$DIR" != /proc && \
	  "$DIR" != /sys && \
          "$DIR" != /nfsroot && \
	  "$DIR" != /tftpboot && \
	  "$DIR" != /cdrom ]]
    then
      echo "  Copying $DIR to $NFSROOT"
      cp -aRx $DIR $NFSROOT
    fi
  done

  rm -Rf $NFSROOT/var/log/mysql 
  rm -Rf $NFSROOT/var/log/mythtv/mythbackend.log
  rm -Rf $NFSROOT/var/lib/mysql/mythconverg

  cd $NFSROOT

  for DIR in /myth /mnt /usr /proc /sys /cdrom ; do
    echo "  Creating $DIR"
    tar c $DIR --exclude=$DIR/* 2> /dev/null | tar x 2> /dev/null
  done

  # To configure audio on the frontend, we must run
  # /etc/init.d/alsa-autoconfig the first time that the frontend is 
  # booted. We will so that by adding that script to
  # the normal runlevel startup scripts, and removing it 
  # after the first boot (done by knoppmyth_diskless_boot)

  cat << EOF > $NSFROOT/etc/init.d/knoppmyth_diskless_boot
#!/bin/bash
update-rc.d -f alsa-autoconfig remove
update-rc.d -f knoppmyth_diskless_boot remove
EOF
  chmod a+x $NSFROOT/etc/init.d/knoppmyth_diskless_boot

  chroot $NFSROOT mount -t nfs localhost:/usr /usr
  chroot $NFSROOT update-rc.d alsa-autoconfig defaults 19
  chroot $NFSROOT update-rc.d knoppmyth_diskless_boot defaults
  chroot $NFSROOT update-rc.d -f mysql remove
  chroot $NFSROOT update-rc.d -f mythtv-backend remove
  chroot $NFSROOT update-rc.d -f nfs-common remove
  chroot $NFSROOT update-rc.d -f nfs-kernel-server remove
  chroot $NFSROOT update-rc.d -f apache remove
  chroot $NFSROOT update-rc.d -f networking remove
  chroot $NFSROOT update-rc.d -f dhcp3-server remove
  chroot $NFSROOT update-rc.d -f folding@home remove
  chroot $NFSROOT update-rc.d -f mountall.sh remove
  chroot $NFSROOT update-rc.d mountall.sh start 16 S .
  chroot $NFSROOT update-rc.d -f mountnfs.sh remove
  chroot $NFSROOT update-rc.d mountnfs.sh start 17 S .
  chroot $NFSROOT umount /usr  

  # Disable asynchronous nfs mounting (otherwise /usr doesnt seem to get 
  # mounted properly).

  if ! grep ASYNCMOUNTNFS=no $NFSROOT/etc/default/rcS ; then
    cp $NFSROOT/etc/default/rcS $NFSROOT/etc/default/rcS.asyncmountnfs
    cat $NFSROOT/etc/default/rcS.asyncmountnfs |
      grep -v ASYNCMOUNTNFS > $NFSROOT/etc/default/rcS
    echo "ASYNCMOUNTNFS=no" >> $NFSROOT/etc/default/rcS
  fi

  # Update the fstab.
  
  cp $NSFROOT/etc/fstab $NFSROOT/etc/fstab~
  cat $NFSROOT/etc/fstab~ | grep -v ext3 |
    grep -v /dev/hda > $NFSROOT/etc/fstab

  echo "\
$BACKEND_IP:/nfsroot / nfs defaults,auto,noatime 0 2
$BACKEND_IP:/usr /usr nfs defaults,auto,noatime 0 2
$BACKEND_IP:/myth /myth nfs defaults,auto,noatime 0 0
" >> $NFSROOT/etc/fstab

  echo $FRONTEND > $NFSROOT/etc/hostname

  cp $NFSROOT/etc/hosts $NFSROOT/etc/hosts~
  echo "127.0.0.1 $FRONTEND localhost" > $NFSROOT/etc/hosts
  cat $NFSROOT/etc/hosts~ | grep -v 127.0.0.1 >> $NFSROOT/etc/hosts

  cp /usr/share/mythtv/mysql.txt $NFSROOT/home/mythtv/.mythtv/mysql.txt

  if grep -q DBHostName=localhost $NFSROOT/home/mythtv/.mythtv/mysql.txt ; then
    echo "Setting database host in frontend's mysql.txt."
      cp $NFSROOT/home/mythtv/.mythtv/mysql.txt \
         $NFSROOT/home/mythtv/.mythtv/mysql.txt.orig
      cat $NFSROOT/home/mythtv/.mythtv/mysql.txt.orig | 
        sed 's/DBHostName=localhost/DBHostName='$BACKEND_IP'/g' > \
        $NFSROOT/home/mythtv/.mythtv/mysql.txt
  else
    echo "Already set Database host in frontend's mysql.txt."
  fi

  chown mythtv:mythtv $NFSROOT/home/mythtv/.mythtv/mysql.txt

  echo > $NFSROOT/etc/mythtv/Cards
}

export_nfsroot() {
  # Ensure that the NFSROOT directory is appropriately exported.

  if ! grep -q ^$NFSROOT[[:space:]] /etc/exports ; then
    echo "Adding line for $NFSROOT in /etc/exports"
    echo "$NFSROOT *(rw,no_root_squash,async)" >> /etc/exports
  else
    echo "Already added line for $NFSROOT in /etc/exports"
  fi
}

create_tftpboot_directory() {
  # Create the directory with the tftp stuff.

  if [ ! -d /tftpboot ] ; then
    echo "Creating /tftpboot"
    mkdir /tftpboot
    mkdir /tftpboot/pxelinux.cfg
    cp /usr/lib/syslinux/pxelinux.0 /tftpboot
    cp /vmlinuz /tftpboot/vmlinuz-nfsroot
    echo "\
DEFAULT vmlinuz-nfsroot
APPEND root=/dev/nfs ip=dhcp nfsroot=$BACKEND_IP:$NFSROOT
" > /tftpboot/pxelinux.cfg/default
  else
    echo "Already created /tftpboot."
  fi
}

get_network_interface
get_network_info
setup_tftpd
create_tftpboot_directory
setup_dhcpd
enable_mysql_and_backend_networking
export_usr
export_nfsroot
enable_nfs
restart_nfs
check_delete_of_existing_nfsroot
create_nfsroot
restart_nfs