#!/bin/bash

#*********************************************************************#
# File Name: upgrade_common.sh
# Description:
# Usage:
# Input:
# Output: return error code, see #ReturnCodes
# Created: 2013-10-19
#*********************************************************************#

#加载依赖脚本
if [ -f "/OSM/script/os_load_base.sh" ]; then
    source /OSM/script/os_load_base.sh
    MY_ECHO=OS_echo
else
    MY_ECHO=echo
fi

#加载os_hotpatch.sh
source /OSM/script/os_hotpatch.sh
G_OEM_DIR=/startup_disk/image/
G_OEM_PKG_NAME=oem.tgz
#script file
g_ScriptFilePath=""
g_ScriptFileName=""
g_ScriptFile=""
#拷贝的源节点和目标节点ip
G_SRC_IP=""
G_DST_IP=""
#UPD script model name
MODEL_NAME="UPD_SCRIPT"
G_DIAG_RESULT=/tmp/upd_diag_result
G_CUR_SYS_VERSION_FILE=/OSM/conf/versions.conf
G_PRODUCT_CFG_FILE=/OSM/conf/product.ini
G_SYNC_IP=""
#ReturnCodes
declare -i RET_SUCC=0
declare -i RET_UNKOWN_OPT=1
declare -i RET_INTTERNAL_ERR=2

#*********************************************************************#
# Function Name: getScriptPathAndName
# Description: 获取脚本所在路径和脚本名
# Usage: getScriptPathAndName
# Parameter: 无
# Return:
#*********************************************************************#
function getScriptPathAndName()
{
    cd $(dirname $0) &>/dev/null
    g_ScriptFilePath="$PWD"
    g_ScriptFileName="$(basename $0)"
    g_ScriptFile="${g_ScriptFilePath}/${g_ScriptFileName}"
    cd - &>/dev/null
}

#*********************************************************************#
# Function Name: log
# Description: 打印日志函数
# Usage: log $1 $2 $3
# Parameter: $1：日志内容
#            $2: 日志打印函数
#            $3: 日志打印所在行数
# Return:
#*********************************************************************#
function log()
{
    local logContent="$1"
    local logFunc="$2"
    local logLine="$3"

    "$MY_ECHO" "[$logContent][$MODEL_NAME][$logFunc:$logLine][$g_ScriptFileName]"
}

#*********************************************************************#
# Function Name: usage
# Description: 帮助信息
# Usage:
# Parameter:
# Return:
#*********************************************************************#
function usage()
{
    echo "./upgrade_common.sh [-T[test-string]] [--Test[=test-string]]"
    echo "./upgrade_common.sh [-t test-string] [--test test-string]"
    echo "./upgrade_common.sh [-xxxxxxx]"
}

#*********************************************************************#
# Function Name: testFunc
# Description: 测试函数
# Usage:
# Parameter:
# Return:
#*********************************************************************#
function testFunc()
{
    if [ -z "$1" ]; then
        log "Run $FUNCNAME without argument." "$FUNCNAME" "$LINENO"
    else
        log "Run $FUNCNAME with argument($1)." "$FUNCNAME" "$LINENO"
    fi

    return $RET_SUCC
}
# **************************************************************************** #
# Function Name:
# Description:
# Parameter:
# Return:
# **************************************************************************** #
OS_SET_DISK_RW()
{
    L_DISK_BOOT=`cat /proc/mounts |grep $G_DISK_MOUNT_IMAGE |awk '{print $1}'`
    if [ -z "$L_DISK_BOOT" ] ; then
        L_DISK_BOOT=$G_DISK_BOOT
    else
        L_DISK_BOOT=${L_DISK_BOOT%[0-9]}
    fi

    OS_echo "UPGRADE_SH Disk Boot Dir = [$L_DISK_BOOT], Set Disk Boot Dir RW Begin" >/dev/null

    OS_SetStartUpDiskProperty $L_DISK_BOOT rw
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH Set Disk Boot Dir RW Error" >/dev/null
        exit 1
    fi

    OS_echo "UPGRADE_SH Set Disk Boot Dir RW Success" >/dev/null
    return 0
}

# **************************************************************************** #
# Function Name:
# Description:
# Parameter:
# Return:
# **************************************************************************** #
OS_SET_DISK_RO()
{
    L_DISK_BOOT=`cat /proc/mounts |grep $G_DISK_MOUNT_IMAGE |awk '{print $1}'|awk -F 1 '{print $1}'`
    if [ -z "$L_DISK_BOOT" ] ; then
        L_DISK_BOOT=$G_DISK_BOOT
    else
        L_DISK_BOOT=${L_DISK_BOOT%[0-9]}
    fi

    OS_echo "UPGRADE_SH Disk Boot Dir = [$L_DISK_BOOT], Set Disk Boot Dir RO Begin" >/dev/null

    for((i=0;i<3;i++))
    do
        OS_SetStartUpDiskProperty $L_DISK_BOOT ro
        if [ 0 = $? ] ; then
            break
        fi
        OS_echo "UPGRADE_SHRemount image RO failed, i=$i"
        sleep 5
    done

    if [ $i -ge 3 ] ; then
        OS_echo "UPGRADE_SH Set Disk Boot Dir RO Error" >/dev/null
        return 1
    else
        OS_echo "UPGRADE_SH Set Disk Boot Dir RO Success" >/dev/null
        return 0
    fi

    return 0
}

# **************************************************************************** #
# Function Name: OS_UPG_CHECK_PATCH
# Description: 检查patch链接，如果链接不存在或者链接指向bak返回1，否则返回0，此函数目前仅用于热补丁回退中
# Parameter:
# Return: 0:链接存在并且执行cur，1：链接不存在或者链接执行bak
# **************************************************************************** #
UPG_HOTPATCH_CHECK_PATCH()
{
    log "begin to check patch link.";
    #如果链接不存在
    if [ ! -L "${G_OS_HP_DIR_LINK}" ] ;then
        log "The patch link is not existed.";
        return 1;
    fi
    #链接存在，并且存在cur目录
    if [ -d "${G_OS_HP_DIR_CUR}" ] ;then
        log "The patch is link to patch_cur.";
        return 0;
    fi
    #链接存在，不存在cur目录，肯定存在bak目录
    log "The patch is link to patch_bak.";
    return 1;
}

#用ping命令检查对端是否在位，不在位返回1
function checkPeerPing()
{
    local L_CheckIp=$1

    if [ -z "$L_CheckIp" ];then
        OS_echo "UPGRADE_SH ip ${L_CheckIp} is null" > /dev/null
        return 1
    fi

    result=`ping -c 3 -w 5 -q $L_CheckIp 2>/dev/stdout`
    OS_echo "UPGRADE_SH The result of ping commond is $result." > /dev/null
    tmp=`echo $result | egrep '100% packet loss|Network is unreachable'`
    if [ -n "$tmp" ];then
        return 1
    fi
    
    return 0
}

