#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2019,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_mirror_group.sh 1.18 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2011 
# 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 
# @(#)  030993e 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_mirror_group.sh, 726, 2147A_aha726, Sep 09 2021 08:37 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_mirror_group

=head1 SYNOPSIS

 : HyperSwap "user" mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ VOLUME_GROUPS=<volume_group>[,<vg#2>,...] ] \
             [ DISKS=<raw_disk>[,<disk#2>,...] ] \
             [ STORAGE_SYSTEMS=<storage_system>[,<ss#2>,...] ] \
             [ HYPERSWAP_ENABLED={no|yes} ] \
             [ CONSISTENT={yes|no} ] \
             [ UNPLANNED_HS_TIMEOUT=## ] \
             [ HYPERSWAP_PRIORITY={medium|high} ] \
             [ RECOVERY={auto|manual} ] \
             [ RESYNC={auto|manual} ] \
             [ ATTRIBUTES=<NAME>@<VALUE>[,<NAME#2>@<VALUE#2>,...] ]

 : HyperSwap "system" mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ VOLUME_GROUPS=<volume_group>[,<vg#2>,...] ] \
             [ DISKS=<raw_disk>[,<disk#2>,...] ] \
             [ NODE=<node> ] \
             [ STORAGE_SYSTEMS=<storage_system>[,<ss#2>,...] ] \
             [ HYPERSWAP_ENABLED={no|yes} ] \
             [ CONSISTENT={yes|no} ] \
             [ UNPLANNED_HS_TIMEOUT=## ] \
             [ HYPERSWAP_PRIORITY={medium|high} ] \
             [ ATTRIBUTES=<NAME>@<VALUE>[,<NAME#2>@<VALUE#2>,...] ]

 : HyperSwap "repository" mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ SITE=<node> ] \
             [ NON_HS_DISK=<non-HyperSwap_disk> ] \
             [ HS_DISK=<HyperSwap_disk> ] \
             [ STORAGE_SYSTEMS=<storage_system>[,<ss#2>,...] ] \
             [ HYPERSWAP_ENABLED={no|yes} ] \
             [ CONSISTENT={yes|no} ] \
             [ UNPLANNED_HS_TIMEOUT=## ] \
             [ HYPERSWAP_PRIORITY={medium|high} ] \
             [ RESYNC={auto|manual} ] \
             [ ATTRIBUTES=<NAME>@<VALUE>[,<NAME#2>@<VALUE#2>,...] ]

 : DS8000 Global Mirror and XIV mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ MODE={sync|async} ] \
             [ RECOVERY={auto|manual} ] \
             [ STORAGE_SYSTEMS=<storage_system>[,<ss#2>,...] ] \
             [ VENDOR_ID=<vendor_specific_identifier> ] \
             [ ATTRIBUTES=<NAME>@<VALUE>[,<NAME#2>@<VALUE#2>,...] ]

 : SVC mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ STORAGE_SYSTEMS=<MASTER_SVC>,<AUXILIARY_SVC> ] \
             [ MIRROR_PAIRS=<mirror_pair>[,<mirror_pair#2>,...] ] \
             [ MODE={sync|async} ] \
             [ RECOVERY={auto|manual} ]

 : Hitachi mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ VENDOR_ID=<device_group> ] \
             [ HORCM_INSTANCE=<instance> ] \
             [ MODE={sync|async} ] \
             [ RECOVERY={auto|manual} ] \
             [ HORCM_TIMEOUT=### ] \
             [ PAIR_EVENT_TIMEOUT=### ]

 : EMC mirror groups
 clmgr modify mirror_group <mirror_group_name> \
             [ NAME=<new_mirror_group_name> ] \
             [ MG_TYPE={composite|device} ] \
             [ MODE={sync|async} ] \
             [ RECOVERY={auto|manual} ] \
             [ CONSISTENT={yes|no} ] \
             [ VENDOR_ID=<device_group> ]

 NOTE: the alias for "mirror_group" is "mig".

=head1 DESCRIPTION

Attempts to modify the specified mirror group
to conform to the provided specifications.

=head1 ARGUMENTS

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

 2. mirror_group [REQUIRED] [string]
    The label of the mirror group to be modified.

 3. new_name [OPTIONAL] [string]
    The new mirror group name. The name must be system-
    wide unique and can range from 1-64 characters.

 4. mode [OPTIONAL] [set]
    The mode of the mirroring: synchronous or asynchronous

 5. recovery [OPTIONAL] [set]
    Indicates the action to be taken in case of a site
    fallover. Valid values include:

       auto:   No manual intervention required
       manual: Manual Intervention required

 6. storage_systems [OPTIONAL] [string]
    The storage systems that are associated with the
    volume groups and raw disks.

 7. mirror_pairs [OPTIONAL] [string]
    One or more mirror pairs to include.

 8. device_groups [OPTIONAL] [string]
    One of more device groups to include.

 9. consistent [OPTIONAL] [boolean]
    Enables/Disables consistency groups.

 10. vendor_id [OPTIONAL] [string]
    Vendor-specific identifier.

 11. attributes [OPTIONAL] [string]
    Vendor-specific, opaque attributes.

 12. horcm_instance [OPTIONAL] [string]
     The HORCM instance. All nodes in the cluster must
     use same HORCM instance.

 13. horcm_timeout [OPTIONAL] [posint]
    The maximum amount of time, in seconds (defaulting
    to 300), to wait for a takeover to complete.

 14. pair_event_timeout [OPTIONAL] [posint]
    The maximum amount of time, in seconds (defaulting
    to 3600), to wait for the pair event waiting command
    (pairevtwait) to complete. The pairevtwait command
    is used to check the status of pair creation and
    and pair resynchronization while waiting for their
    completion. It waits until the paired volume status
    becomes identical to a specified status, then
    completes (i.e. returns; stops waiting/sleeping).

 15. volume_groups [OPTIONAL] [string]
    The volume group(s) used for the replication setup.

 16. disks [OPTIONAL] [string]
    The raw disk(s) used for the replication setup.

 17. hs_enabled [OPTIONAL] [boolean]
    Enables/Disables Hyperswap.

 18. hs_priority [OPTIONAL] [set]
    The priority for the Hyperswap operation.

    Valid values: medium, high

 19. unpl_hs_timeout [OPTIONAL] [posint]
    The number of seconds for the unplanned hyperswap
    operation. The default is 60 seconds.

 20. node [OPTIONAL] [string]
    The node used for the replication setup.

 21. site [OPTIONAL] [string]
    The site for the cluster repository mirror group.
    There will be more than one site name if the
    cluster is a stretched cluster. For a linked
    cluster you will need to add cluster repository
    mirror group details for each site separately.

 22. non_hs_disk [OPTIONAL] [string]
    The non-HyperSwap disk for the cluster repository
    mirror group. Please note that this disk will be
    available for use by the mirror group when HyperSwap
    is *not* enabled.

 23. hs_disk [OPTIONAL] [string]
    The HyperSwap disk for the cluster repository
    mirror group. Please note that this disk will be
    available for use by the mirror group when HyperSwap
    *is* enabled.

 24. mg_type [OPTIONAL] [set]
    The type of EMC mirror group to set: composite or device.

 25. resync [REQUIRED] [set]
    In case replication volume or path recovers, the HyperSwap
    function makes sure to perform a re-sync automatically for
    'auto'. For 'manual', a user recommended action would be
    displayed in the errpt log for HyperSwap-enabled mirror
    groups, and in hacmp.out for HyperSwap-disabled mirror
    groups. A split and merge policy is recommended to be
    configured for using 'auto'.

    Valid values include:
       automatic
       manual

=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.


#============================================================================
#
# Name:        KLIB_HACMP_modify_mirror_group
#
# Description: This is the main, FPATH function that is invoked by clmgr
#              to modify mirror groups in the cluster configuration.
#
# Inputs:      See the "devDoc()" function, above.
#
# Outputs:     The properties hash is populated. The only other outputs are
#              any error messages that might be needed.
#
# Returns:     Zero if no errors are detected. Otherwise, an appropriate
#              non-zero value is returned. Refer to the "RETURN" section
#              of the "devDoc()" function, above, for the standard return
#              code values/meanings for clmgr.
#
#============================================================================
function KLIB_HACMP_modify_mirror_group {
    . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  030993e 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_mirror_group.sh, 726, 2147A_aha726, Sep 09 2021 08:37 AM
    : INPUTS: $*

    typeset -n properties=$1
    typeset    mirror_group=${2//\"/}
    typeset    new_name=${3//\"/}
    typeset    mode=${4//\"/}
    typeset    recovery=${5//\"/}
    typeset    storage_systems=${6//\"/}
    typeset    mirror_pairs=${7//\"/}
    typeset    device_groups=${8//\"/}
    typeset    consistent=${9//\"/}
    typeset    vendor_id=${10//\"/}
    typeset    attributes=${11//\"/}
    typeset    horcm_instance=${12//\"/}
    typeset    horcm_timeout=${13//\"/}
    typeset    pair_event_timeout=${14//\"/}
    typeset    volume_groups=${15//\"/}
    typeset    disks=${16//\"/}
    typeset -l hs_enabled=${17//\"/}
    typeset -l hs_priority=${18//\"/}
    typeset    unpl_hs_timeout=${19//\"/}
    typeset    node=${20//\"/}
    typeset    site=${21//\"/}
    typeset    non_hs_disk=${22//\"/}
    typeset    hs_disk=${23//\"/}
    typeset    mg_type=${24//\"/}
    typeset -l resync=${25//\"/}

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

    #================================================================
    : Check for a defined cluster. No need to continue without one.
    #================================================================
    CL=$LINENO isClusterDefined
    if (( $? != RC_SUCCESS )); then
        log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO"
        return $?
    fi

    CL=$LINENO isEnterprise
    if (( $? != 1 )); then
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 184 "\nERROR: this operation requires IBM PowerHA SystemMirror for AIX Enterprise Edition.\n\n" 1>&2
        log_return_msg "$RC_MISSING_DEPENDENCY" "$0()" "$LINENO"
        return $?
    fi

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset -A mgAttrs
    typeset type="" value=""
    typeset -l lc_val=""

    #=================
    : Validate input
    #=================
    if [[ -z $mirror_group ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT
    else
        CL=$LINENO KLIB_HACMP_get_mirror_group_attributes "$mirror_group" mgAttrs
        if (( $? != RC_SUCCESS )); then
            log_return_msg "$rc" "$0()" "$LINENO"
            return $?
        else
            type=${mgAttrs[TYPE]}

            if [[ -n $mg_type ]]; then
                if [[ $type == "emc" ]]; then
                    case $mg_type in
                        @(c|C)*) mg_type="CompGroup" ;;
                        @(d|D)*) mg_type="DevGroup"  ;;
                        *)       /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" MG_TYPE "$mg_type" 1>&2
                                 /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "composite, device" 1>&2
                                 rc=$RC_INCORRECT_INPUT
                        ;;
                    esac
                elif [[ $type != "ds8k_inband_mm" ]]; then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' MG_TYPE "TYPE={ds8k_inband_mm|emc}" 1>&2
                fi
            else  # HyperSwap
                if [[ -z $LANG || $LANG=@(C|en|En|EN)* ]]; then
                    : Convert other languages to English, for internal processing
                    typeset -l UTYPE=$(dspmsg -s 4 genxd.cat 56 "User")
                    typeset -l STYPE=$(dspmsg -s 4 genxd.cat 57 "System")
                    typeset -l RTYPE=$(dspmsg -s 4 genxd.cat 58 "Repositories")

                    : Perform a case-insensitive comparison
                    lc_val=${mgAttrs[MG_TYPE]}
                    if [[ $UTYPE == $lc_val ]]; then
                        mg_type="user"
                    elif [[ $STYPE == $lc_val ]]; then
                        mg_type="system"
                    elif [[ $RTYPE == $lc_val ]]; then
                        mg_type="repository"
                    fi
                else
                    mg_type=${mgAttrs[MG_TYPE]}
                fi
            fi
        fi
    fi

    if [[ $mode != *([[:space:]]) ]]; then
        #=============================================
        : Validating the specified MODE value: $mode
        #=============================================
        if [[ $type == @(emc|hitachi|xiv_rm|svc) ]]; then
            case $mode in
                @(a|A)*)
                    mode="async"
                    [[ $type == @(emc|hitachi) ]] && mode="ASYNC"
                ;;
                @(s|S)*)
                    mode="sync"
                    [[ $type == @(emc|hitachi) ]] && mode="SYNC"
                ;;
                *)  /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" MODE "$mode" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "sync, async" 1>&2
                    rc=$RC_INCORRECT_INPUT
                ;;
            esac

        elif [[ $type == ds8k_i* ]]; then
            if [[ -n $mode && $mode != s* ]]; then
                CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 282 '\nERROR: invalid value specified for "%1$s" ("%2$s") with "%3$s".\n\n' MODE "$mode" "$type" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "sync" 1>&2
                rc=$RC_INCORRECT_INPUT
            fi

        elif [[ -n $type ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 283 '\nERROR: "%1$s" does not apply to "%2$s".\n\n' "MODE" "$type" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $consistent != *([[:space:]]) ]]; then
        #=========================================================
        : Validating the specified CONSISTENT value: $consistent
        #=========================================================
        if [[ $type == @(ds8k_inband_mm|emc) ]]; then
            if [[ $consistent == @(y|Y|t|T)* ]]; then
                [[ $type == "emc" ]] && consistent="YES" || consistent="yes"
            elif [[ $consistent == @(n|N|f|F)* ]]; then
                [[ $type == "emc" ]] && consistent="NO"  || consistent="no"
            else
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" CONSISTENT "$consistent" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "yes, no" 1>&2
                rc=$RC_INCORRECT_INPUT
            fi

        elif [[ -n $type ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 283 '\nERROR: "%1$s" does not apply to "%2$s".\n\n' "CONSISTENT" "$type" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $storage_systems != *([[:space:]]) ]]; then
        #===================================================================
        : Validating the specified STORAGE_SYSTEMS value: $storage_systems
        #===================================================================
        if [[ $type == @(svc|xiv_rm|ds8k_gm|ds8k_inband_mm) ]]; then
            for value in ${storage_systems//,/ }; do
                [[ $value == *([[:space:]]) ]] && continue
                CL=$LINENO KLIB_HACMP_is_known_storage_system "$value"
                if (( $? != RC_SUCCESS )); then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$value" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 164 "Available Storage Systems:\n\n" 1>&2

                    typeset available
                    CL=$LINENO KLIB_HACMP_list_storage_systems available
                    for (( i=0; i<${#available[*]}; i++ )); do
                        if [[ ${available[$i]} != *([[:space:]]) ]]; then
                            print -u2 "\t${available[$i]}"
                        fi
                    done
                    print -u2 ""

                    rc=$RC_INCORRECT_INPUT
                fi
            done

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' STORAGE_SYSTEMS "TYPE={xiv_rm|ds8k_gm}" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $mirror_pairs != *([[:space:]]) ]]; then
        #=============================================================
        : Validating the specified MIRROR_PAIRS value: $mirror_pairs
        #=============================================================
        if [[ $type == "svc" ]]; then
            typeset -i BAD_MIP=0
            for value in ${mirror_pairs//,/ }; do
                [[ $value == *([[:space:]]) ]] && continue
                CL=$LINENO KLIB_HACMP_is_known_mirror_pair "$value"
                if (( $? != RC_SUCCESS )); then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$value" 1>&2
                    BAD_MIP=1
                fi
            done

            if (( BAD_MIP )); then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 166 "Available Mirror Pairs:\n\n" 1>&2

                typeset available
                CL=$LINENO KLIB_HACMP_list_mirror_pairs available
                for (( i=0; i<${#available[*]}; i++ )); do
                    if [[ ${available[$i]} != *([[:space:]]) ]]; then
                        print -u2 "\t${available[$i]}"
                    fi
                done
                print -u2 ""

                rc=$RC_INCORRECT_INPUT
            fi

        elif [[ -n $type ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' MIRROR_PAIRS TYPE=svc 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $hs_enabled != *([[:space:]]) ]]; then
        #=========================================================
        : Validating the specified HS_ENABLED value: $hs_enabled
        #=========================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $hs_enabled == @(e|y|t)* ]]; then
                hs_enabled="enabled"
            elif [[ $hs_enabled == @(d|n|f)* ]]; then
                hs_enabled="disabled"
            else
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" HYPERSWAP_ENABLED "$hs_enabled" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "no, yes" 1>&2
                rc=$RC_INCORRECT_INPUT
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HS_ENABLED "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $hs_priority != *([[:space:]]) ]]; then
        #===========================================================
        : Validating the specified HS_PRIORITY value: $hs_priority
        #===========================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            case $hs_priority in
                @(m|M)*) hs_priority="Medium" ;;
                @(h|H)*) hs_priority="High"   ;;
                *) /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" HYPERSWAP_PRIORITY "$hs_priority" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "medium, high" 1>&2
                rc=$RC_INCORRECT_INPUT
                ;;
            esac

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HS_PRIORITY "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $hs_unpl_timeout != *([[:space:]]) ]]; then
        #========================================================================
        : Validating the specified UNPLANNED_HS_TIMEOUT value: $hs_unpl_timeout
        #========================================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            CL=$LINENO verify_is_numeric "$hs_unpl_timeout" 2 UNPLANNED_HS_TIMEOUT
            (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' UNPLANNED_HS_TIMEOUT "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $volume_groups != *([[:space:]]) ]]; then
        #===============================================================
        : Validating the specified VOLUME_GROUPS value: $volume_groups
        #===============================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type == "repository" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' VOLUME_GROUPS "MG_TYPE={user|system}" 1>&2
                rc=$RC_INCORRECT_INPUT

            else
                typeset vg=""
                typeset -i all_vgs_found=1
                for vg in ${volume_groups//,/ }; do
                    if [[ $vg == "rootvg" ]]; then
                        if [[ $mg_type != "system" ]]; then
                            dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' "$vg" "MG_TYPE=system" 1>&2
                            rc=$RC_INCORRECT_INPUT
                            all_vgs_found=0
                        fi
                        continue  # Special case; avoid validation
                    fi

                    CL=$LINENO KLIB_HACMP_is_known_volume_group "$vg" >/dev/null 2>&1
                    if (( $? != RC_SUCCESS )); then
                        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$vg" 1>&2
                        rc=$RC_INCORRECT_INPUT
                        all_vgs_found=0
                    fi
                done
                if (( ! all_vgs_found )); then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 160 "Available Volume Groups:\n\n" 1>&2
                    typeset available
                    CL=$LINENO KLIB_HACMP_list_volume_groups available
                    for (( i=0; i<${#available[*]}; i++ )); do
                        if [[ ${available[$i]} != *([[:space:]]) ]]; then
                            print -u2 "\t${available[$i]}"
                        fi
                    done
                    print -u2 ""
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' VOLUME_GROUPS "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $disks != *([[:space:]]) ]]; then
        #===================================================
        : Validating the specified RAW_DISKS value: $disks
        #===================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type == "repository" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' RAW_DISKS "MG_TYPE={user|system}" 1>&2
                rc=$RC_INCORRECT_INPUT

            else
                typeset new_disks=""
                if [[ -n $disks ]]; then
                    typeset -i all_disks_found=1
                    typeset disk="" dname="" duuid="" rem=""
                    typeset -A diskMap
                    LC_ALL=C LANG=C $HAXDCLI/clxd_list_rdisk |\
                    while read dname duuid rem; do
                        [[ $dname == "Device" ]] && continue
                        [[ $dname == *([[:space:]]) ]] && continue
                        diskMap[$dname]=$duuid
                    done

                    for disk in ${disks//,/ }; do
                        if [[ " ${!diskMap[*]} " != *\ $disk\ * && \
                              " ${diskMap[*]} "  != *\ $disk\ * ]]
                        then
                            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 285 '\nERROR: "%1$s" either does not exist, or is not a raw disk.\n\n' "$disk" 1>&2
                            rc=$RC_INCORRECT_INPUT
                            all_disks_found=0
                        else
                            typeset pv=""
                            for pv in ${!diskMap[*]}; do
                                if [[ $pv == $disk ]]; then
                                    new_disks="$new_disks $pv:${diskMap[$pv]}"
                                    break
                                elif [[ ${diskMap[$pv]} == $disk ]]; then
                                    new_disks="$new_disks $pv:${diskMap[$pv]}"
                                    break
                                fi
                            done
                        fi
                    done
                    if (( ! all_disks_found )); then
                        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 153 "Available Physical Volumes:\n\n" 1>&2
                        $HAXDCLI/clxd_list_rdisk 1>&2
                        print -u2 ""
                    else
                        disks=${new_disks# }
                    fi
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' RAW_DISKS "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $node != *([[:space:]]) ]]; then
        #=============================================
        : Validating the specified NODE value: $node
        #=============================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type != "system" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' NODE "MG_TYPE=system" 1>&2
                rc=$RC_INCORRECT_INPUT

            else
                CL=$LINENO KLIB_HACMP_is_known_node $node >/dev/null
                if (( $? != RC_SUCCESS )); then
                    rc=$RC_NOT_FOUND
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$node" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 151 "Available Nodes:\n\n" 1>&2

                    typeset available
                    CL=$LINENO KLIB_HACMP_list_nodes available
                    for (( i=0; i<${#available[*]}; i++ )); do
                        if [[ ${available[$i]} != *([[:space:]]) ]]; then
                            print -u2 "\t${available[$i]}"
                        fi
                    done
                    print -u2 ""
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' NODE "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $site != *([[:space:]]) ]]; then
        #=============================================
        : Validating the specified SITE value: $site
        #=============================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type != "repository" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' SITE "MG_TYPE=repository" 1>&2

            else
                CL=$LINENO KLIB_HACMP_is_known_site $site >/dev/null
                if (( $? != RC_SUCCESS )); then
                    rc=$RC_NOT_FOUND
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$site" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 157 "Available Sites:\n\n" 1>&2

                    typeset available
                    CL=$LINENO KLIB_HACMP_list_sites available
                    for (( i=0; i<${#available[*]}; i++ )); do
                        if [[ ${available[$i]} != *([[:space:]]) ]]; then
                            print -u2 "\t${available[$i]}"
                        fi
                    done
                    print -u2 ""
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' SITE "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $non_hs_disk != *([[:space:]]) ]]; then
        #===========================================================
        : Validating the specified NON_HS_DISK value: $non_hs_disk
        #===========================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type != "repository" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' NON_HS_DISK "MG_TYPE=repository" 1>&2

            else
                typeset -i found=0
                typeset dname="" duuid="" rem=""
                LC_ALL=C LANG=C $HAXDCLI/clxd_list_rdisk |\
                while read dname duuid rem; do
                    [[ $dname == "Device" ]] && continue
                    [[ $dname == *([[:space:]]) ]] && continue
                    if [[ $dname == $non_hs_disk || \
                          $duuid == $non_hs_disk ]]
                    then
                        non_hs_disk="$duuid"  # Convert to UUID
                        found=1
                    fi
                done

                if (( ! found )); then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 285 '\nERROR: "%1$s" either does not exist, or is not a raw disk.\n\n' "$non_hs_disk" 1>&2
                    rc=$RC_INCORRECT_INPUT

                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 153 "Available Physical Volumes:\n\n" 1>&2
                    $HAXDCLI/clxd_list_rdisk 1>&2
                    print -u2 ""
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' NON_HS_DISK "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $hs_disk != *([[:space:]]) ]]; then
        #===================================================
        : Validating the specified HS_DISK value: $hs_disk
        #===================================================
        if [[ $type == "ds8k_inband_mm" ]]; then
            if [[ $mg_type != "repository" ]]; then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HS_DISK "MG_TYPE=repository" 1>&2

            else
                typeset -i found=0
                typeset dname="" duuid="" rem=""
                LC_ALL=C LANG=C $HAXDCLI/clxd_list_rdisk |\
                while read dname duuid rem; do
                    [[ $dname == "Device" ]] && continue
                    [[ $dname == *([[:space:]]) ]] && continue
                    if [[ $dname == $hs_disk || \
                          $duuid == $hs_disk ]]
                    then
                        hs_disk="$duuid"  # Convert to UUID
                        found=1
                    fi
                done

                if (( ! found )); then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 285 '\nERROR: "%1$s" either does not exist, or is not a raw disk.\n\n' "$hs_disk" 1>&2
                    rc=$RC_INCORRECT_INPUT

                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 153 "Available Physical Volumes:\n\n" 1>&2
                    $HAXDCLI/clxd_list_rdisk 1>&2
                    print -u2 ""
                fi
            fi

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HS_DISK "TYPE=ds8k_inband_mm" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    #========================================
    : Check the Hitachi-specific attributes
    #========================================
    if [[ -n $horcm_instance && $type != "hitachi" ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HORCM_INSTANCE TYPE=hitachi 1>&2
    fi
    if [[ -n $horcm_timeout ]]; then
        if [[ $type != "hitachi" ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' HORCM_TIMEOUT TYPE=hitachi 1>&2
        else
            CL=$LINENO verify_is_numeric "$horcm_timeout" 2 HORCM_TIMEOUT
            (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
        fi
    fi
    if [[ -n $pair_event_timeout ]]; then
        if [[  $type != "hitachi" ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' PAIR_EVENT_TIMEOUT TYPE=hitachi 1>&2
        else
            CL=$LINENO verify_is_numeric "$pair_event_timeout" 2 PAIR_EVENT_TIMEOUT
            (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $recovery != *([[:space:]]) ]]; then
        #=====================================================
        : Validating the specified RECOVERY value: $recovery
        #=====================================================
        if [[ $type == "ds8k_inband_mm" && $mg_type == "user" ]] || \
           [[ $type == @(ds8k_gm|emc|hitachi|svc|xiv_rm) ]]
        then
            case $recovery in
                @(a|A)*)
                    recovery="auto"
                    [[ $type == @(emc|hitachi) ]] && recovery="AUTO"
                ;;
                @(m|M)*)
                    recovery="manual"
                    [[ $type == @(emc|hitachi) ]] && recovery="MANUAL"
                ;;
                *)  /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" RECOVERY "$recovery" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "auto, manual" 1>&2
                    rc=$RC_INCORRECT_INPUT
                ;;
            esac

        elif [[ $type == "ds8k_inband_mm" ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' RECOVERY "MG_TYPE=user" 1>&2
            rc=$RC_INCORRECT_INPUT

        else
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' RECOVERY "TYPE={ds8k_inband_mm|ds8k_gm|emc|svc|xiv_rm}" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

    if [[ $resync != *([[:space:]]) ]]; then
        if [[ $type == "ds8k_inband_mm" && \
              $mg_type != @(u|r)* ]]
        then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 45 '\nERROR: "%1$s" may only be used with "%2$s".\n\n' RECOVERY "MG_TYPE=user" 1>&2
            rc=$RC_INCORRECT_INPUT
        else
            if [[ $resync != *([[:space:]]) ]]; then
                CL=$LINENO verify_in_set RESYNC "$resync" "manual, automatic" resync
                (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT
            fi
        fi
    fi

    #====================================================================
    : If no errors have been detected thus far, load up any values from
    : the specified mirror group that have not been overridden. This is
    : required by the underlying XD utility.
    #====================================================================
    if (( $rc == RC_UNKNOWN )); then
        typeset value="" internal=""
        typeset -u external=""
        for PAIR in consistent horcm_instance horcm_timeout \
                    storage_systems hs_enabled:HYPERSWAP_ENABLED \
                    hs_priority:HYPERSWAP_PRIORITY \
                    unpl_hs_timeout:UNPLANNED_HS_TIMEOUT \
                    hs_disk:REPOSITORY_MG_HS_DISK \
                    non_hs_disk:REPOSITORY_MG_NONHS_DISK resync \
                    mode pair_event_timeout recovery site:REPOSITORY_MG_SITES \
                    node:SYS_MG_NODE vendor_id volume_groups disks:RAW_DISKS
        do
            internal=${PAIR%%:*}
            external=${PAIR##*:}
            [[ -z $external ]] && external=$internal

            eval "value=\$$internal"
            if [[ -z $value && -n ${mgAttrs[$external]} ]]; then
                eval "$internal=\"${mgAttrs[$external]}\""
            fi
        done
    fi

    #================================================================
    : Modify the mirror group if no input errors have been detected
    #================================================================
    if (( $rc == RC_UNKNOWN )); then
        typeset SOpts="" vOpt="" oOpts="" pOpts="" gOpt=""
        typeset IOpt="" HOpt="" POpt="" NOpt="" mOpt="" rOpt="" aOpts=""
        typeset lOpts="" xOpt="" tOpt="" pOpt="" eOpt="" iOpt=""
        typeset wOpt="" dOpt="" YOpt="" yOpt="" ROpt=""

        [[ -n $new_name           ]] && NOpt=" -N $new_name"
        if [[ -n $vendor_id ]]; then
            case $type in
                hitachi) vOpt=" -D $vendor_id" ;;
                emc)     vOpt=" -D $vendor_id" ;;
                *)       vOpt=" -v $vendor_id" ;;
            esac
        fi
        [[ -n $consistent         ]] && gOpt=" -g $consistent"
        [[ -n $mode               ]] && mOpt=" -m $mode"
        [[ -n $recovery           ]] && rOpt=" -r $recovery"
        [[ -n $resync             ]] && ROpt=" -R $resync"
        [[ -n $horcm_instance     ]] && IOpt=" -I $horcm_instance"
        [[ -n $horcm_timeout      ]] && HOpt=" -H $horcm_timeout"
        [[ -n $pair_event_timeout ]] && POpt=" -P $pair_event_timeout"
        [[ -n $hs_enabled         ]] && xOpt=" -x $hs_enabled"
        [[ -n $unpl_hs_timeout    ]] && tOpt=" -t $unpl_hs_timeout"
        [[ -n $hs_priority        ]] && YOpt=" -Y $hs_priority"
        [[ -n $node               ]] && eOpt=" -e $node"
        [[ -n $site               ]] && iOpt=" -i $site"
        [[ -n $non_hs_disk        ]] && wOpt=" -w $non_hs_disk"
        [[ -n $hs_disk            ]] && dOpt=" -d $hs_disk"
        [[ -n $mg_type            ]] && yOpt=" -y $mg_type"

        if [[ -n $attributes ]]; then
            for value in ${attributes//,/ }; do
                oOpts="$oOpts -o${value//@/ }"
            done
        fi

        if [[ -n $storage_systems ]]; then
            for value in ${storage_systems//,/ }; do
                SOpts="$SOpts -S $value"
            done
        fi

        if [[ -n $mirror_pairs ]]; then
            for value in ${mirror_pairs//,/ }; do
                pOpts="$pOpts -p $value"
            done
        fi

        if [[ -n $disks ]]; then
            for value in ${disks//,/ }; do
                aOpts="$aOpts -a $value"
            done
        fi

        if [[ -n $volume_groups ]]; then
            for value in ${volume_groups//,/ }; do
                lOpts="$lOpts -l $value"
            done
        fi

        print -- "$0()[$LINENO]($SECONDS): $HAXDWIZ/clxd_change_mg_director -n $mirror_group -s $type$yOpt$NOpt$mOpt$rOpt$ROpt$SOpts$vOpt$pOpts$gOpt$IOpt$HOpt$POpt$oOpts$lOpts$aOpts$iOpt$eOpt$wOpt$dOpt$xOpt$tOpt$YOpt" >>$CLMGR_TMPLOG  # Always log commands
        $HAXDWIZ/clxd_change_mg_director -n $mirror_group -s $type$yOpt$NOpt$mOpt$rOpt$ROpt$SOpts$vOpt$pOpts$gOpt$IOpt$HOpt$POpt$oOpts$lOpts$aOpts$iOpt$eOpt$wOpt$dOpt$xOpt$tOpt$YOpt
        rc=$?
        print "$0()[$LINENO]($SECONDS): clxd_change_mg_director RC: $rc" >>$CLMGR_TMPLOG  # Always log command result

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

        #===========================================================
        : If output from this operation was requested, retrieve it
        #===========================================================
        if (( $rc == RC_SUCCESS )); then
            if (( CLMGR_VERBOSE )) || [[ -n $CLMGR_ATTRS ]]; then
                CL=$LINENO KLIB_HACMP_get_mirror_group_attributes "$mirror_group" properties
            fi
        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" \
        "add mirror_group -h" "MIRROR GROUP:" "$CLMGR_PROGNAME" 1>&2
    fi

    log_return_msg "$rc" "$0()" "$LINENO"
    return $?
} # End of "KLIB_HACMP_modify_mirror_group()"
#================================================
# The following, commented line enforces coding
# standards when this file is edited via vim.
#================================================
# vim:tabstop=4:shiftwidth=4:expandtab:smarttab
#================================================
