#!/bin/sh


# WARNING!!!!
# Making changes here may require you to also change the wwinitrd itself (ie.
# the VNFS_GET_METHOD clients, or even mkfs binaries).

# What method do you wish to use to download the VNFS image? Default for most
# clusters is preferred, but if you have extreamly large numbers of nodes,
# with large VNFS images (ie. full distro images), you can use other
# mechanisms. Default is VNFSD, but others that could be considered is
# TORRENT, and/or RSYNC.
# 
# note: For using TORRENT and RSYNC, you will have to make changes to the
# wwinitrd (initial ram disk).

VNFS_GET_METHOD=VNFSD


# Were do you want to create the new root file system? Options are TMPFS and
# DISKFS. If you select DISKFS, be sure to customize the below create_diskfs()
# function!

STORAGE_DEV=TMPFS


# If/when using STORAGE_DEV == DISKFS, it will call this function. Because
# there are so many wacky ways of partitioning it is pointless for me to
# script a portable solution. I did however provide a basic template that
# should work for most infrastructures.

create_diskfs() {
   # Must install sfdisk mkfs.??? into /var/warewulf/wwinitrd/sbin/ if you 
   # wish to use this function!

   # What disk to use?
   DISK=/dev/hda
   # What file system to use for the root partition?
   FILESYSTEM=ext2

   # This will partition the drive with a ~2GB swap, and then the rest as a
   # standard Linux partition
   echo -ne ",254,82\n,,83\n" | /sbin/sfdisk $DISK

   # Format the partitions
   mkswap              ${DISK}1
   mkfs.$FILESYSTEM    ${DISK}2

   # Do the mount
   mount -t $FILESYSTEM ${DISK}2 /newroot
}



exit_error() {
   # This is a utility function, it doesn't actually do work...
   # Make sure you call me after any critical commands to be sure that the
   # node reboots if there is an error!
   echo "*** ERROR ***"
   echo
   echo "I will reboot in 30 seconds..."
   sleep 30
   reboot
}

create_tmpfs() {
   # This is the default file system for Warewulf. It works well because tmpfs
   # will get pushed into swap space (if configured on local disk) in the
   # event that a local program needs access to all RAM. It is also fast, and
   # generally works well.
   echo "creating the newroot tmpfs file system"
   mkdir /newroot
   mount -t tmpfs none /newroot
   if [ $? -ne "0" ]; then
      exit_error
   fi
   echo "making this (RAM) file system the real root dev"
   mount -t proc none /proc
   echo 0x100 > /proc/sys/kernel/real-root-dev
   umount /proc
}

vnfs_vnfsd() {
   # This is the default vnfs mechanism. It scales very well for large
   # clusters, that don't utilize large disk images (the way it should be
   # under normal circumstances).
   echo "obtaining the VNFS::$VNFS image"
   cd /newroot
   wget -O - http://$MASTER:9874/$VNFS/vnfs.tar.gz | tar xzf -
   if [ $? -ne "0" ]; then
      exit_error
   fi
}

vnfs_torrent() {
   # note: The 1.03 version of libbt/btget seemed to have some bugs that 
   #       I(GMK) worked out. Get my hacked version if you want to get the i
   #       vnfs via the torrent.
   echo "obtaining the TORRENT:$VNFS image, and then seeding for 10 extra seconds"
   mkdir -p /newroot/tmp
   cd /newroot
   # Run btget locally if it exsists, otherwise try to pull it from vnfsd on
   # the master.
   if [ -f "/bin/btget" -o -f "/sbin/btget" ]; then
      btget -q 10 -f /newroot/tmp/vnfs.tar.gz -u http://$MASTER:9874/$VNFS/vnfs.tar.gz.torrent
   else
      wget http://$MASTER:9874/$VNFS/btget
      chmod +x btget 2>/dev/null
      ./btget -q 10 -f /newroot/tmp/vnfs.tar.gz -u http://$MASTER:9874/$VNFS/vnfs.tar.gz.torrent
      if [ $? -ne "0" ]; then
         exit_error
      fi
   fi
   if [ $? -ne "0" ]; then
      exit_error
   fi
   echo "exploding the VNFS image..."
   cd /newroot
   tar xvf vnfs.tar.gz
   if [ $? -ne "0" ]; then
      exit_error
   fi
}

vnfs_rsync() {
   # Typically used to keep local disk images in sync with the master vnfs. If
   # using this method, you may want to not format the disk on every boot. See
   # the create_diskfs() function defined above. Just a thought....
   echo "obtaining the RSYNC::$VNFS image"
   cd /newroot
   # You must install rsync either statically compiled, or include all of the
   # libs into /var/warewulf/wwinitrd/(bin|lib)/ if you wish to use rsync.
   rsync -aHP --delete $MASTER::$VNFS/ .
   if [ $? -ne "0" ]; then
      exit_error
   fi
}


##############################################################################
# TIME FOR WORK


# Mount the /newroot file system
STORAGE=`echo $STORAGE_DEV | cut -d ':' -f 1`
DEV=`echo $STORAGE_DEV | cut -d ':' -f 2`

if [ "x$STORAGE" = "xTMPFS" ]; then
   create_tmpfs
   FILESYSTEM=tmpfs
elif [ "x$STORAGE" = "xDISKFS" ]; then
   create_diskfs
else
   echo "I don't know how to create the storage device \"$STORAGE_DEV\"..."
   sleep 5
fi

# Obtain the VNFS
if [ "x$VNFS_GET_METHOD" = "xVNFSD" ]; then
   vnfs_vnfsd
elif [ "x$VNFS_GET_METHOD" = "xTORRENT" ]; then
   vnfs_torrent
elif [ "x$VNFS_GET_METHOD" = "xRSYNC" ]; then
   vnfs_rsync
fi


# If udev is in the VNFS, we should probably start the thing!
if [ -x "/newroot/sbin/start_udev" ]; then
   mount -t proc none /newroot/proc
   chroot /newroot /sbin/start_udev
   umount /newroot/proc
fi


echo "some final configurations"
# Logging will need this!
mknod /newroot/dev/console c 5 1

# replace the root file system macro in the fstab with the root file system
sed -i "s@%{root entry}@VNFS($VNFS)       /       $FILESYSTEM   defaults        1 1@" /newroot/etc/fstab

echo "all done..."