# **************************************************************************** #
# Function Name: SelectOneConnectedIp
# Description: 从两个IP中选择一个能ping通的
# Parameter:
# Return:
# **************************************************************************** #
function SelectOneConnectedIp()
{
    local L_SOURCE_IP=$1
    local L_SOURCE_IP_1=""
    local L_SOURCE_IP_2=""
    L_SOURCE_IP_1=`echo $L_SOURCE_IP | awk -F"," '{print $1}'`
    L_SOURCE_IP_2=`echo $L_SOURCE_IP | awk -F"," '{print $2}'`
    
    # 检查传入IP是否连通
    checkPeerPing $L_SOURCE_IP_1
    if [ "$?" == "0" ]; then
        G_SYNC_IP=$L_SOURCE_IP_1
        return 0
    fi

    # 检查传入IP是否连通
    checkPeerPing $L_SOURCE_IP_2
    if [ "$?" == "0" ]; then
        G_SYNC_IP=$L_SOURCE_IP_2
        return 0
    fi

    return 1
}
# **************************************************************************** #
# Function Name: GetConnectedIpIndex
# Description: 获取L_SOURCE_IP中第一个能连通的IP，并返回index
# Parameter:
# Return: 1 选择L_SOURCE_IP_1，2 选择L_SOURCE_IP_2，3 L_SOURCE_IP_1和L_SOURCE_IP_2皆不通
# **************************************************************************** #
function GetConnectedIpIndex()
{
    local L_SOURCE_IP=$1
    local L_SOURCE_IP_1=""
    local L_SOURCE_IP_2=""
    L_SOURCE_IP_1=`echo $L_SOURCE_IP | awk -F"," '{print $1}'`
    L_SOURCE_IP_2=`echo $L_SOURCE_IP | awk -F"," '{print $2}'`
    
    # 检查传入IP是否连通
    checkPeerPing $L_SOURCE_IP_1
    if [ "$?" == "0" ]; then
        return 1
    fi

    # 检查传入IP是否连通
    checkPeerPing $L_SOURCE_IP_2
    if [ "$?" == "0" ]; then
        return 2
    fi
    #传入的IP都不通
    return 3
}

# **************************************************************************** #
# Function Name: OM_ExecuteMMLCommand
# Description: 执行diagnose命令
# Parameter:
# Return:
# **************************************************************************** #
OM_ExecuteDiagnoseCommand()
{ 
    rm -rf $G_DIAG_RESULT
    OS_echo "exec diagnose "
(
diagnose --auto <<EOF > $G_DIAG_RESULT
$1
quit
EOF
) 
return 0
}
# **************************************************************************** #
# Function Name: UpgradeSetNetBootCallDmi
# Description: 调用DMI的diagnose接口设置网络引导
# Parameter:
# Return: 
# **************************************************************************** #
function UpgradeSetNetBootCallDmi()
{   
    WaitForLoadDmi
    if [ "$?" != "0" ];then
        return 1
    fi
    #设置升级FW路径
    OM_ExecuteDiagnoseCommand "dpl setbootid 3"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SH fail to setbootid" >/dev/null
        return 1
    fi
    
    return 0
}

# **************************************************************************** #
# Function Name: UpgradeCtrlFwCallDmi
# Description: 调用DMI的diagnose接口升级控制器的FW
# Parameter:
# Return: 
# **************************************************************************** #
function UpgradeCtrlFwCallDmi()
{
    local VERSIONS_CONF=$1
    local L_FW_PKG_DIR=$2
    local L_CTRL_WWN=""
    
    #设置升级FW路径
    OS_echo "UPGRADE_SHbegin to setfwpath" >/dev/null
    OM_ExecuteDiagnoseCommand "dpl setfwpath $L_FW_PKG_DIR"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SHfail to setfwpath" >/dev/null
        return 1
    fi
    #设置配套表
    OS_echo "UPGRADE_SHbegin to setenclverconf" >/dev/null
    OM_ExecuteDiagnoseCommand "dpl setenclverconf $VERSIONS_CONF"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SHfail to setenclverconf" >/dev/null
        return 1
    fi
    #获取控制器的wwn
    OM_ExecuteDiagnoseCommand "dpl ls encl"
    while read LINE; 
    do
        OS_echo "UPGRADE_SHencl is $LINE"
        if [ -n "${LINE}" ] ; then
            if [ -z "$(echo ${LINE} | awk '{print $6}' | grep "Controller")" ];then
                continue
            fi
            L_CTRL_WWN=`echo ${LINE} | awk '{print $2}'`
            OS_echo "UPGRADE_SH wwn is $L_CTRL_WWN." >/dev/null
            break
        fi
    done < $G_DIAG_RESULT &>/dev/null
    if [ -z "$L_CTRL_WWN" ];then
        OS_echo "UPGRADE_SH not find ctrl wwn." >/dev/null
        return 1
    fi
    
    #停例测失败继续升级
    OS_echo "UPGRADE_SHbegin to upgradestart" >/dev/null
    OM_ExecuteDiagnoseCommand "dpl upgradestart $L_CTRL_WWN"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SHfail to upgradestart" >/dev/null
    fi
    
    #传包
    OS_echo "UPGRADE_SHbegin to enclupgradesendfile" >/dev/null
    OM_ExecuteDiagnoseCommand "dpl enclupgradesendfile $L_CTRL_WWN"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SHfail to enclupgradesendfile" >/dev/null
        return 1
    fi
    #升级
    OS_echo "UPGRADE_SHbegin to upgradeencl" >/dev/null
    OM_ExecuteDiagnoseCommand "dpl upgradeencl $L_CTRL_WWN"
    local ret=`cat $G_DIAG_RESULT |grep "Failed"`
    if [ -n "$ret" ];then
        OS_echo "UPGRADE_SHfail to upgradeencl" >/dev/null
        return 1
    fi
    #校验,和升级控制框保持一致，初次等待10S，轮训10分钟;校验超时失败不再重试
    sleep 10
    declare -i L_TRIAL_TIME=60
    while [ $L_TRIAL_TIME -gt 0 ] 
    do  
        OS_echo "UPGRADE_SHbegin to checkenclver" >/dev/null
        OM_ExecuteDiagnoseCommand "dpl checkenclver $L_CTRL_WWN 0"
        local ret=`cat $G_DIAG_RESULT |grep "Failed"`
        if [ -n "$ret" ];then
            OS_echo "UPGRADE_SHfail to checkenclver" >/dev/null
            return 1
        fi
        local ret=`cat $G_DIAG_RESULT |grep "wrong"`
        if [ -n "$ret" ];then
            OS_echo "UPGRADE_SHthe wrong fw is $ret"
            L_TRIAL_TIME=L_TRIAL_TIME-1
            sleep 10
            continue
        fi
        break
    done

    return 0
}

