#!/bin/sh
#
# Author: Paul Robertson
# 
# This script automates the process of creating a mirror of the boot
# disk with Solstice DiskSuite.
#

PATH=/usr/ucb:/bin:/usr/bin:/sbin:/usr/sbin:/usr/opt/SUNWmd/sbin
SYSROOT=
OS=`uname -r`
bootdir="/etc/rc3.d"
rebootscript="S99sdsattach"
version="$Id$"

tmpfile1=/tmp/sdsinstall1.$$
tmpfile2=/tmp/sdsinstall2.$$
tmpfile3=/tmp/sdsinstall3.$$

bail()
{
  # clean up any temporary files and return system to known state
  exit 101
}

xcmd()
{
  if [ ! -z "$debug" ]
  then
          echo "$@" >&2
  fi
  "$@"
  [ $? = 0 ] || bail
}

preinstall()
{
  # Check to make sure the system is ready for us

  if [ ! -x $BINDIR/metadb ]; then
    echo "Error: Disksuite does not appear to be installed. Exiting."
    exit 102
  fi

  # If any state database replicas exist, then quit
  if [ `metadb|wc -l 2>/dev/null` -gt 0 ]; then
    echo "Error: There appears to be a preexisting DiskSuite installation. Exiting."
    exit 102
  fi
  # If any metadevices exist, then quit
  if [ `metastat|wc -l 2>/dev/null` -gt 0 ]; then
    echo "Error: There appears to be a preexisting DiskSuite installation. Exiting."
    exit 102
  fi
}

read_vfstab()
{
  # determine which slices to mirror to the secondary disk(s)
  if [ "x$debug" != "x" ]; then
    echo "Reading /etc/vfstab..."
  fi

  if [ ! -f $SYSROOT/etc/vfstab ]; then
     "Error: $SYSROOT/etc/vfstab"
     exit 101
  fi

  exec 9<&0 < $SYSROOT/etc/vfstab
  while read _special _fsckdev _mountp _fstype _fsckpass _automnt _mntopts
  do
    case ${_special} in
      '#'* | '')  #  Ignore comments, empty lines
    	   continue ;;
      '-')                #  Ignore no-action lines
    	   continue ;;
      /dev/dsk/${primary}*)
           _slice=`expr "\${_special}" : '/dev/dsk/.*s\(.\)\$'`
           slices="$slices ${_slice}"
           ;;
    esac

  done
  exec <&9 9<&-

  init_metadbs
}

partition_secondaries()
{
  if [ "x$debug" != "x" ]; then
    echo "Partitioning $secondaries..."
  fi

  for _secondary in $secondaries
  do
    # Copy the partition table from the primary disk to the destination disk
    xcmd prtvtoc /dev/rdsk/${primary}s2 | fmthard -s - /dev/rdsk/${_secondary}s2
    # ensure that the destination is bootable
    xcmd installboot /usr/platform/`uname -i`/lib/fs/ufs/bootblk /dev/rdsk/${_secondary}s0
  done
}

init_metadbs()
{
  if [ "x$debug" != "x" ]; then
    echo "Initializing metadevices..."
  fi

  for _disk in $primary $secondaries
  do
    for _metadb in $metadbs
    do
      xcmd metadb -c $copies -f -a /dev/rdsk/${_disk}${_metadb}
    done
  done
}

update_vfstab()
{
  if [ "x$debug" != "x" ]; then
    echo "Updating /etc/vfstab..."
  fi
  
  sed "s/\/dev\/dsk\/${primary}s/\/dev\/md\/dsk\/d/; s/\/dev\/rdsk\/${primary}s/\/dev\/md\/rdsk\/d/" $SYSROOT/etc/vfstab > $tmpfile2

}

yorn()
{
  echo -n "$1"
  while true
  do
          read input
          case $input in
          y|Y|yes)  return 0;;
          n|N|no)   return 1;;
          *)      echo -n "Please respond with \"y\" or \"n\": "
                  continue;;
          esac
  done
}

finish()
{
  #make a backup copy of the vfstab file
  xcmd cp -p $SYSROOT/etc/vfstab $SYSROOT/etc/vfstab.bak.`date '+%m%d'`

  # I think it's a safe assumption that the root metadevice will be 0
  xcmd metaroot -v $tmpfile2 d0

  # Put the SDS-aware vfstab into place
  xcmd mv $tmpfile2 $SYSROOT/etc/vfstab
  xcmd chmod 644 $SYSROOT/etc/vfstab 

  _dump_device=`awk '/^\/dev\/md\/dsk\/d.*swap/ {print $1}' $SYSROOT/etc/vfstab| head -1`

  if [ ! -z "$_dump_device" -a -f /usr/sbin/dumpadm ]; then
      echo "Setting dump device to metadevice $_dump_device"
      echo "/usr/sbin/dumpadm -c kernel -d $_dump_device"
      /usr/sbin/dumpadm -c kernel -d $_dump_device
  else 
      echo "NOTICE: Unable to automatically configure dump device."
  fi

  # Put the reboot script in place
  xcmd mv $tmpfile1 ${bootdir}/$rebootscript
  xcmd chmod 755 ${bootdir}/$rebootscript

  cleanup

  if [ "x$quiet" != "xtrue" ]; then
    # Prompt the user to reboot the system
    yorn "The system needs to be rebooted for changes to take affect. Proceed?: " && \
     /usr/sbin/shutdown -y -g0 -i6
  else
    # Just reboot now
     /usr/sbin/shutdown -y -g0 -i6
  fi 
}

