#!/bin/ksh93 # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2017,2018,2019,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # 61haes_r721 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_volume_group.sh 1.16 # # 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 # @(#) 7b36ae1 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_volume_group.sh, 726, 2147A_aha726, Sep 08 2021 09:17 PM # Start of POD-formatted documentation. Viewing suggestions: # perldoc # pod2text -c # pod2text -c --code # pod2html function devDoc { : <<'=cut' >/dev/null 2>&1 =head1 NAME KLIB_HACMP_modify_volume_group =head1 SYNOPSIS clmgr modify volume_group \ [ ADD=,[,...] [ MIRROR_POOL_NAME="" ] ] \ [ REMOVE=,[,...] ] \ [ TYPE={big|scalable} ] \ [ ACTIVATE_ON_RESTART={false|true} ] \ [ QUORUM_NEEDED={true|false} ] \ [ LTG_SIZE=### ] \ [ MIGRATE_FAILED_DISKS={false|one|pool|remove} ] \ [ MAX_PHYSICAL_PARTITIONS={32|64|128|256| 512|768|1024} ] \ [ MAX_LOGICAL_VOLUMES={256|512|1024|2048} ] \ [ STRICT_MIRROR_POOLS={no|yes|super} ] \ [ CRITICAL={false|true} ] \ [ FAILUREACTION={halt|notify|fence| stoprg|moverg} ] \ [ NOTIFYMETHOD="" ] \ [ SCSIPR_ACTION= ] \ [ LVM_PREFERRED_READ= ] \ [ ENABLE_LV_ENCRYPTION = {yes|no} ] NOTE: "MAX_PHYSICAL_PARTITIONS", "MAX_LOGICAL_VOLUMES", "MIRROR_POOL_NAME", and "STRICT_MIRROR_POOLS", only apply to "scalable" volume groups. NOTE: an alias for "volume_group" is "vg". =head1 DESCRIPTION Attempts to modify a volume_group to conform to the specified parameters. =head1 ARGUMENTS 1. properties [REQUIRED] [hash ref] An associative array within which data about the created object can be returned to the caller. 2. volume_group [OPTIONAL] [string] The name of the volume group that is to be modified. 3. add [OPTIONAL] [string] One or more disks to add to the volume group - if the supplied name is specific to a node, then the format is @. Multiple, comma separated entries are allowed. 4. remove [OPTIONAL] [string] One or more disks to remove from the volume group - if the supplied name is specific to a node, then the format is @. 5. mp_name [OPTIONAL] [string] The name of the mirror pool to add disks to. 6. new_type [OPTIONAL] [string] Requests that the volume group be converted to the indicated type, either "Big" or "Scalable". 7. activate [OPTIONAL] [boolean] Indicates if the volume group should be activated after the system is restarted. 8. quorum [OPTIONAL] [boolean] Indicates whether or not a quorum of the disks in the volume group are needed to keep the volume group online. 9. ltg_size [OPTIONAL] [integer] Sets the logical track group size, in number of kilobytes. 10. migrate [OPTIONAL] [string] Indicates whether or not to automatically migrate failed disks. Accepted values: false|one|pool|remove 11. max_pparts [OPTIONAL] [integer] For "Scalable" volume group types only, this setting indicates the the maximum number of physical partitions for the volume group, using units of 1024. Defaults to 32 (32 * 1024 = 32768 partitions). 12. max_lvs [OPTIONAL] [integer] For "Scalable" volume group types only, this setting indicates the the maximum number of logical volumes for the volume group. Defaults to 256. 13. mp_strictness [OPTIONAL] [string] Mirror pool strictness can have one of the following three values: no, yes, "super". When strictness is enabled, any logical volume in the volume group must have mirror pools enabled for every copy of the logical volume and all of the logical volumes in the volume group must use mirror pools. A "super" strict allocation policy specifies that the partitions allocated for one mirror cannot share a physical volume with the partitions from another mirror. 14. critical [OPTIONAL] [boolean] Indicates if this is a critical volume group. Used to satisfy the quorum requirements of Oracle RAC. Defaults to "false", or "no". 15. failure_action [OPTIONAL] [boolean] Defines the action to take upon loss of access to the volume group. Valid values are: halt, notify, fence, stoprg, moverg 16. notify_method [OPTIONAL] [string] Defines the full path to an executable file that will be run whenever any failure action is triggered. 17. scsipr_action [OPTIONAL] [string] To clear the volume group of scsi persistent reserve registrations. 18. encryption [OPTIONAL] [boolean] Enables the data encryption option in the volume group. Default value is "yes". =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_volume_group { . $HALIBROOT/log_entry "$0()" "$CL" : INPUTS: $* typeset -n properties=$1 typeset volume_group=${2//\"/} shift; shift typeset add=${1//\"/} add=${add//+([[:space:]])/,} typeset remove=${2//\"/} remove=${remove//,/ } typeset mp_name=${3//\"/} typeset new_type=${4//\"/} typeset -l activate=${5//\"/} typeset -l quorum=${6//\"/} typeset ltg_size=${7//\"/} typeset migrate=${8//\"/} typeset max_pparts=${9//\"/} typeset max_lvs=${10//\"/} typeset -l mp_strictness=${11//\"/} typeset -l critical=${12//\"/} typeset -l failure_action=${13//\"/} typeset notify_method=${14//\"/} typeset scsipr_action=${15//\"/} typeset preferred_read=${16//\"/} typeset -l encryption=${17//\"/} [[ $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 #=================================== : Declare and initialize variables #=================================== typeset -i rc=$RC_UNKNOWN typeset typeOpt= POpt= vOpt= pOpt= hOpt= sOpt= QOpt= aOpt= LOpt= typeset INPUT= ATTR= VALUE= ORDER= nodes= RGNAME= devname= pvid= rest= typeset LEGACY= ORIGINAL= BIG= SCALABLE= REM= typeset LINE=$(dspmsg -s 43 cspoc.cat 40 "Legacy Original Big Scalable") print -- "$LINE" |read LEGACY ORIGINAL BIG SCALABLE REM typeset -l BIG_LC=$BIG typeset -l SCALABLE_LC=$SCALABLE if [[ $LANG == @(|C|en_US) ]]; then BIG_LC=b SCALABLE_LC=s fi typeset cur_oslevel=$(oslevel -r|sed 's/-//g') typeset -i min_req_ver=730000 # # Set so we can invoke cspoc utilities using smit style # [[ -z $_CSPOC_CALLED_FROM_SMIT ]] && _CSPOC_CALLED_FROM_SMIT=true export _CSPOC_CALLED_FROM_SMIT #================================================================ : Assuming an object was specified, see if it is a known object #================================================================ if [[ $volume_group != *([[:space:]]) ]]; then CL=$LINENO KLIB_HACMP_is_known_volume_group "$volume_group" (( $? != RC_SUCCESS )) && rc=$RC_NOT_FOUND fi #================= : Validate input #================= if [[ -z $volume_group ]]; then 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 # vg name given but does not exist - show whats available dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$volume_group" 1>&2 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 "" rc=$RC_NOT_FOUND else # Found the specified vg - lookup any mirror pool configuration LC_ALL=C cl_lsmpvgs -V |\ while IFS= read LINE; do LINE=${LINE##+([[:space:]])} # Remove any leading whitespace typeset vgname=${LINE%%[[:space:]]*} if [[ $vgname == $volume_group ]]; then typeset vgtype= LINE=${LINE/\<*\>/\} print -- "$LINE" | read vgname RGNAME nodes vgtype [[ $RGNAME == *\<* ]] && RGNAME=${RGNAME//_/ } nodes=${nodes//+([[:space:]])/,} break fi done fi # Can only add disks to a mirror pool, so if mp is given, there must also # be disks specified if [[ -n $mp_name && -z $add ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 449 "\nERROR:no disks were specified for \"%1\$s\"\n" "$mp_name" 1>&2 rc=$RC_INCORRECT_INPUT fi if [[ -n $new_type ]]; then # Caller wants to change the vg type - map the input to the NLS equivalent typeset -l type_lc=$new_type case $type_lc in $BIG_LC*) typeOpt="-B" ;; $SCALABLE_LC*) typeOpt="-G" ;; *) dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\"\n" TYPE "$new_type" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "$BIG, $SCALABLE" 1>&2 rc=$RC_INCORRECT_INPUT ;; esac fi #======================================================== : Attempt to validate all provided disks, attempting to : convert them from PVID form into devnames, if needed. #======================================================== if [[ -n $add || -n $remove ]]; then typeset disks="$add $remove" typeset -i cmd_rc=$RC_UNKNOWN for disk in ${disks//,/ }; do [[ $disk == *([[:space:]]) ]] && continue # disks can be specified with a specific node using the form # @ # get the data from that node, if specified if [[ $disk == *@* ]]; then print -- "$disk" | IFS=@ read disk node CL=$LINENO getDiskData "$disk" "$node" IDENTIFIERS true cmd_rc=$rc else # just get the data from the local node if [[ " ${nodes//,/ } " == *\ $LOCAL_NODE\ * ]]; then CL=$LINENO getDiskData "$disk" "$LOCAL_NODE" IDENTIFIERS true cmd_rc=$? if (( $cmd_rc != RC_SUCCESS )); then rc=$RC_INCORRECT_INPUT cmd_rc=$rc break fi fi fi if (( $cmd_rc != RC_SUCCESS )); then rc=$RC_NOT_FOUND # No such disk found break else # found the disk - make sure it is known to this node print -- "$IDENTIFIERS" | IFS=: read devname pvid uuid refnode rest CL=$LINENO verify_disk "$pvid" "$refnode" 0 0 true cmd_rc=$? (( $cmd_rc != RC_SUCCESS )) && rc=$cmd_rc fi done fi # Validate mirror pool strictness setting if [[ $mp_strictness != *([[:space:]]) ]]; then case $mp_strictness in @(n|f)*) mp_strictness="n" ;; @(y|t)*) mp_strictness="y" ;; s*) mp_strictness="s" ;; *) dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" "STRICT_MIRROR_POOLS" "$mp_strictness" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "no, yes, super" 1>&2 rc=$RC_INCORRECT_INPUT ;; esac fi # Failure action specifies what to do when the critical volume group fails if [[ $failure_action != *([[:space:]]) ]]; then case $failure_action in h*) failure_action="halt" ;; n*) failure_action="notify" ;; f*) failure_action="fence" ;; s*) failure_action="shutdown" ;; m*) failure_action="fallover" ;; *) dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" "FAILURE_ACTION" "$failure_action" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "halt, notify, fence, stoprg, moverg" 1>&2 rc=$RC_INCORRECT_INPUT ;; esac fi # chvg can be used to migrate data off of failed disks or pools, or just # remove them if [[ $migrate != *([[:space:]]) ]]; then case $migrate in @(f|n)*) migrate="n" ;; @(o|1)*) migrate="y" ;; y) migrate="y" ;; @(p|P)*) migrate="Y" ;; Y) migrate="Y" ;; @(r|R)*) migrate="r" ;; *) dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" "MIGRATE_FAILED_DISKS" "$migrate" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "false, one, pool, remove" 1>&2 rc=$RC_INCORRECT_INPUT ;; esac fi # : Validate the integer inputs # for INPUT in LTG_SIZE@$ltg_size \ MAX_PHYSICAL_PARTITIONS@$max_pparts \ MAX_LOGICAL_VOLUMES@$max_lvs do print -- "$INPUT" | IFS=@ read ATTR VALUE if [[ -n $VALUE && $VALUE != +([[:digit:]]) ]]; 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 done # : Validate the boolean inputs # for INPUT in ACTIVATE@$activate@false,true \ QUORUM@$quorum@true,false \ CRITICAL@$critical@false,true \ ENABLE_LV_ENCRYPTION@$encryption@no,yes do print -- "$INPUT" | IFS=@ read ATTR VALUE ORDER if [[ -n $VALUE && $VALUE != @(y|t|n|f)* ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" "$ATTR" "$VALUE" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "$ORDER" 1>&2 rc=$RC_INCORRECT_INPUT fi done #=============================================================== : check for aix version 7.3 if lvm encryption option is provided #=============================================================== if [[ $encryption == @(y|t)* ]];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 rc=$RC_MISSING_DEPENDENCY fi fi # : Determine the current type of the vg by looking at the pv data # typeset CURRENT_TYPE="UNKNOWN" typeset vgnode= PVDATA= CL=$LINENO getPVData "$nodes" vgnode PVDATA $volume_group if [[ -n $PVDATA ]]; then print -- "$PVDATA" |\ while IFS= read LINE; do typeset devname pvid vgname rest IFS=$ORIG_IFS print -- "$LINE" | read devname pvid vgname rest [[ $volume_group != $vgname ]] && continue # The max number of PVs determines the vg type (original, big, etc) print "$0()[$LINENO]($SECONDS): LC_ALL=C lqueryvg -Atp $devname | grep -i \"^MAX PVs:\"" >>$CLMGR_TMPLOG max_pvs=$(LC_ALL=C lqueryvg -Atp $devname |\ grep -i "^MAX PVs:") print "grep RC: $?; MAX PVs == \"$max_pvs\"" >>$CLMGR_TMPLOG max_pvs=${max_pvs##*+([[:space:]])} if [[ $max_pvs == +([[:digit:]]) ]]; then case $max_pvs in 32) CURRENT_TYPE="ORIGINAL" ;; 128) CURRENT_TYPE="BIG" ;; 1024) CURRENT_TYPE="SCALABLE" ;; esac fi done fi # Check for allowed modifications for scalable vgs (or vgs about to # become scalable because we are changing the type) if [[ $typeOpt == "-G" || $CURRENT_TYPE != "SCALABLE" ]]; then for INPUT in MAX_PHYSICAL_PARTITIONS@$max_pparts \ MAX_LOGICAL_VOLUMES@$max_lvs \ STRICT_MIRROR_POOLS@$mp_strictness \ MIRROR_POOL_NAME@$mp_name \ LVM_PREFERRED_READ@$preferred_read do print -- "$INPUT" | IFS=@ read ATTR VALUE if [[ $VALUE != *([[:space:]]) ]]; then dspmsg -s $CLMGR_SET $CLMGR_MSGS 1166 "\nERROR: Cannot update %1\$s, unless the current type of Volume group is \"%2\$s\".\n Volume group type changes cannot be combined with any other operation.\n" "$ATTR" "$SCALABLE" 1>&2 rc=$RC_INCORRECT_INPUT fi done fi #========================================================= : Mirror pool names must conform to the following rules: : * Can only contains alphanumeric characters. : * Must be less than or equal to 15 characters. : * Must be unique in the volume group. #========================================================= if [[ $mp_name != *([[:space:]]) ]]; then if [[ -n "${mp_name//[a-zA-Z0-9_-]/}" ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 105 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid characters include letters, numbers, and underscores only.\n\n" "$mp_name" "${mp_name//[a-zA-Z0-9_-]/}" 1>&2 rc=$RC_INCORRECT_INPUT fi if (( ${#mp_name} > 15 )); then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 43 'ERROR: "%1\$s" has exceeded the maximum allowed length of %2\$s.\n\n' "$mp_name" 15 1>&2 rc=$RC_INCORRECT_INPUT fi fi # # If a notify method has been specified, check that it exists on this # node - clverify will check the rest of the nodes at sync time, but # we try to catch any simple error here. # if [[ $notify_method != *([[:space:]]) && ! -x $notify_method ]]; then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2\$s": %1$s\n\n' "$notify_method" "$LOCAL_NODE" 1>&2 rc=$RC_NOT_FOUND fi # Notify method can only be specified for critical vgs if [[ $notify_method != *([[:space:]]) ]] && [[ -z $critical || $critical == @(f|n)* ]] then typeset -i bad_combo=1 if [[ -z $critical ]]; then cl_ls_shared_vgs -c -C -O | grep -wq $volume_group (( $? == 0 )) && bad_combo=0 fi if (( bad_combo )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 37 "\nERROR: option \"%1\$s\" is required when any of the following option(s) are used: %2\$s\n\n" "CRITICAL=true" "NOTIFY_METHOD" 1>&2 rc=$RC_INCORRECT_INPUT fi fi # Failure action can only be specified for critical vgs if [[ $failure_action != *([[:space:]]) ]] && [[ -z $critical || $critical == @(f|n)* ]] then typeset -i bad_combo=1 if [[ -z $critical ]]; then cl_ls_shared_vgs -c -C -O | grep -wq $volume_group (( $? == 0 )) && bad_combo=0 fi if (( bad_combo )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 37 "\nERROR: option \"%1\$s\" is required when any of the following option(s) are used: %2\$s\n\n" "CRITICAL=true" "FAILURE_ACTION" 1>&2 rc=$RC_INCORRECT_INPUT fi fi #============================================================== : Verify preferred read option is valid or not, if any value is specified. #============================================================== if [[ ${preferred_read} != *([[:space:]]) ]]; then if [[ $CLUSTER_TYPE == "NSC" ]]; then CL=$LINENO verify_in_set LVM_PREFERRED_READ "$preferred_read" "roundrobin, favorcopy" preferred_read else # siteaffinity option is available only for site based cluster. CL=$LINENO verify_in_set LVM_PREFERRED_READ "$preferred_read" "roundrobin, favorcopy, siteaffinity" preferred_read fi if (( $? != RC_SUCCESS )); then rc=$RC_INCORRECT_INPUT fi fi #================================================================ : Modify the volume group if no input errors have been detected #================================================================ if (( $rc == RC_UNKNOWN )) && [[ -n "$new_type$activate$quorum$ltg_size$migrate$max_pparts$max_lvs$mp_strictness$preferred_read$encryption" ]] then typeset aOpt= QOpt= LOpt= hOpt= POpt= vOpt= MOpt= [[ $activate == @(y|t)* ]] && aOpt="-a y" || aOpt="-a n" [[ $quorum == @(y|t)* ]] && QOpt="-Q y" || QOpt="-Q n" [[ -n $ltg_size ]] && LOpt="-L $ltg_size" [[ -n $migrate ]] && hOpt="-h $migrate" [[ -n $max_pparts && $max_pparts == +([[:digit:]]) ]] && POpt="-P $max_pparts" [[ -n $max_lvs && $max_lvs == +([[:digit:]]) ]] && vOpt="-v $max_lvs" [[ -n $mp_strictness ]] && MOpt="-M $mp_strictness" [[ -n $encryption && $encryption == @(y|t)* ]] && kOpt="-k y" [[ -n $encryption && $encryption == @(n|f)* ]] && kOpt="-k n" [[ -n $preferred_read ]] && rOpt="-r $preferred_read" print -- "$0()[$LINENO]($SECONDS): cl_chvg -cspoc \"-n $nodes\" $aOpt $QOpt $typeOpt $LOpt $hOpt $POpt $vOpt $MOpt $rOpt $kOpt $volume_group" >>$CLMGR_TMPLOG # Always log commands cl_chvg -cspoc "-n $nodes" \ $aOpt \ $QOpt \ $typeOpt \ $LOpt \ $hOpt \ $POpt \ $vOpt \ $MOpt \ $rOpt \ $kOpt \ $volume_group rc=$? print "cl_chvg RC: $rc" >>$CLMGR_TMPLOG # Always log command result fi if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && [[ -n $critical ]]; then # If here, either there were no modifications or the specified # modifications were successful - check for changes to critical vg. # Critical vg is an attribute stored by PowerHA so there are no lvm # level changes made in this block. if [[ $critical == @(y|t)* ]]; then # see if the vg is already marked as critical cl_ls_shared_vgs -c -C -O | grep -wq $volume_group if (( $? == 0 )); then rc=$RC_SUCCESS # Already marked as CRITICAL else # only concurrent vgs in an OAAN resource group can be marked # critical - see if the specified vg is a candidate if ! clodmget -q value=$volume_group HACMPresource | grep -wq "CONCURRENT_VOLUME_GROUP" then cl_dspmsg -s 24 cspoc.cat 34 "Warning: Marking volume group %1\$s as crtitcal is not allowed on non-concurrent resource group. To mark VG as critical, add VG to a concurrent resource group.\n" "$volume_group" rc=$RC_INCORRECT_INPUT else # change the designation in odm if ! odmget -q value=$volume_group HACMPresource | sed -n '/name =/s/CONCURRENT_VOLUME_GROUP/CRITICAL_VG/p;/group =/p;/value =/p;/HACMPresource/p' | odmadd then cl_dspmsg -s 24 cspoc.cat 30 "%1\$s: Marking volume group %2\$s in resource group %3\$s as CRITICAL failed." clmgr "$volume_group" "$RGNAME" 1>&2 rc=$RC_ERROR else # PowerHA config changed - reset the cluster handle to # force a sync print "HACMPcluster: handle=0" | odmchange -o HACMPcluster cl_dspmsg -s 43 cspoc.cat 36 "%1\$s: The cluster configuration has been changed - %2\$s %3\$s has been added. The configuration must be synchronized to make this change effective across the cluster." clmgr 'CRITICAL Volume Group' "$volume_group" rc=$RC_SUCCESS fi fi fi else # critical was specified as "no" - see if our vg is currently # marked as critical cl_ls_shared_vgs -c -C -O | grep -wq $volume_group if (( $? != 0 )); then rc=$RC_SUCCESS # Already not CRITICAL else # Currently marked as critical - delete the entry if ! odmdelete -q "value = $volume_group and name = CRITICAL_VG" -o HACMPresource then CL=$LINENO cl_dspmsg -s 24 cspoc.cat 30 "%1\$s: Marking volume group %2\$s in resource group %3\$s as non-CRITICAL failed." clmgr "$volume_group" "$RGNAME" 1>&2 rc=$RC_ERROR else # PowerHA config changed - reset the cluster handle to # force a sync print "HACMPcluster: handle=0" | odmchange -o HACMPcluster cl_dspmsg -s 24 cspoc.cat 31 "%1\$s: The cluster configuration has been changed - %2\$s %3\$s is no longer marked CRITICAL. The configuration must be synchronized to make this change effective across the cluster." clmgr 'CRITICAL Volume Group' "$volume_group" rc=$RC_SUCCESS fi fi fi fi # : Add new disks to the volume group # if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && [[ -n $add ]] then typeset vgnode= PVDATA= CL=$LINENO getPVData "$nodes" vgnode PVDATA $volume_group compatibleDisks=$(/usr/es/sbin/cluster/sbin/cl_lsfreedisks $volume_group | awk -F' ' '{print $1 " " $3}') # loop through all specified disks for disk in ${add//,/ }; do # first check if it is already in the vg typeset -i alreadyInVG=0 typeset -i isCompatible=0 typeset devname pvid vgname rest print -- "$PVDATA" |\ while IFS= read LINE; do IFS=$ORIG_IFS print -- "$LINE" | read devname pvid vgname rest [[ $volume_group != $vgname ]] && continue if [[ $disk == $devname || $disk == $pvid ]]; then alreadyInVG=1 break fi done # Check $add disks for compatibility. # Should ignore dedicated disks for a shared VG. # Should ignore disks which are already part of other VGs. if (( ! alreadyInVG )); then isCompatible=0 print -- "$compatibleDisks" | while IFS=" " read pvid diskname do if [[ $disk == $pvid || $disk == $diskname ]]; then isCompatible=1 fi done if (( ! isCompatible )); then cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1433 "\nWarning: Ignoring \"%1\$s\".\nEither it's a dedicated disk which cannot be used to extend the shared VG:\"%2\$s\"\nor this disk is already part of some other VG.\n\n" "$disk" "$volume_group" continue fi fi if (( ! alreadyInVG )); then # # Get a valid reference node - disks can be specified with # a reference node using the form @ # typeset refnode= if [[ $disk == *@* ]]; then # already have a reference node - get the data there print -- "$disk" | IFS=@ read disk refnode CL=$LINENO getDiskData "$disk" "$refnode" IDENTIFIERS true else # no explicit reference node given - try the local if its # among the candidates if [[ " ${nodes//,/ } " == *\ $LOCAL_NODE\ * ]]; then CL=$LINENO getDiskData "$disk" "$LOCAL_NODE" IDENTIFIERS true if (( $? != RC_SUCCESS )); then rc=$RC_INCORRECT_INPUT break fi print -- "$IDENTIFIERS" | IFS=: read devname pvid uuid refnode rest fi # try all nodes CL=$LINENO getDiskData "$pvid" "$nodes" IDENTIFIERS true fi if (( $? == RC_SUCCESS )); then print -- "$IDENTIFIERS" | IFS=: read devname pvid uuid refnode rest disk=$pvid fi print -- "$0()[$LINENO]($SECONDS): _CSPOC_CALLED_FROM_SMIT=true cl_extendvg -cspoc \"-n $nodes\" -R \"$refnode\" $volume_group $disk" >>$CLMGR_TMPLOG _CSPOC_CALLED_FROM_SMIT=true cl_extendvg -cspoc "-n $nodes" \ -R "$refnode" \ "$volume_group" \ $disk rc=$? print "cl_extendvg RC: $rc" >>$CLMGR_TMPLOG (( $rc != RC_SUCCESS )) && break else CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 417 "Warning: the specified disk, \"%1\$s\", is already in volume group \"%2\$s\".\n\n" "$disk" "$volume_group" rc=$RC_SUCCESS fi #================================================ : If the customer also specified a mirror pool, : add the newly added disk to it now. #================================================ if (( $rc == RC_SUCCESS )) && [[ $mp_name != *([[:space:]]) ]] then print "$0()[$LINENO]($SECONDS): cl_mp_disks -cspoc \-n $nodes\" -p \"$mp_name\" \"$volume_group\" $pvid" >>$CLMGR_TMPLOG # Log the command cl_mp_disks -cspoc "-n $nodes" \ -p "$mp_name" \ "$volume_group" \ $pvid rc=$? print "cl_mp_disks RC: $rc" >>$CLMGR_TMPLOG fi done fi # done adding disks to vg and mp # : Remove disks from the volume group # if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && [[ -n $remove ]] then for disk in ${remove//,/ }; do #Convert PVID to DiskName as cl_reducevg expects disk name disk=$(LC_ALL=C lspv -u | grep -w $disk | awk -F" " '{print $1}') typeset refnode=${nodes%%,*} print -- "$0()[$LINENO]($SECONDS): _CSPOC_CALLED_FROM_SMIT=true cl_reducevg -cspoc \"-n $nodes\" -f -R \"$refnode\" $volume_group $disk" >>$CLMGR_TMPLOG # Log the command _CSPOC_CALLED_FROM_SMIT=true cl_reducevg -cspoc "-n $nodes" \ -f -R "$refnode" \ "$volume_group" \ $disk rc=$? print "cl_reducevg RC: $rc" >>$CLMGR_TMPLOG # Log command result (( $rc != RC_SUCCESS )) && break done fi # : Check for updates to notify method or failure action # if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && \ [[ -n $failure_action || -n $notify_method ]] then typeset fa= nm= [[ -n $failure_action ]] && fa="FAILURE_ACTION=$failure_action" [[ -n $notify_method ]] && nm="NOTIFY_METHOD=$notify_method" print -- "$0()[$LINENO]($SECONDS): clchappmon MONITOR_TYPE=selective_fallover $fa $nm name=$volume_group" >>$CLMGR_TMPLOG # Always log commands clchappmon MONITOR_TYPE=selective_fallover $fa $nm name=$volume_group rc=$? print "clchappmon RC: $rc" >>$CLMGR_TMPLOG # Always log command result fi # : Check for updates to scsi persistent reserve configuration # if (( $rc == RC_UNKNOWN || $rc == RC_SUCCESS )) && [[ -n $scsipr_action ]];then if [[ $scsipr_action == clear ]];then # Check if VG is reserved or not , if it is not reserved then throw # an error else go ahead and clear the reservation print "$0()[$LINENO]($SECONDS): clpr_ReadRes_vg $volume_group" >>$CLMGR_TMPLOG clpr_ReadRes_vg $volume_group 2>>$CLMGR_TMPLOG rc=$? print "$0()[$LINENO]($SECONDS): clpr_ReadRes_vg RC: $rc" >>$CLMGR_TMPLOG if (( $rc != RC_SUCCESS ));then dspmsg -s $CLMGR_SET $CLMGR_MSGS 399 "\nERROR:volume group \"%1\$s\" is not reserved , this operation\nmust be run to clear the reservation of volume group if it is reserved.\n\n" "$volume_group" 1>&2 rc=RC_ERROR else # : Clear the registrations from the volume group # print "$0()[$LINENO]($SECONDS): clpr_clear_vg $volume_group" >>$CLMGR_TMPLOG clpr_clear_vg $volume_group 2>>$CLMGR_TMPLOG rc=$? print "$0()[$LINENO]($SECONDS): clpr_clear_vg RC: $rc" >>$CLMGR_TMPLOG if (( $rc != RC_SUCCESS ));then dspmsg -s $CLMGR_SET $CLMGR_MSGS 109 "\nERROR: the operation appears to have failed.\n\n" 1>&2 rc=RC_ERROR fi fi else # set dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" SCSIPR_ACTION "$scsipr_action" 1>&2 dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n" "clear" 1>&2 rc=RC_INCORRECT_INPUT fi fi # done processing scsi pr updates # # All done with the updates - make sure there were some # if (( $rc == RC_UNKNOWN )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 401 "\nERROR: no valid modifications were specified for \"%1\$s\".\n\n" "$volume_group" 1>&2 rc=$RC_MISSING_INPUT elif (( $rc != RC_SUCCESS )); then dspmsg -s $CLMGR_SET $CLMGR_MSGS 400 "\nERROR: failed to modify \"%1\$s\".\n\n" "$volume_group" 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_volume_group_attributes "$volume_group" properties 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 \"$HAUTILS/clmgr %1\$s\". As an alternative, if the PowerHA SystemMirror man pages have been installed, invoke \"$HAUTILS/clmgr -hv\" (or \"/usr/bin/man clmgr\"), searching for \"%2\$s\" in the displayed text.\n\n" \ "add volume_group -h" "VOLUME GROUP:" "$CLMGR_PROGNAME" 1>&2 fi log_return_msg "$rc" "$0()" "$LINENO" return $? } # End of "KLIB_HACMP_modify_volume_group()" #================================================ # The following, commented line enforces coding # standards when this file is edited via vim. #================================================ # vim:tabstop=4:shiftwidth=4:expandtab:smarttab #================================================