# **************************************************************************** #
# Function Name: WaitForLoadDmi
# Description: 2分钟等待DMIko加载
# Parameter:
# Return: 
# **************************************************************************** #
function WaitForLoadDmi()
{
    local bLoad=0
    
    declare -i L_TRIAL_TIME=12
    while [ $L_TRIAL_TIME -gt 0 ] 
    do  
        lsmod | grep dmi >/dev/null
        if [ "$?" != "0" ];then
            sleep 10
            let L_TRIAL_TIME=$L_TRIAL_TIME-1
            continue
        fi
        bLoad=1
        break
    done
    
    if [ "0" == "$bLoad" ];then
        OS_echo "UPGRADE_SH dmi load faild ">/dev/null
        return 1
    fi
    
    OS_echo "UPGRADE_SH dmi load success. ">/dev/null
    return 0
}

# **************************************************************************** #
# Function Name: UpgradeCtrlFw
# Description: 升级控制器的FW，为防止DMI内部对象没有准备好，失败隔30S后重试一次
# Parameter:
# Return: 
# **************************************************************************** #
function UpgradeCtrlFw()
{
    local L_BOOT_LINK=`ls -l $G_DISK_MOUNT_IMAGE | grep -a "boot ->" |awk '{print $11}'`
    if [ "$L_BOOT_LINK" != "boot_osp_bak" ] ; then
        OS_echo "UPGRADE_SH sync version faild, the link is $L_BOOT_LINK.">/dev/null
        return 1
    fi
    
    local L_PRODUCT_TYPE=$(grep "Product Name is" /proc/osp/bsp | cut -d' ' -f4 | tr 'a-z' 'A-Z')
    local VERSIONS_CONF=product_versions.${L_PRODUCT_TYPE}.conf
    local L_UPDATE_FW_DIR=update_pkg/${L_PRODUCT_TYPE}
    local L_PKG_DIR=/startup_disk/image/boot
    local L_PKG_VERSION=""
    
    WaitForLoadDmi
    if [ "$?" != "0" ];then
        return 1
    fi
    
    OS_echo "UPGRADE_SH product type is ${L_PRODUCT_TYPE}. ---">/dev/null
    if [ ! -f $L_PKG_DIR/$VERSIONS_CONF ];then
        OS_echo "UPGRADE_SH version file is not exsit. ---">/dev/null
        return 1
    fi
    
    L_PKG_VERSION=`cat $L_PKG_DIR/$VERSIONS_CONF |grep -m 1 Version |awk -F"=" '{print $2}'`
    if [ -z "$L_PKG_VERSION" ];then
        OS_echo "UPGRADE_SH failed to get version. ---">/dev/null
        return 1
    fi
    if [ ! -d "$L_PKG_DIR/$L_UPDATE_FW_DIR" ];then
        OS_echo "UPGRADE_SH no fw path. ---">/dev/null
        return 1
    fi
    
    #升级BIOS，跟升级的保持一致，使用老的KO升级新的rom
    /OSM/script/os_system_update.sh -Y ${L_PKG_VERSION}
    
    UpgradeCtrlFwCallDmi $L_PKG_DIR/$VERSIONS_CONF $L_PKG_DIR/$L_UPDATE_FW_DIR
    if [ "0" != "$?" ];then
        sleep 30
        OS_echo "UPGRADE_SHretry to upgrade ctrl" >/dev/null
        UpgradeCtrlFwCallDmi $L_PKG_DIR/$VERSIONS_CONF $L_PKG_DIR/$L_UPDATE_FW_DIR
    fi
    
    
    return 0
}
# **************************************************************************** #
# Function Name: DiffPartitionFile
# Description: 区分两边的分区表
# Parameter:
# Return: 2 流程出错，1 分区不同，需要走入网络引导 0分区相同
# **************************************************************************** #
function DiffPartitionFile()
{
    local peerfilepath=/tmp
    local localfilepach=/usr/Euler/conf
    
    local partition_file=`ls $peerfilepath | grep "partition" | grep -m 1 "conf"`
    if [ ! -f $peerfilepath/$partition_file ];then
        OS_echo "UPGRADE_SH $peerfilepath/$partition_file is not exsit. ">/dev/null
        return 2
    fi
    
    if [ ! -f $localfilepach/$partition_file ];then
        OS_echo "UPGRADE_SH $localfilepatch/$partition_file is not exsit. ">/dev/null
        return 2
    fi

    diff $peerfilepath/$partition_file  $localfilepach/$partition_file >/dev/null
    if [ "0" == "$?" ];then
        OS_echo "UPGRADE_SH partition_file is same. ---">/dev/null
        return 0
    fi
    
    #找到其中的一个盘符，如sda
    local driver=`cat $peerfilepath/$partition_file | grep -m 1 -w "clearpart" | awk -F '=' '{print $2}' | awk -F ',' '{print $1}'`
    #找到分区数量，并比较，不相同则认为分区发生了变化
    local numpeer=`cat $peerfilepath/$partition_file | grep "part"| grep "size" | grep "$driver" | wc -l`
    local numlocal=`cat $localfilepach/$partition_file | grep "part"| grep "size" | grep "$driver" | wc -l`
    OS_echo "UPGRADE_SH partition_file peer is $numpeer local is $numlocal. ">/dev/null
    if [ "$numpeer" != "$numlocal" ];then
        return 1
    fi
    
    #读取分区大小进行比较
    local partition_num_peer=""
    local partition_num_local=""
    while read line
    do
        if [ -z "$line" ];then
            continue
        fi
        local tmpnum=`echo ${line} | grep "part"| grep "size" | grep "$driver" |sed 's/  */\n/g' | grep "size" | awk -F '=' '{print $2}'`
        if [ -z "$tmpnum" ];then
            continue
        fi
        partition_num_peer+="$tmpnum"
    done < $peerfilepath/$partition_file
    while read line
    do
        if [ -z "$line" ];then
            continue
        fi
        local tmpnum=`echo ${line} | grep "part"| grep "size" | grep "$driver" |sed 's/  */\n/g' | grep "size" | awk -F '=' '{print $2}'`
        if [ -z "$tmpnum" ];then
            continue
        fi
        partition_num_local+="$tmpnum"
    done < $localfilepach/$partition_file
    
    OS_echo "UPGRADE_SH partition_file peer is $partition_num_peer local is $partition_num_local. ">/dev/null
    if [ "$partition_num_peer" != "$partition_num_local" ];then
        return 1
    fi
    
    return 0

}
# **************************************************************************** #
# Function Name: CheckSparepartCompatible
# Description: 判断传入的版本号是否在指定版本文件的备件兼容性列表中
# Parameter:
# Return: 
# **************************************************************************** #
function CheckSparepartCompatible()
{
    local l_peer_vesions=$1
    local l_local_versions_file=$2
    
    declare -i ComLine=$(sed -n -e '/\[SPARE_PART_COMPAT\]/=' $l_local_versions_file)
    ComLine=ComLine+1
    
    ComVersion=`echo $(sed -n "${ComLine}p" $l_local_versions_file)| awk -F"=" '{print $2}'`
    declare -i Index=1
    ComFirst=`echo $ComVersion|awk -F";" '{print $'$Index'}'` 
    
    if [ -z "$ComFirst" ] ; then
        OS_echo "UPGRADE_SH no white list">/dev/null
        return 0
    fi 
    
    while [ true ];do
        declare -i ComVerlow=`echo $ComFirst|awk -F"-" '{print $1}'`
        declare -i ComVerhig=`echo $ComFirst|awk -F"-" '{print $2}'`
        #是否在白名单
        if [ $l_peer_vesions -ge $ComVerlow ] && [ $l_peer_vesions -le $ComVerhig ];then
            return 0
        fi
        Index=Index+1
        ComFirst=`echo $ComVersion|awk -F";" '{print $'$Index'}'`
        if [ -z "$ComFirst" ] ; then
            OS_echo "UPGRADE_SH not in white list">/dev/null
            return 1
        fi 
    done
    
    return 0
}
# **************************************************************************** #
# Function Name: GetpeerVersionAndCheckFromOther
# Description: 比较源从源IP获取，再和指定IP的版本号和单板号进行比较
# Parameter:
# Return: 
# **************************************************************************** #
function GetpeerVersionAndCheckFromOther()
{
    local L_SrcIp=$1
    local L_PeerIP=$2
    local L_SrcVersionFile=/tmp/versions.conf
    local l_Srcbsp=/tmp/bsp
    local L_SrcVersionFiletmp=/tmp/versionssrc.conf
    local l_Srcbsptmp=/tmp/bspsrc
    local L_PeerVersionFile=/tmp/versions.conf
    local l_Peerbsp=/tmp/bsp
    
    #从源 IP 拷贝版本
    /OSM/script/os_get_file.sh ${L_SrcIp} /OSM/conf/versions.conf /tmp/
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_SrcIp} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/versions.conf
    mv $L_SrcVersionFile $L_SrcVersionFiletmp

    /OSM/script/os_get_file.sh ${L_SrcIp} /tmp/bsp /tmp/
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_SrcIp} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/bsp
    mv $l_Srcbsp $l_Srcbsptmp
    
    #从指定IP 拷贝版本
    /OSM/script/os_get_file.sh ${L_PeerIP} /OSM/conf/versions.conf /tmp/
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_PeerIP} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/versions.conf
    /OSM/script/os_get_file.sh ${L_PeerIP} /tmp/bsp /tmp/
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_PeerIP} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/bsp
    L_MIRROR_VERSION_STR=`cat $L_PeerVersionFile | grep -m 1 Version | awk -F"=" '{print $2}'`
    L_CUR_VERSION_STR=`cat $L_SrcVersionFiletmp |grep -m 1 Version |awk -F"=" '{print $2}'`
    OS_echo "UPGRADE_SH peer version is ${L_MIRROR_VERSION_STR}, local version is ${L_CUR_VERSION_STR}"
    if [ "$L_CUR_VERSION_STR" == "$L_MIRROR_VERSION_STR" ]; then 
        return 2
    fi
    
    #判断版本号兼容性
    CheckSparepartCompatible $L_MIRROR_VERSION_STR $L_SrcVersionFiletmp
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH peer version is not compatible." > /dev/null
        return 1
    fi
    
    #判断单板型号是否一致
    local L_PRODUCT_TYPE_PEER=$(grep "Product Name is" $l_Peerbsp | cut -d' ' -f4 | tr 'a-z' 'A-Z')
    local L_PRODUCT_TYPE_SRC=$(grep "Product Name is" $l_Srcbsptmp | cut -d' ' -f4 | tr 'a-z' 'A-Z')
    OS_echo "UPGRADE_SH src board is  $L_PRODUCT_TYPE_SRC,peer is $L_PRODUCT_TYPE_PEER." > /dev/null
    if [ "$L_PRODUCT_TYPE_PEER" != "$L_PRODUCT_TYPE_SRC" ];then
        return 1
    fi
    
    return 0
}
# **************************************************************************** #
# Function Name: GetPeerVersionAndCheck
# Description: 获取对端软件版本号在，如果兼容再获取硬件单板版本判断兼容
# Parameter:第二个参数true针对引擎内的心跳引导，false是跨引擎不能跳到其他引擎执行命令。
############第三个参数local本端兼容性表为准，peer对端兼容性表为准
# Return: 
# **************************************************************************** #
function GetPeerVersionAndCheck()
{
    local L_PeerIP=$1
    local b_Check_Producttype=$2
    local b_local_comp=$3
    local L_TmpVersion=/tmp/versions.conf
    local l_tmpbsp=/tmp/bsp
    
    #从源 IP 拷贝版本
    /OSM/script/os_get_file.sh ${L_PeerIP} /OSM/conf/versions.conf /tmp
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_PeerIP} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/versions.conf
    
    L_MIRROR_VERSION_STR=`cat $L_TmpVersion | grep -m 1 Version | awk -F"=" '{print $2}'`
    if [ -z "$L_MIRROR_VERSION_STR" ];then
        OS_echo "UPGRADE_SH read file $L_TmpVersion failed."
        return 1
    fi
    L_CUR_VERSION_STR=`cat $G_CUR_SYS_VERSION_FILE |grep -m 1 Version |awk -F"=" '{print $2}'`
    if [ -z "$L_CUR_VERSION_STR" ];then
        OS_echo "UPGRADE_SH read file $G_CUR_SYS_VERSION_FILE failed."
        return 1
    fi
    OS_echo "UPGRADE_SH peer version is ${L_MIRROR_VERSION_STR}, local version is ${L_CUR_VERSION_STR}"
    if [ "$L_CUR_VERSION_STR" == "$L_MIRROR_VERSION_STR" ]; then 
        return 2
    fi
    
    #判断版本号兼容性,local本端兼容性表为准，peer对端兼容性表为准
    if [ "$b_local_comp" == "local" ];then
        CheckSparepartCompatible $L_MIRROR_VERSION_STR $G_CUR_SYS_VERSION_FILE
        if [ "0" != "$?" ]; then
            OS_echo "UPGRADE_SH peer version is not compatible in local config." > /dev/null
            return 1
        fi
    elif [ "$b_local_comp" == "all" ];then
        CheckSparepartCompatible $L_MIRROR_VERSION_STR $G_CUR_SYS_VERSION_FILE        
        if [ "0" != "$?" ]; then            
            CheckSparepartCompatible $L_CUR_VERSION_STR $L_TmpVersion
            if [ "0" != "$?" ]; then
                OS_echo "UPGRADE_SH both version is not compatible in both config." > /dev/null
                return 1
            fi  
        fi           
    else
        CheckSparepartCompatible $L_CUR_VERSION_STR $L_TmpVersion
        if [ "0" != "$?" ]; then
            OS_echo "UPGRADE_SH local version is not compatible in peer config." > /dev/null
            return 1
        fi  
    fi
    
    #如果为false，在C代码中用消息拷贝了，因为跨引擎ExecRemoteCmd命令使用不了
    if [ "$b_Check_Producttype" == "true" ];then 
        #/proc/osp/bsp不是实体文件，无法直接获取
        ExecRemoteCmd $L_PeerIP "sudo cp /proc/osp/bsp /tmp/" 10
    fi

    /OSM/script/os_get_file.sh ${L_PeerIP} /tmp/bsp /tmp/
    if [ "0" != "$?" ]; then
        OS_echo "UPGRADE_SH copy from ${L_PeerIP} to local failed." > /dev/null
        return 1
    fi
    chmod 770 /tmp/bsp
    
    #判断单板型号是否一致
    local L_PRODUCT_TYPE_PEER=$(grep "Product Name is" $l_tmpbsp | cut -d' ' -f4 | tr 'a-z' 'A-Z')
    local L_PRODUCT_TYPE_LOCAL=$(grep "Product Name is" /proc/osp/bsp | cut -d' ' -f4 | tr 'a-z' 'A-Z')

    OS_echo "UPGRADE_SH local board is  $L_PRODUCT_TYPE_LOCAL,peer is $L_PRODUCT_TYPE_PEER." > /dev/null
    if [ "$L_PRODUCT_TYPE_PEER" != "$L_PRODUCT_TYPE_LOCAL" ];then
        return 1
    fi
    
    return 0
}
# **************************************************************************** #
# Function Name: GetOtherCtrlVersionAndCheck
# Description: 提供给网络使用，Ping127.127.127.10-13，ping通则去获取对端的版本文件，然后判断兼容性列表
# Parameter:
# Return: 
# **************************************************************************** #
function GetOtherCtrlVersionAndCheck()
{
    local l_FOUR_CTR_ARR=("127.127.127.10" "127.127.127.11" "127.127.127.12" "127.127.127.13")
    #获取本节点IP
    L_LOCAL_NODE=`cat /proc/osp/bsp | grep "Slot ID" | awk -F "is " '{print $2}'`
    L_LOCAL_IP="127.127.127.1"
    L_LOCAL_IP=${L_LOCAL_IP}${L_LOCAL_NODE}
    OS_echo "UPGRADE_SH local ip is $L_LOCAL_IP.">/dev/null
    
    for IP in ${l_FOUR_CTR_ARR[*]}
    do
        if [ "$IP" != "${L_LOCAL_IP}" ] ; then
            checkPeerPing $IP
            if [ "1" == "$?" ] ; then 
                OS_echo "UPGRADE_SH Node $IP can't connect.">/dev/null
                continue
            fi
            GetPeerVersionAndCheck $IP "true" "peer"
            local ret=$?
            if [ "0" == "$ret" ] || [ "2" == "$ret" ]; then 
                return 0
            fi
            return 1
        fi
    done
    
    return 0
    
}
# **************************************************************************** #
# Function Name: CheckPeerVersion
# Description: 
# Parameter:
# Return: 1 版本相同不同步，
# **************************************************************************** #
function CheckPeerVersion()
{
    local L_TmpVersion=/tmp/versions.conf
    local L_VerConfPath=/OSM/conf/versions.conf

        
    L_MIRROR_VERSION_STR=`cat $L_TmpVersion | grep -m 1 Version | awk -F"=" '{print $2}'`
    OS_echo "UPGRADE_SH peer version is ${L_MIRROR_VERSION_STR}"
    
    L_LOCAL_VERSION_STR=`cat $L_VerConfPath | grep -m 1 Version | awk -F"=" '{print $2}'`
    OS_echo "UPGRADE_SH local version is ${L_LOCAL_VERSION_STR}"
    
    if [ "$L_LOCAL_VERSION_STR" == "$L_MIRROR_VERSION_STR" ]; then
        OS_echo "UPGRADE_SH version is not need replace."  
        return 1
    fi
        
    OS_echo "UPGRADE_SH peer version is need replace."
    return 0
}

