#!/bin/sh
# ----------------------------------------------------------------
# file   : usbsetup.sh
# purpose: Script to setup usb based on image.
# author : Vittal.S
#
# usage  : usbsetup.sh
#
# modifications:
# 09-05-12  Initial Creation .
# ----------------------------------------------------------------

source /usr/bin/common8k

initvars( )
{
   # ////////////////////////////////////////////////////////
   # ---------------  Begin: Error Codes --------------------

   SUCCESS=0
   FAIL=2
   NOUSBFOUND=3
   USBMOUNTED=4
   ISONOTFOUND=5
   FORMATUSBFAILED=6
   BOOTSETUPFAILED=7
   CFGNOTFOUND=8
   SETUPIMAGEFAILED=9

   # ////////////////////////////////////////////////////////
   # ---------------  End:Error Codes -----------------------

   REPOSITORY=/repository
   USBMNT=/mnt
   ISOMNT=/media/cdrom
   USBDEVICE=""
   IMAGE=""

   # ////////////////////////////////////////////////////////
   # ---------------  Begin:Colour Codes --------------------

   BoldGreen="\033[1;32m"
   BoldBlue="\033[1;34m"
   BoldCyan="\033[1;36m"
   BoldWhite="\033[1;37m"
   BoldRed="\033[1;31m"
   UnderLine="\033[4m"
   Yellow="\033[1;33m"
   Norm="\033[0m"

   # ////////////////////////////////////////////////////////
   # ---------------  End:Colour Codes --------------------

   
}

#---------------------------------------------------------------
# function: checkpsintegrity
# args    : None
# description:
#   checks the integrity of patchsets using spa files.
#   Its spa time!.
#---------------------------------------------------------------

checkpsintegrity( )
{
   Iloc=$1

   #<CheckPatchsets>
      Ispa=`ls $Iloc/*.spa 2>/dev/null`
      for spaidx in $Ispa
      do
         echo "   - spa file : `basename $spaidx` located."
         cat $spaidx| awk 'BEGIN           { copy = 0 } \
                                   /\[/            { copy = 0 } \
                                   /\[Files\]/     { copy = 1 } \
                                   copy { print }' | egrep -v "^\[" > /tmp/upgrade8k.flist
         cat $spaidx| awk 'BEGIN           { copy = 0 } \
                                   /\[/            { copy = 0 } \
                                   /\[Checksums\]/ { copy = 1 } \
                                   copy { print }' | egrep -v "^\[" > /tmp/upgrade8k.cksum
         for idx in `cat /tmp/upgrade8k.flist | awk -F '=' '{ print $1 }'`
         do
            fileidx=$idx
            fileset=`cat /tmp/upgrade8k.flist | grep "${idx}=" | awk -F '=' '{ print $2 }'`
            filecksum=`cat /tmp/upgrade8k.cksum | grep "${idx}=" | awk -F '=' '{ print $2 }'`
            if [ "$fileset" != "" -a "$filecksum" != "" -a -f $Iloc/${fileset} ];
            then
               nextcksum=`md5sum $Iloc/${fileset} | awk '{ print $1 }'`
               if [ "$nextcksum" != "$filecksum" ];
               then
                  echo "   - $fileset checksum is invalid"
                  echo "   -    Expected: $filecksum"
                  echo "   -    Observed: $nextcksum"
                  exit $SETUPIMAGEFAILED
               else
                  echo "   - $fileset checksum is o.k."
               fi
            fi
         done
      done
   #</CheckPatchsets>
}

# ---------------------------------------------------------------
# function: findimage
# args    : None
# description:
#   find the image to setup on USB.
# ---------------------------------------------------------------

