#!/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 &"