# **************************************************************************** #
# Function Name: ExecRemoteCmd
# Description: 执行远程命令
# Parameter:对端节点IP
# Return: 
# **************************************************************************** #
function ExecRemoteCmd()
{
    local L_PeerIP=$1
    local L_CMD=$2
    local L_TIMEOUT=$3
    
    local L_EXPECT_CMD="$L_CMD && echo 'Upgrade success' || echo 'Upgrade fail'"
    
    upgrade_expect_exec_cmd.sh $L_PeerIP "$L_EXPECT_CMD" $L_TIMEOUT    
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Peer execute $L_CMD failed. ---">/dev/null
        return 1
    fi
    return 0
}
# **************************************************************************** #
# Function Name: PromotePeerRight
# Description: 提升对端权限
# Parameter:对端节点IP
# Return: 
# **************************************************************************** #
function PromotePeerRight()
{
    local L_PRODUCT_TYPE=$(grep "Product Name is" /proc/osp/bsp | cut -d' ' -f4 | tr 'a-z' 'A-Z')
    if [ -z "$L_PRODUCT_TYPE" ]; then
        OS_echo "UPGRADE_SH --- Warnning, can not get product type from bsp. ---">/dev/null
    elif [ "PANGEA_V2R1C00" != "$L_PRODUCT_TYPE" ] && [ "PANGEA_V2R1C01" != "$L_PRODUCT_TYPE" ] && [ "PANGEA_V2R2C10" != "$L_PRODUCT_TYPE" ]; then
        OS_echo "UPGRADE_SH --- No need promote peer right. ---">/dev/null
        return 0
    fi
    
    #如果INI配置了应该有备件标识，是新备件，可以不用提权
    local bSparePartFlagExist=$(cat $G_PRODUCT_CFG_FILE |grep -m 1 "SparePartFlagExist" |awk -F"=" '{print $2}')
    if [ -n "$bSparePartFlagExist" ];then
        if [ "$bSparePartFlagExist" == "true" ];then
            OS_echo "UPGRADE_SH --- No need promote peer right. ---">/dev/null
            return 0    
        fi
    fi
    
    local L_PeerIP=$1
    local L_PromoteRight="ibc_os_hs ALL=(ALL) NOPASSWD: /tmp/upgrade_common.sh"
    
    cp /etc/sudoers /tmp/
    chmod +w /tmp/sudoers
    echo -e "$L_PromoteRight\n" >> /tmp/sudoers
    chmod -w /tmp/sudoers
    
    /OSM/script/os_put_file.sh $L_PeerIP /tmp/sudoers /tmp
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Put sudoers failed. ---">/dev/null
        return 1
    fi
    ExecRemoteCmd $L_PeerIP "sudo chmod 770 /tmp/sudoers" 10
	
    rm /tmp/sudoers
    #OS_echo "UPGRADE_SH backup sudoers"
    ExecRemoteCmd $L_PeerIP "sudo cp /etc/sudoers /etc/sudoers.bak" 10
    
    ExecRemoteCmd $L_PeerIP "sudo cp /tmp/sudoers /etc/" 10
    ExecRemoteCmd $L_PeerIP "sudo rm /tmp/sudoers" 10
    return 0
}
# **************************************************************************** #
# Function Name: PutFileToPeer
# Description: 传输版本文件，分区表和执行脚本到对端，失败重试一次，防止ftp服务没有拉起
# Parameter:对端节点IP
# Return: 
# **************************************************************************** #
function PutFileToPeer()
{
    local L_PeerIP=$1
    local partition_path=/usr/Euler/conf
    local partition_file
    
    #传输版本文件到对端
    /OSM/script/os_put_file.sh $L_PeerIP /OSM/conf/versions.conf /tmp
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Put versions.con to peer failed. ---">/dev/null
        return 1
    fi
    ExecRemoteCmd $L_PeerIP "sudo chmod 770 /tmp/versions.conf" 10
    
    #根据型号选择分区表文件
    local L_PRODUCT_TYPE=$(grep "Product Name is" /proc/osp/bsp | cut -d' ' -f4 | tr 'a-z' 'A-Z') 
    local IS_NVME=`cat /proc/osp/bsp |grep "Disk State"`
    OS_echo "UPGRADE_SH --- product type is $L_PRODUCT_TYPE, disk state is $IS_NVME. ---">/dev/null
    if [ -n "$IS_NVME" ];then
        local NVME_TYPE=`echo $IS_NVME |awk '{print $4}'`
        partition_file=`ls $partition_path | grep "partition" | grep "$L_PRODUCT_TYPE" | grep "$NVME_TYPE"`
    else
        partition_file=`ls $partition_path | grep "partition" | grep "$L_PRODUCT_TYPE"` 
    fi

    if [ ! -f $partition_path/$partition_file ];then
        OS_echo "UPGRADE_SH $L_PRODUCT_TYPE/$partition_file is not exsit. ---">/dev/null
        return 2
    fi
    /OSM/script/os_put_file.sh $L_PeerIP $partition_path/$partition_file /tmp
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Put $L_PRODUCT_TYPE/$partition_file to peer failed. ---">/dev/null
        return 1
    fi
    ExecRemoteCmd $L_PeerIP "sudo chmod 770 /tmp/$partition_file" 10
    
    /OSM/script/os_put_file.sh $L_PeerIP /OSM/script/upgrade_common.sh /tmp
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Put upgrade_common to peer failed. ---">/dev/null
        return 1
    fi
    ExecRemoteCmd $L_PeerIP "sudo chmod 770 /tmp/upgrade_common.sh" 10
    
    /OSM/script/os_put_file.sh $L_PeerIP /OSM/script/os_system_update.sh /tmp
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Put os_system_update to peer failed. ---">/dev/null
        return 1
    fi
    ExecRemoteCmd $L_PeerIP "sudo chmod 770 /tmp/os_system_update.sh" 10
    
    return 0
}

