#!/bin/sh
###############################################################################
# The pddeupgrade script performs upgrades on the PDDE storage
###############################################################################
# $Copyright: Copyright (c) 2022 Veritas Technologies LLC. All rights reserved $
#
# The copyright notice above does not evidence any actual or intendent
# publication of such source code.
#
###############################################################################

INSTALL_PATH="/usr/openv/pdde"
OSTPLUGINS_PATH="/usr/openv/lib/ost-plugins"
PDCFG="${INSTALL_PATH}/pdag/bin/pdcfg"
BACKUP_DATE=`date +%F_%H:%M:%S`
TIMESTAMP=`date +%F_%H:%M`
LOGDIR="/var/log/puredisk"
if [ ! -d "${LOGDIR}" ] ; then
    mkdir -p ${LOGDIR}
fi
LOGFILE=${LOGDIR}/${TIMESTAMP}-pddeupgrade.log

# Remove group and world writable permissions
umask 0022

if [ $# -gt 0 ] ; then
    INSTALL_TYPE=$1
    case "$1" in
        'all')
            INSTALL_TYPE="all"
        ;;
        'agent')
            INSTALL_TYPE="agent"
        ;;
        'server')
            INSTALL_TYPE="server"
        ;;
        *)
            INSTALL_TYPE="help"
        ;;
    esac
else
    INSTALL_TYPE="all"
fi

if [ "${INSTALL_TYPE}" = "help" ] ; then
    echo "$0: Upgades the PDDE configuration to the current installed version."
    echo "Usage: $0 [agent|server]"
    echo "Options:"
    echo "    all        Upgrade both agent and server components (default)"
    echo "    agent      Upgrade agent components only"
    echo "    server     Upgrade server components only"
    exit 0
fi

###############################################################################
# Helper function that uses pdcfg to modify config files
#     Parameters:
#         1: The config file to change (required)
#         2: The template config file to fetch default values from (optional, use "")
#         3: The section in the config file
#         4: The option in the config file
#         5: The value to use in the config file
#         6: 1 means always write, 0 means do not overwrite current value
###############################################################################
Set_Cfg_Parameter()
{
    CONFIG_FILE=${1}     # Required
    DEF_CONFIG_FILE=${2} # Optional: "" means don't check template for default value
    CFG_SECTION=${3}     # Required
    CFG_OPTION=${4}      # Required
    CFG_VALUE=${5}       # Required
    OVERWRITE=${6}       # Required: 0: Do not overwrite if parameter is present
                         #           1: Change whatever value is present to $CFG_VALUE

    if [ "X${DEF_CONFIG_FILE}" != "X" -a -f "${DEF_CONFIG_FILE}" ]; then
        TEMP="`${PDCFG} --read=${DEF_CONFIG_FILE} --section=${CFG_SECTION} --option=${CFG_OPTION}`"
        if [ "X$TEMP" = "X" ]; then
            echo "Warning, could not read [${CFG_SECTION}]${CFG_OPTION} from ${DEF_CONFIG_FILE}, using default value ${CFG_VALUE} instead"
        elif [ "$TEMP" != "$CFG_VALUE" ]; then
            echo "Warning, the specified [${CFG_SECTION}]${CFG_OPTION} is different with the default value in ${DEF_CONFIG_FILE}"
        fi
    fi

    if [ -f "${CONFIG_FILE}" ]; then
        SETVALUE=1
        if [ "${OVERWRITE}" -ne "1" ] ; then
            TEMP=`${PDCFG} --read="${CONFIG_FILE}" --section=${CFG_SECTION} --option=${CFG_OPTION} 2>/dev/null`
            if [ "X$TEMP" != "X" ]; then
                SETVALUE=0
                echo "[${CFG_SECTION}]${CFG_OPTION} already exists in ${CONFIG_FILE} (value: ${TEMP}).  Skipping..."
            fi
        fi
        if [ ${SETVALUE} -eq 1 ]; then
            echo "Updating ${CONFIG_FILE}: [${CFG_SECTION}]${CFG_OPTION} = ${CFG_VALUE}"
            ${PDCFG} --write="${CONFIG_FILE}" --section=${CFG_SECTION} --option=${CFG_OPTION} --value="${CFG_VALUE}"
            if [ $? -ne 0 ] ; then
                echo "Failed to upgrade [${CFG_SECTION}]${CFG_OPTION} to ${CONFIG_FILE}"
            fi
        fi
        if [ -f "${DEF_CONFIG_FILE}" ]; then
            ${PDCFG} --write="${CONFIG_FILE}" --section=${CFG_SECTION} --option=${CFG_OPTION} --commentfile="${DEF_CONFIG_FILE}"
        fi
    else
        echo "Warning, could not locate ${CONFIG_FILE}"
    fi
}

