#!/bin/sh
#
# (C) aryzhov@excite.com
#
# Now, we have already encapsulated the rootdisk, and rebooted
# from ${RootVolName}. Sure rootdisk structure looks terrible, and some volumes
# may even be not visible in VTOC... And none will be visible
# on a second submirror if we create it the "Veritas recommended" way... :-(
#
# Be a man...
#
# Initialise the second disk and clone the subdisks and plexes the way we like,
# then attach new plexes to ${RootVolName} and friends
#
# At the same time, generate a better VTOC that reflects ALL volumes,
# (or at least 5 of them :-)
# and overwrite the existing VTOC (on a newly cloned disk only!)
#
# After the mirrors will have been resynced, I recommend to detach the
# submirrors that are on the original rootdisk and run the whole procedure
# in opposite direction, i.e. clone rootdisk from secondary disk
# using the same script. (You may have to modify first 4 lines of the script)
#
# As a result, you get two absolutely symmetric mirrored disks,
# with all physical slices visible.. just like with old good DiskSuit :-)
#
#
#                  "... and the ONLY copy of 'restore' was on that disk :-("
#

[ $# -ne 4 ] && {
  echo "
	USAGE: $0 FROM NEWNAME MEDIA INDEX

		FROM      -  vxdisk name where current root mirror is
		NEWNAME   -  what to name the new submirror vxdisk
		MEDIA     -  where to put the new vxdisk, like c1t3d0
		INDEX     -  what to name the plex indices, like ${RootVolName}-$INDEX
  "
  exit 1
}

SRCDISK=$1
TRGDISK=$2
PHYSBAS=$3
NMIRR=$4
GRACE=10        # Grace period for warnings
MAKEVX=YES      # Do we want the plexes made and attached, or just generate the label/VTOC?

RootVolName=root
SwapVolName=swap
VTOC=""
FORM="pa\n"
COMM=""
PRIVREGCYL=0    # Normal starting cylilnder for a private region
DEFPRIVSLC=3    # Default slice for private region
DEFPUBLSLC=4    # -- " ---" --- for public region


