#!/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
#                                                                              
# @(#)  5d6dd76 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_file_system.sh, 726, 2147A_aha726, Sep 09 2021 10:49 AM

# 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_file_system

=head1 SYNOPSIS

 clmgr modify file_system <fsname> \
             UNITS=### \
                 [ SIZE_PER_UNIT={megabytes|gigabytes|512bytes} ] \
             [ NEW_FS_NAME=<new fs name> ] \
             [ PERMISSIONS={rw|ro} ] \
             [ EFS={yes|true} ]

 NOTE: the mininmum size for an enhanced file system is 16MB.

 NOTE: an alias for "file_system" is "fs".

=head1 DESCRIPTION

Attempts to add a new file system.

=head1 ARGUMENTS

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

 2. file_system [REQUIRED] [string]
    The mount point for this file system.

 3. units [OPTIONAL] [posint]
    The number of units of the specified unit size
    (which defaults to megabytes). Combined, these
    determine the size of the file system.

 4. size_per_unit [OPTIONAL] [set]
    The size of each of the specified units defaulting
    to megabytes. Combined, these determine the size of
    the file system.

    Valid values: 512bytes, megabytes, gigabytes                          

 5. new_fs_name [OPTIONAL] [string]
    Enter the new filesystem name

 6. permissions [OPTIONAL] [set]
    Sets the permissions for the file system, defaulting
    to "rw" (read/write).

    Valid values: rw (read/write), ro (read only)

 7. enable_efs [OPTIONAL] [boolean]
    Enter "yes" to enable encryption for this file
    system (EFS).

    Valid values: yes, true, enable and 1.

    NOTE: this option is only valid with enhanced
          file systems.

=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

=cut
} # End of POD-formatted documentation.