# **************************************************************************** #
# Function Name: ReplacePeerVersion
# Description: 心跳到对端执行替换
# Parameter:
# Return: 
# **************************************************************************** #
function ReplacePeerVersion()
{
    local L_PeerIP=$1
    
    PromotePeerRight $L_PeerIP    
    if [ 0 != $? ]; then
        OS_echo "UPGRADE_SH --- Promote peer right failed. ---">/dev/null
        return 1
    fi
    
    #如果INI配置了应该有备件标识，则会升级控制器的FW和BIOS，超时时间设置的长一点 BIOS 40分钟+控制器FW 10分钟,定成1个小时
    local bSparePartFlagExist=$(cat $G_PRODUCT_CFG_FILE |grep -m 1 "SparePartFlagExist" |awk -F"=" '{print $2}')
    if [ -n "$bSparePartFlagExist" ];then
        if [ "$bSparePartFlagExist" == "true" ];then
            ExecRemoteCmd $L_PeerIP "sudo /tmp/upgrade_common.sh -b $G_DST_IP" 3600
            if [ 0 != $? ] ; then
                OS_echo "UPGRADE_SH --- Peer execute new command failed. ---">/dev/null
                return 1
            fi
            return 0    
        fi
    fi
    
    ExecRemoteCmd $L_PeerIP "sudo /tmp/upgrade_common.sh -b $G_DST_IP" 300
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- Peer execute command failed. ---">/dev/null
        return 1
    fi
    return 0
}

