#!/usr/bin/env bash

export LC_ALL=C

export PATH=/bin:/sbin:/usr/bin:/usr/sbin


usage() {

    cat <<EOF

raid.sh: raid config tool

Usage: raid.sh [OPTION...]

  -c, --clear         Clear raid config

  -n, --noneraid      No need to create any raid

  -f, --first         The first raid info: 300GB,2,raid10 or 800GB,0,raid10 - 0 means all of the disks

                                           [config size, num, level(raid0 just support each disk mode)]

  -s, --second        The second raid info: 2TB,5,raid5 or 2TB,0,raid5 - 0 means all of the rest disks

  -t, --third         The third raid info

  -o, --forth         The forth raid info

  -i, --fifth         The fifth raid info

  -w, --writemode     The write mode: WB - write back; WT - write throught; default is WB

  -a, --cachemode     The cache mode: Cached - cache mode; Direct - direct mode; default is Cached

  -r, --ramode        The cache mode: NORA - No read ahead; RA - read ahead; ADRA - Adaptive read ahead; default is RA

  -adp, --adapter     The adapter num of the Controller

  

  

Help options:

  -h, --help          Show this help message

EOF

}


[[ $# -lt 1 ]] && usage && exit


ARGS=$(getopt -q -o cnf:s:t:o:i:w:a:r: -l clear,noneraid:,first:,second:,third:,forth:,fifth:,writemode:,cachemode:,ramode:,adapter:,help -- "$@")

[[ $? -ne 0 ]] && echo "Unknown options: $1" && exit 1

eval set -- "${ARGS}"


_writemode="WB"

_cachemode="Cached"

_ramode="RA"

_adapter="a0"


while [[ $# -gt 0 ]]

do

    case "$1" in

        -c|--clear)

            _clr=1

            ;;

        -n|--noraid)

            _noraid=1

            ;;

        -f|--first)

            _first=$2

            shift

            ;;

        -s|--second)

            _second=$2

            shift

            ;;

        -t|--third)

            _third=$2

            shift

            ;;

        -o|--forth)

            _forth=$2

            shift

            ;;

        -i|--fifth)

            _fifth=$2

            shift

            ;;

        -w|--writemode)

            _writemode=$2

            shift

            ;;

        -a|--cachemode)

            _cachemode=$2

            shift

            ;;

        -r|--ramode)

            _ramode=$2

            shift

            ;;

-adp|--adapter)

            _adapter=$2

            shift

            ;;

        -h|--help)

            usage

            ;;

    esac

    shift

done


#######################################


#######################################

MEGACLI=/opt/MegaRAID/MegaCli/MegaCli64

ENCLOSURE=$($MEGACLI -EncInfo -aAll | awk '/Device ID/ { print $NF }' | sed q)

DISKNUM=$($MEGACLI -EncInfo -aAll | awk '/Number of Physical Drives/ { print $NF }' | sed q)


declare -a disks_cfgsize

declare -a disks_unit

declare -a disks_esid

x=1

for((i=1;i<=$DISKNUM;i++))

do

    e_id=`$MEGACLI -pdlist -aall |grep "Enclosure Device ID" | head -n $i | tail -n 1 | awk  '{print $4}'`

    s_id=`$MEGACLI -pdlist -aall |grep "Slot Number" | head -n $i | tail -n 1 | awk  '{print $3}'`

    disk_cfgsize_raw=`$MEGACLI -pdInfo -PhysDrv[$e_id:$s_id] -aALL|grep "Raw Size"|awk '{print $3}'`

    disk_size_unit=`/opt/MegaRAID/MegaCli/MegaCli64 -pdInfo -PhysDrv[$e_id:$s_id] -aALL|grep "Raw Size"|awk '{print $4}'`


    [ "$disk_size_unit" = "GB" ] && disk_cfgsize=`echo "scale=0; $disk_cfgsize_raw/100*100" | bc`

    [ "$disk_size_unit" = "TB" ] && disk_cfgsize=`echo "scale=1; $disk_cfgsize_raw/1" | bc`


    disks_cfgsize[$x]=$disk_cfgsize

    disks_unit[$x]=$disk_size_unit

    disks_esid[$x]=$e_id:$s_id


    let x++

done

###################################

#Done

###################################


parameter_verify(){

    local size=$1

    local num=$2

    local level=$3


    # all can't be null

    [ -z "$size" -o -z "$num" -o -z "$level" ] && echo "All parameters cann't be empty." && return 1


    # just support raid0(each disk), raid1, raid10, raid5 so far

    [ $level != "raid0" -a $level != "raid5" -a $level != "raid10" -a $level != "raid1" -a $level != "raid50" -a $level != "raid60" ] && echo "Just support raid0, raid1, raid10, raid5, raid50, raid60 so far" && return 2


    return 0

}