Deprecate_Parameter()
{
    CONFIG_FILE=${1}
    CFG_SECTION=${2}
    CFG_OPTION=${3}
    echo "Deprecate [${CFG_SECTION}]${CFG_OPTION}"
    ${PDCFG} --write="${CONFIG_FILE}" --section=${CFG_SECTION} --option=${CFG_OPTION} --clear-comment >/dev/null 2>&1
    ${PDCFG} --write="${CONFIG_FILE}" --section=${CFG_SECTION} --option=${CFG_OPTION} --add-comment=" Deprecated" >/dev/null 2>&1
}

Check_Generate_Identity()
{
    if [ "X${DATA_PATH}" != "X" ] ; then
        echo "Found data path: ${DATA_PATH}"

        if [ -d "${DATA_PATH}" ] ; then
            echo "Checking for .identity file"

            if [ -f "${DATA_PATH}/.identity" ] ; then
                echo ".identity file exists, no action needed"
            else
                echo "Attempting to run spoold --genidentity"
                ${INSTALL_PATH}/pdcr/bin/spoold --genidentity -v --trace "${LOG_PATH}/spoold/genidentity.log"
                if [ $? -ne 0 ] ; then
                    echo "spoold --genidentity failed"
                else
                    echo "spoold --genidentity was successful"
                fi
            fi
        fi
    fi
}

Split_Tlog_files()
{
    echo "Attempting to check tlog partition." | tee -a ${LOGFILE}
    if [ -d "${STORAGE_PATH}/queue" ] ; then
        if [ -f "${STORAGE_PATH}/queue/.lsu" ] ; then
            echo "Tlog files are already splitted, skip." | tee -a ${LOGFILE}
        else
            echo "Attempting to run spoold --splittlog" | tee -a ${LOGFILE}
            ${INSTALL_PATH}/pdcr/bin/spoold --splittlog
            if [ $? -eq 0 ] ; then
                echo "Split tlog successful." | tee -a ${LOGFILE}
            else
                echo "spoold --splittlog failed." | tee -a ${LOGFILE}
                exit 1
            fi
        fi
    else
        echo "WARN: ${STORAGE_PATH}/queue does not exist, skip to split tlog." | tee -a ${LOGFILE}
    fi
    echo "Checking tlog partition finished." | tee -a ${LOGFILE}
}

############################################################################
# delete symantec/puredisk from pdregistry.cfg  on linux platform.
############################################################################
Upgrade_Pdregistry()
{
    sed -e 's;Symantec/PureDisk/;;g' /etc/pdregistry.cfg >/etc/pdregistry.cfg.tmp
    cat /etc/pdregistry.cfg.tmp >/etc/pdregistry.cfg
    if [ $? -eq 0 ] ; then
        rm /etc/pdregistry.cfg.tmp >/dev/null 2>&1
    fi
    chmod o-w /etc/pdregistry.cfg
}

###############################################################################
# Helper function that modifies pd.conf
#     Parameters:
#         1: The name of the config parameter to change (required)
#         2: The value to use for this parameter (required)
###############################################################################
Set_Pd_Conf_Parameter()
{
    PARAMVAL="$1 = $2"
    sed -e "s/$1.*/${PARAMVAL}/g" ${OSTPLUGINS_PATH}/pd.conf > ${OSTPLUGINS_PATH}/pd.conf.tmp
    cat ${OSTPLUGINS_PATH}/pd.conf.tmp > ${OSTPLUGINS_PATH}/pd.conf
    if [ $? -eq 0 ] ; then
        rm ${OSTPLUGINS_PATH}/pd.conf.tmp > /dev/null 2>&1
    fi
    chmod o-w ${OSTPLUGINS_PATH}/pd.conf
}

