#!/usr/bin/ksh 
#******************************************************************************
#* PROGRAM 	: crmklvall.ksh						      *
#* AUTHOR  	: James M. Santos					      *
#* DESCRIPTION	: Reverse engineer the creation of logical volumes.	      *
#* NOTES   	: 1) This program is not designed for LVs that were created   *
#*		     with a non-strict allocation policy. 		      *
#*		  2) The output of this program does not retain the 	      *
#*		     original positioning of the LVs within the physical      *
#*		     disks (e.g. center, inner middle, etc.).		      *
#* PARAMETERS	: 1) -o filename - send the output of the script to the	      *
#* 				   filename specified.			      *
#******************************************************************************
USAGE="Usage: $0 [-o file] "

OUTFILE=/home/santosj/bin_dev/mklvall.sh
TMPFILE=/tmp/@@crmklvall.tmp

trap 'rm -f $TMPFILE; exit' 1 2 15		# Remove temp file when signals
						#   1, 2 or 15 is received.
while getopts ":o:" OPT
do
  case $OPT in
    o ) OUTFILE=$OPTARG ;;
    * ) echo "\nERROR : $USAGE\n"
        exit 1 ;;
  esac
done

exec 1>$OUTFILE 
					
/home/santosj/bin/listpvlv.ksh -p -o $TMPFILE

echo "#************************************************************************"
echo "#* For Host    : `hostname` "
echo "#* Date        : `date +%D%t%T` "
echo "#* Description : This script contains mklv commands to create the LVs "
echo "#*               that existed when crmklvall.ksh was run on this "
echo "#*               host (`hostname`). "
echo "#* "
echo "#*               crmklvall.ksh generates this script. All existing LVs "
echo "#*               are included here (including the LVs that are "
echo "#*               automatically created when AIX is installed). For safety"
echo "#*               reasons, all lines in this script are commented out. "
echo "#* "
echo "#*               Uncomment only the lines that you need. "
echo "#************************************************************************"

awk '
NF == 3 && /^Info/ {
  PVNAME = $3;
}
NF == 6 && /^Part/ {
  VGNAME = $6;
}
NF == 7 && /^1|^2|^3/ {
printf("%s %-20s %-2s %-10s %4d %s\n",$1,$3,$2,VGNAME,$6,PVNAME);
}' $TMPFILE | \
sort -k 1,3 -k 6 | \
awk '
BEGIN { FIRST_REC = 1; FIRST_MIR_REC = 1; i=1 }
{
  if ($1 == 1)				# If the current LV is not mirrored.
  {					
    if ($3 !~ "S$")			# If the current LV is not striped.
    {
      if (STR_ARRAY_PV[1] != "")	# Test for striped LV processing break.
      {					# If there is a break, invoke the
        print_strlv();			#   function to print the mklv 
      }					#   command with disk striping.
      if (FIRST_REC)			# Test for the first input record.
      {
        print_line("1dsk");
        PREVLV_1 = $2;
        FIRST_REC = 0;
        next;
      }
      if ($2 == PREVLV_1)		# If the current record pertains to the
      {					#   the same LV in the previous record,
        print_line("ext");		#   then print an extendlv command.
        next;
      }
      else
      {					# If the current record pertains to a 
        print_line("1dsk");		#   new LV, then print a mklv command.
        PREVLV_1 = $2;
        next;
      }  
    }
    else
    if ($3 ~ "S$")			# If the current LV is striped.
    {
      if ($2 == STRLV)			# If the current record pertains to the
      {					#   same striped LV in the previous
        STR_ARRAY_SZ[i]=$5;		#   record, then save the size and
        STR_ARRAY_PV[i]=$6;		#   physical volume name in an array.
        i++;				#   This will be used later when
      }					#   printing the mklv command with
      else				#   disk striping.
      {
        if (STR_ARRAY_PV[1] != "")	# Test for striped LV processing break.
        {				# If there is a break, invoke the
          print_strlv();		#   function to print the mklv 
        }				#   command with disk striping.
        STRLV=$2;
        STRVG=$4;
        STRSZ=$5;
        STRPV=$6;
      }
      next;
    }
  }
  else
  if ($1 > 1) 				# If the current LV is mirrored.
  {
    if (STR_ARRAY_PV[1] != "")		# Test for striped LV processing break.
    {					# If there is a break, invoke the
      print_strlv();			#   function to print the mklv
    }					#   command with disk striping.
    if (FIRST_MIR_REC)			# Test for the first mirrored LV  
    {					#   encountered.  Do not print any
      PREVLV_1 = $2;			#   mklv commands yet.  Just save the
      PREVPV_1 = $6;			#   information in the first set of
      FIRST_MIR_REC = 0;		#   variables.
      next;
    }
    if ($2 == PREVLV_1 && $2 != PREVLV_2) # Test whether the current record
    {					  #   pertains to the same LV in the
      PREVCP_2 = $1;			  #   previous record. Do not print any
      PREVLV_2 = $2;			  #   mklv commands yet.  Just save the
      PREVVG_2 = $4;			  #   information in the second set of
      PREVSZ_2 = $5;			  #   variables.
      PREVPV_2 = $6;
      next;
    }					# Break processing for 3 copy LVs.
    if ($2 == PREVLV_2)  		#   Assumes a maximum of 3 copies.
      print_line("3mir");		#   This tests whether the current LV
    else				#   is the same as the LV in the two
    {					#   previous records ($2 == PREVLV_2).
      if (PREVCP_2 == 2)		# Everything inside this else is 
        print_line("2mir");		#   executed whether the LV has two
      PREVLV_1 = $2;			#   or three copies.  This is why this
      PREVPV_1 = $6;			#   if (PREVCP_2 == 2) is needed.
    }  					#   Execute the printing of 2 disk 
  }					#   mirrors only for break processing
  else					#   of two copy LVs.
    print "Error in parsing !!!";
} END { if (PREVCP_2 == 2)  		# If the last record processed was 
          print_line("2mir");		#   a mirrored LV, then print that rec.
        if (STR_ARRAY_PV[1] != "")	# If the last record processed was
          print_strlv();		#   a striped LV, then print that rec.
} 

