#!/bin/sh # BULDVOL v1.2 January 29, 2000 # ----------------------------- # BULDVOL does for your volume set configuration what BULDACCT.PUB.SYS does # for your accounting structure. The output is a command file that can be # fed back to VOLUTIL.PUB.SYS: # # :XEQ SH.HPBIN.SYS BULDVOL >SOMEFILE # :XEQ VOLUTIL.PUB.SYS "USE SOMEFILE" # # Downloading this script: # # http://www.bixby.org/ftp/pub/mpe/buldvol-1.2.sh # ftp://ftp.bixby.org/pub/mpe/buldvol-1.2.sh # # Contacting the author: # # Mark Bixby # mark@bixby.org # http://www.bixby.org/mark/ # # THIS FREEWARE IS NOT SUPPORTED BY HP! # # CHANGE HISTORY # -------------- # 1.2 January 29, 2000 # # Oops! The previous update broke the old :DSTAT format. # # 1.1 January 22, 2000 # # Updated to handle the new :DSTAT format. Should still be compatible # with the old format. # # 1.0 March 13, 1998 # # Initial public release. # # Configuration constants. # VOLUTIL=/SYS/PUB/VOLUTIL TEMP=/tmp/buldvol.$$ # # Functions. # # # Obtain the master volume name and LDEV for a volume set. # function dstat_extract { # Strip optional parentheses and split volume set name into VSN and GEN. VSNG=$1 `echo $VSNG | sed -e 's/^(//' -e 's/)$//' | awk '\ { match($0,/[0-9]+$/); printf "eval VSN=%s GEN=%s", substr($0,1,RSTART-2),substr($0,RSTART,RLENGTH) }'` # Scan :DSTAT output to find the master volume entries for this volume set. `awk -v VSNG="$VSNG" '\ BEGIN { HITS=0; printf "eval " } $NF == VSNG && substr($(NF-2),1,6) == "MASTER" { HITS++; ldevlen=index($1,"-")-1; if (ldevlen < 0) ldevlen=length($1); ldev=substr($1,1,ldevlen); printf " LDEV%d=%d MASTER%d=%s",HITS,ldev,HITS,$(NF-1) }' $TEMP.dstat` } # # Obtain the list of all classes in a volume set. # function get_all_classes { ALLCLASSES=`callci xeq $VOLUTIL "\"showset $1 info=classes\"" |\ awk '$2 ~ /^[0-9]+$/ { print $1 }'` } # # Obtain the list of member classes for a volume. # function get_vol_classes { CLASSES=`callci xeq $VOLUTIL "\"showvol $1 info=classes\"" |\ awk '$2 ~ /^[0-9]+$/ { print $1 }'` } # # Obtain the permanent and transient percentages for a volume. # function get_percent { `callci xeq $VOLUTIL "\"showvol $1 info=volinfo\"" | awk '\ BEGIN { print "eval " } $2 == "permanent" { printf "PERM=%d ",substr($4,1,length($4)-1) } $2 == "transient" { printf "TRANS=%d ",substr($4,1,length($4)-1) }'` } # # Generate NEWCLASS commands for additional non-master classes. # function newclass { NEWCLASSES=`echo $ALLCLASSES $CLASSES | tr ' ' '\n' | sort | uniq -u` if [ "$NEWCLASSES" ]; then for CLASS in $NEWCLASSES; do echo "NEWCLASS CNAME=$VSN:$CLASS" done fi } # # Generate NEWVOL and ALTERVOL commands for all volumes in a volume set. # function newvol { VOLUMES=`callci xeq $VOLUTIL "\"showset $VSN info=volumes\"" |\ awk '$2 ~ /^[0-9]+$/ { print $1 }'` for VOLUME in $VOLUMES; do LDEV=`callci xeq $VOLUTIL "\"showvol $VSN:$VOLUME info=dstatus\"" |\ awk '$3 ~ /^[0-9]+$/ { print $3 }'` get_percent "$VSN:$VOLUME" get_vol_classes "$VSN:$VOLUME" FMTCLASSES=`echo $CLASSES | sed -e 's/ /,/g'` echo "NEWVOL VNAME=$VSN:$VOLUME PERM=$PERM TRANS=$TRANS LDEV=$LDEV \ CLASSES=($FMTCLASSES)" echo "ALTERVOL VNAME=$VSN:$VOLUME PERM=$PERM TRANS=$TRANS" done } # # Generate a NEWSET command for a volume set. # function newset { dstat_extract $1 get_all_classes $VSN get_vol_classes "$VSN:$MASTER1" FMTCLASSES=`echo $CLASSES | sed -e "s/ /,/g"` get_percent "$VSN:$MASTER1" echo "NEWSET SNAME=$VSN MASTER=$MASTER1 PERM=$PERM TRANS=$TRANS LDEV=$LDEV1 \ CLASSES=($FMTCLASSES) GEN=$GEN" newclass newvol } # # Generate NEWMIRRVOL/ALTERVOL commands for a mirrored volume set. # function newmirrvol { callci xeq $VOLUTIL "\"showset $VSN info=mirror\"" |\ awk '$4 ~ /^[0-9]+$/ { printf "%s %d %d\n",$1,$4,$5; getline }' >$TEMP.mirror set -A VOLUME `cut -f 1,1 -d " " $TEMP.mirror` set -A LDEV `cut -f 2,2 -d " " $TEMP.mirror` set -A MIRR `cut -f 3,3 -d " " $TEMP.mirror` I=0 while [ $I -lt ${#VOLUME[*]} ]; do get_percent "$VSN:${VOLUME[$I]}" get_vol_classes "$VSN:${VOLUME[$I]}" FMTCLASSES=`echo $CLASSES | sed -e 's/ /,/g'` echo "NEWMIRRVOL VNAME=$VSN:${VOLUME[$I]} PERM=$PERM TRANS=$TRANS \ LDEVS=(${LDEV[$I]},${MIRR[$I]}) CLASSES=($FMTCLASSES)" echo "ALTERVOL VNAME=$VSN:${VOLUME[$I]} PERM=$PERM TRANS=$TRANS" I=`expr $I + 1` done } # # Generate a NEWMIRRSET command for a mirrored volume set. # function newmirrset { dstat_extract $1 get_all_classes $VSN get_vol_classes "$VSN:$MASTER1" FMTCLASSES=`echo $CLASSES | sed -e 's/ /,/g'` get_percent "$VSN:$MASTER1" echo "NEWMIRRSET SNAME=$VSN MASTER=$MASTER1 PERM=$PERM TRANS=$TRANS \ LDEVS=($LDEV1,$LDEV2) CLASSES=($FMTCLASSES) GEN=$GEN" newclass newmirrvol } # # Main body. # callci dstat all >$TEMP.dstat # Process all non-mirrored volume sets. NVSNS=`awk '\ $(NF-2) == "MASTER" || $(NF-2) == "MEMBER" { print $NF }' $TEMP.dstat | sort | uniq` for NAME in $NVSNS; do newset $NAME done # Process all mirrored volume sets. MVSNS=`awk '\ $(NF-2) == "MASTER-MD" || $(NF-2) == "MEMBER-MD" { print $NF }' $TEMP.dstat | sort | uniq` for NAME in $MVSNS; do newmirrset $NAME done rm -f $TEMP.dstat rm -f $TEMP.mirror