Upgrade_Pd_Conf()
{
    PD_CONF_PATH=${1}

    PD_CONF_ENTRY_CHECK=`grep "MTSTRM_BACKUP_CLIENTS" ${PD_CONF_PATH}`
    if [ "$?" -ne "0" ]; then
        echo "#" >> ${PD_CONF_PATH}
        echo "# If set, limits backups using the multi-threaded agent to specified clients" >> ${PD_CONF_PATH}
        echo "# Format is a comma-separated list of clients, treated as case insensitive" >> ${PD_CONF_PATH}
        echo "# MTSTRM_BACKUP_CLIENTS = client1,client2,client3" >> ${PD_CONF_PATH}
    else
        echo "MTSTRM_BACKUP_CLIENTS already in pd.conf" | tee -a ${LOGFILE}
    fi

    PD_CONF_ENTRY_CHECK=`grep "MTSTRM_BACKUP_ENABLED" ${PD_CONF_PATH}`
    if [ "$?" -ne "0" ]; then
        echo "#" >> ${PD_CONF_PATH}
        echo "# Run backups through the multi-threaded streaming agent (1=On, 0=Off)" >> ${PD_CONF_PATH}
        echo "MTSTRM_BACKUP_ENABLED = 0" >> ${PD_CONF_PATH}
    else
        echo "MTSTRM_BACKUP_ENABLED already in pd.conf" | tee -a ${LOGFILE}
    fi

    PD_CONF_ENTRY_CHECK=`grep "MTSTRM_BACKUP_POLICIES" ${PD_CONF_PATH}`
    if [ "$?" -ne "0" ]; then
        echo "#" >> ${PD_CONF_PATH}
        echo "# If set, limits backups using the multi-threaded agent to specified policies" >> ${PD_CONF_PATH}
        echo "# Format is a comma-separated list of policy names, treated as case sensitive" >> ${PD_CONF_PATH}
        echo "# MTSTRM_BACKUP_POLICIES = policy1,policy2,policy3" >> ${PD_CONF_PATH}
    else
        echo "MTSTRM_BACKUP_POLICIES already in pd.conf" | tee -a ${LOGFILE}
    fi

    PD_CONF_ENTRY_CHECK=`grep "MTSTRM_IPC_TIMEOUT" ${PD_CONF_PATH}`
    if [ "$?" -ne "0" ]; then
        echo "#" >> ${PD_CONF_PATH}
        echo "# Number of seconds to wait for responses from the multi-threaded streaming process before timing out with an error" >> ${PD_CONF_PATH}
        echo "# Values:  1-86400" >> ${PD_CONF_PATH}
        echo "MTSTRM_IPC_TIMEOUT = 1200" >> ${PD_CONF_PATH}
    else
        echo "MTSTRM_IPC_TIMEOUT already in pd.conf"
    fi

    PD_CONF_ENTRY_CHECK=`grep "VLD_POLICY_NAME" ${PD_CONF_PATH}`
    if [ "$?" -ne "0" ]; then
        echo "#" >> ${PD_CONF_PATH}
        echo "# The minimum segment size must NOT be greater than the maximum." >> ${PD_CONF_PATH}
        echo "# If the VLD_POLICY_NAME only give policy name, and VLD_CLIENT_NAME only give client name, " >> ${PD_CONF_PATH}
        echo "# the VLD_MIN_SEGKSIZE and VLD_MAX_SEGKSIZE will be used as default minimum and maximum segment size." >> ${PD_CONF_PATH}
        echo "# Do not change default value unless know what will happen. Technically, Bigger VLD_MIN_SEGKSIZE, " >> ${PD_CONF_PATH}
        echo "# will use less CPU cycles and get worse dedupe rate." >> ${PD_CONF_PATH}
        echo "# VLD_MIN_SEGKSIZE = 32" >> ${PD_CONF_PATH}
        echo "# VLD_MAX_SEGKSIZE = 128" >> ${PD_CONF_PATH}
        echo "#" >> ${PD_CONF_PATH}
        echo "# Specify policy names use the Variable Length Deduplication feature, different policy can have different minimum and maximum segment size parameters." >> ${PD_CONF_PATH}
        echo "# Support up to 50 policies. If not specify minimum and maximum segment size, the default VLD_MIN_SEGKSIZE and VLD_MAX_SEGKSIZE" >> ${PD_CONF_PATH}
        echo "# will be used." >> ${PD_CONF_PATH}
        echo "# Do not change default value unless know what will happen." >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for all policies. No Fuzzy Matching" >> ${PD_CONF_PATH}
        echo "# VLD_POLICY_NAME = *" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for test_vld policy, use default VLD_MIN_SEGKSIZE and VLD_MAX_SEGKSIZE" >> ${PD_CONF_PATH}
        echo "# VLD_POLICY_NAME = test_vld" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for test_vld1 policy and use 32KB as minimum segment size, 128KB as maximum segment size" >> ${PD_CONF_PATH}
        echo "# VLD_POLICY_NAME = test_vld1(32,128)" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for test_vld2 policy and use 64KB as minimum segment size, 256KB as maximum segment size" >> ${PD_CONF_PATH}
        echo "# VLD_POLICY_NAME = test_vld2(64,256)" >> ${PD_CONF_PATH}
        echo "#" >> ${PD_CONF_PATH}
        echo "# Specify client names use the Variable Length Deduplication feature, different client can have different minimum and maximum segment size parameters." >> ${PD_CONF_PATH}
        echo "# Support max 50 clients. If not specify minimum and maximum segment size, the default VLD_MIN_SEGKSIZE and VLD_MAX_SEGKSIZE" >> ${PD_CONF_PATH}
        echo "# will be used." >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for all clients. No Fuzzy Matching" >> ${PD_CONF_PATH}
        echo "# VLD_CLIENT_NAME = *" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for abc client, use default VLD_MIN_SEGKSIZE and VLD_MAX_SEGKSIZE" >> ${PD_CONF_PATH}
        echo "# VLD_CLIENT_NAME = abc" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for abc client and use 32KB as minimum segment size, 128KB as maximum segment size" >> ${PD_CONF_PATH}
        echo "# VLD_CLIENT_NAME = abc(32,128)" >> ${PD_CONF_PATH}
        echo "# Enable Variable Length Deduplication for abc client and use 64KB as minimum segment size, 256KB as maximum segment size" >> ${PD_CONF_PATH}
        echo "# VLD_CLIENT_NAME = abc(64,256)" >> ${PD_CONF_PATH}
    else
        echo "VLD_POLICY_NAME already in pd.conf"
    fi
}

