#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG
#  This is an automatically generated prolog.
#
#  Copyright (C) Altran ACT S.A.S. 2021.  All rights reserved.
#
#  ALTRAN_PROLOG_END_TAG
#
# @(#)  7b36ae1 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_logical_volume.sh, 726, 2147A_aha726, Sep 08 2021 09:17 PM
#
#================================================
# The following, commented line enforces coding
# standards when this file is edited via vim.
#================================================
# vim:tabstop=4:shiftwidth=4:expandtab:smarttab
#================================================

# Start of POD-formatted documentation. Viewing suggestions:
#      perldoc <FILENAME>
#      pod2text -c <FILENAME>
#      pod2text -c --code <FILENAME>
#      pod2html <FILENAME>
function devDoc {
    : <<'=cut' >/dev/null 2>&1

=head1 NAME

 KLIB_HACMP_modify_logical_volume

=head1 SYNOPSIS

 clmgr modify logical_volume <lvname> \
             [ TYPE={jfs|jfs2|sysdump|paging|
                     jfslog|jfs2log|aio_cache|boot} ] \
             [ POSITION={outer_middle|outer_edge|center|
                         inner_middle|inner_edge  } ] \
             [ PV_RANGE={minimum|maximum} ] \
             [ MAX_PVS_FOR_NEW_ALLOC=## ] \
             [ MAX_LPARTS=#### ] \
             [ SCHEDULING_POLICY={parallel|sequential|
                                  parallel_sequential|
                                  parallel_round_robin} ] \
             [ LABEL="<lv_label>" ] \
             [ LOGICAL_PARTITIONS=#### ]
             [ ENABLE_LV_ENCRYPTION={yes|no} ] \
             [ AUTH_METHOD={keyserv|pks} ] \
             [ METHOD_DETAILS=<key server ID> ] \
             [ AUTH_METHOD_NAME=<Alias name for auth method> ] \
             [ REMOVE_AUTH_METHOD=<auth method name for lv> ]

 NOTE: STRIPE_SIZE may not be used with LPARTS_ON_SEPARATE_PVS,
       PV_RANGE, or SCHEDULING_POLICY.

 NOTE: an alias for "logical_volume" is "lv".

=head1 DESCRIPTION

Attempts to add a new volume group.

=head1 ARGUMENTS

 1. properties [REQUIRED] [hash ref]
    An associative array within which data about the
    created object can be returned to the caller.

 2. logical_volume [REQUIRED] [string]
    The logical volume label. The default label is None.
    The maximum size of the Label variable is 127
    characters. Note: If the logical volume is going to
    be used as a journaled file system (jfs), then the
    JFS will use this field to store the mount point of
    the file system on the logical volume for future
    reference.                

 3. type [OPTIONAL] [set]
    Sets the logical volume type. The default type is "jfs"
    ("journaled file system").

    Valid values: jfs, jfs2, sysdump, paging, jfslog, jfs2log,
                  aio_cache, boot

 4. position [OPTIONAL] [set]
    The Intra-Physical Volume Allocation Policy to use for
    choosing physical partitions on a physical volume.

    "EDGE" and "INNER EDGE" - allocates partitions to the edges
    of the physical volume. These partitions have the slowest
    average seek times, which generally result in longer response
    times for any application that uses them.

    "MIDDLE" and "INNER MIDDLE" - allocates partitions away from
    the edges of the physical volume and out of the center. These
    strategies allocate reasonably good locations for partitions
    with reasonably good average seek times. Most of the
    partitions on a physical volume are available for allocation
    using these strategies.

    "CENTER" - allocates partitions to the center section of
    each physical volume. These partitions have the fastest
    average seek times, which generally result in the best
    response time for any application that uses them. There
    are fewer partitions on a physical volume that satisfy the
    "CENTER" strategy than for any other general strategy.

    Valid values: outer_edge, outer_middle, center,
                  inner_middle, inner_edge

 5. pv_range [OPTIONAL] [set]
    Specifies which Inter-Physical Volume Allocation Policy to
    use for choosing physical devices to allocate the physical
    partitions of a logical volume:

    "MINIMUM" - with 1 copy specified, indicates that, if
    possible, one physical volume should contain all the
    physical partitions of this logical volume. Otherwise,
    use the minimum number possible consistent with other
    parameters. This policy provides the greatest reliability,
    without mirrored copies, for a logical volume.

    "MINIMUM" - with 2 or 3 copies specified, indicates that
    as many physical volumes as there are copies should be
    used. Otherwise, the minimum number of physical volumes
    possible are used to hold all the physical partitions. At
    all times, the constraints imposed by other parameters are
    observed.

    "MAXIMUM" - indicates that the physical partitions of this
    logical volume should be spread over as many physical
    volumes as possible. This is a performance-oriented option
    and should be used with copies to improve availability. If
    a logical volume is not copied and is spread across multiple
    physical volumes, the loss of any physical volume containing
    a physical partition from that logical volume is enough to
    cause the logical volume to be incomplete.

    Valid values: minimum, maximum

 6. max_pvs_for_new_alloc [OPTIONAL] [integer]
    Sets the maximum number of physical volumes for new
    allocation. The value should be between one and the
    total number of physical volumes in the volume group.

 7. max_lparts [OPTIONAL] [integer]
    Sets the maximum number of logical partitions that can be
    allocated to the logical volume.

 8. sched_policy [OPTIONAL] [set]
    The scheduling policy to use for the mirrored (copies > 1)
    logical volume:

    Sequential - performs copied write procedures in order:
    primary, secondary, tertiary. This policy waits for the
    write operation to complete for the previous physical
    partition before starting the write operation to the next
    one.

    For read operations, the primary copy is read. If the read
    operation is unsuccessful, the next copy is read. The
    primary copy is then fixed by turning the read operation
    into a write operation with hardware relocation specified
    on the call to the physical device driver.

    Parallel - starts the write operation for all the physical
    partitions in a logical partition at the same time. When
    the write operation to the physical partition that takes
    the longest to complete finishes, the write operation
    returns.

    Valid values: parallel, sequential, parallel/sequential,
                  parallel/round robin

 9. label [OPTIONAL] [string]
    Sets the logical volume label. The default label is
    "None". The maximum size of the label is 127 characters.
    Note: If the logical volume is going to be used as a
    journaled file system (JFS), then the JFS will use this
    field to store the mount point of the file system on that
    logical volume for future reference.
 
10. logical_partitions [OPTIONAL] [integer]
    Sets the logical partition size of logical volume.
   
    logical volume size = PP SIZE * logical partition size

11. ENABLE_LV_ENCRYPTION [OPTIONAL] [boolean]
    Enables the data encryption option for the logical volume.
    To enable the encryption, auth_method should be passed.

12. AUTH_METHOD [OPTIONAL]
    Supported authentication methods are pks or keyserv.
    For pks authentication, AUTH_METHOD_NAME should be passed.
    For keyserv authentication, METHOD_DETAILS and AUTH_METHOD_NAME should be passed.

13. METHOD_DETAILS [OPTIONAL]
    If keyserv is configured as an authentication methods,
    key server ID should be passed to this attribute.

14. AUTH_METHOD_NAME [OPTIONAL]
    Alias name should be passed for both pks and keyserv
    authentication methods.

15. REMOVE_AUTH_METHOD [OPTIONAL]
    This field is used to remove specific authentication method.
    Other LVM authentication options are not allowed when this is used.

=head1 RETURN

 0: no errors were detected; the operation appears to have been successful
 1: a general error has occurred
 2: a specified resource does not exist, or could not be found
 3: some required input was missing
 4: some detected input was incorrect in some way
 5: a required dependency does not exist
 6: a specified search failed to match any data

=head1 COPYRIGHT

COPYRIGHT International Business Machines Corp. 2005,2010
All Rights Reserved

=cut
} # End of POD-formatted documentation.


function KLIB_HACMP_modify_logical_volume {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  7b36ae1 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_logical_volume.sh, 726, 2147A_aha726, Sep 08 2021 09:17 PM
    : INPUTS: $*
    typeset -n properties=$1
    typeset logical_volume=${2//\"/}
    typeset type=${3//\"/}
    typeset position=${4//\"/}
    typeset pv_range=${5//\"/}
    typeset max_pvs_for_new_alloc=${6//\"/}
    typeset max_lparts=${7//\"/}
    typeset sched_policy=${8//\"/}
    typeset label=${9//\"/}
    typeset logical_partitions=${10//\"/}
    typeset -l enable_encryption=${11//\"/}
    typeset -l auth_method=${12//\"/}
    typeset method_details=${13//\"/}
    typeset auth_method_name=${14//\"/}
    typeset remove_auth_method=${15//\"/}
    typeset enable_encrypt_support="true"
    typeset cur_oslevel=$(oslevel -r|sed 's/-//g')
    typeset -i min_req_ver=730000

    [[ $CLMGR_LOGGING == 'med' ]] && set +x  # Only trace param values

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset typeOpt="" nodes="" clstate=""
 
    typeset volume_group="" vg_disk="" rg_name=""
    typeset primarynodes="" secondarynodes="" nodes=""

    if [[ -z $logical_volume ]];then
        dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT
        log_return_msg "$rc" "$0()" "$LINENO"
        return $?
    else
        print "$0()[$LINENO]($SECONDS): clodmget -q "name=$logical_volume" -f parent -n CuDv" >>$CLMGR_TMPLOG
        volume_group=$(clodmget -q "name=$logical_volume" -f parent -n CuDv)
        typeset volume_group_rc=$?
        print "$0()[$LINENO]($SECONDS): clodmget command to get volume group name RC: $volume_group_rc" >>$CLMGR_TMPLOG
        volume_group=${volume_group##*VOLUME GROUP:+([[:space:]])}
        volume_group=${volume_group%%+([[:space:]])*}
    fi

    active_node=""
    if [[ -n $volume_group ]];then
        print "$0()[$LINENO]($SECONDS): clodmget -q "name=GMVG_REP_RESOURCE and value=$volume_group" -f group HACMPresource" >>$CLMGR_TMPLOG
        gmvg_type=$(clodmget -q "name=GMVG_REP_RESOURCE and value=$volume_group" -f group HACMPresource 2>/dev/null)
        typeset gmvg_type_rc=$?
        print "$0()[$LINENO]($SECONDS): clodmget command to get volume group $volume_group type $gmvg_type RC: $gmvg_type_rc" >>$CLMGR_TMPLOG
        if [[ -n $gmvg_type ]];then
            typeset -A rgAttrs
            print "$0()[$LINENO]($SECONDS): clodmget -q "name = VOLUME_GROUP and value = $volume_group" -f group -n HACMPresource" >>$CLMGR_TMPLOG
            rg_name=$(clodmget -q "name = VOLUME_GROUP and value = $volume_group" -f group -n HACMPresource)
            typeset rg_name_rc=$?
            print "$0()[$LINENO]($SECONDS): clodmget command to get Resource group name $rg_name associated to volume group $volume_group RC: $rg_name_rc" >>$CLMGR_TMPLOG
            if [[ -n $rg_name ]];then
                CL=$LINENO KLIB_HACMP_get_resourcegroup_state "$rg_name" rgAttrs
                primarynodes=${rgAttrs[PRIMARYNODES]}
                secondarynodes=${rgAttrs[SECONDARYNODES]}
                nodes="$primarynodes $secondarynodes"
            fi

            # For GLVM volume groups,allow changing logical volume size when cluster services are running
            for node in $nodes
            do
                clstate=$(LC_ALL=C cl_rsh $node lssrc -ls clstrmgrES | grep "Current state:" | cut -f2 -d":")
                if [[ ${clstate//[[:blank:]]/} == "ST_STABLE" ]] ; then
                    if [[ -n $logical_partitions && -z $type && -z $position && -z $pv_range && -z $max_pvs_for_new_alloc && -z $max_lparts && -z $sched_policy &&  -z $label && -z $enable_encryption &&  -z $auth_method && -z $method_details && -z $auth_method_name && -z $remove_auth_method ]]
                    then
                        print "$0()[$LINENO]($SECONDS): cl_rsh $node lsvg $volume_group 2>&1" >>$CLMGR_TMPLOG
                        typeset lsvg_out=$(cl_rsh $node LC_ALL=C lsvg $volume_group 2>&1)
                        if print -- "$lsvg_out" | grep -i -q 'VG STATE: * active ' ;then
                            active_node=$node
                            print "$0()[$LINENO]($SECONDS): GLVM volume group $volume_group is active on node $active_node" >>$CLMGR_TMPLOG
                            break
                        fi
                    else
                        print "$0()[$LINENO]($SECONDS): ERROR: GLVM Volume group $volume_group properties cannot be changed other than logical volume size when cluster services are active." >>$CLMGR_TMPLOG
                        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1488 "\nERROR: GLVM Volume group \"%1\$s\" properties cannot be changed other than logical volume size when cluster services are active.\n\n" "$volume_group" 1>&2
                        log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO"
                        return $RC_MISSING_DEPENDENCY
                    fi
                fi
            done
        fi
    else
        print "$0()[$LINENO]($SECONDS): logical volume $logical_volume is not configured or its not associated to any volume group" >>$CLMGR_TMPLOG
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1472 "\nERROR: Logical volume \"%1\$s\" is either not configured or not associated with any volume group.\n\n" "$logical_volume" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n $type ]]; then
        typeset -l type_lc=$type
        case $type_lc in
            a*)     typeOpt=" -t aio_cache" ;;
            b*)     typeOpt=" -t boot"      ;;
            jfs)    typeOpt=" -t jfs"       ;;
            jfs2)   typeOpt=" -t jfs2"      ;;
            jfsl*)  typeOpt=" -t jfslog"    ;;
            jfs2l*) typeOpt=" -t jfs2log"   ;;
            p*)     typeOpt=" -t paging"    ;;
            s*)     typeOpt=" -t sysdump"   ;;
            *) CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\"\n" TYPE "$type" 1>&2
               CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "aio_cache, boot, jfs, jfs2, jfslog, jfs2log, paging, sysdump" 1>&2
               rc=$RC_INCORRECT_INPUT
            ;;
        esac     
    fi

    if [[ -n $enable_encryption || -n $auth_method || -n $auth_method_name || -n $method_details ]] && [[ -n $remove_auth_method ]];then
        dspmsg -s $CLMGR_SET $CLMGR_MSGS 1486 "\nERROR: There is a conflict between add and remove LVM authentication,\nprovide either of these attributes.\n" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi
    
    #==============================
    : Validate the integer inputs
    #==============================
    for INPUT in MAX_PVS_FOR_NEW_ALLOC@$max_pvs_for_new_alloc \
                 MAX_LPARTS@$max_lparts \
                 PERMISSIONS@$permissions
    do
        print -- "$INPUT" | IFS=@ read ATTR VALUE ORDER
        if [[ -n $VALUE ]]; then
            if [[ $VALUE != +([[:digit:]]) ]] || \
               (( $VALUE == 0 ))
            then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" "$ATTR" 1>&2
                rc=$RC_INCORRECT_INPUT
            fi
        fi
    done
   
    #==============================
    : Validate the boolean inputs
    #==============================
    if [[ -n $enable_encryption && $enable_encryption != @(y|t|n|f)* && $rc != $RC_INCORRECT_INPUT ]]; then
          dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" "ENABLE_LV_ENCRYPTION" "$enable_encryption" 1>&2
          dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "no,yes" 1>&2
          rc=$RC_INCORRECT_INPUT
    fi 
    
    #===============================================================
    : check for aix version 7.3 if lvm encryption option is provided
    #===============================================================
    if [[ $enable_encryption == @(y|t)* || -n $auth_method || -n $auth_method_name || -n $method_details || -n $remove_auth_method ]] && [[ $rc != $RC_INCORRECT_INPUT ]];then
        hdcrypt_version=$(LC_ALL=C lslpp -L | grep -w hdcrypt | awk '{print $2}')
        if [[ -z $hdcrypt_version || $cur_oslevel < $min_req_ver ]]
        then
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 1480 "\nERROR: Installed AIX level %1\$s is not supported to use LVM Encryption,\n\
minimum level required to use AIX LVM Encryption is AIX %2\$s.\n\n" "$cur_oslevel" "$min_req_ver" 1>&2
            enable_encrypt_support="false"
            rc=$RC_MISSING_DEPENDENCY
        fi
        if [[ $auth_method == "pks" ]];then
            print -- "$0()[$LINENO]($SECONDS): check for pks support by executing command: hdcryptmgr pksshow" >>$CLMGR_TMPLOG
            pks_status=$(hdcryptmgr pksshow >>$CLMGR_TMPLOG 2>&1)
            if (( $? != 0 ));then
                # Get clutils.log fullpath
                clutils_log_dir=$(clodmget -q "name = clutils.log" -f value -n HACMPlogs)
                [[ -z $clutils_log_dir ]] &&
                    clutils_log_dir=$(clodmget -q "name = clutils.log" -f defaultdir -n HACMPlogs)
                clutils_log_dir=${clutils_log_dir:-"/var/hacmp/log"}

                clutils_log=${clutils_log_dir}/clutils.log
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 1481 "\nERROR: %1\$s authentication is not supported on node %2\$s, enable %1\$s authentication and rerun the command.\n\
Check log file %3\$s for more details.\n" "pks" "$LOCAL_NODE" "$clutils_log" 1>&2
                enable_encrypt_support="false"
                rc=$RC_MISSING_DEPENDENCY
            fi 
        fi
    fi

    typeset -l position_lc=$position

    if [[ -n $position ]];then
        CL=$LINENO verify_in_set position "$position_lc" "outer_middle outer_edge center inner_middle inner_edge" position_lc
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
    fi
    
    typeset -l pv_range_lc=$pv_range
    if [[ -n $pv_range ]];then
        CL=$LINENO verify_in_set pv_range "$pv_range" "minimum maximum" pv_range
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
    fi

    typeset -l sched_policy_lc=$sched_policy
    if [[ -n $sched_policy ]];then
        CL=$LINENO verify_in_set sched_policy "$sched_policy_lc" "parallel sequential parallel_sequential parallel_round_robin" sched_policy_lc
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
    fi
     
    typeset -l auth_method_lc=$auth_method
    if [[ -n $auth_method && $enable_encryption != @(n|f)* && $enable_encrypt_support == "true" && $RC != $RC_INCORRECT_INPUT ]];then
        CL=$LINENO verify_in_set auth_method "$auth_method_lc" "keyserv pks" auth_method_lc
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
    fi
 
    # Bring rpvserver and rpvclients to available state in all nodes
    rpv_flag=0
    if [[ -n $gmvg_type && -z $active_node && $rc != $RC_INCORRECT_INPUT ]] ;then
        rpv_flag=1
        change_rpv_state "$primarynodes" "$secondarynodes" "$volume_group" "mkdev"
        change_rpv_state "$secondarynodes" "$primarynodes" "$volume_group" "mkdev"
    fi
    # Increase the size of logical volume
    if [[ $logical_partitions != *([[:space:]]) && -n $gmvg_type ]]; then
        # Run extendlv on active node, if active node is not present, do on local node by bringing up the volume group.
        # Also, make sure to extend the logical volume for both cache logical volumes.
        local_node=$(/usr/es/sbin/cluster/utilities/get_local_nodename)
        run_remotely=""
        if [[ -n "$active_node" && "$active_node" != "$local_node" ]];then
            run_remotely="cl_rsh $active_node"
        fi
        # varyon volume group when cluster service are not running
        if [[ -z $active_node ]]
        then
            varyonvg $volume_group
            if (( $? != 0 ))
            then
                print "$0()[$LINENO]($SECONDS): Failed to varyon volume group \"$volume_group\"." >>$CLMGR_TMPLOG
                rc=$RC_INCORRECT_INPUT
            fi
        fi
        print "$0()[$LINENO]($SECONDS): $run_remotely extendlv $logical_volume $logical_partitions." >>$CLMGR_TMPLOG
        lv_size=$($run_remotely extendlv $logical_volume $logical_partitions >>$CLMGR_TMPLOG)
        rc=$?
        print "$0()[$LINENO]($SECONDS): $run_remotely extendlv $logical_volume $logical_partitions RC: $rc" >>$CLMGR_TMPLOG
        # check the logical volume type is aio_cache, if so then update the same size to remote or local lv.
        check_lv=$($run_remotely lsvg -l $volume_group | grep -w aio_cache | grep -w $logical_volume)
        if (( $? == 0 ))
        then
            #Get peer Cache logical volume name
            aio_lv=$($run_remotely lsvg -l $volume_group | grep -w aio_cache | grep -wv $logical_volume | awk '{print $1}')
            if [[ -n $aio_lv ]]
            then
                print "$0()[$LINENO]($SECONDS): $run_remotely extendlv $aio_lv $logical_partitions." >>$CLMGR_TMPLOG
                next_lv_size=$($run_remotely extendlv $aio_lv $logical_partitions >>$CLMGR_TMPLOG)
                rc=$?
                print "$0()[$LINENO]($SECONDS): $run_remotely extendlv $aio_lv $logical_partitions RC: $rc" >>$CLMGR_TMPLOG
            fi
        fi
 
        # varyoff volume group when cluster service are not running
        if [[ -z $active_node ]]
        then
            varyoffvg $volume_group
            if (( $? != 0 ))
            then
                print "$0()[$LINENO]($SECONDS): Failed to varyoff volume group \"$volume_group\"." >>$CLMGR_TMPLOG
                rc=$RC_INCORRECT_INPUT
            fi
        fi

        if (( $rc != RC_SUCCESS ))
        then
            print "$0()[$LINENO]($SECONDS): Failed to extend logical volume \"$logical_volume\"." >>$CLMGR_TMPLOG
            rc=$RC_INCORRECT_INPUT
        fi

    elif [[ $logical_partitions != *([[:space:]]) ]]; then
        print "$0()[$LINENO]($SECONDS): cl_extendlv $logical_volume $logical_partitions" >>$CLMGR_TMPLOG
        lv_size=$(cl_extendlv $logical_volume $logical_partitions >>$CLMGR_TMPLOG)
        rc=$?
        print "$0()[$LINENO]($SECONDS): cl_extendlv RC: $rc" >>$CLMGR_TMPLOG
        if (( $rc != RC_SUCCESS ))
        then
            print "$0()[$LINENO]($SECONDS): Failed to extend logical volume \"$logical_volume\"." >>$CLMGR_TMPLOG
            rc=$RC_INCORRECT_INPUT
        fi
    fi


    #==============================================================
    # Verify all arguments are passed for LV encryption or not.
    #==============================================================
    if [[ $rc != $RC_INCORRECT_INPUT && $enable_encryption == @(y|t)* && $enable_encrypt_support == "true" ]]
    then
        if [[ -z $auth_method ]]
        then
            cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1478 "\nERROR: Enabling logical volume encryption requires %1\$s attribute.\n" "AUTH_METHOD" 1>&2
            rc=$RC_INCORRECT_INPUT
        elif [[ $auth_method == "keyserv" ]] && [[ -z $auth_method_name || -z $method_details ]]
        then
            cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1476 "\nERROR: Enabling logical volume encryption using %1\$s authentication method requires %2\$s and %3\$s attributes.\n" "keyserv" "AUTH_METHOD_NAME" "METHOD_DETAILS" 1>&2
            rc=$RC_INCORRECT_INPUT
        elif [[ $auth_method == "pks" && -z $auth_method_name ]]
        then
            cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1475 "\nERROR: Enabling logical volume encryption using %1\$s authentication method requires %2\$s attribute.\n" "pks" "AUTH_METHOD_NAME" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $rc != $RC_INCORRECT_INPUT && $enable_encryption != @(y|t)* && $enable_encrypt_support == "true" ]]
    then
        typeset isLV_encrypted=""
        #
        : Check is lv encrypted
        #
        typeset -A lvProps
        CL=$LINENO KLIB_HACMP_get_logical_volume_attributes $logical_volume lvProps
        isLV_encrypted=${lvProps[ENCRYPTION]}
        if [[ -z $auth_method ]] && [[ -n $auth_method_name || -n $method_details ]]
        then
            cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1478 "\nERROR: Enabling logical volume encryption requires %1\$s attribute.\n" "AUTH_METHOD" 1>&2
             rc=$RC_INCORRECT_INPUT
        fi
        if [[ -n $auth_method ]] && [[ $enable_encryption == "no" || $isLV_encrypted == "no" ]]
        then
             cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1479 "\nERROR: To use the authentication attributes, %1\$s should be set with yes.\n" "ENABLE_LV_ENCRYPTION" 1>&2
             rc=$RC_INCORRECT_INPUT
        fi
    fi
  
    #Check whether lv label name with "/" as first character, if it does not exist then add "/" at starting lv label.
    if [[ -n $label && $label != /* ]];then
        label="/$label"
        cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1489 "\nAbsolute path is not given for logical volume label, hence using standard path as %1\$s.\n" "$label" 1>&2
    fi

    #====================================================================
    : If no errors have been detect in the input, perform the operation
    #====================================================================
    if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )); then
        typeset yOpt="" tOpt="" aOpt="" eOpt="" uOpt="" wOpt="" sOpt="" rOpt=""
        typeset LOpt="" xOpt="" bOpt="" dOpt="" vOpt="" mOpt="" SOpt="" TOpt=""
        typeset pOpt="" GOpt="" UOpt="" POpt="" ROpt="" kOpt="" typeOpt="" mdOpt="" anOpt=""

        [[ $label             != *([[:space:]]) ]] && LOpt=" -L $label"
        [[ $max_lparts        != *([[:space:]]) ]] && xOpt=" -x $max_lparts"
        [[ $type              != *([[:space:]]) ]] && tOpt=" -t $type"
        [[ $enable_encryption == @(y|t)* ]] && kOpt=" -k y"
        [[ $enable_encryption == @(n|f)* ]] && kOpt=" -k n" 
        [[ $auth_method != *([[:space:]]) ]] && typeOpt=" -t $auth_method"
        [[ $method_details != *([[:space:]]) ]] && mdOpt=" -m $method_details"
        [[ $auth_method_name != *([[:space:]]) ]] && anOpt=" -n $auth_method_name"


        if [[ $max_pvs_for_new_alloc != *([[:space:]]) ]]; then
            uOpt=" -u $max_pvs_for_new_alloc"
        fi
        if [[ $verify_writes != *([[:space:]]) ]]; then
            [[ $verify_writes == @(y|t)* ]] && vOpt=" -v y" || vOpt=" -v n"
        fi

        if [[ $position != *([[:space:]]) ]]; then
            case $position in
                center)       aOpt=" -a c"  ;;
                inner_middle) aOpt=" -a im" ;;
                inner_edge)   aOpt=" -a ie" ;;
                outer_edge)   aOpt=" -a e"  ;;
                outer_middle) aOpt=" -a m"  ;;
            esac
        fi

        if [[ $pv_range != *([[:space:]]) ]]; then
            case $pv_range in
                min*) eOpt=" -e m"  ;;
                max*) eOpt=" -e x"  ;;
            esac
        fi

        if [[ $sched_policy != *([[:space:]]) ]]; then
            case $sched_policy in
                parallel)             dOpt=" -d p"  ;;
                sequential)           dOpt=" -d s"  ;;
                parallel_sequential)  dOpt=" -d ps" ;;
                parallel_round_robin) dOpt=" -d pr" ;;
            esac
        fi

        if [[ -n $ROpt$aOpt$bOpt$cOpt$dOpt$eOpt$GOpt$UOpt$LOpt$mOpt$pOpt$POpt$rOpt$sOpt$SOpt$tOpt$TOpt$uOpt$vOpt$wOpt$xOpt$yOpt ]]; then

            print "$0()[$LINENO]($SECONDS): _CSPOC_MODE=both cl_chlv $ROpt$aOpt$bOpt$cOpt$dOpt$eOpt$GOpt$UOpt$LOpt$mOpt$pOpt$POpt$rOpt$sOpt$SOpt$tOpt$TOpt$uOpt$vOpt$wOpt$xOpt$yOpt ${logical_volume//,/ }" >>$CLMGR_TMPLOG  # Always log commands
            _CSPOC_MODE=both cl_chlv $ROpt$aOpt$bOpt$cOpt$dOpt$eOpt$GOpt$UOpt$LOpt$mOpt$pOpt$POpt$rOpt$sOpt$SOpt$tOpt$TOpt$uOpt$vOpt$wOpt$xOpt$yOpt ${logical_volume//,/ }
            rc=$?
            print "$0()[$LINENO]($SECONDS): cl_chlv RC: $rc" >>$CLMGR_TMPLOG  # Always log command result
        elif [[ $rc != RC_INCORRECT_INPUT ]] && [[ -n $enable_encryption || -n $auth_method || -n $auth_method_name || -n $method_details || -n $remove_auth_method || -n $logical_volume ]];then
            : Calling chlv is not required when only lvm encryption attributes are given
            : hence updating return value as success
            rc=$RC_SUCCESS
        fi

        if (( $rc != RC_SUCCESS )); then
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 400 "\nERROR: failed to modify \"%1\$s\".\n\n" "$logical_volume" 1>&2
            rc=$RC_ERROR

        #===========================================================
        : If output from this operation was requested, retrieve it
        #===========================================================
        else
            if (( CLMGR_VERBOSE )) || [[ -n $CLMGR_ATTRS ]]; then
               CL=$LINENO KLIB_HACMP_get_logical_volume_attributes "$logical_volume" properties
            fi
            if [[ -n $auth_method || -n $enable_encryption ]] && [[ $cur_oslevel -ge $min_req_ver ]]
            then
                if [[ -n $auth_method ]];then
                    print "$0()[$LINENO]($SECONDS): cl_enable_encryption -a authadd -l $logical_volume -v $volume_group $typeOpt $mdOpt $anOpt $kOpt" >>$CLMGR_TMPLOG  # Always log commands
                    cl_enable_encryption -a authadd -l $logical_volume -v $volume_group $typeOpt $mdOpt $anOpt $kOpt
                    rc1=$?
                    print "cl_enable_encryption RC: $rc1" >>$CLMGR_TMPLOG  # Always log command result
                    if (( $rc1 != RC_SUCCESS )); then
                        dspmsg -s $CLMGR_SET $CLMGR_MSGS 1477 "\nWARNING: Failed to add authentication for \"%1\$s\".\nYou can run \"%2\$s %1\$s [..]\" or\n\
\"use Change a Logical Volume from %3\$s menu\" to provide the authentication.\n\
If the problem persists, please contact IBM support.\n" "$logical_volume" "clmgr modify lv" "smitty cl_lv" 1>&2
                    fi
                else
                    print "$0()[$LINENO]($SECONDS): cl_enable_encryption -l $logical_volume -v $volume_group $kOpt" >>$CLMGR_TMPLOG  # Always log commands
                    cl_enable_encryption -l $logical_volume -v $volume_group $kOpt
                    rc1=$?
                    print "cl_enable_encryption RC: $rc1" >>$CLMGR_TMPLOG  # Always log command result
                    if (( $rc1 != RC_SUCCESS )); then
                        dspmsg -s $CLMGR_SET $CLMGR_MSGS 1483 "\nWARNING: Failed to disable LVM encryption for %1\$s.\n" "$logical_volume" 1>&2
                    fi
                fi
            elif [[ -n $remove_auth_method ]];then
                print "$0()[$LINENO]($SECONDS): cl_enable_encryption -l $logical_volume -v $volume_group -r $remove_auth_method" >>$CLMGR_TMPLOG
                cl_enable_encryption -l $logical_volume -v $volume_group -r $remove_auth_method
                rc1=$?
                print "$0()[$LINENO]($SECONDS): cl_enable_encryption -l $logical_volume -v $volume_group -r $remove_auth_method RC:$rc1" >>$CLMGR_TMPLOG
                if (( $rc1 != RC_SUCCESS )); then
                        dspmsg -s $CLMGR_SET $CLMGR_MSGS 1487 "\nWARNING: Failed to remove authentication method name(s).\n" 1>&2
                fi
            elif [[ -z $auth_method && -z $enable_encryption ]] && [[ $cur_oslevel -ge $min_req_ver ]];then
                typeset -A vgProps
                CL=$LINENO KLIB_HACMP_get_volume_group_attributes $volume_group vgProps
                isVG_encrypted=${vgProps[ENCRYPTION]}
                if [[ $isVG_encrypted == "yes" && $isLV_encrypted != "yes" ]];then
                    dspmsg -s 32 cspoc.cat 6 "\nWARNING: Encryption for volume group \"%1\$s\" is enabled, but the logical volume \"%2\$s\" is not encrypted.\n\
To enable the encryption for logical volume,\n\
You can run \"%3\$s %2\$s [...] or\n\
use Change a Logical Volume from %4\$s menu\".\n\n" "$volume_group" "$logical_volume" "clmgr modify lv" "smitty cl_lv" 1>&2
                fi
            fi
        fi
    
        if (( $rc == RC_SUCCESS )); then
            CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1473 "\nLogical volume \"%1\$s\" modified successfully.\n\n" "$logical_volume" 1>&2
        fi
    
    fi

    # Bring rpvserver and rpvclients to defined state in all nodes
    if (( $rpv_flag == 1 )) ;then
        change_rpv_state "$primarynodes" "$secondarynodes" "$volume_group" "rmdev"
        change_rpv_state "$secondarynodes" "$primarynodes" "$volume_group" "rmdev"
    fi
        
    #=======================================================================
    : If a user input error was detected, provide some helpful suggestions
    #=======================================================================
    if (( $rc == RC_MISSING_INPUT || $rc == RC_INCORRECT_INPUT ))
    then
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 104 "For more information about available options and syntax, try\n\"$HAUTILS/clmgr %1\$s\". As an\nalternative, if the PowerHA SystemMirror man pages have been installed, invoke\n\"$HAUTILS/clmgr -hv\" (or \"/usr/bin/man clmgr\"),\nsearching for \"%2\$s\" in the displayed text.\n\n" \
        "modify logical_volume -h" "LOGICAL VOLUME:" "$CLMGR_PROGNAME" 1>&2
    fi

    log_return_msg "$rc" "$0()" "$LINENO"
    return $?
} # End of "KLIB_HACMP_modify_logical_volume()"


#============================================================================
#
# Name:        change_rpv_state
#
# Description: This function change the rpvserver/client to available to defined state and vice-versa
#
# Inputs:      siteA_nodes - nodes where to change the rpvservers state 
#              siteB_nodes - nodes where to change the rpvclients state
#              vg_name - volume group
#              cmd - mkdev/rmdev
#
# Outputs:     None.
#
# Returns:     None
#
#============================================================================
function change_rpv_state
{
    typeset siteA_nodes=$1
    typeset siteB_nodes=$2
    typeset vg_name=$3
    typeset cmd=$4
    typeset node=""
    for node in $siteA_nodes
    do
        print "$0()[$LINENO]($SECONDS): cl_rsh $node lspv | grep -w $vg_name | awk '{print $1}'" >>$CLMGR_TMPLOG
        typeset vg_disk=$(cl_rsh $node lspv | grep -w $vg_name | awk '{print $1}')
        print "$0()[$LINENO]($SECONDS): cl_rsh $node lspv command with VG disk list : $vg_disk" >>$CLMGR_TMPLOG
        for disk in $vg_disk
        do
            print "$0()[$LINENO]($SECONDS): lsrpvserver | grep -w $disk | awk '{print $1}'" >>$CLMGR_TMPLOG
            server=$(cl_rsh $node lsrpvserver | grep -w $disk | awk '{print $1,$2}')
            print "$0()[$LINENO]($SECONDS): lsrpvserver command with server list : $server">>$CLMGR_TMPLOG
            if [[ -n $server ]];then
                typeset ser=$(echo $server | cut -d' ' -f1)
                typeset pvid=$(echo $server | cut -d' ' -f2)
                if [[ -n $ser ]];then
                    print "$0()[$LINENO]($SECONDS): cl_rsh $node $cmd -l $ser" >>$CLMGR_TMPLOG
                    typeset ch_ser=$(cl_rsh $node $cmd -l $ser)
                    typeset ch_ser_rc=$? 
                    print "$0()[$LINENO]($SECONDS): $cmd RC : $ch_ser_rc">>$CLMGR_TMPLOG
                fi
                if [[ -n $pvid ]];then
                    for noden in $siteB_nodes
                    do
                        print "$0()[$LINENO]($SECONDS): cl_rsh $noden lsrpvclient | grep -w $pvid | awk '{print $1}''" >>$CLMGR_TMPLOG
                        client=$(cl_rsh $noden lsrpvclient | grep -w $pvid | awk '{print $1}')
                        print "$0()[$LINENO]($SECONDS): lsrpvclient command with client list : $client">>$CLMGR_TMPLOG
                        if [[ -n $client ]];then
                            print "$0()[$LINENO]($SECONDS): cl_rsh $noden $cmd -l $client" >>$CLMGR_TMPLOG
                            ch_clt=$(cl_rsh $noden $cmd -l $client)
                            typeset ch_clt_rc=$? 
                            print "$0()[$LINENO]($SECONDS): $cmd RC : $ch_clt_rc">>$CLMGR_TMPLOG
                        fi
                    done
                fi
            fi
        done
    done
} # End of "change_rpv_state()"