ROOT=/      ; [ -d /*-specific/hacks ] && ROOT="/a"
VFSTAB_TARGET=$ROOT/etc/vfstab.append.$PHYSBAS

[ "$SRCDISK" = "$TRGDISK" ] && {
  echo "Source and Target disks are the same - generating new VTOC only, no VXmake things"
  MAKEVX=NO
} || vxprint | grep ${TRGDISK}- >&- 2>&- && { echo Target VxVM disk already defined - exiting ; exit 1 ; }

SKIP="" ; [ "$MAKEVX" != YES ] && SKIP="echo Skipping"
# Initialise the new disk
#SKIP    vxdisk online $PHYSBAS                         || exit 1
$SKIP    /etc/vx/bin/vxdisksetup -i $PHYSBAS            || exit 1
$SKIP    vxdg -g rootdg adddisk ${TRGDISK}=$PHYSBAS     || exit 1

# Prepare the list of existing volumes on rootdisk and arrange them
# in exactly the order we want # on the targetdisk. First, find the existing volumes
# in $DEFAULT_ORDER list, and then print all others on random order
# Skip the slices 3 and 4, as we presume they hold the Private and Public regions.

DEFAULT_ORDER="${RootVolName} ${SwapVolName} var usr opt home export" # Whatever is there
VOLUMES="`(
  for i in $DEFAULT_ORDER ; do vxprint -g rootdg -v -F '%{name:-20}%{len:20}' | grep \"^$i\" ; done
  vxprint -g rootdg -v -F '%{name:-20}%{len:20}' | egrep -v \"^\`echo $DEFAULT_ORDER | sed 's/ /\ \|\^/g'\`\"
) | (
  TSLICE=0 ; while read VOL LEN ; do [ $TSLICE -eq 2 ] && TSLICE=5
    printf \"%02d      %-20s %20d\n\" $TSLICE $VOL $LEN
    TSLICE=\`expr $TSLICE + 1\`
   done
)`"

# Some sanity checks.
vxdisk list | grep $TRGDISK  >&- 2>&- || { echo $TRGDISK is not defined ; exit 1 ; }
vxprint -v | grep "${RootVolName}-${NMIRR}"  >&- 2>&- && { echo Mirror $NMIRR already taken ; exit 1 ; }
PHYSSRC=`vxprint -F '%{da_name}' $SRCDISK`
PHYSTRG=`vxprint -F '%{da_name}' $TRGDISK`
[ -z "$PHYSSRC"  -o  -z "$PHYSTRG" ] && { echo "$SRCDISK or $TRGDISK not found by VxVM" ; exit 1 ; }
[ "`echo $PHYSTRG | sed -e 's/s2//'`" != "$PHYSBAS" ] && { echo "$PHYSTRG is not a slice of $PHYSBAS" ; exit 1 ; }
ROOTSRCSD=`vxprint -s | grep "^sd ${SRCDISK}-" | sort | uniq | grep " ${RootVolName}-" | awk '{print $2}'`
ROOTLEN=`vxprint -F '%{len}' $ROOTSRCSD`
VTOCTRG="`prtvtoc -h /dev/rdsk/$PHYSTRG`"
PRIVSLICE=`echo "$VTOCTRG" | awk '{ if ($2 == 15) print $1}'`
PRIVSTART=`echo "$VTOCTRG" | awk '{ if ($2 == 15) print $4}'`
PRIVLENGT=`echo "$VTOCTRG" | awk '{ if ($2 == 15) print $5}'`
PRIVEND=`expr $PRIVSTART + $PRIVLENGT"`
PUBLSLICE=`echo "$VTOCTRG" | awk '{ if ($2 == 14) print $1}'`
PUBLSTART=`echo "$VTOCTRG" | awk '{ if ($2 == 14) print $4}'`
PUBLLENGT=`echo "$VTOCTRG" | awk '{ if ($2 == 14) print $5}'`
PUBLEND=`expr $PUBLSTART + $PUBLLENGT"`
PUBENDVTC=`echo "$VTOCTRG" | awk '{ if ($2 == 14) print $6}'`
ENDOFDISK=`echo "$VTOCTRG" | awk '{ if ($2 == 5)  print $6}'`
[ $ENDOFDISK -ne $PUBENDVTC ] && { echo public region of $TRGDISK not on the disk end ; exit 1 ; }
CSZ=`prtvtoc /dev/rdsk/$PHYSTRG | grep 'sectors/cylinder' | awk '{print $2}'`
OFFSET=0
TSLICE=0

echo "$VOLUMES" |  while read TSLICE VOL LEN ; do
  [ $TSLICE -gt 7 ] && { echo "WARNING: No more slices to allocate for $VOL:\n$VOLUMES" ; break ; }
  SDX=$TSLICE
  SUBDISKBEG=`expr $PUBLSTART + $OFFSET`
  # What if PRIVATE region is physically INSIDE the PUBLIC region?! (yeah, original rootdisk...)
  [ $PRIVSTART -gt $PUBLSTART -a  $PRIVEND -lt $PUBLEND -a $SUBDISKBEG -ge $PRIVSTART ] && SUBDISKBEG=`expr $SUBDISKBEG + $PRIVLENGT`
  SUBDISKEND=`expr $SUBDISKBEG + $LEN - 1`
  [ "$SUBDISKEND" -gt "$PUBENDVTC" ] && { echo "$SUBDISK calculated end is beyond the public region of $TRGDISK" ; exit 1 ; }
  BEGCYL=`expr $SUBDISKBEG / $CSZ`
  NUMCYL=`expr $LEN / $CSZ`
  [ `expr $BEGCYL \* $CSZ` -ne $SUBDISKBEG ] && { echo "$SUBDISK begin $SUBDISKBEG is not on cylinder $BEGCYL boundary " ; exit 1 ; }
  [ `expr $NUMCYL \* $CSZ` -ne $LEN ] && { echo "$SUBDISK length $LEN is not a multiple of cylinder size $CSZ   " ; exit 1 ; }

  COMM="$COMM\n
    $SKIP    vxmake sd ${TRGDISK}-${SDX} dm_name=$TRGDISK dm_offset=$OFFSET len=$LEN    || exit 1
    $SKIP    vxmake plex ${VOL}-$NMIRR sd=${TRGDISK}-$SDX                               || exit 1
    $SKIP    time vxplex att $VOL ${VOL}-$NMIRR &
  "

  OFFSET=`expr $OFFSET + $LEN`

  FSECT=`expr $BEGCYL \* $CSZ`
  NSECT=`expr $NUMCYL \* $CSZ`
  LSECT=`expr $NSECT + $FSECT - 1`

  case $VOL in
    ${RootVolName})  TAG=root        ; TNM=2 ; FLAGS=00 ; WM=wm       ;;
    ${SwapVolName})  TAG=swap        ; TNM=3 ; FLAGS=01 ; WM=wu       ;;
    var)             TAG=$VOL        ; TNM=7 ; FLAGS=00 ; WM=wm       ;;
    usr)             TAG=$VOL        ; TNM=4 ; FLAGS=00 ; WM=wm       ;;
    home)            TAG=$VOL        ; TNM=8 ; FLAGS=00 ; WM=wm       ;;
    *)               TAG=unassigned  ; TNM=0 ; FLAGS=00 ; WM=wm       ;;
  esac

  VTOC="$VTOC\n`echo $TSLICE $TNM $FLAGS $FSECT $NSECT $LSECT`"
  FORM="$FORM`printf '%1d' $TSLICE`\n$TAG\n$WM\n$BEGCYL\n${NUMCYL}c"
done

echo Initialising the $TRGDISK, creating and attaching plexes
echo "About to run\n$COMM\nSleeping $GRACE seconds... \nLast chance ..."
sleep $GRACE
eval `echo "$COMM"`
sleep 1
VOLD="`prtvtoc -h /dev/rdsk/${PHYSBAS}s2`"

VTOC="$VTOC`
  prtvtoc -h /dev/rdsk/${PHYSBAS}s2 | while read Nm Tg Rest ; do
    [ $Tg -eq 5  -o   $Tg -eq 15   -o   $Tg -eq 14 ]  && echo $Nm $Tg $Rest
  done
`"

FORM="$FORM\nla\ny\nq\nq"
echo "=== VTOC ===\n $VTOC \n==="
echo "=== FORM ===\n $FORM \n==="

echo "$FORM" | format -s /dev/rdsk/${PHYSBAS}s2 || {
  echo "$VTOC" | fmthard -s - /dev/rdsk/${PHYSBAS}s2 || {
    [ $TRGDISK = rootdisk ] && {
      dd if=/dev/rdsk/${PHYSSRC} of=/dev/rdsk/${PHYSBAS}s2 count=1
    }
  }
}

#
# This part is still a bit dirty - we need to wait till resync
# af at least rootfs is done... Shall write a nicer checkup later.
#
/etc/vx/bin/vxbootsetup
nohup sh -x "sleep 1200 ; /etc/vx/bin/vxbootsetup &"