Set_Recommended_Mtstrm_Config_Values()
{
    # Save IFS
    OLDIFS=$IFS
    IFS=","

    MTSTRMCTL="${INSTALL_PATH}/pdag/bin/mtstrmctl"

    if [ ! -f ${MTSTRMCTL} ]; then
        echo "${MTSTRMCTL} not found, skipping generation of recommended settings for mtstrm.conf and pd.conf"
    else
        TMPFILE="${OSTPLUGINS_PATH}/mtstrmctl_output.csv"
        MTSTRMCONF_PATH="${OSTPLUGINS_PATH}/mtstrm.conf"

        echo "Running the mtstrmctl utility to generate recommended settings for ${MTSTRMCONF_PATH}"
        ${MTSTRMCTL} --get-recommended-settings ${TMPFILE}

        if [ "$?" -eq "0" ]; then
            echo "Parsing ${TMPFILE}"
            if [ ! -f ${TMPFILE} ]; then
                echo "${TMPFILE} not found, default values will be used instead"
            else
                echo "$TMPFILE found, reading.."
                while read filename section param value
                do
                    if [ "$filename" = "mtstrm.conf" ]; then
                        echo "Updating $filename with value $value for parameter $param in section $section"
                        Set_Cfg_Parameter ${MTSTRMCONF_PATH} "" ${section} ${param} ${value} 1
                    elif [ "$filename" = "pd.conf" ]; then
                        echo "Updating $filename with value $value for parameter $param"
                        Set_Pd_Conf_Parameter $param $value
                    else
                        echo "Invalid filename $filename. Can only update mtstrm.conf and pd.conf"
                    fi
                done < $TMPFILE

                # Revert to the original state
                rm $TMPFILE > /dev/null 2>&1
            fi
        else
            echo "mtstrmctl failed to generate recommended settings for ${MTSTRMCONF_PATH}, default values will be used instead"
        fi
    fi

    # Revert to the original state
    IFS=$OLDIFS
}