makeraid0(){

    echo "Make raid0"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    for((i=1;i<=${#disks[@]};i++))

    do

        [ ! -z "${disks[$i]}" ] && $MEGACLI -CfgLdAdd -r0 [${disks[$i]}] $write $cache $ramode -$adapter || return 1

        disks[$i]=""

    done

}


makeraid50(){

    echo "Make raid50"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    disknum=${#disks[@]}

    [ $disknum -lt 6 ] && echo "Disk num cann't be less then 6." && return 2


    let raid0_num=disknum/2

    let raid1_begin=raid0_num+1

    _parameter=$(

    echo -n "-Array0["

    for((i=1;i<=$raid0_num;i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//'

    echo -n "] "

    echo -n "-Array1["

    for((i=$raid1_begin;i<=$disknum;i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//'

    echo -n "]"

    )

    $MEGACLI -CfgSpanAdd -r50 $_parameter $write $cache $ramode -a0

}


makeraid60(){

    echo "Make raid60"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    disknum=${#disks[@]}

    [ $disknum -lt 8 ] && echo "Disk num cann't be less then 8." && return 2


    let raid0_num=disknum/2

    let raid1_begin=raid0_num+1

    _parameter=$(

    echo -n "-Array0["

    for((i=1;i<=$raid0_num;i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//'

    echo -n "] "

    echo -n "-Array1["

    for((i=$raid1_begin;i<=$disknum;i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//'

    echo -n "]"

    )

    $MEGACLI -CfgSpanAdd -r60 $_parameter $write $cache $ramode -a0

}


makeraid10(){

    echo "Make raid10"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    disknum=${#disks[@]}

    let disknum=disknum/2

    _parameter=$(

    for((i=1;i<=$disknum;i++))

    do

        echo -n "-Array${i}[${disks[((i*2-1))]},${disks[((i*2))]}]"

    done)

    $MEGACLI -CfgSpanAdd -r10 $_parameter $write $cache $ramode -a0

}


makeraid5(){

    echo "Make raid5"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    _parameter=$(

    for((i=1;i<=${#disks[@]};i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//')

    $MEGACLI -CfgLdAdd -r5 [$_parameter] $write $cache $ramode -a0

}


makeraid1(){

    echo "Make raid1"

    declare -a disks

    local disks_txt=`echo "$@" | awk -F'ENDDISK' '{print $1}'`

    local write_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $1}'`

    local cache_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $2}'`

    local ra_mode=`echo "$@" | awk -F'ENDDISK' '{print $2}' | awk '{print $3}'`


    local i=1;

    for disk in `echo $disks_txt` ; do disks[$i]=$disk; let i=i+1; done


    local write="WB"

    local cache="Cached"

    local ramode="RA"

    [ "$write_mode" = "WT" ] && write="WT"

    [ "$cache_mode" = "Direct" ] && cache="Direct"

    [ "$ra_mode" = "NORA" ] && ramode="NORA"

    [ "$ra_mode" = "ADRA" ] && ramode="ADRA"


    _parameter=$(

    for((i=1;i<=${#disks[@]};i++))

    do

        echo -n ${disks[$i]},

    done | sed 's/,$//')

    $MEGACLI -CfgLdAdd -r1 [$_parameter] $write $cache $ramode -a0

}


clearcfg() {

    echo "clear"

    $MEGACLI -CfgClr -aALL

    # make all disks good

    for((i=1;i<=${#disks_cfgsize[@]};i++)); do

        [ "${disks_esid[$i]}" != "" ] && $MEGACLI -PDMakeGood -PhysDrv[${disks_esid[$i]}] -force -a0 1>/dev/null 2>/dev/null

    done

    sleep 2s

}


diskinit() {

    $MEGACLI -LDinit -start -L0 -a0

}


[[ "$_clr" -eq 1 ]] && clearcfg


[[ $_noraid -eq 1 ]] && echo "no need to create any raid." && exit 0



create_raid(){

    local size=`echo $1 | awk -F',' '{print $1}'`

    local num=`echo $1 | awk -F',' '{print $2}'`

    local level=`echo $1 | awk -F',' '{print $3}'`


    # verify the paramters

    parameter_verify "$size" "$num" "$level" || exit 1


    # When num is zero, all disks to be one raid and exit

    if [ $num -eq 0 ] ; then

        echo "All disks will be one raid group."


        declare -a disks_esid_notnull

        for((i=1;i<=${#disks_cfgsize[@]};i++)); do

            [ "${disks_esid[$i]}" != "" ] && disks_esid_notnull[$x]=${disks_esid[$i]} && disks_esid[$i]=""  && let x++

        done


        make${level} ${disks_esid_notnull[@]} "ENDDISK" "$_writemode" "$_cachemode" "$_ramode"

        if [ $? -ne 0 ] ;then echo "Make $level failed"; exit 1; fi


        diskinit

        exit 0

    else

        echo "Create $level($num disks with size $size)"


        # find the disks with the specified config size

        declare -a raid_disks

        x=1

        for((i=1;i<=${#disks_cfgsize[@]};i++)); do

            [ ${disks_cfgsize[$i]}${disks_unit[$i]} = "$size" ] && [ "${disks_esid[$i]}" != "" ] && raid_disks[$x]=${disks_esid[$i]} && disks_esid[$i]=""  && let x++

            [ $x -gt $num ] && break

        done


        [ ${#raid_disks[@]} -ne $num ] && echo "No enought disks with config size $size to create the RAID." && exit 1


        make${level} ${raid_disks[@]} "ENDDISK" "$_writemode" "$_cachemode" "$_ramode"

        if [ $? -ne 0 ] ;then echo "Make $level failed"; exit 2; fi

    fi

}


if [ -n "$_first" ] ; then

    create_raid "$_first"

fi


if [ -n "$_second" ] ; then

    create_raid "$_second"

fi


if [ -n "$_third" ] ; then

    create_raid "$_third"

fi


if [ -n "$_forth" ] ; then

    create_raid "$_forth"

fi


if [ -n "$_fifth" ] ; then

    create_raid "$_fifth"

fi


diskinit

exit 0