function print_line(opt)
{
  if (opt == "1dsk")
    printf("#%s %-20s %2s %s %-10s %4d %s\n", "mklv -y",$2,"-c",$1,$4,$5,$6); 
  else
  {
    if (opt == "ext")
      printf("#%s %-20s %4d %s\n", "extendlv",$2,$5,$6); 
    else
    {
      if (opt == "2mir")
        printf("#%s %-20s %2s %s %-10s %4d %s %s\n", \
         "mklv -y",PREVLV_2,"-c",PREVCP_2,PREVVG_2,PREVSZ_2,PREVPV_1,PREVPV_2); 
      else
      {
        if (opt == "3mir")
          printf("#%s %-20s %2s %s %-10s %4d %s %s %s\n", \
                 "mklv -y",$2,"-c",$1,$4,$5,PREVPV_1,PREVPV_2,$6); 
        else
        {
          printf("%s\n", "Error : print_line()");
          return 1;
        }
      }
    }
  }  
  return 0;
}

function print_strlv() 
{
  TOT_STRSZ = STRSZ;
  for (i=1; STR_ARRAY_SZ[i] != ""; i++)	# Add up the size pertaining to each
  {					#   physical volume.
    TOT_STRSZ += STR_ARRAY_SZ[i];
    STR_ARRAY_SZ[i] = "";		# Initialize the array.
  }

					# Run the lslv command to get the
					#   stripe size. 
  "lslv "STRLV" | tail -1 | cut -c21-24" | getline STRIPE_SIZE;
  printf("#%s %-20s %2s%4s %-10s %4d %s", \
         "mklv -y",STRLV,"-S",STRIPE_SIZE,STRVG,TOT_STRSZ,STRPV); 

  for (i=1; STR_ARRAY_PV[i] != ""; i++)	# Loop through the PV array and print
  {					#   the rest of the PVs that are part
    printf(" %s", STR_ARRAY_PV[i]);	#   of the same stripe set.
    STR_ARRAY_PV[i] = "";		# Initialize the array.
  }
  printf("\n");

  i=1;
  return 0;
}' -  

rm $TMPFILE