Get_Kms_Options()
{
    if [ -f "${KMS_CONFIG_FILE}" ]; then
        KMS_ENABLE="`${PDCFG} --read="${KMS_CONFIG_FILE}" --section=KMSOptions --option=KMSEnable`"
        if [ $? -ne 0 ]; then
            echo "Warning, could not read KMSEnable from ${KMS_CONFIG_FILE}"
        fi
        KMS_SERVER_NAME="`${PDCFG} --read="${KMS_CONFIG_FILE}" --section=KMSOptions --option=KMSServerName`"
        if [ $? -ne 0 ]; then
            echo "Warning, could not read KMSServerName from ${KMS_CONFIG_FILE}"
        fi
        KMS_KEY_GROUP_NAME="`${PDCFG} --read="${KMS_CONFIG_FILE}" --section=KMSOptions --option=KMSKeyGroupName`"
        if [ $? -ne 0 ]; then
            echo "Warning, could not read KMSKeyGroupName from ${KMS_CONFIG_FILE}"
        fi
        KMS_TYPE="`${PDCFG} --read="${KMS_CONFIG_FILE}" --section=KMSOptions --option=KMSType`"
        if [ $? -ne 0 ]; then
            echo "Warning, could not read KMSType from ${KMS_CONFIG_FILE}"
        fi
        KMS_KEY_NAME="`${PDCFG} --read="${KMS_CONFIG_FILE}" --section=KMSOptions --option=KeyName`"
        if [ $? -ne 0 ]; then
            echo "Warning, could not read KeyName from ${KMS_CONFIG_FILE}"
        fi

    else
        echo "Warning, could not locate ${KMS_CONFIG_FILE}"
    fi
}

hook_access() {
    if [ "x${CR_CFG_PATH}" != "x" -a -f "${CR_CFG_PATH}" ] ; then
        Set_Cfg_Parameter "${CR_CFG_PATH}" "" Cache AllocationUnitSize "16MiB" 1
        Set_Cfg_Parameter "${CR_CFG_PATH}" "" CRDataStore WriteThreadNum "1" 1
        Set_Cfg_Parameter "${CR_CFG_PATH}" "" CRDataStore MaxBufSize "64Mib" 1
        Set_Cfg_Parameter "${CR_CFG_PATH}" "" CRDataStore RebaseLocalityThreshold "32" 1
        Set_Cfg_Parameter "${CR_CFG_PATH}" "" CRDataStore RebaseMaxTime "15" 1
    fi
    if [ "x${SPA_CFG_PATH}" != "x" -a -f "${SPA_CFG_PATH}" ] ; then
        Set_Cfg_Parameter "${SPA_CFG_PATH}" "" DataCheck DataCheckDays 60 1
    fi
}

###############################################################################
# Start of upgrade code!
###############################################################################
echo "Checking to see if the PDDE configuration needs upgrading"

if [ ! -x "${PDCFG}" ] ; then
    echo "Unable to use ${PDCFG}, which is required by this script."
    echo "Is the PDDE agent package installed?"
    exit 1
fi

OS=`uname -s`

if [ "$OS" = "SunOS" ] ; then
    PLATFORM="Solaris"
elif [ "$OS" = "AIX" ] ; then
    PLATFORM="AIX"
elif [ "$OS" = "HP-UX" ] ; then
    PLATFORM="hpux"
else
    PLATFORM="RedHat"
    if [ -f /etc/SuSE-release -o -f /sbin/SuSEconfig ]; then
        PLATFORM="SuSE"
    elif [ -f /etc/os-release ] ; then
        # Both Red Hat 7 and SUSE 12 have an os-release file.
        grep -i SUSE /etc/os-release > /dev/null 2>&1
        if [ $? = 0 ] ; then
            PLATFORM="SuSE"
        fi
    fi
fi

Upgrade_Pdregistry