# **************************************************************************** #
# Function Name: CHECK_PEER_VERSION_AND_REPLACE
# Description: 在位端心跳同步入口
# Parameter:
# Return: 
# **************************************************************************** #
function CHECK_PEER_VERSION_AND_REPLACE()
{
    local L_PeerIP=$G_SRC_IP
       
    checkPeerPing $L_PeerIP
    if [ 0 != $? ] ; then
        return 0
    fi
    
    #返回2时流程往下走，V5备件需要删除备件标识再重启
    GetPeerVersionAndCheck $L_PeerIP "true" "all"
    local ret=$?
    if [ 1 == $ret ]; then
        OS_echo "UPGRADE_SH --- peer version is not need replace ---">/dev/null
        return 0
    elif [ 2 == $ret ];then
        local bSparePartFlagExist=$(cat $G_PRODUCT_CFG_FILE |grep -m 1 "SparePartFlagExist" |awk -F"=" '{print $2}')
        if [ -n "$bSparePartFlagExist" ];then
            if [ "$bSparePartFlagExist" != "true" ];then
                return 0    
            fi
        else
            return 0
        fi
    fi
    
    PutFileToPeer $L_PeerIP
    local ret=$?
    if [ 2 == $ret ]; then
        OS_echo "UPGRADE_SH file is not exsit. ---">/dev/null
        return 0
    elif [ 1 == $ret ]; then
        sleep 5
        PutFileToPeer $L_PeerIP
        if [ 0 != $? ] ; then
            OS_echo "UPGRADE_SH --- put file fail ---">/dev/null
            return 0
        fi
    fi
    
    ReplacePeerVersion $L_PeerIP
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- replace peer version failed! ---">/dev/null
        return 0
    fi
    
    OS_echo "UPGRADE_SH --- check peer and replace success! ---">/dev/null
    return 0
}

