#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2017,2020,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r721 src/43haes/usr/sbin/cluster/events/utils/cl_sync_vgs.sh 1.24.1.4 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1990,2016 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)  67ccefc 43haes/usr/sbin/cluster/events/utils/cl_sync_vgs.sh, 726, 2147A_aha726, Oct 27 2021 05:08 PM
#
#   COMPONENT_NAME: EVENTUTILS
#
#   FUNCTIONS: check_sync
#
#   ORIGINS: 27
#
#
#   (C) COPYRIGHT International Business Machines Corp. 1990,1994
#   All Rights Reserved
#   Licensed Materials - Property of IBM
#   US Government Users Restricted Rights - Use, duplication or
#   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
###############################################################################
#  
#  Name:  cl_sync_vgs
#
#  This script will call syncvg for the volume groups passed in as arguments.
#
#  Input:   list of volume group names
#	    volume groups must be already vary'd on
#
#  Environment: VERBOSE_LOGGING, PATH
#
#   Questions?	Comments?   Expressions of Astonishment?    mailto:hafeedbk@us.ibm.com
#
###############################################################################


#########################################################################
#
#  Name: check_sync
#
#  This function checks the volume group passed in as an argument to
#  see if it has any STALE partitions, and if so starts a sync for
#  each lv that is marked as STALE.
#
#  Arguments: Volume group
#
#########################################################################

