#!/bin/sh # # (C) aryzhov@excite.com # # Now, we have already encapsulated the rootdisk, and rebooted # from rootvol. 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 rootvol 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 rootvol-$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? ROOT=/ ; [ -d /*-specific/hacks ] && ROOT="/a" VFSTAB_APPEND=/tmp/vfstab.append 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="rootvol swapvol 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 )`" vxdisk list | grep $TRGDISK >&- 2>&- || { echo $TRGDISK is not defined ; exit 1 ; } vxprint -v | grep "rootvol-${NMIRR}" >&- 2>&- && { echo Mirror $NMIRR already taken ; exit 1 ; } FORMATF=/tmp/.format.$$; VTOC=/tmp/.vtoc.$$; VXCOMMF=/tmp/.vxcomm.$$ PRIVREGCYL=0 # Normal starting cylilnder for a private region DEFPRIVSLC=3 # Default slice for private region DEFPUBLSLC=4 # -- " ---" --- for public region # Some sanity checks. 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 ' rootvol-' | 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 ; } FORMATT="" CSZ=`prtvtoc /dev/rdsk/$PHYSTRG | grep 'sectors/cylinder' | awk '{print $2}'` OFFSET=0 TSLICE=0 echo pa >$FORMATF echo "" >$VTOC echo "" >$VFSTAB_APPEND 2>&- echo >$VXCOMMF || exit 1 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 ; } [ `expr $NUMCYL \* $CSZ` -ne $LEN ] && { NUMCYL=`expr $NUMCYL + 1` ; LEN=`expr $NUMCYL \* $CSZ` ; } echo " $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 & " >>$VXCOMMF OFFSET=`expr $OFFSET + $LEN` FSECT=`expr $BEGCYL \* $CSZ` NSECT=`expr $NUMCYL \* $CSZ` LSECT=`expr $NSECT + $FSECT - 1` case $VOL in rootvol) TAG=root ; TNM=2 ; FLAGS=00 ; WM=wm ;; swapvol) 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 echo $TSLICE $TNM $FLAGS $FSECT $NSECT $LSECT >>$VTOC echo "`printf '%1d' $TSLICE`\n$TAG\n$WM\n$BEGCYL\n${NUMCYL}c" >>$FORMATF echo "/dev/dsk/${PHYSBAS}s$TSLICE /dev/rdsk/${PHYSBAS}s$TSLICE /$VOL ufs $TSLICE no -" >>$VFSTAB_APPEND 2>&- done echo Initialising the $TRGDISK, creating and attaching plexes echo About to run cat $VXCOMMF echo echo Sleeping $GRACE seconds... Last chance ... sleep $GRACE sh $VXCOMMF && rm -f $VXCOMMF || exit 1 sleep 1 VOLD="`prtvtoc -h /dev/rdsk/${PHYSBAS}s2`" 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 >>$VTOC echo === echo $FORMATF === cat $FORMATF echo === echo === $VTOC === cat $VTOC echo === echo "la\nq\nq" >>$FORMATF format -s -f $FORMATF /dev/rdsk/${PHYSBAS}s2 || { fmthard -s - /dev/rdsk/${PHYSBAS}s2 <$VTOC || { [ $TRGDISK = rootdisk ] && { dd if=/dev/rdsk/${PHYSSRC} of=/dev/rdsk/${PHYSBAS}s2 count=1 } } } rm -f $FORMATF $VTOC # # 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 &" # # Skip this, as modifying /a may be dangerous in Postinstall scripts # # sh -c "cat $VFSTAB_APPEND >$VFSTAB_TARGET 2>&- ; exit 0"