# **************************************************************************** #
# Function Name: PEER_REPLACE_VERSION
# Description: 备件端执行心跳同步入口
# Parameter:
# Return: 
# **************************************************************************** #
function PEER_REPLACE_VERSION()
{
    local L_PeerIP=$1
    local l_spare_part_flag=/startup_disk/conf/conf_local/spare_part_flag
    
    if [ -f /startup_disk/conf/conf_local/state_upd.lua ];then 
        OS_echo "UPGRADE_SH ---It is upgrading---">/dev/null
        echo "Upgrade success"
        if [ -f /etc/sudoers.bak ];then
            #OS_echo "UPGRADE_SHrestore sudoers"       
            sudo cp /etc/sudoers.bak /etc/sudoers
            sudo rm /etc/sudoers.bak
        fi
        return 0
    fi
    
    CheckPeerVersion
    if [ "$?" == "1" ];then
        echo "Upgrade success"
        if [ -f /etc/sudoers.bak ];then
            #OS_echo "UPGRADE_SHrestore sudoers"       
            sudo cp /etc/sudoers.bak /etc/sudoers
            sudo rm /etc/sudoers.bak
        fi
        #有V5备件标识则必须重启
        if [ -f $l_spare_part_flag ];then
            rm -f $l_spare_part_flag
            sync
            reboot -f &
        fi
        return 0
    fi
    
    #有V5备件标识则区分两边的分区表，分区表不一致则设置网络引导，烧盘成一致；V3不走此流程
    if [ -f $l_spare_part_flag ];then
        DiffPartitionFile
        local ret=$?
        if [ "$ret" == "1" ];then
            #调用DMI接口设置网络引导，然后重启
            UpgradeSetNetBootCallDmi
            echo "Upgrade success"
            sync
            reboot -f &
            return 0
        elif [ "$ret" == "2" ];then
            echo "Upgrade fail"
            return 0
        fi
    fi
    
    #创建同步中，节点加入集群之前的固件同步中判断有个标志，则等待2分钟让版本拷贝完成
    touch /tmp/sync_upgrading
    sh /tmp/os_system_update.sh -j $L_PeerIP
    if [ 0 != $? ] ; then
        OS_echo "UPGRADE_SH --- replace peer version failed! ---">/dev/null
        echo "Upgrade fail"
        rm /tmp/sync_upgrading
        return 0
    fi
    
    #调用DMI新接口升级控制器固件,V3都是老备件不走此流程。防止因备件版本太旧导致的升级失败，失败继续重启
    if [ -f $l_spare_part_flag ];then
        UpgradeCtrlFw
    fi
    if [ -f $l_spare_part_flag ];then   
        rm -f $l_spare_part_flag
    fi
    
    echo "Upgrade success"
    /OSM/script/os_coffer_main.sh -e
    sync
    reboot -f &
    return 0
}

function RM_OEM()
{
    local L_OEM_PKG=$G_OEM_DIR/$G_OEM_PKG_NAME
    declare -i RETRY_TIMES=0
    
    if [ ! -f $L_OEM_PKG ];then
        OS_echo "UPGRADE_SH --- $L_OEM_PKG is not exist! ---">/dev/null
        return 0
    fi
    
    while [ true ];do
        OS_echo "UPGRADE_SH --- Rmmove the $L_OEM_PKG ! ---">/dev/null
        OS_SET_DISK_RW
        let RETRY_TIMES=$RETRY_TIMES+1
        if [ $RETRY_TIMES -gt 3 ];then
            OS_echo "UPGRADE_SH --- It has retry max times! ---">/dev/null
            OS_SET_DISK_RO
            return 1
        fi

        rm -rf $L_OEM_PKG &>/dev/kmsg
        if [ ! -f $L_OEM_PKG ];then
            OS_echo "UPGRADE_SH --- It has been removed! ---">/dev/null
            OS_SET_DISK_RO
            return 0
        fi
    done
}

function UNZIP_OEM()
{
    local L_OEM_PATH_NAME=$1
    local L_UPDATE_TMP_DIR=/tmp/oem/
    local result
    
    OS_echo "UPGRADE_SH begin to unzip $L_OEM_PATH_NAME !">/dev/null
    if [ ! -f $L_OEM_PATH_NAME ];then
        OS_echo "UPGRADE_SH $L_OEM_PATH_NAME is not exist">/dev/null
        return 1
    fi

    result=`rm -rf $L_UPDATE_TMP_DIR 2>/dev/stdout`
    if [ "$?" != "0" ] ; then
        OS_echo "UPGRADE_SH rm -f $L_UPDATE_TMP_DIR error, result is ($result)" >/dev/null
        return 1
    fi
    
    result=`mkdir $L_UPDATE_TMP_DIR 2>/dev/stdout`
    if [ "$?" != "0" ] ; then
        OS_echo "UPGRADE_SH mkdir $L_UPDATE_TMP_DIR error, result is ($result)" >/dev/null
        return 1
    fi
    
    #预校验下，直接解压到内存有风险
    OS_echo "UPGRADE_SH begin to check the oem.tgz" >/dev/null
    result=`tar -tf $L_OEM_PATH_NAME | grep -w "oem.js"`
    if [ -z "$result" ] ; then
        OS_echo "UPGRADE_SH the special file is not exist." >/dev/null
        return 1
    fi 
    
    OS_echo "UPGRADE_SH begin to tar the oem.tgz" >/dev/null
    result=`tar -xzf $L_OEM_PATH_NAME -C $L_UPDATE_TMP_DIR 1>/dev/null 2>/dev/stdout`
    if [ "$?" != "0" ] ; then
        OS_echo "UPGRADE_SH tar -xzf $L_OEM_PATH_NAME -C $L_UPDATE_TMP_DIR error, result is ($result)" >/dev/null
        return 1
    fi 

    #oem包没有校验文件，通过oem.js来判断是否是非法文件
    if [ ! -f $L_UPDATE_TMP_DIR/oem.js ];then
        OS_echo "UPGRADE_SH $L_OEM_PATH_NAME is not exist">/dev/null
        return 1
    fi
    
    OS_echo "UPGRADE_SH cp $L_OEM_PATH_NAME to $G_OEM_DIR/$G_OEM_PKG_NAME success." >/dev/null
    OS_SET_DISK_RW
    result=`cp $L_OEM_PATH_NAME $G_OEM_DIR/$G_OEM_PKG_NAME 2>/dev/stdout`
    if [ "$?" != "0" ] ; then
        OS_echo "UPGRADE_SH cp $L_OEM_PATH_NAME to $G_OEM_DIR/$G_OEM_PKG_NAME error, result is ($result)" >/dev/null
        return 1
    fi
    OS_SET_DISK_RO
    
    return 0
}

function SYNC_OEM()
{
    local oem_path=$G_OEM_DIR/$G_OEM_PKG_NAME
    local master_ip=$1
    local cmd="/OSM/script/upgrade_trans_file.sh $oem_path $G_OEM_DIR GET_FILE $master_ip"

    for i in {1..2}
    do
        if [ -f $oem_path ];then
            OS_echo "UPGRADE_SH --- $oem_path is exist! ---">/dev/null
            return 0
        fi
        
        if [ $i -ne 1 ];then
            OS_echo "UPGRADE_SHSync oem from master failed, sleep for retry." >/dev/null
            sleep 5
            OS_SET_DISK_RW
        fi
        
        $(${cmd})
        if [ "$?" == "0" ];then
            OS_echo "UPGRADE_SHSync oem from master success." >/dev/null
            return 0
        fi
    done
    
    return 1
}

function deleteStateVersionFile()
{
    local fn="/startup_disk/conf/conf_local/state_version.lua";

    [ -f $fn ] && { log "Delete the state_version.lua file."; rm $fn; }

    echo "Upgrade success";
    return 0;
}