function check_sync {

   if [[ $VERBOSE_LOGGING == "high" ]]
    then
        typeset PS4_FUNC="check_sync"
        typeset PS4_LOOP="$1"
        typeset PS4_TIMER=true
        set -x
    fi

    typeset vg_name		    # volume group being processed
    typeset vgid		    # LVM volume group identifier
    typeset disklist		    # list of disks in that volume group
    typeset lv_name		    # logical volume being checked
    integer stale_count		    # count of stale partitions in lv
    integer mode		    # type of vary on - concurrent or not
    integer RC=0		    # LVM varyonvg return code
    typeset site_node_list	    # the nodes in the defined recovery site
    typeset site_choice		    # local or remote site for recovery

    vg_name=$1			    # pick up passed volume group name
    disklist=""			    
    
    vgid=$(getlvodm -v $vg_name)    # determine the LVM VG ID

    #
    :   find disks in the VG that LVM thinks are inaccessable
    #
    disklist=$(LC_ALL=C lsvg -L -p $vg_name)
    missing_disklist=$(print -- "$disklist" | grep -w 'missing' | cut -f1 -d' ')
    removed_disklist=$(print -- "$disklist" | grep -w 'removed' | cut -f1 -d' ')


    #
    :	Proceeed if there are some disks that LVM thinks are inaccessable
    #
    if [[ -n $missing_disklist || -n $removed_disklist ]] 
    then
        #
        :   make disks accessable to AIX, and tell LVM to bring them online
        #
        [[ -n $missing_disklist ]] && cl_disk_available -s -v $missing_disklist

        if [[ -n $removed_disklist && -z $GMVGS && -z $GMVG_REP_RESOURCE ]]
        then
	    #
            :	make disks available
	    #
            chpv -v a $removed_disklist
	else
	    #
	    :   user is expected to do chpv -v a manually and then
	    :   chdev -a resume=yes for GLVM resources if disks
	    :   are not seen available after event processing
	    #
        fi
	#
	:   Discover VG varyon mode, and repeat varyon to refresh LVM
	#
	mode=$(lqueryvg -g $vgid -C)
	if (( mode == 0 )) 
	then
	    #
	    :	Ordinary varyon
	    #
	    conc=""
	else
	    #
	    :	Concurrent varyon
	    #
	    conc="-c"
	fi
	#
	:   Perform appropriate - concurrent or normal - varyon
	#
	varyonvg -n $conc $vg_name
	RC=$?
	if (( $RC == 31 ))
	then
	    #
	    :   There has been data divergence on VG "'$vg_name'"
	    :   Check if HACMP has been configured to handle this
	    #
            if [[ -n $DATA_DIVERGENCE_RECOVERY &&
                    $DATA_DIVERGENCE_RECOVERY != "DIVERGENCE_RECOVERY_NOT_SPECIFIED" ]]
	    then
		#
		:	Figure out which site the user, in an act of supreme foresight, 
		:	has determined has the data to trust
		#
		[[ -z $LOCALNODENAME ]] && LOCALNODENAME=$(get_local_nodename)	    
		#
		:	Find the list of nodes in the recovery site
		#
		site_node_list=$(clodmget -q "name = $DATA_DIVERGENCE_RECOVERY" -f nodelist -n HACMPsite)
		if [[ $site_node_list == ?(* )$LOCALNODENAME?( *) ]]
		then
		    #
		    :   This node "'$LOCALNODENAME'" is in the recovery site "'$DATA_DIVERGENCE_RECOVERY'"
		    #
		    site_choice="loc"
		else
		    #
		    :   This node "'$LOCALNODENAME'" is not in the recovery site, so the other
		    :   site "'$DATA_DIVERGENCE_RECOVERY'" is the recovery site
		    #
		    site_choice="rem"
		fi
		#
		:   There has been data divergence, and HACMP has been configured to 
		:   assume that site "'$DATA_DIVERGENCE_RECOVERY'" is the one to trust.
		:   Try the varyonvg again, telling it to use the "'$site_choice'" site.
		#
		#   Note that we always varyon in non-concurrent mode for GLVM
		#
		varyonvg -n -k $site_choice $vg_name
		RC=$?
	    else
		#
		:   The DATA_DIVERGENCE_RECOVERY variable has no value.
		:   The user has not told us which site has the version of the
		:   data to preserve during data divergence recovery.
		#
		#   $RC is still set to 31 from above, so fall through.
		#
	    fi
	fi  # if RC=31
    fi  # if $disklist

    #
    :	sync if any LVs in the VG that have stale partitions
    #
    if (( $RC == 0 ))			    #	varyonvg eventually worked
    then
        #
        :   A status of 2,3,5 or 7 indicates the presence of dirty and/or stale partitions
        #

        #As part of lvm, VG sync data in availabilty metrics report for the VG 
        #is displayed only when logical volumes are present and call to syncvg 
        # is successful for at least one logical volume in the VG 
        
        #As we are going to loop on all the logical volumes in a VG,the start 
        #log for the VG should be logged only when there are logical volumes 
        #present in that VG, also it should be logged only once and not for
        # all logical volumes hence is_start_logged is used. 
        
        is_start_logged=0

        #at_least_one_sync_success makes sure faliure is logged when syncvg fails 
        #for all LVs in a VG 
        
        at_least_one_sync_success=0
        lqueryvg -g $vgid -L | while read lv_id lv_name lv_status ;
        do
            [[ $VERBOSE_LOGGING == "high" ]] && PS4_LOOP="${vg_name}.${lv_name}"
            if (( $lv_status != 2 && $lv_status != 3 && $lv_status != 5 && $lv_status != 7 ))
            then
                #
                :   Anything else indicates no stale partitions
                #
                continue
            fi
            if [[ -n $lv_id ]]
            then
                lv_copies=$(lquerylv -L $lv_id -C)
                RC=$?
                if (( $RC != 0 || $lv_copies == 1 ))
                then
                    continue
                fi
            fi
            #logging for sync operation begin on VG only if it is called from process_resources
            #and if it has not been done atleast once which is checked using is_start_logged 
            if [[ -n $AM_SYNC_CALLED_BY ]] && (( $is_start_logged == 0 ))
            then
                #The event log string is made using the value of AM_SYNC_CALLED_BY and saved into log_tag_name. 
                eval echo "\$AM_VG_SYNC_BEGIN_$AM_SYNC_CALLED_BY"|read log_tag_name
                amlog_trace $log_tag_name "Sync the active volume groups|$1|$EVENT_SERIAL_NUMBER"
                #setting is_start_logged as TRUE so that start for VG sync is not logged more than once 
                is_start_logged=1
            fi
            #
            :   This logical volume has stale partitions, so sync it.
            #
            #   If NUM_PARALLEL_LPS is set, syncflag is not set, since
            #   syncvg will pick it up directly, else it is "-P4".
            #
            cl_echo 999 "Warning: syncvg for $lv_name can take considerable amount of time, depending on data size and network bandwidth." $lv_name
            time syncvg $syncflag -l $lv_name
            syncvg_RC=$?
            if (( $syncvg_RC == 0 ))
            then
                cl_echo 999 "syncvg for $lv_name completed successfully" $lv_name
                # set at_least_one_sync_success as TRUE if atleast for one LV in VG syncvg returns 0   
                at_least_one_sync_success=1
            else
                cl_log 999 "syncvg for $lv_name did not complete successfully" $lv_name
            fi
        done
        #log in clavailability.log for end or failure log only if start has been logged 
        # and the script is called from process_resources 
        if [[ -n $AM_SYNC_CALLED_BY ]] && (( $is_start_logged == 1 ))
        then
            #Log failure in clavailability.log if all the LVs fail syncvg else log end  
            if (( $at_least_one_sync_success == 0 ))
            then
                #The event log string is made using the value of AM_SYNC_CALLED_BY 
                #and saved into log_tag_name.
                eval echo "\$AM_VG_SYNC_FAILURE_$AM_SYNC_CALLED_BY"|read log_tag_name
                amlog_err $log_tag_name "Sync the active volume groups|$1|$EVENT_SERIAL_NUMBER"
            else
               #The event log string is made using the value of AM_SYNC_CALLED_BY 
               #and saved into log_tag_name.
               eval echo "\$AM_VG_SYNC_END_$AM_SYNC_CALLED_BY"|read log_tag_name
               amlog_trace $log_tag_name "Sync the active volume groups|$1|$EVENT_SERIAL_NUMBER"
            fi
        fi
    else
        cl_RMupdate resource_error $vg_name $PROGNAME
        exit $RC
    fi
}


