#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r721 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_group.sh 1.5 
#  
# 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 
# @(#)98	1.5  src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_group.sh, hacmp.assist, 61haes_r721, 1618A_hacmp721 4/29/16 05:34:01

#================================================
# 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_group

=head1 VERSION

 Version Number:  1.5
 Last Extracted:  5/3/16 18:54:15
 Last Changed:    4/29/16 05:34:01

 Path, Component, Release(, Level):
 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_group.sh, hacmp.assist, 61haes_r721, 1618A_hacmp721

=head1 SYNOPSIS

 clmgr modify group <group_name> \
             [ RESOURCE_GROUP=<resource_group> ] \
             [ ID=### ] \
             [ ADMINISTRATIVE={false|true} ] \
             [ USERS=<user#1>[,<user#2>,...] ] \
             [ ADMINS=<admin#1>[,<admin#2>,...] ] \
             [ PROJECTS=<project#1>[,<project#2>,...] ] \
             [ KEYSTORE_MODE={admin|guard} ] \
             [ KEYSTORE_ENCRYPTION={RSA_1024|RSA_2048|RSA_4096} ] \
             [ KEYSTORE_ACCESS={file|none} ] \
             [ REGISTRY={ldap|local(files)} ]

 NOTE: the alias for "group" is "gp".

=head1 DESCRIPTION

Attempts to modify an AIX group to either all the nodes in the cluster,
or to just those nodes within the specified resource 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. group [REQUIRED] [string]
    The label that is to be applied to this group. A group represents
    one or more system users who can access and work with protected
    resources.
                                                                     
    The system uses groups to control access to files and resources
    by users who do not own them. When a user starts a process, the
    system associates the process with the user's ID and the group
    IDs of the groups the user belongs to. If the user owns the
    resource or is a member of a group that can access it, the
    system grants read write, or execute access to it according to
    the access control list of the resource or file.

    A group name is specified as a string.  The maximum length
    depends on the configuration of the individual nodes, and can
    be queried using the lsattr command to view the max_logname
    attribute of the sys0 device, but all AIX systems will accept
    a length of up to 8 characters.  See the documentation on the
    AIX mkuser command for more information.

    You can use letters, numbers, and some special characters in
    the name. The string cannot start with a hyphen (-), plus (+),
    tilde (~), or at sign (@). The string cannot contain any spaces
    or any of the following characters: colon (:), double quote ("),
    pound sign, comma (,), asterisk (*), single quote ('), equal
    sign (=), newline (\n), tab (\t), backslash (\), forward slash
    (/), question mark (?), back quote (`), or the key words "ALL"
    or "default".

 3. rg [OPTIONAL] [string]
    A resource group within the cluster. If specified, the new group
    will only be added to the nodes that this resource group is able
    to run on. If no resource group is specified, the new groups will
    be added to all nodes within the cluster.

 4. id [OPTIONAL] [posint]
    A unique ID number associated with this group. If an ID number
    is not specified, AIX will automatically assign one for you.

 5. administrative [OPTIONAL] [boolean]
    Indicates if the group is an administrative group. Only the root
    user can modify the attributes of an administrative group.
                                                                
    This field is displayed with False or True as its value. True
    indicates that group is an administrative group. False indicates
    that it is a nonadministrative group (its attributes can be
    modified by the group's specified administrators and the root
    user).

 6. users [OPTIONAL] [string]
    Specifies the names of the users that belong to this group. The
    members of a group can access (that is, read, write, or execute)
    a resource or file owned by another member of the group as
    specified by the resource's access control list.

    To enter the user members of this group, type in their names
    (separated by commas), or use the List box and select the users
    from the choices displayed (the users are displayed in the field
    in the correct format.

    Note: A user cannot be removed from the user's primary group
    unless you first redefine the user's primary group.

 7. admins [OPTIONAL] [string]
    Specifies the members that can modify this group (for example,
    add new members to the group, or remove members from it) if
    the group is a non-administrative group.

    Note: The group attributes of an administrative group can be
    modified by only the root user; so if the group is an
    administrative group (specified in the ADMINISTRATIVE group
    attribute), no administrators can be defined in this field.

 8. projects [OPTIONAL] [string]

 9. keystore_mode [OPTIONAL] [set]
    The efs_initalks_mode of admin allows for root or other
    security privileged system users to reset the user's key
    store password. Otherwise, if the user forgets their key
    store password, they will not be able to access their
    Encrypted File System files.

    If the guard mode is selected, then root cannot reset the
    user's key store password.

    Allowed values: admin, guard

 10. keystore_encryption [OPTIONAL] [set]
    This option specifies the algorithm for the user's key within
    the key store. This key will protect the encrypting key of
    files the user creates within the Encrypted File System.

    Allowed values: RSA_1024, RSA_2048, RSA_4096

    RSA_1024 = 1024 bit RSA key
    RSA_2048 = 2048 bit RSA key
    RSA_4096 = 4096 bit RSA key

 11. keystore_access [OPTIONAL] [set]
    The key store will allow the user to utilize files in Encrypted    
    File System. The selection of file will create a key store file
    associated with this user. It is recommended that file is
    selected.  Select none for no key store to be created. All
    other EFS (efs_*) attributes will not have any effect.

    Allowed values: file, node

 12. registry [OPTIONAL] [set]
    Indicates where the group's information is currently stored,
    so the modification(s) can be made in the correct place.
    If the group is defined locally, within AIX, than the value
    "files" should be used. If the group is defined remotely, on
    the LDAP server, then "LDAP" should be 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_group {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=1.5, src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_group.sh, hacmp.assist, 61haes_r721, 1618A_hacmp721
    : INPUTS: $*

    typeset -n properties=$1
    typeset group=${2//\"/}
    typeset rg=${3//\"/}
    typeset id=${4//\"/}
    typeset -l administrative=${5//\"/}
    typeset users=${6//\"/}
            users=${users//,/ }
    typeset admins=${7//\"/}
            admins=${admins//,/ }
    typeset projects=${8//\"/}
            projects=${projects//,/ }
    typeset keystore_mode=${9//\"/}
    typeset keystore_encryption=${10//\"/}
    typeset keystore_access=${11//\"/}
    typeset registry=${12//\"/}

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

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN

    [[ $registry == "local" || $registry == "LOCAL" ]] && registry="files"

    #================================================================
    : Assuming an object was specified, see if it is a known object
    #================================================================
    if [[ $group != *([[:space:]]) ]]; then
        CL=$LINENO KLIB_HACMP_is_known_group "$group"
        (( $? != RC_SUCCESS )) && rc=$RC_NOT_FOUND
    fi

    #=================
    : Validate input
    #=================
    if [[ -z $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

    elif (( $rc == RC_NOT_FOUND )); then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$group" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 161 "Available Groups:\n\n" 1>&2

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

    #=================
    : Validate input
    #=================
    if [[ $rg != *([[:space:]]) ]]; then
        CL=$LINENO KLIB_HACMP_is_known_rg $rg
        if (( $? != RC_SUCCESS )); then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$rg" 1>&2
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 154 "Available Resource Groups:\n\n" 1>&2

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

            rc=$RC_NOT_FOUND
        fi
    fi

    if [[ $id != *([[:space:]]) && $id != +([[:digit:]]) ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" ID 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n $administrative && $administrative != @(y|t|n|f)* ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" ADMINISTRATIVE "$administrative" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "true, false" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n $users ]]; then
        for user in $users; do
            CL=$LINENO KLIB_HACMP_is_known_user $user
            if (( $? != RC_SUCCESS )); then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$user" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 162 "Available Users:\n\n" 1>&2

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

                rc=$RC_NOT_FOUND
            fi
        done
    fi

    if [[ -n $admins ]]; then
        for admin in $admins; do
            CL=$LINENO KLIB_HACMP_is_known_user $admin
            if (( $? != RC_SUCCESS )); then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$admin" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 162 "Available Users:\n\n" 1>&2

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

                rc=$RC_NOT_FOUND
            fi
        done
    fi

    #================================================================
    : Attempt to determine where the specified group is registered,
    : so that the modifications can be made in the right place.
    #================================================================
    typeset -u source= user_source=
    if (( $rc == RC_UNKNOWN )); then
        if [[ $registry != *([[:space:]]) ]]; then
            typeset -u registryUC=$registry
            case $registryUC in
                LD*) registry="LDAP" ;;
                LO*) registry="files"  ;;
                 F*) registry="files" ;;
                  *) /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 '\nERROR: invalid value specified for "%1$s":  "%2$s".\n' REGISTRY "$registry" 1>&2
                     /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "files, LDAP" 1>&2
                     rc=$RC_INCORRECT_INPUT
                  ;;
            esac
            (( $rc == RC_UNKNOWN )) && user_source=$registry
        fi

        if (( $rc == RC_UNKNOWN )); then
            print -- "$0()[$LINENO]($SECONDS): /usr/sbin/lsgroup -R files -a registry $group" >>$CLMGR_TMPLOG
            typeset LOCAL=$(/usr/sbin/lsgroup -R files -a registry $group 2>>$CLMGR_TMPLOG)
            print "$0()[$LINENO]($SECONDS): lsgroup (files) RC: $?" >>$CLMGR_TMPLOG

            print -- "$0()[$LINENO]($SECONDS): /usr/sbin/lsgroup -R LDAP -a registry $group" >>$CLMGR_TMPLOG
            typeset REMOTE=$(/usr/sbin/lsgroup -R LDAP -a registry $group 2>>$CLMGR_TMPLOG)
            print "$0()[$LINENO]($SECONDS): lsgroup (LDAP) RC: $?" >>$CLMGR_TMPLOG

            if [[ -n $LOCAL && -n $REMOTE ]]; then
                if [[ -z $user_source ]]; then
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 9999 '\nERROR: "%1$s" is registered both locally and remotely. Please use the "REGISTRY" option to indicate which definition of "%1$s" you want to modify.\n' "$group" 1>&2
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "files, LDAP" 1>&2
                    rc=$RC_MISSING_INPUT
                else
                    source=$user_source
                fi
            elif [[ -n $LOCAL ]]; then
                source=${LOCAL##*=}
                if [[ -n $user_source && $user_source != $source ]]; then
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 9999 '\nERROR: "%1$s" is not registered remotely, so the specified REGISTRY setting, "%2$s", will not work.\n\n' "$group" "$registry" 1>&2
                    rc=$RC_INCORRECT_INPUT
                fi
            elif [[ -n $REMOTE ]]; then
                source=${REMOTE##*=}
                if [[ -n $user_source && $user_source != $source ]]; then
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 9999 '\nERROR: "%1$s" is not registered locally, so the specified REGISTRY setting, "%2$s", will not work.\n\n' "$group" "$registry" 1>&2
                    rc=$RC_INCORRECT_INPUT
                fi
            fi
        fi
    fi

    #========================================================
    : Create the group if no input errors have been detected
    #========================================================
    if (( $rc == RC_UNKNOWN )); then
        typeset rgOpt= adminOpt= idOpt= usersOpt= adminsOpt=
        [[ $rg != *([[:space:]]) ]] && rgOpt=" -cspoc-g $rg"
        [[ $administrative == @(y|t)* ]] && adminOpt=" admin=true"
        [[ $administrative == @(n|f)* ]] && adminOpt=" admin=false"
        [[ $id != *([[:space:]]) ]] && idOpt=" id=$id"
        [[ $users != *([[:space:]]) ]] && usersOpt=" users=${users//+([[:space:]])/,}"
        [[ $admins != *([[:space:]]) ]] && adminsOpt=" adms=${admins//+([[:space:]])/,}"

        if [[ $source == "LDAP" ]]; then
            print -- "$0()[$LINENO]($SECONDS): mode=LDAP $HACSPOC/fix_args nop cl_chgroup$rgOpt$adminOpt$idOpt$usersOpt$adminsOpt $group" >>$CLMGR_TMPLOG  # Always log commands
            mode=LDAP $HACSPOC/fix_args nop cl_chgroup$rgOpt$adminOpt$idOpt$usersOpt$adminsOpt $group
        else
            print -- "$0()[$LINENO]($SECONDS): $HACSPOC/fix_args nop cl_chgroup$rgOpt$adminOpt$idOpt$usersOpt$adminsOpt $group" >>$CLMGR_TMPLOG  # Always log commands
            $HACSPOC/fix_args nop cl_chgroup$rgOpt$adminOpt$idOpt$usersOpt$adminsOpt $group
        fi
        rc=$?
        print "$0()[$LINENO]($SECONDS): cl_chgroup 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" "$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_group_attributes "$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 group -h" "GROUP:" "$CLMGR_PROGNAME" 1>&2
    fi

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