#*********************************************************************#
# Function Name: main
# Description: 解析命令选项
# Usage: ./upgrade_common.sh [-T[test-string]] [--Test[=test-string]]
#        ./upgrade_common.sh [-t test-string] [--test test-string]
#        ./upgrade_common.sh [-xxxxxxx]
# Parameter:
# Return:
#*********************************************************************#
function main()
{
    local -i subRet=$RET_SUCC

    #若无选项参数，则显示帮助信息并退出
    if [ "$#" -lt "1" ]; then
        usage
        return $RET_SUCC
    fi

    #使用getopt排列参数
    TEMP=$(getopt -o hT::t:xwla:b:cd:e:fgi:j:S: --long help,Test::,test: -- "$@")
    if [ "$?" != "0" ]; then
        log "Failed to call getopt..." "$FUNCNAME" "$LINENO"
        return $RET_INTTERNAL_ERR
    fi

    #以排列后的选项参数重新设置位置变量
    eval set -- "$TEMP"

    while true; do
        case "$1" in
            -h|--help)
                usage
                return $RET_SUCC
                ;;
            -T|--Test)
                log "Run $1 function..." "$FUNCNAME" "$LINENO"
                testFunc "$2"
                subRet=$?
                if [ "$subRet" != "$RET_SUCC" ]; then
                    log "Fail to run $1 function." "$FUNCNAME" "$LINENO"
                    return $subRet
                fi
                log "Success to run $1 function." "$FUNCNAME" "$LINENO"
                shift 2
                ;;
            -t|--test)
                log "Run $1 function..." "$FUNCNAME" "$LINENO"
                testFunc "$2"
                subRet=$?
                if [ "$subRet" != "$RET_SUCC" ]; then
                    log "Fail to run $1 function." "$FUNCNAME" "$LINENO"
                    return $subRet
                fi
                log "Success to run $1 function." "$FUNCNAME" "$LINENO"
                shift 2
                ;;
            -x)
                log "Run $1 function..." "$FUNCNAME" "$LINENO"
                testFunc ""
                subRet=$?
                if [ "$subRet" != "$RET_SUCC" ]; then
                    log "Fail to run $1 function." "$FUNCNAME" "$LINENO"
                    return $subRet
                fi
                log "Success to run $1 function." "$FUNCNAME" "$LINENO"
                shift 1
                ;;
            -l)
                #检查patch链接，如果链接不存在或者链接指向bak返回1，否则返回0
                UPG_HOTPATCH_CHECK_PATCH
                subRet=$?
                return $subRet
                ;;
            -a)
                #检查对端是否是备件
                local L_IP=$2
                log "execute $g_ScriptFile -a $L_IP." "$FUNCNAME" "$LINENO"
                G_SRC_IP=`echo $L_IP | awk -F"," '{print $1}'`
                G_DST_IP=`echo $L_IP | awk -F"," '{print $2}'`
                CHECK_PEER_VERSION_AND_REPLACE
                subRet=$?
                return $subRet
                ;;
            -b)
                #替换对端的版本
                log "execute $g_ScriptFile -b." "$FUNCNAME" "$LINENO"
                PEER_REPLACE_VERSION $2
                subRet=$?
                return $subRet
                ;;
            -c)
                #删除oem包
                log "execute $g_ScriptFile -c." "$FUNCNAME" "$LINENO"
                RM_OEM
                subRet=$?
                return $subRet
                ;;
            -d)
                #解压oem包，并拷贝到image目录下
                log "execute $g_ScriptFile -d." "$FUNCNAME" "$LINENO"
                UNZIP_OEM $2
                subRet=$?
                if [ "$subRet" != "0" ];then
                    log "execute failed, retry one time" "$FUNCNAME" "$LINENO"
                    UNZIP_OEM $2
                    subRet=$?
                fi
                return $subRet
                ;;
            -e)
                #从主控同步oem包
                log "execute $g_ScriptFile -e." "$FUNCNAME" "$LINENO"
                OS_SET_DISK_RW
                SYNC_OEM $2
                subRet=$?
                OS_SET_DISK_RO
                return $subRet
                ;;
            -f)
                log "execute $g_ScriptFile -f." "$FUNCNAME" "$LINENO"
                deleteStateVersionFile
                subRet=$?
                return $subRet
                ;;
            -g)
                log "execute $g_ScriptFile -g." "$FUNCNAME" "$LINENO"
                GetOtherCtrlVersionAndCheck
                subRet=$?
                return $subRet
                ;;
            -i)
                local l_peeriptmp=$2
                log "execute $g_ScriptFile -i $l_peeriptmp." "$FUNCNAME" "$LINENO"
                SelectOneConnectedIp $l_peeriptmp
                if [ "$?" != "0" ];then
                    return 1
                fi
                l_peerip=$G_SYNC_IP
                GetPeerVersionAndCheck $l_peerip "false" "all"
                local ret=$?
                if [ "0" == "$ret" ] || [ "2" == "$ret" ]; then 
                    return 0
                else
                    ##防止心跳定时同步和加入集群后的版本同步并发操作文件而导致失败，重试一次
                    log "check again." "$FUNCNAME" "$LINENO"
                    GetPeerVersionAndCheck $l_peerip "false" "all"
                    local ret=$?
                    if [ "0" == "$ret" ] || [ "2" == "$ret" ]; then 
                        return 0
                    fi
                fi
                return 1
                ;;
            -j)
                local L_IPtmp=$2
                log "execute $g_ScriptFile -j $L_IPtmp." "$FUNCNAME" "$LINENO"
                l_srciptmp=`echo $L_IPtmp | awk -F";" '{print $1}'`
                l_peeriptmp=`echo $L_IPtmp | awk -F";" '{print $2}'`
                if [ "$l_peeriptmp" != "local" ];then
                    SelectOneConnectedIp $l_srciptmp
                    if [ "$?" != "0" ];then
                        return 1
                    fi
                    l_srcip=$G_SYNC_IP
                    SelectOneConnectedIp $l_peeriptmp
                    if [ "$?" != "0" ];then
                        return 1
                    fi
                    l_peerip=$G_SYNC_IP
                    GetpeerVersionAndCheckFromOther $l_srcip $l_peerip
                    local ret=$?
                    if [ "0" == "$ret" ] || [ "2" == "$ret" ]; then 
                        return 0
                    fi
                    return 1
                else
                    SelectOneConnectedIp $l_srciptmp
                    if [ "$?" != "0" ];then
                        return 1
                    fi
                    l_srcip=$G_SYNC_IP
                    GetPeerVersionAndCheck $l_srcip "false" "peer"
                    local ret=$?
                    if [ "0" == "$ret" ] || [ "2" == "$ret" ]; then 
                        return 0
                    fi
                    return 1        
                fi                    
                ;;
            -S)
                local l_IpListtmp=$2
                log "execute $g_ScriptFile -S $l_IpListtmp." "$FUNCNAME" "$LINENO"
                GetConnectedIpIndex $l_IpListtmp
                local ret=$?
                return $ret
                ;;
            --)
                log "Success to run $g_ScriptFile." "$FUNCNAME" "$LINENO"
                return $subRet
                ;;
            *)
                log "Unkown option" "$FUNCNAME" "$LINENO"
                return $RET_UNKOWN_OPT
                ;;
        esac
    done
}

#MAIN
getScriptPathAndName

declare -i retCode=$RET_SUCC

log "Enter $g_ScriptFile" "$FUNCNAME" "$LINENO"

main "$@"
retCode="$?"

log "LEAVE $g_ScriptFile, retCode:$retCode" "$FUNCNAME" "$LINENO"

exit $retCode
