#!/bin/ksh
#
# @(#)confccdssa.sh 1.11 97/12/16 SMI
#

#####################################################################################
#
# lookup a value in ccd static file
#
#####################################################################################

function enccdmatch
{
        ${mybin}/ccdmatch $* ${ccdfile} || \
                (log_error "$pre.4703" "ccdmatch $* ${ccdfile} failed" 1>&2; return 1)
}
################################################################################
#
# function build_devset mode
#
# This function will build the 'devset' list that will be used when
# parsing up the devices. If the devset being built is for an
# ssa then the format: SSA:disk
#
# If the devset being built is for a disk then the format is:
# DISK:disk:serialno
#
# Input:  
#	passed in: mode
#		   'ssa' or 'disk' - tells which format to create
#	global:     ssa_array for ssa disks (set in function get_devices)
#		    disks_array and id_array for disks (set in
#		    function get_devices).
#
# Output: 
#	devset
#        

function build_devset
{
typeset mode
typeset devset
typeset i

mode=$1
devset=""
if [[ $mode == ssa ]]; then
 devices=${ssa_array[*]}
 for i in $devices; do
  devset="${devset} SSA:${i}"
 done
elif [[ $mode == disk ]]; then
 let i=0
 while (( i < ${#disks_array[*]} )); do
	devset="${devset} DISK:${disks_array[i]}:${id_array[i]}"
	(( i = i + 1 ))
 done 
fi

print "${devset}"
} 
################################################################################
#
# function construct_ssa_list <c#>.<WWN>...
#
# This function takes an argument list consisting of <c#>:<WWN>... The c# is the
# controller number on which a particular SSA is present and the WWN is the
# world-wide number of the corresponding SSA. The purpose of this function is to
# break up the input list into two different lists - one corresponding to the
# controller number list - ctlr_list - and the other corresponding to the WWN
# list - ssa_list. The controller number and the WWN have corresponding
# positions on the two output lists. This correspondence is relied upon by the
# calling function.
 
function construct_ssa_list
{
  ctlr_list=""
  ssa_list=""
 
  for item in $*; do
    ctlr=${item%%:*}
    ssa=${item##*:}
    ctlr_list="${ctlr_list} ${ctlr}"
    ssa_list="${ssa_list} ${ssa}"
  done
}

###############################################################################
#
# function get_devices [diskdevice]
#
# Get the list of disks attached to the system. Remove the root device 
# of the system from the final list. 
#
# Input:
#	diskdevice - extra device to remove from the final list.
#	This is used for the second list of available devices. By
#	providing as input here the disk device that was selected
#	for device 1, it can be eliminated here since the user
#	cannot select that disk again.
#
# Output:
#	devset - the list of all ssa disks or jbods.
 
function get_devices
{
  typeset -i j
  typeset rootdev
  set -A disks_array
  set -A id_array

  rootdev=$(${FINDDEVICES} rootdev | tr '\012' '')
  ssadevlist=$(${FINDDEVICES} ssa ${ssafile} | tr '\012' ' ')
  if (( $# == 1 )); then
	diskdevlist=$(${FINDDEVICES} disks | /bin/grep -v ${rootdev} | \
	 /bin/grep -v ${1} | tr '\012' ' ')
  else
  	diskdevlist=$(${FINDDEVICES} disks | /bin/grep -v ${rootdev} | \
	 tr '\012' ' ')
  fi
  construct_ssa_list ${ssadevlist}
  set -A ctlr_array ${ctlr_list}
  set -A ssa_array ${ssa_list}

  let j=0 
  for diskgroup in ${diskdevlist}; do
	disk=${diskgroup%%:*}
	diskid=${diskgroup##*:}

	err1=$(/usr/sbin/vxdisk list ${disk} \
		| /bin/grep errno | /bin/awk '{print $1}')
	if [[ "$err1" = "errno:" ]] ; then
  		disks_array[j]=${disk}
  		id_array[j]=${diskid}
		let j=j+1
	fi
  done

  rootc_array=${rootdev%%t*}
 
  set -A ssaset $(build_devset ssa ) 
  set -A diskset $(build_devset disk)

  devset="${ssaset[*]} ${diskset[*]}"

}

###############################################################################
#
# function select_dev devset
#
# Select a device from among the set of
# devices in devset. The selected device 
# comes in one of three flavors - <WWN>,
# <WWN>.<disk serial id>, or <disk address>:<disk serial id>
 
function select_dev
{
  typeset devset
  typeset qdev
  typeset wwn
  typeset -i done

  deviceno=$1; shift 
  devset=$*

  if [[ -z "$devset" ]]; then
	print
	print "================================="
	print "WARNING: No Storage Device found. Please check configuration"
	print "================================="
	print 
	exit 1
  fi 
  print
  print "Select devices from list."
  print "Type the number corresponding to the desired selection."
  print "For example: 1<CR>"
  print

  let done=0 
  PS3="Device ${deviceno}: "
  while (( done == 0 )); do
  select qdev in ${devset}; do
    if [[ -n "${qdev}" ]]; then
      
      if [[ "${qdev}" = SSA:* ]]; then
        wwn=${qdev##SSA:}
        select_qdisk_from_ssa ${wwn} 
	if [[ -z ${quorumdiskdev} ]]; then
		continue
	fi
        print
        print "Disk ${quorumdiskdev%%:*} with serial id ${quorumdiskdev##*:}"
        print "in SSA ${wwn} has been selected as device ${deviceno}."
        print
        ccddev=${quorumdiskdev%%*:}
	let done=1
      else
        qdev=${qdev##DISK:}
        print
        print "Disk ${qdev%%:*} with serial id ${qdev##*:} has been selected"
        print "as device ${deviceno}."
        print
        ccddev=${qdev}
	let done=1
      fi
      break
    else
      print
      print "Invalid Selection"
      print
      continue
    fi
  done
  done # while
}

################################################################################
#
# function select_qdisk_from_ssa ssa
#
# This function provides the option of selecting a disk from the
# specified ssa. The ssa to be used is passed in as a parameter.
# If the root devices of these nodes reside in
# this ssa exclude the corresponding disks from the selection
# process.
 
function select_qdisk_from_ssa
{
  typeset ssa
  typeset item
  typeset td
  typeset diskdevaddr
  typeset disksid
  typeset ctlr_node
  typeset ssadisks

  ssa=$1
  disk_list=""
 
  ctlr_node=$(get_ctlr_for_ssa ${ssa})

  if [[ ${ccdpath1} != 0 ]]; then
	ssadisks=$(${FINDDEVICES} disks ${ctlr_node} | \
	  /bin/grep -v ${ccdpath1} | tr '\012' ' ')
  else 
  	ssadisks=$(${FINDDEVICES} disks ${ctlr_node} | tr '\012' ' ')
  fi
 
  let j=0
  for diskgroup in ${ssadisks}; do
        disk=${diskgroup%%:*}

        err1=$(/usr/sbin/vxdisk list ${disk} \
                | /bin/grep errno | /bin/awk '{print $1}')
        if [[ "$err1" = "errno:" ]] ; then
                disk_list="${disk_list} ${disk}"
                let j=j+1
        fi
  done

 
  # set of disks in the ssa is now in the variable disk_list. First step is to
  # remove the controller number from this list to facilitate easy elimination
  # of the root devices of the two nodes from this list.
 
  disk_list=$(print ${disk_list} | sed -e 's/c[0-9]\{1,\}//g')
 
  # eliminate node's root disk from this list
 
  if [[ "${ctlr_node}" = ${rootc_array} ]]; then
    td=${rootdev##c[0-9]*([0-9])}
    disk_list=$(print ${disk_list} | sed -e "s/${td}//g")
  fi
 
  # eliminate the "s2" suffix from each item in the remaining list
 
  disk_list=$(print ${disk_list} | sed -e 's/s2//g')

  if [[ -z $disk_list ]]; then
        print
        print "================================================="
        print "WARNING: All disks on this SSA (ctlr: ${ctlr_node})"
	print "are either already in disk groups, have already"
	print "been selected as one of the devices for the shared"
	print "ccd or otherwise unavailable."
        print "================================================="
        print
	quorumdiskdev=""
	return
  fi
 
  PS3='Disk: '
  select quorumdiskdev in ${disk_list}; do
    if [[ -n "${quorumdiskdev}" ]]; then
      diskdevaddr=${ctlr_node}${quorumdiskdev}s2
      disksid=$(${PDBSSA} inquiry ${diskdevaddr})
      quorumdiskdev=${diskdevaddr}:${disksid}
      break
    else
      print
      print "Invalid selection."
    fi
  done
}

###############################################################################
#
# function get_ctlr_for_ssa wwn
#
# Get the controller number through which the SSA with the specified wwn is
# accessible on the given node.

function get_ctlr_for_ssa
{
  typeset ssa
  typeset ii
  typeset ctlrnum

  ssa=$1
  set -A ssa_array_on_node ${ssa_array[*]}
  set -A ctlr_array_on_node ${ctlr_array[*]}

  let ii=0
  while (( $ii < ${#ssa_array_on_node[*]} )); do
    if [[ ${ssa_array_on_node[ii]} = ${ssa} ]]; then
      ctlrnum=${ctlr_array_on_node[ii]}
      break
    fi
    let ii=ii+1
  done

  print ${ctlrnum}
}

#####################################################################################
# This function performs the following:
#
#	get all the shared devices to select which device will be used to
#	to store the shared CCD. This is only valid for a 2-node configured
#	cluster.
#
#####################################################################################

function Select_sharedCCD
{ 
	DONE=0
	CCDDEVICE1="0"
	CCDDEVICE2="0"
	CCDSSA[0]="Combo1"
	CCDSSA[1]="Combo2"

	print " "	
	print "On a 2-node configured cluster you may select two disks"
	print "that are shared between the 2 nodes to store the CCD"
	print "database in case of a single node failure."
	print " "
	print "Please, select the disks you want to use from the following list:"
	get_devices
	ccdpath1="0"
	ccdpath2="0"
	while [[ $ccdpath1 = $ccdpath2 ]]; do
		select_dev 1 "${devset}"
		ccdpath1=${ccddev%%:*}
		get_devices ${ccdpath1}
		select_dev 2 "${devset}"
		ccdpath2=${ccddev%%:*}
		if [[ $ccdpath1 == $ccdpath2 ]];then
			print
			print "Error: device 1 and 2 must be different!"
			print
		fi
	done

# a device *must* be selected prior to getting here. select_dev
# will not allow nothing to be enterned.
#
	CCDDEVICE1=${ccdpath1%s*}
	CCDDEVICE2=${ccdpath2%s*}

}

#
# initialize
#


mybin=/opt/SUNWcluster/bin
myetc=/etc/opt/SUNWcluster
myvar=/var/opt/SUNWcluster

PDBSSA=${mybin}/scssa
FINDDEVICES=${mybin}/finddevices
ccdfile=${myetc}/conf/ccd.database.init
devssa=`enccdmatch ccd.ccddevice.ssa`

if [[ "$devssa" = "none" ]]; then
	print ""
	print "	No shared CCD volume is specified"
	print ""
	ccdshare="0"
	while [[ "$ccdshare" != "yes" && "$ccdshare" != "no" ]]; do
	    ccdshare=$(ckstr -Q -p "Do you want to configure a shared CCD volume (yes/no) ?")
	done
	if [[ "$ccdshare" = "no" ]]; then
		exit 0
	fi
	echo "	Please run the following command on BOTH nodes"
	echo "	of the cluster : 'scconf <clustername> -S ccdvol'"
	echo "	then re-run this command 'confccdssa' on a SINGLE node"
	exit 0
fi

#
# First of all select 2 disk devices for
# the CCD volume
#

Select_sharedCCD

#
# if no devices are selected exit
#

if [[ $CCDDEVICE1 = "0" || $CCDDEVICE2 = "0" ]]; then
	exit 1;
fi

#
# vxsetup the two selected disks
#

/etc/vx/bin/vxdisksetup -i ${CCDDEVICE1}
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi
/etc/vx/bin/vxdisksetup -i ${CCDDEVICE2}
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi


#
# setup the disk group
#
#	"sc_dg" = disk group name for CCD disk group

y=${CCDDEVICE1%d*}
Y=${y#c*t}
Z=${CCDDEVICE1#c*d}

b=${CCDDEVICE2%d*}
B=${b#c*t}
C=${CCDDEVICE2#c*d}

/usr/sbin/vxdg init sc_dg ${CCDSSA[0]}@$Y.$Z=${CCDDEVICE1} ${CCDSSA[1]}@$B.$C=${CCDDEVICE2}
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi

#
# create volume and mirror
#
#	size = Size of volume in 512b segments
#		eg. size for a 10MB volume would be 20000
#
#	"ccdvol" = Name for CCD volume

/usr/sbin/vxassist -g sc_dg  -U fsgen make ccdvol 20000
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi
/usr/sbin/vxassist -g sc_dg  -U fsgen mirror ccdvol
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi
 

#
# create file-system on volume raw device (ccdvol)
#

/usr/sbin/newfs /dev/vx/rdsk/sc_dg/ccdvol
stat=$?
if [[ $stat != 0 ]]; then
	exit 1
fi

/usr/sbin/vxdg deport sc_dg
stat=$?
if [[ $stat != 0 ]]; then
	exit 1;
fi

exit 0