buildmetadevices()
{
  read_vfstab

  for _slice in $slices
  do
    _i=1
    xcmd metainit -f d1${_slice} 1 1 ${primary}s${_slice}
    xcmd metainit d${_slice} -m d1${_slice}
    for _secondary in $secondaries
    do
      _i=`expr "${_i}" + 1`
      xcmd metainit -f d${_i}${_slice} 1 1 ${_secondary}s${_slice}
      echo "metattach d${_slice} d${_i}${_slice}" >> $tmpfile1
    done
  done

  if [ -f $DATADIR/md.tab ]; then
    mv $DATADIR/md.tab $DATADIR/md.tab.`date '+%m%d'`
  fi

  metastat -p > $DATADIR/md.tab
  
  # The last thing the reboot script does is ensure it only runs once
  echo "mv ${bootdir}/$rebootscript /tmp/_dont_start_${rebootscript}" >> $tmpfile1
}

createrebootscript()
{
  if [ "x$debug" != "x" ]; then
    echo "Creating reboot script..."
  fi

  echo "#!/bin/sh" > $tmpfile1
  echo "#" >> $tmpfile1
  echo "# This script simply attaches the SDS mirrors to" >> $tmpfile1
  echo "# the primaries after reboot" >> $tmpfile1
  echo "#" >> $tmpfile1
  echo "PATH=/bin:/usr/bin:/sbin:/usr/sbin:$BINDIR" >> $tmpfile1
}

cleanup()
{
  rm -f $tmpfile1 $tmpfile2
}

printusage()
{
  echo "Usage: `basename $0` [-v] [-h] [-d] [-c copies] [-p primary] [-s secondary]... [-m metadb]..."
  echo " "
  echo "Eg: ./sdsinstall -p c0t0d0 -s c0t1d0 -m s5 -m s6"
  exit 0
}


if [ $# -eq 0 ]; then
   printusage
else
    while getopts qhvdc:p:s:m: OPTION
    do
          case $OPTION in
            q)quiet=true;; # don't run interactively
            d)debug=true;;
            v)echo "`basename $0`$version"
              exit 0;;
            p)primary=$OPTARG;;
            s)secondaries="$secondaries $OPTARG";;
            m)metadbs="$metadbs $OPTARG";;
            c)copies=$OPTARG;;
            \?|h)printusage;;
          esac
    done
    shift `expr $OPTIND - 1`
fi

case $OS in
    5.6|5.7)
	BINDIR=/usr/opt/SUNWmd/sbin
        DATADIR=/etc/opt/SUNWmd/
	;;
    *)  BINDIR=/usr/sbin
        DATADIR=/etc/lvm
esac

# If we are running non-interactively, we may not know the primary
if [ -z "$primary" ]; then
  # find the c0t0d0 part of the df -k
  primary=`df -k / | tail -1 | \
   sed "s+/dev/dsk/\(c[0-9][0-9]*t[0-9][0-9]*d[0-9][0-9]*\)s[0-9][0-9]*.*+\1+"`
fi

if [ "x$quiet" != "xtrue" ]; then
  echo "This program will mirror all the slices on $primary"
  echo "listed in $SYSROOT/etc/vfstab to their corresponding"
  echo "slices on $secondaries."
  echo " "
  echo "It will then configure the system to use Disksuite, and"
  echo "ask you to reboot the system. After the reboot, the mirrors"
  echo "on $secondaries will be attached."
  echo ""
  echo "You have selected the following:"
  echo ""
  echo " Primary Disk            : $primary"
  echo " Secondary Disk(s)       :$secondaries"
  echo -n " State database replicas :"
  for _disk in $primary $secondaries
  do
    for _slice in $metadbs
    do
      echo -n " ${_disk}${_slice}"
    done
  done
  echo " "
  echo " "
  echo "Warning: All data on$secondaries will be destroyed!"
  yorn "Continue? [y/n]: " || exit 0
fi
  
if [ "x$debug" != "x" ]; then
   echo "primary       : $primary"
   echo "secondaries   : $secondaries"
   echo "metadb slices : $metadbs"
fi
 
preinstall
partition_secondaries
createrebootscript
buildmetadevices
update_vfstab
finish