# Server components   
if [ "${INSTALL_TYPE}" = "all" -o "${INSTALL_TYPE}" = "server" -a -f /etc/pdregistry.cfg ] ; then
    AGENT_CFG_PATH=`${PDCFG} --read /etc/pdregistry.cfg --section="Agent" --option=configfilepath 2> /dev/null`
    SPA_CFG_PATH=`${PDCFG} --read /etc/pdregistry.cfg --section="StoragePoolAuthority" --option=configfilepath 2> /dev/null`
    CR_CFG_PATH=`${PDCFG} --read /etc/pdregistry.cfg --section="ContentRouter" --option=configfilepath 2> /dev/null`
    AGENT_CFG_TEMPLATE_PATH="$INSTALL_PATH/pdcr/etc/agent.cfg"
    CR_CFG_TEMPLATE_PATH="$INSTALL_PATH/pdcr/etc/contentrouter.cfg"
    SPA_CFG_TEMPLATE_PATH="$INSTALL_PATH/pdcr/etc/spa.cfg"
    if [ X"${CR_CFG_PATH}" != "X" ]; then
        DATA_PATH=`${PDCFG} --read="${CR_CFG_PATH}" --section=StorageDaemon --option=Storage`
        DATABASES_PATH=`${PDCFG} --read="${CR_CFG_PATH}" --section=StorageDatabase --option=Path 2> /dev/null`
        HISTORY_PATH="`${PDCFG} --read="${CR_CFG_PATH}" --section=StorageDaemon --option=HistoryPath`"
        LOG_PATH=`${PDCFG} --read="${CR_CFG_PATH}" --section=Logging --option=LogPath`
        FIPS_ENABLED=`${PDCFG} --read="${CR_CFG_PATH}" --section=Main --option=FIPS 2> /dev/null`
    fi
    if [ X"${SPA_CFG_PATH}" != "X" ]; then
        STORAGE_PATH=`${PDCFG} --read="${SPA_CFG_PATH}" --section=Paths --option=Storage`
    fi

    OCSD="OpenCloudStorageDaemon"

    # in case of upgrade adding OCSD entry to pdregistry.cfg
    if [ "$PLATFORM" = "RedHat" ] && [ X"${CR_CFG_PATH}" != "X" ]; then
        if [ X"${FIPS_ENABLED}" != "X" ]; then
            Set_Cfg_Parameter   /etc/pdregistry.cfg "" ${OCSD} FIPS "${FIPS_ENABLED}" 0
        fi
        Set_Cfg_Parameter   /etc/pdregistry.cfg "" ${OCSD} loglevel "1" 0
        if [ X"${LOG_PATH}" != "X" ]; then
            Set_Cfg_Parameter   /etc/pdregistry.cfg "" ${OCSD} logpath "${LOG_PATH}" 0
        fi
    fi

    KMS_CONFIG_FILE="$INSTALL_PATH/kms.cfg"
    KMS_ENABLE="false"
    KMS_SERVER_NAME=""
    KMS_KEY_GROUP_NAME=""
    KMS_TYPE=0
    KMS_KEY_NAME=""

    # contentrouter.cfg
    if [ "X${CR_CFG_PATH}" != "X" ] ; then
        if [ -f "${CR_CFG_PATH}" ] ; then
            echo "Found content router config file.  Checking for upgrades..."
            cp "${CR_CFG_PATH}" "${CR_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1

            Check_Generate_Identity

            if [ "$PLATFORM" = "RedHat" ] && [ -d "${STORAGE_PATH}" ] ; then
                Split_Tlog_files
            fi

            Deprecate_Parameter "${CR_CFG_PATH}"                       ContentRouter FingerprintType
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore RebaseMinContainers "20" 1
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore RebaseLocalityThreshold "120" 1
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH ReferenceDatabase LockPoolSize "102400" 1

            # Update [StorageDaemon]DO verify options
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH StorageDaemon DOVerifyEnable "true" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH StorageDaemon DOVerifyBatchDOCount 256 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH StorageDaemon DOVerifyBatchSizeMB 1024000 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH StorageDaemon DOVerifyCheckSOData "false" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH StorageDaemon MaxCRQPRunMinutes 360 0

            # Update [CRDataStore]CacheValidTime to 365 for CC
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore CacheValidTime "365" 1

            # Update [CRDataStore]Cloud Related options
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore CloudDataCacheSize "500GiB" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore CloudMapCacheSize "5GiB" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore CloudMetaCacheSize "500GiB" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH CRDataStore CloudUploadCacheSize "12GiB" 0

            # Update [Cache]Cloud Related options
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH Cache MaxCloudCacheSize "20%" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH Cache UsableMemoryLimit "80%" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH Cache MaxSamplingCacheSize "5%" 0

            # Update [AgingCheck]Cloud Related options
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck EnableAgingCheck "true" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckAllContainers "false" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckSleepSeconds "20" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckBatchNum "400" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckContainerInterval "180" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckSizeLowBound "8Mib" 0
            Set_Cfg_Parameter   "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH AgingCheck AgingCheckLowThreshold "10%" 0

            #if kms exist, get kms config file and set to contentrouter.cfg
            Get_Kms_Options
            if [ "${KMS_ENABLE}" = "true" ] ; then
                Set_Cfg_Parameter   "${CR_CFG_PATH}" ""  KMSOptions KMSEnable ${KMS_ENABLE} 1
                Set_Cfg_Parameter   "${CR_CFG_PATH}" ""  KMSOptions KMSServerName ${KMS_SERVER_NAME} 0
                Set_Cfg_Parameter   "${CR_CFG_PATH}" ""  KMSOptions KMSKeyGroupName ${KMS_KEY_GROUP_NAME} 0
                Set_Cfg_Parameter   "${CR_CFG_PATH}" ""  KMSOptions KMSType  ${KMS_TYPE} 0
                Set_Cfg_Parameter   "${CR_CFG_PATH}" ""  KMSOptions KeyName  ${KMS_KEY_NAME} 0
                # ServerOptions: Add "encrypt" if it's not there
                SERVER_OPTIONS=`${PDCFG} --read="${CR_CFG_PATH}" --section="ContentRouter" --option="ServerOptions" 2> /dev/null`
                echo $SERVER_OPTIONS | grep encrypt > /dev/null 2>&1
                if [ $? -ne 0 ] ; then
                    Set_Cfg_Parameter "${CR_CFG_PATH}" $CR_CFG_TEMPLATE_PATH ContentRouter ServerOptions "encrypt,$SERVER_OPTIONS" 1
                fi
                # In MSDP, proc directory doesn't exist. In CC, proc directory exists.
                if [ X"${STORAGE_PATH}" != "X" -a -d "${STORAGE_PATH}/proc" ] ; then
                    echo ${KMS_KEY_GROUP_NAME} > ${STORAGE_PATH}/proc/keygroupname
                fi
            fi

            cmp -s "${CR_CFG_PATH}" "${CR_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1
            if [ $? -eq 0 ] ; then
                rm "${CR_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1
            fi
            chmod o-w "${CR_CFG_PATH}"
        else
            echo "WARN: Missing content router config file! Path found from pdregistry.cfg: ${CR_CFG_PATH}"
        fi
    fi

    # spa.cfg
    if [ "X${SPA_CFG_PATH}" != "X" ] ; then
        if [ -f "${SPA_CFG_PATH}" ] ; then
            echo "Found spa config file.  Checking for upgrades..."
            cp "${SPA_CFG_PATH}" "${SPA_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1

            # Update [CA]Cloud Related options
            Set_Cfg_Parameter   "${SPA_CFG_PATH}" $SPA_CFG_TEMPLATE_PATH CA CloudLSUCheckInterval "1800" 1

            # Lastfullimage options
            Set_Cfg_Parameter   "${SPA_CFG_PATH}" $SPA_CFG_TEMPLATE_PATH StorageDatabase LastFullMaxImageCount "512" 0
            Set_Cfg_Parameter   "${SPA_CFG_PATH}" $SPA_CFG_TEMPLATE_PATH StorageDatabase LastFullMaxImageCountSmallDO "32" 0
            Set_Cfg_Parameter   "${SPA_CFG_PATH}" $SPA_CFG_TEMPLATE_PATH StorageDatabase LastFullSmallDOSize "20971520" 0

            cmp -s "${SPA_CFG_PATH}" "${SPA_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1
            if [ $? -eq 0 ] ; then
                rm "${SPA_CFG_PATH}.${BACKUP_DATE}" > /dev/null 2>&1
            fi
            chmod o-w "${SPA_CFG_PATH}"
        else
            echo "WARN: Missing spa config file! Path found from pdregistry.cfg: ${SPA_CFG_PATH}"
        fi
    fi

    # agent.cfg

    # upgrade plain password to encrypted in spa.cfg, agent.cfg and replication targets.
    SPAUSER="${INSTALL_PATH}/pdcr/bin/spauser"
    if [ ! -f ${SPAUSER} ]; then
        echo "WARN: ${SPAUSER} not found, skip to encrypt password in spa.cfg, agent.cfg, replication targets." | tee -a ${LOGFILE}
    else
        if [ "X${SPA_CFG_PATH}" != "X" -a -f "${SPA_CFG_PATH}" ] || [ "X${AGENT_CFG_PATH}" != "X" -a -f "${AGENT_CFG_PATH}" ] ; then
            echo "Running the spauser utility to check and encrypt password in spa.cfg, agent.cfg, replication targets." | tee -a ${LOGFILE}
            ${SPAUSER} --upgradepassword | tee -a ${LOGFILE}

            if [ "$?" -eq "0" ]; then
                echo "Success to check and encrypt password in spa.cfg, agent.cfg, replication targets." | tee -a ${LOGFILE}
            else
                echo "spauser failed to check and encrypt password in spa.cfg, agent.cfg, replication targets." | tee -a ${LOGFILE}
            fi
        else
            echo "WARN: Missing spa config file and agent config file! skip to encrypt password." | tee -a ${LOGFILE}
        fi
    fi

    # Update running version file with the current version
    if [ ! -z "$STORAGE_PATH" ] ; then
        echo "U" `cat ${INSTALL_PATH}/pdag/version.txt` >> "$STORAGE_PATH/etc/runningversion.log"
        chmod o-w "$STORAGE_PATH/etc/runningversion.log"
    fi

    # Create cloud metadata conversion marker file for RedHat
    if [ "$PLATFORM" = "RedHat" ] && [ X"${STORAGE_PATH}" != "X" ]; then
        touch "${STORAGE_PATH}/etc/puredisk/.cloudmetadataconvert.all"
    fi