findimage( )
{
   nisos="`find $REPOSITORY/upload -iname \*.iso -print | wc -l`"
   if [ "$nisos" -eq 0 ];
   then
      textncolor $BoldRed "[usbsetup] No images found for setup under $REPOSITORY/upload."
      exit $ISONOTFOUND
   fi
   if [ "$nisos" -gt 1 ];
   then
      textncolor $BoldRed "[usbsetup] Many images found for setup under $REPOSITORY/upload."
      exit $ISONOTFOUND
   fi
   IMAGE="`find $REPOSITORY/upload -iname \*.iso -print`"
   if [ ! -r $IMAGE ];
   then
      textncolor $BoldRed "[usbsetup] Cannot read $IMAGE for setup."
      exit $ISONOTFOUND
   fi
   if [ -f ${REPOSITORY}/upload/node.cfg.primary -o -f ${REPOSITORY}/upload/node.cfg.secondary ];
   then
      echo "[usbsetup] Detected node.cfg."
   else
      textncolor $BoldRed "[usbsetup] No node.cfg found for setup under $REPOSITORY/upload."
      exit $CFGNOTFOUND
   fi

   checkpsintegrity ${REPOSITORY}/upload
}

# ---------------------------------------------------------------
# function: findusb
# args    : None
# description:
#   detect the 1st usb device which can be used for setup.
# ---------------------------------------------------------------

findusb( )
{
   scsilist=`sg_map -i | awk '{ print $2 }' | egrep "^/dev/sd[b-z]"`
   if [ "$scsilist" = "" ];
   then
      textncolor $BoldRed "[usbsetup] No USB device found."
      exit $NOUSBFOUND
   fi
   count=1
   devicemenu="[usbsetup] Choose one of the following device(s).\n"
   devicemenu="$devicemenu Note: The selected device will be formatted, and all data will be lost.\n"
   for idx in $scsilist 
   do
      mount | egrep -q "$idx |$idx\t"
      if [ $? -eq 0 ];
      then
         textncolor $BoldRed "[usbsetup] Device($idx) is already mounted."
         exit $USBMOUNTED
      fi
      device[$count]=$idx
      devicename=`sg_map -i| grep "$idx" | awk '{ print $3 }'`
      devicemenu="$devicemenu `echo $count $idx $devicename | awk '{ printf \"%2d. %12s %s\",$1,$2,$3 }'`\n" 
      count=$[count+1]
   done
   devicemenu="$devicemenu `echo $count None Exit |  awk '{ printf \"%2d. %12s %s\",$1,$2,$3 }'`\n"
   
   echo -e $devicemenu
   echo -n " > ?"
   read answer
   echo $answer | egrep -q "[0-9]+$"
   if [ $? -ne 0 ];
   then
      textncolor $BoldRed "[usbsetup] Invalid option."
      exit $NOUSBFOUND
   fi
   if [ $answer -lt 0 -o $answer -gt $count ];
   then
      textncolor $BoldRed "[usbsetup] Invalid option($answer)."
      exit $NOUSBFOUND
   fi
   if [ $answer -eq $count ];
   then
      textncolor $BoldCyan "[usbsetup] Goodbye."
      exit $SUCCESS
   fi

   USBDEVICE=${device[$answer]}
   if [ "$USBDEVICE" = "" ];
   then
      textncolor $BoldRed "[usbsetup] No USB device found."
      exit $NOUSBFOUND
   fi
}

# ---------------------------------------------------------------
# function: formatusb
# args    : None
# description:
#   format usb dected.
# ---------------------------------------------------------------

formatusb( )
{
   textncolor $BoldCyan "[usbsetup] Formatting USB($USBDEVICE)."
   mkfs.vfat -I $USBDEVICE
   if [ $? -ne 0 ];
   then 
      textncolor $BoldRed "[usbsetup] Could not format USB device."
      exit $FORMATUSBFAILED
   fi
}


# ---------------------------------------------------------------
# function: copyusb
# args    : None
# description:
#   copy the image to usb.
# ---------------------------------------------------------------