function KLIB_HACMP_modify_file_system {
    . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  5d6dd76 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_file_system.sh, 726, 2147A_aha726, Sep 09 2021 10:49 AM
    : INPUTS: $*
    typeset -n properties=$1
    typeset file_system=${2//\"/}
    typeset units=${3//\"/}
    typeset size_per_unit=${4//\"/}
    typeset new_file_system=${5//\"/}
    typeset -l permissions=${6//\"/}
    typeset -l enable_efs=${7//\"/}
    [[ $CLMGR_LOGGING == 'med' ]] && set +x  # Only trace param values
        
    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset INPUT="" ATTR="" VALUE=""

    typeset volume_group="" vg_disk="" rg_name=""
    typeset primarynodes="" secondarynodes="" nodes=""

    if [[ -z $file_system ]];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): lsfs -c "$file_system" | tail -1 | cut -d: -f2 | cut -c6- 2>/dev/null" >>$CLMGR_TMPLOG
        lv_name=$(lsfs -c "$file_system" | tail -1 | cut -d: -f2 | cut -c6- 2>/dev/null)
        typeset lv_name_rc=$?
        print "$0()[$LINENO]($SECONDS): lsfs command to get filesystem $lv_name RC: $lv_name_rc" >>$CLMGR_TMPLOG
        if [[ -n $lv_name ]];then
            print "$0()[$LINENO]($SECONDS): clodmget -q "name=$lv_name" -f parent -n CuDv" >>$CLMGR_TMPLOG
            volume_group=$(clodmget -q "name=$lv_name" -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
    fi
    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): odmget 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): odmget 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, we should not allow changing filesystem 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
                    print "$0()[$LINENO]($SECONDS): ERROR: Failed to modify filesystem,cluster state stable in one of the node $node" >>$CLMGR_TMPLOG
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1470 "\nERROR: Failed to modify filesystem \"%1\$s\". Cluster services are still active on at least one node in the cluster: %2\$s.\n\n" "$file_system" "$node" 1>&2 
                    log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO"
                    return $RC_MISSING_DEPENDENCY
                fi
            done
        fi
    else
        print "$0()[$LINENO]($SECONDS): filesystem $file_system is not configured or its not associated to any volume group" >>$CLMGR_TMPLOG
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1471 "\nERROR: Filesystem \"%1\$s\" is either not configured or not associated with any volume group.\n\n" "$file_system" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi
    #==============================
    : Validate the integer inputs
    #==============================
    for INPUT in UNITS@$units
    do
        print -- "$INPUT" | IFS=@ read ATTR VALUE
        if [[ $VALUE != *([[:space:]]) ]]; then
            CL=$LINENO verify_is_numeric "$VALUE" 2 "$ATTR"
            (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
        fi
    done
    #==========================
    : Validate the set inputs
    #==========================

    if [[ -n $permissions ]]; then
        typeset -l permissions_lc=$permissions
        CL=$LINENO verify_in_set permissions_lc "$permissions" "rw ro" permissions_lc
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n $enable_efs ]]; then
        typeset -l EFS=$enable_efs
        CL=$LINENO verify_in_set EFS "$enable_efs" "yes true enable 1" EFS
        if (( $? == RC_SUCCESS )); then
            [[ $enable_efs == @(y|e|t|1)* ]] && enable_efs="yes"
        else
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ -n $size_per_unit ]]; then
        typeset -l spu_lc=$size_per_unit
        if [[ -n $size_per_unit ]];then
            CL=$LINENO verify_in_set size_per_unit "$spu_lc" "megabytes gigabytes 512bytes" spu_lc
            (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
        fi
    fi

    #======================================================================
    : If no errors have been detected in the input, perform the operation
    #======================================================================
    if (( rc == RC_UNKNOWN )); then
        typeset gOpt="" vOpt=" -v jfs" mOpt="" unitsOpt="" FOpt="" pOpt=""
        typeset bsOpt="" optOpt="" ilOpt="" lvOpt="" lsOpt="" eafOpt=""
        typeset quotaOpt="" efsOpt="" tOpt="" fragOpt="" nbpiOpt="" agOpt=""
        typeset dOpt=""
        
        [[ $new_file_system != *([[:space:]])  ]] && mOpt=" -m $new_file_system"
        [[ $units != *([[:space:]])        ]] && unitsOpt=" -a size=$units"
        [[ $permissions != *([[:space:]])  ]] && pOpt=" -p $permissions"
        [[ $enable_efs != *([[:space:]])   ]] && efsOpt=" -a efs=$enable_efs"
       
        if [[ $size_per_unit != *([[:space:]]) ]]; then
            typeset uos_lc=$size_per_unit
            [[ $uos_lc == "megabytes" ]] && FOpt=" -FM"
            [[ $uos_lc == "gigabytes" ]] && FOpt=" -FG"
            [[ $uos_lc == "512bytes" ]] && FOpt=" -FH"
        fi
        
        # Bring rpvserver and rpvclients to available state in all the nodes if file system is associated with GLVM volume group.
        # This is used to avoid errors during varyon the volume group.
        if [[ -n $gmvg_type ]];then
            change_rpv_state "$primarynodes" "$secondarynodes" "$volume_group" "mkdev"
            change_rpv_state "$secondarynodes" "$primarynodes" "$volume_group" "mkdev"
        fi
       
        nodes=$(echo $nodes | tr ' ' ',')
        case $file_system in
        /*)
             ;;
        *)
             file_system=/$file_system
             ;;
        esac
        print "$0()[$LINENO]($SECONDS): cl_chfs -cspoc \"-n'$nodes'\"$gOpt$dOpt$mOpt$pOpt$bsOpt$optOpt$ilOpt$lvOpt$lsOpt$eafOpt$quotaOpt$efsOpt$tOpt$fragOpt$nbpiOpt$agOpt$mandatoryOpts$unitsOpt$FOpt $file_system" >>$CLMGR_TMPLOG
        cl_chfs -cspoc -n"$nodes" $gOpt$dOpt$mOpt$pOpt$bsOpt$optOpt$ilOpt$lvOpt$lsOpt$eafOpt$quotaOpt$efsOpt$tOpt$fragOpt$nbpiOpt$agOpt$mandatoryOpts$unitsOpt$FOpt $file_system
        rc=$?
        print "$0()[$LINENO]($SECONDS): cl_chfs RC: $rc" >>$CLMGR_TMPLOG  # Always log command result
        if (( $rc != RC_SUCCESS )); then
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 400 "\nERROR: failed to modify \"%1\$s\".\n\n" "$file_system" 1>&2
            rc=$RC_ERROR
        
        #===========================================================
        : If output from this operation was requested, retrieve it
        #===========================================================
        elif (( CLMGR_VERBOSE )) || [[ -n $CLMGR_ATTRS ]]; then
            CL=$LINENO KLIB_HACMP_get_file_system_attributes "$file_system" properties
        fi
    
        # Bring rpvserver and rpvclients to defined state in all the nodes if file system is associated with GLVM volume group.

        if [[ -n $gmvg_type ]];then
            change_rpv_state "$primarynodes" "$secondarynodes" "$volume_group" "rmdev"
            change_rpv_state "$secondarynodes" "$primarynodes" "$volume_group" "rmdev"
        fi

        if (( $rc == RC_SUCCESS )); then
            CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1474 "\nFilesystem \"%1\$s\" modified successfully.\n\n" "$file_system" 1>&2
        fi
    fi
    

    #=======================================================================
    : If a user input error was detected, provide some helpful suggestions
    #=======================================================================
    if (( $rc == RC_MISSING_INPUT || $rc == RC_INCORRECT_INPUT )) && \
       [[ $CLMGR_GUI == *([[:space:]]) ]]
    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 file_system -h" "FILE SYSTEM:" "$CLMGR_PROGNAME" 1>&2
    fi

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

#============================================================================
#
# 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()"