#########################################################################
#
:   Main routine - process each volume group in turn
#
#########################################################################
# Including Availability metrics library file
. /usr/es/lib/ksh93/availability/cl_amlib
PROGNAME=${0##*/}
export PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)"
if [[ $VERBOSE_LOGGING == "high" ]]
then
    set -x
    version='1.24.1.4'
fi

if (( $# == 0 )) ; then
    #   Caller used incorrect syntax
    cl_echo 498 "usage: $PROGNAME volume group(s)" $PROGNAME
    exit 2
fi
#
:   syncing 4 stale PPs at a time seems to be a win most of the time, but
:   we honor the NUM_PARALLEL_LPS value from /etc/environment, as does 
:   syncvg.
#
export syncflag=""
export PS4_LOOP=""
typeset -i npl
if ! grep -q '^NUM_PARALLEL_LPS=' /etc/environment 
then
    syncflag="-P4"
else
    nplvar=$(grep '^NUM_PARALLEL_LPS=' /etc/environment)
    npl=${nplvar//NUM_PARALLEL_LPS=/}
    (( $npl > 0 && $npl <= 32)) && syncflag="-P$npl" || syncflag="-P4"
fi

echo "NOTE: While the sync is going on, volume group can be used"
for vg_name in $* 
do
    :   For GLVM volume groups, read PARALLEL LPS count from HACMPresource if it is set from GUI,
    :   else, read from environment variables, if it is not set use 32 as default value.
    #
    glvm_rg=$(clodmget -q "name=GMVG_REP_RESOURCE and value=$vg_name" -f group HACMPresource 2>/dev/null)
    if [[ -n $glvm_rg ]]
    then
        typeset -i odm_np1
        odm_np1=$(clodmget -q "name=NO_PARALLEL_LPS and group=$glvm_rg" -f value HACMPresource 2>/dev/null)
        if [[ -n $odm_np1 ]]
        then
            np1=$odm_np1
        else
            nplvar=$(grep '^NUM_PARALLEL_LPS=' /etc/environment)
            npl=${nplvar//NUM_PARALLEL_LPS=/}
        fi        
        if [[ -z $np1 ]] || (( $np1 > 32 || $np1 <= 0 ))
        then
            syncflag="-P32"
        else
            syncflag="-P$np1"
        fi
    fi
    check_sync $vg_name
done
exit 0