copyusb( )
{
   if [ -x /bin/mountpoint ];
   then
      mountpoint -q $USBMNT
   else
      cat /proc/mounts | cut -d' ' -f2 | egrep -q "^${USBMNT}$"
   fi
   if [ $? -eq 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry $USBMNT is already mounted."
      exit $FORMATUSBFAILED
   fi
   mkdir -p $ISOMNT
   if [ -x /bin/mountpoint ];
   then
      mountpoint -q $ISOMNT
   else
      cat /proc/mounts | cut -d' ' -f2 | egrep -q "^${ISOMNT}$"
   fi
   if [ $? -eq 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry $ISOMNT is already mounted."
      exit $FORMATUSBFAILED
   fi

   mount $USBDEVICE $USBMNT
   if [ $? -ne 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry Count not mount $USBDEVICE on $USBMNT."
      exit $FORMATUSBFAILED
   fi

   mount -o loop,ro $IMAGE $ISOMNT
   if [ $? -ne 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry, Count not mount $IMAGE on $ISOMNT."
      exit $FORMATUSBFAILED
   fi

   rsync -cavz -x --whole-file --force --sparse --delete ${ISOMNT}/ ${USBMNT}/
   sync
   cp -f ${USBMNT}/boot/x86_64/loader/linux  ${USBMNT}/.
   cp -f ${USBMNT}/boot/x86_64/loader/initrd ${USBMNT}/.
   cp -f ${USBMNT}/boot/x86_64/rescue        ${USBMNT}/.
   cat << EOF > ${USBMNT}/syslinux.cfg
DEFAULT linux
APPEND initrd=initrd rescue=1 install=hd:/dev/sdb root=/dev/sdb
EOF
   sync
   find ${REPOSITORY}/upload -name node.cfg.* -exec cp -f {} $USBMNT/. \;
   find ${REPOSITORY}/upload -name "*.tar"    -exec cp -f {} $USBMNT/. \;
   find ${REPOSITORY}/upload -name "*.spa"    -exec cp -f {} $USBMNT/. \;
   find ${REPOSITORY}/upload -name "*.lic"    -exec cp -f {} $USBMNT/. \;
   find ${REPOSITORY}/upload -name "*.rpm"    -exec cp -f {} $USBMNT/patch/. \;
   touch $USBMNT/patch/dev.8kps
   sync
   umount $ISOMNT
   umount $USBMNT
}

# ---------------------------------------------------------------
# function: setupusb
# args    : None
# description:
#   setus up the usb stick for boot.
# ---------------------------------------------------------------

setupusb( )
{
   textncolor $BoldCyan "[usbsetup] Setting up bootloader."
   syslinux -f $USBDEVICE
   if [ $? -ne 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry, Cound not setup bootloader."
      exit $BOOTSETUPFAILED
   fi
}

# ---------------------------------------------------------------
# function: verifyusb
# args    : None
# description:
#   verify the usb created is integral.
# ---------------------------------------------------------------

verifyusb( )
{
   textncolor $BoldCyan "[usbsetup] Verifying the usb."
   mount $USBDEVICE $USBMNT
   if [ $? -ne 0 ];
   then
      textncolor $BoldRed "[usbsetup] Sorry Count not mount $USBDEVICE on $USBMNT."
      exit $FORMATUSBFAILED
   fi
   if [ -f $USBMNT/integriy.unix ];
   then
      m5sum -c $USBMNT/integriy.unix
      pushd $USBMNT
      if [ $? -ne 0 ];
      then
         textncolor $BoldRed "[usbsetup] Sorry Count not create $USBDEVICE without errors."
         exit $FORMATUSBFAILED
      fi
      popd
   fi
   checkpsintegrity $USBMNT
   umount $USBMNT
}


initvars
textncolor $BoldCyan "[usbsetup] Starting usb setup."

#[1]. Detect the usb
findusb

#[2]. Find the image that needs to be setup
findimage

#[3]. Format the usb
formatusb

#[4]. Copy the image to USB
copyusb

#[5]. Set up boot loader
setupusb

#[6]. Verify usb
verifyusb

echo "[usbsetup] Elapsed time is `expr $SECONDS / 60` minutes."
echo "Done."
exit $SUCCESS