fi

# Agent components
if [ "${INSTALL_TYPE}" = "all" -o "${INSTALL_TYPE}" = "agent" ] ; then
    # pd.conf
    if [ -f "${OSTPLUGINS_PATH}/pd.conf" ] ; then
        echo "Found pd.conf.  Checking for upgrades..."
        cp "${OSTPLUGINS_PATH}/pd.conf" "${OSTPLUGINS_PATH}/pd.conf.${BACKUP_DATE}" > /dev/null 2>&1

        Upgrade_Pd_Conf "${OSTPLUGINS_PATH}/pd.conf"

        cmp -s "${OSTPLUGINS_PATH}/pd.conf" "${OSTPLUGINS_PATH}/pd.conf.${BACKUP_DATE}" > /dev/null 2>&1
        if [ $? -eq 0 ] ; then
            rm "${OSTPLUGINS_PATH}/pd.conf.${BACKUP_DATE}" > /dev/null 2>&1
        fi
        chmod o-w "${OSTPLUGINS_PATH}/pd.conf"
    fi

    # mtstrm.conf
    if [ -f "${OSTPLUGINS_PATH}/mtstrm.conf" ] ; then
        echo "Found mtstrm.conf.  Checking for upgrades..."

        # mtstrm.conf [Logging]LogPath is set to CHANGEME in the template.
        # Set it to the right default path for this platform.
        MTSTRM_LOG_PATH="`${PDCFG} --read=${OSTPLUGINS_PATH}/mtstrm.conf --section=Logging --option=LogPath`" > /dev/null
        if [ "${MTSTRM_LOG_PATH}" = "MTSTRM_DEFAULT_LOG_PATH" ] ; then
            Set_Cfg_Parameter "${OSTPLUGINS_PATH}/mtstrm.conf" "" Logging LogPath "/var/log/puredisk" 1
            Set_Recommended_Mtstrm_Config_Values
        fi
        Set_Cfg_Parameter "${OSTPLUGINS_PATH}/mtstrm.conf" "" Process MaxConcurrentSessions "4" 0
        Set_Cfg_Parameter "${OSTPLUGINS_PATH}/mtstrm.conf" "" Threads BackupFpThreads "4" 0
        chmod o-w "${OSTPLUGINS_PATH}/mtstrm.conf"
    fi
fi

if [ -f "/etc/ltr-app-release" ]; then
    hook_access
fi

exit 0

