#!/bin/sh
####################################################################
# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP.
# @(#) Serviceguard DR Rehearsal Package Prepartion Script.
# @(#) Product Name              :  HP Serviceguard
# @(#) Product Version           :  A.12.10.00
# @(#) Patch Name                :  
#%%DO_NOT_MODIFY_TEXT%%
################################################################

. ${SGCONFFILE:=/etc/cmcluster.conf}

date_prefix=$(date +"%H_%M_%S_%N")

typeset tmp_dir="/var/tmp"
typeset -i serviceindex=0
typeset target_nodes=""
typeset magic="DRxR"

function get_correct_value
{
    type=$1
    if [ "$type" == "VMFS Parameters" -o "$type" == "3PAR Replication Parameters" \
        -o "$type" == "Host Based Replication Parameters" -o "$type" == "Persistent Reservation" \
        -o "$type" == "Storage" -o "$type" == "File System" -o "$type" == "storage" ]
    then
        value=storage
    elif [ "$type" == "Network" -o "$type" == "network" ]
    then
        value=network
    else
        value=compute
    fi

    echo $value
}

function exclude_service_cmd
{
    pkg=$1
    service=$2

    # Do not include DR3PARRCMon monitoring services in rehearsal package #
    grep -q "^package:$pkg|service:$service|command=.*DR3PARRCMon" $vfline_output
    if [[ $? -eq 0 ]]
    then
        return 0
    else 
        return 1
    fi
}

function get_package_services_details
{
    pkg=$1
    config_file=$2
    pkg_id=`grep "^package:$pkg|id=" $vfline_output | cut -d "=" -f 2`
    servicelist=(`awk -F'=' '/:'$pkg'\|service:.*\|name=/ {print $NF}' $vfline_output`)
    servicedetails=$tmp_dir/$date_prefix_$pkg_"servicedetails.txt"
    if [ ! -z $servicelist ]
    then
        for service in ${servicelist[*]}
        do  
            exclude_service_cmd "$pkg" "$service"
            if [[ $? -eq 1 ]]
            then
                echo service_name DRxR"$serviceindex"_"$pkg_id" > $servicedetails
                awk -F'=' '/:'$pkg'\|service:'$service'\|command/ \
                    {print "service_cmd "$NF}' $vfline_output >> $servicedetails
                awk -F'=' '/:'$pkg'\|service:'$service'\|restart/ \
                    {print "service_restart "$NF}' $vfline_output >> $servicedetails
                awk -F'=' '/:'$pkg'\|service:'$service'\|failfast/ \
                    { if ($NF=="disabled") print "service_fail_fast_enabled no"; \
                    else if ($NF=="enabled") print "service_fail_fast_enabled yes"}' \
                    $vfline_output >> $servicedetails
                awk -F'=' '/:'$pkg'\|service:'$service'\|halt_timeout/ \
                    {print "service_halt_timeout "$NF}' \
                    $vfline_output >> $servicedetails
                awk -F'=' '/:'$pkg'\|service:'$service'\|halt_on_maintenance/ \
                    {print "service_halt_on_maintenance "$NF}' \
                    $vfline_output >> $servicedetails
                sed -i "\$r $servicedetails" $config_file
                rm -rf $servicedetails
                ((serviceindex=serviceindex+1))
            fi      
        done
    fi        
}

function update_rehearsalid_and_eligible_target_nodes
{
    typeset _package_name=$1
    typeset _config_file=$2

    echo "rehearsal_id                    $rehearsal_id" >> $_config_file
    node_name=`awk -F'[:|]' '/:'$_package_name'\|.*\|action=starting/ \
       {print \$4}' $cmeval_output`
    echo "enabled_target_nodes            $node_name" >> $_config_file
}

function add_generic_resource
{
    typeset _package_name=$1
    typeset _config_file=$2

    echo "generic_resource_name                 $gr_name" >> $_config_file
    echo "generic_resource_evaluation_type      during_package_start" >> $_config_file
}

function expand_ipv6_address
{
    IP_ADDR="$(tr 'A-F' 'a-f' <<< "$@")"

    O=""

    while [ "$O" != "$IP_ADDR" ]; do
    O="$IP_ADDR"

    IP_ADDR="$( sed  's|:\([0-9a-f]\{3\}\):|:0\1:|g' <<< "$IP_ADDR" )"
    IP_ADDR="$( sed  's|:\([0-9a-f]\{3\}\)$|:0\1|g'  <<< "$IP_ADDR")"
    IP_ADDR="$( sed  's|^\([0-9a-f]\{3\}\):|0\1:|g'  <<< "$IP_ADDR" )"

    IP_ADDR="$( sed  's|:\([0-9a-f]\{2\}\):|:00\1:|g' <<< "$IP_ADDR")"
    IP_ADDR="$( sed  's|:\([0-9a-f]\{2\}\)$|:00\1|g'  <<< "$IP_ADDR")"
    IP_ADDR="$( sed  's|^\([0-9a-f]\{2\}\):|00\1:|g'  <<< "$IP_ADDR")"

    IP_ADDR="$( sed  's|:\([0-9a-f]\):|:000\1:|g'  <<< "$IP_ADDR")"
    IP_ADDR="$( sed  's|:\([0-9a-f]\)$|:000\1|g'   <<< "$IP_ADDR")"
    IP_ADDR="$( sed  's|^\([0-9a-f]\):|000\1:|g'   <<< "$IP_ADDR")"

    done

    ZEROES=""

    grep -qs "::" <<< "$IP_ADDR"
    if [ "$?" -eq 0 ]; then
      GRPS="$(sed  's|[0-9a-f]||g' <<< "$IP_ADDR" | wc -m)"
      ((GRPS--)) # carriage return
      ((MISSING=8-GRPS))
      for ((i=0;i<$MISSING;i++)); do
          ZEROES="$ZEROES:0000"
          done

     IP_ADDR="$( sed  's|\(.\)::\(.\)|\1'$ZEROES':\2|g'   <<< "$IP_ADDR")"
     IP_ADDR="$( sed  's|\(.\)::$|\1'$ZEROES':0000|g'   <<< "$IP_ADDR")"
     IP_ADDR="$( sed  's|^::\(.\)|'$ZEROES':0000:\1|g;s|^:||g'   <<< "$IP_ADDR")"

    fi

    echo $IP_ADDR 
}


function get_package_ip_subnet
{
    pkg=$1
    config_file=$2
    iid=ip_address
    sid=ip_subnet
    valid=0
    
    owner=`awk -F= '/package:'$pkg'\|owner=/ {print \$2}' $vfline_output`

    iplist=(`awk -F'|' '/\<package:'$pkg'\>/  {getline; if($1=="'$iid'") \
            for(i=2;i<=NF;i++) {print $i}}' $input_file`)
    if [ -z $iplist ]
    then
        return 0
    fi

    sublist=(`grep "^package:$pkg|.*|ip_subnet" $vfline_output | cut -d "=" -f 2`)

    for ip in ${iplist[*]}
    do
        beta=0
        echo $ip | grep "\." > /dev/null
        if [ $? -eq 0 ] 
        then
            # The given IP address is IPv4
            while [[ $beta -lt ${#sublist[*]} ]]
            do
                alpha=$beta
                ((beta=beta+1))
                echo ${sublist[$alpha]} | grep "\." > /dev/null
                if [ $? -ne 0 ]
                then 
                    # Not IPv4 subnet. Ignore
                    continue
                fi

                { IFS=. read -r i1 i2 i3 i4; } <<< $ip
                { IFS=. read -r m1 m2 m3 m4; } <<< ${sublist[$alpha]}
                subnet=`echo "$((i1 & m1))"."$((i2 & m2))"."$((i3 & m3))"."$((i4 & m4))"`
                if [[ $subnet == ${sublist[$alpha]} ]]
                then
                    sed -i "\$a$sid ${sublist[$alpha]}" $config_file
                    sed -i "\$a$iid $ip" $config_file
                    ((valid=valid+1))
                    break
                fi
            done        
        fi 

        echo $ip | grep "\:" > /dev/null
        if [ $? -eq 0 ]
        then
            # The given IP address is IPv6
            IPv6_ADDR=`expand_ipv6_address $ip`
            while [[ $beta -lt ${#sublist[*]} ]]
            do
                alpha=$beta
                ((beta=beta+1))
                echo ${sublist[$alpha]} | grep "\:" > /dev/null
                if [ $? -ne 0 ]
                then
                    # Not ipv6 subnet. Ignore
                    continue
                fi

                prefix=`awk -F= '/node:'$owner'\|.*\|subnet='${sublist[$alpha]}'/ {print \$1}' $vfline_output`
                prefix=`echo ${prefix::-6}`
                netmask=`cat $vfline_output | grep $prefix"netmask=" | cut -d "=" -f 2`
                netmask=`echo "${netmask::-2}"`
               # octets=`echo $netmask | grep -o ":" | wc -l`
               # ((octets=octets+1))
                { IFS=: read -r i1 i2 i3 i4 i5 i6 i7 i8; } <<< $IPv6_ADDR
                { IFS=: read -r n1 n2 n3 n4 n5 n6 n7 n8; } <<< $netmask
                { IFS=: read -r s1 s2 s3 s4 s5 s6 s7 s8; } <<< ${sublist[$alpha]}
                c_subnet=`echo "$((16#$i1 & 16#$n1))":"$((16#$i2 & 16#$n2))":"$((16#$i3 & 16#$n3))":\
                              "$((16#$i4 & 16#$n4))":"$((16#$i5 & 16#$n5))":"$((16#$i6 & 16#$n6))":\
                              "$((16#$i7 & 16#$n7))":"$((16#$i8 & 16#$n8))" | sed 's/ //g'`
                p_subnet=`echo "$((16#$s1))":"$((16#$s2))":"$((16#$s3))":"$((16#$s4))":"$((16#$s5))":\
                                "$((16#$s6))":"$((16#$s7))":"$((16#$s8))" | sed 's/ //g'`
                if [[ $c_subnet == $p_subnet ]]
                then
                    sed -i "\$a$sid ${sublist[$alpha]}" $config_file
                    sed -i "\$a$iid $ip" $config_file
                    ((valid=valid+1))
                    break
                fi
            done
        fi 
    done
   
    if [ $valid == ${#iplist[*]} ]
    then
        return 0
    fi
   
    return 1
}

function get_package_node
{
    pkg=$1
    config_file=$2
    node_name=`awk -F'[:|]' '/:'$pkg'\|.*\|action=starting/ \
               {print \$4}' $cmeval_output`
    if [ -z $node_name ]
    then
        return 1
    fi
    if [ ! -z $config_file ]
    then 
        # Remove multiple entries
        sed -i "/^node_name/d" $config_file
        echo "node_name $node_name" >> $config_file
    fi
    return 0
}


function check_rehearsal_package
{
    awk -F: '/Good:/ {print "'$rehearsal_dir'/"$2".ascii"}' \
                       $rehearsal_dir/packages > $rehearsal_dir/filelist
    $SGSBIN/cmcheckconf -r $rehearsal_id -p $rehearsal_dir/filelist -z &> $rehearsal_dir/checkconf.log
    if [[ $? -eq 0 ]]
    then
        return 
    fi
    for package in ${packagelist[*]}
    do
        pkg_id=`grep "^package:$package|id=" $vfline_output | cut -d "=" -f 2`
        grep -q ":ERROR|.*|resource:DRxR_$pkg_id|.*|value.*=" $rehearsal_dir/checkconf.log
        if [[ $? -eq 0 ]]
        then
            sed -i "s/\<Good:$package\>/Bad:$package/" $rehearsal_dir/packages
            awk -F'[:|=]' '/:ERROR\|.*\|resource:DRxR_'$pkg_id'\|.*\|value.*=/ \
             {printf "'$package'""|"$10"|ERROR:"$12" "; for(i=13;i<=NF;i++) printf "%s", $i; printf "\n"}' \
                                                 $rehearsal_dir/checkconf.log >> $error_file
        fi            
    done
 
    awk -F: '/Good:/ {print "'$rehearsal_dir'/"$2".ascii"}' \
                          $rehearsal_dir/packages > $rehearsal_dir/filelist

    return 
}

function rename_remove_parameters
{
    config_file=$1
    pkg_id=$2

    # Rename package description, script log file path, auto_run to no #
    # Remove services, ip, dts parameters, vmdk_file_name, datastore_name, scsi_controller, disk_type #
    sed -i 's/^package_description.*/package_description\t\tRehearsal package/' $config_file
    sed -i 's/^auto_run.*/auto_run\t\tno/' $config_file
    sed -i "s|^script_log_file.*|script_log_file\t\t$SGRUN/log/DRxR_$pkg_id.log|g" $config_file
    sed -i '/^service_.*/d' $config_file
    sed -i '/^ip_.*/d' $config_file
    sed -i '/^vmdk_file_name.*/d' $config_file
    sed -i '/^datastore_name.*/d' $config_file
    sed -i '/^scsi_controller.*/d' $config_file
    sed -i '/^disk_type.*/d' $config_file
    sed -i '/^dts\/.*/d' $config_file
    sed -i '/module_name.*dts\/.*/,+1 d' $config_file
    sed -i '/^operation_sequence.*\/dts\/.*/d' $config_file
    sed -i '/^\s*$/d' $config_file
}

function make_rehearsal_package
{
    pkg=$1 
    pkg_id=`grep "^package:$pkg|id=" $vfline_output | cut -d "=" -f 2`
    config_file=$rehearsal_dir/$pkg.ascii
    tmp_file=$rehearsal_dir/tmp.ascii
    $SGSBIN/cmgetconf -p $pkg -v 0 $tmp_file > /dev/null
    $SGSBIN/cmmakepkg -i $tmp_file -m sg/sg_internal_drr_module \
                                   -m sg/generic_resource \
                                   -n $magic"_"$pkg_id \
                                   -v 0 $config_file > /dev/null
    if [[ $? -ne 0 ]]
    then
        sed -i "s/\<Good:$pkg\>/Bad:$pkg/" $rehearsal_dir/packages
        echo $pkg"|compute|ERROR:Failed to create rehearsal package" >> $error_file
        rm -rf $tmp_file
        rm -rf $config_file
        return
    fi
    
    rename_remove_parameters "$config_file" "$pkg_id"
    rm -rf $tmp_file
   
    get_package_node "$pkg" "$config_file"
    if [[ $? -ne 0 ]]
    then
        # "No eligible target node to perform rehearsal"
        sed -i "s/\<Good:$pkg\>/Bad:$pkg/" $rehearsal_dir/packages
        echo $pkg"|compute|ERROR:No eligible nodes to perform rehearsal" >> $error_file
        rm -rf $config_file
        return
    fi 
    
    get_package_ip_subnet "$pkg" "$config_file"
    if [[ $? -ne 0 ]]
    then 
        # Invalid IP
        sed -i "s/\<Good:$pkg\>/Bad:$pkg/" $rehearsal_dir/packages
        echo $pkg"|network|ERROR:One or more Invalid IP address provided" >> $error_file
        rm -rf $config_file
        return
    fi 

    get_package_services_details "$pkg" "$config_file"

    # Update the new module attributes.
    update_rehearsalid_and_eligible_target_nodes "$pkg" "$config_file"
    add_generic_resource "$pkg" "$config_file"
}

function update_error_file
{
    while read line; do
        var=`awk -F'|' '{print $2}' <<< $line`
        if [ "$var" != "storage" -o "$var" != "network" -o "$var" != "compute" ]
        then
            value=$( get_correct_value "$var" )
            sed -i "s/|$var|/|$value|/" $error_file
        fi
    done < $error_file

    node_list=(`$SGSBIN/cmviewcl -f line -s config | grep "^node:.*|name=" | cut -d "=" -f 2`)
    for node in ${node_list[*]}
    do
        $SGSBIN/cmcp $error_file $node:$error_file > /dev/null 2>&1
    done
}

function print_packages_targets
{
    grep -q "Good:" $rehearsal_dir/packages 
    if [[ $? -eq 0 ]]
    then
        awk -F'|' -v var="node:" '{print var $2}' $rehearsal_dir/enabled_pkg_nodes | sort -u
        awk -F: -v var="pass:" "/Good:/ {print var \$2}" $rehearsal_dir/packages
    fi

    awk -F: -v var="fail:" "/Bad:/ {print var \$2}" $rehearsal_dir/packages
}

function cleanup_before_exit
{
    typeset -i ret=$1
    rm -f $tmp_dir/$date_prefix* > /dev/null 2>&1
    if [[ -f $error_file ]]
    then
        update_error_file
    fi

    print_packages_targets

    rm -f $rehearsal_dir/packages
    rm -f $input_file
    # Exit to indicate success/failure 
    exit $ret
}


function cache_cmviewclvfline_output
{
    typeset cmviewclvfline_command="${SGSBIN}/cmviewcl -vf line"

    rm -f $vfline_output 2>/dev/null
    $cmviewclvfline_command > $vfline_output 2>/dev/null
    if [ $? -ne 0 ]
    then
        return 1
    fi    
    return 0
}


function find_target_nodes_for_packages
{
    cmeval_input=$rehearsal_dir/cmeval_input 
    cp $vfline_output $cmeval_input
 
    # For each package, find the owner and DC nodelist
    for pkg in ${packagelist[*]}
    do
        j=0
        nodes=""
        nodelist=""
        owner=`awk -F= '/package:'$pkg'\|owner=/ {print \$2}' $vfline_output`
        if [[ $owner == "unowned" ]]
        then
            # Detected a halt/down package. Mark all packages as Bad
            # and fail the rehearsal.
            sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
            for package in ${packagelist[*]}
            do
                echo $package"|compute|ERROR:Failing rehearsal as we detected a down package" \
                                                  >> $error_file
            done
            return 1
        fi 
        nodes+=`awk -F'[= ]' '/package:'$pkg'\|.*DC.*_NODE_LIST=.*\<'$owner'\>/ {for(i=2;i<=NF;i++) \
                                                           {printf "%s \n", $i}}' $vfline_output`

        # For each package, make the current DC nodelist as unavaiable
        nodelist=(`printf '%s\n' ${nodes[*]} | sort -u`)
        while [[ $j -lt ${#nodelist[*]} ]]
        do
            prefix=":$pkg|node:${nodelist[$j]}|available"
            sed -i "s/$prefix=yes/$prefix=no/" $cmeval_input
            ((j=j+1))
        done
    done

    $SGSBIN/cmeval -o $cmeval_output $cmeval_input
    if [[ `stat -c%s $cmeval_output` -eq 0 ]]
    then 
        sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
        for package in ${packagelist[*]}
        do
            echo $package"|compute|ERROR:No eligible nodes to perform rehearsal" \
                                           >> $error_file
        done
        return 1
    fi


    # Check if we have found any target nodes
    target_nodes=(`awk -F'[:|]' '/\|action=starting/ {print \$4}' $cmeval_output | sort -u`)
    if [ -z $target_nodes ]
    then 
        # None of the packages have eligible nodes to failover.
        sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
        for package in ${packagelist[*]}
        do
            echo $package"|compute|ERROR:No eligible nodes to perform rehearsal" \
                                            >> $error_file
        done
        return 1
    fi


    # For each package, check if there are eligible target nodes
    for package in ${packagelist[*]}
    do
        get_package_node $package
        if [[ $? -ne 0 ]]
        then 
            sed -i "s/\<Good:$package\>/Bad:$package/" $rehearsal_dir/packages
            echo $package"|compute|ERROR:No eligible nodes to perform rehearsal" \
                                              >> $error_file
        fi
    done

    rm -f $cmeval_input
    return 0
}

function perform_configuration_check
{
    awk -F: "/Good:/ {print \$2}" $rehearsal_dir/packages \
                                     > $rehearsal_dir/config_check.list
    $SGSBIN/cmcheckconf -V package -p $rehearsal_dir/config_check.list -z \
                                     &> $rehearsal_dir/config_check.log

    for target in ${target_nodes[*]}
    do 
        # Find the packages with Errors and mark them as Bad
        bad_pkg=(`awk -F'[:|]' '/:ERROR\|.*\|value.*='$target'/ \
                               {print \$6}' $rehearsal_dir/config_check.log`)
        for pkg in ${bad_pkg[*]}
        do
            sed -i "s/\<Good:$pkg\>/Bad:$pkg/" $rehearsal_dir/packages
        done

        # Update .prep_error_file with Errors
        awk -F'[:|=]' '/:ERROR\|.*\|value.*='$target'/ {printf $6"|"$10"|ERROR:"$12" "; \
                           for(i=13;i<=NF;i++) printf "%s", $i; printf "\n"}' \
                           $rehearsal_dir/config_check.log >> $error_file 

        # Update .prep_error_file with warnings
        awk -F'[:|=]' '/:WARNING\|.*\|value.*='$target'/ {printf $6"|"$10"|WARNING:"$12" "; \
                           for(i=13;i<=NF;i++) printf "%s", $i; printf "\n"}' \
                           $rehearsal_dir/config_check.log >> $error_file
    done 
    return 
}

function get_pri_pkg_name_from_drr_pkg_name
{
    _pkg_name=$1
    _pkg_id=`echo $_pkg_name | cut -d '_' -f 2`
    # package:pkg1|id=15361
    echo `cat $vfline_output | awk '/^package[^|]*\|id='$_pkg_id'/' | sed 's/|id='${_pkg_id}'//;s/package://'`
}

function create_file_and_distribute_for_node_switching
{
    _file_list=$rehearsal_dir/filelist
    _enabled_file=$rehearsal_dir/enabled_pkg_nodes
    for file in `cat $_file_list`
    do
        _drr_pkg_name=`cat $file | awk '/^package_name/ {print $2}'`
        _nodes=`cat $file | awk '/^enabled_target_nodes/ {print $2}'`
        _pri_pkg_name=`get_pri_pkg_name_from_drr_pkg_name $_drr_pkg_name`
        echo "$_pri_pkg_name|$_nodes" >> $_enabled_file
    done
    node_list=(`$SGSBIN/cmviewcl -f line -s config | grep "^node:.*|name=" | cut -d "=" -f 2`)
    for node in ${node_list[*]}
    do
        $SGSBIN/cmcp $_enabled_file $node:$_enabled_file > /dev/null 2>&1
    done
}

function switching_primary_package_on_target_nodes
{
    _rehearsal_id=$1
    _switching_type=$2
    if [[ "X$rehearsal_dir" == "X" ]]; then
        rehearsal_dir=${SGRUN}/$magic/$rehearsal_id
        error_file=$rehearsal_dir/.prep_error_file
    fi
    _enabled_file=$rehearsal_dir/enabled_pkg_nodes
    _ret=0

    if [ ! -f ${_enabled_file} ]; then
        return $_ret
    fi

    for line in `cat $_enabled_file`
    do
        _pri_pkg_name=`echo $line | cut -d '|' -f 1`
        _node=`echo $line | cut -d '|' -f 2`
        # Get the target nodes
        tgt_node_list=$tgt_node_list" "$_node

        # enable/disable node switching on for the package
        if [[ $_switching_type == "enable" ]]; then
            $SGSBIN/cmmodpkg -r -e -n $_node $_pri_pkg_name >> $rehearsal_dir/cmmodpkg_enable.log
            if [[ $? -ne 0 ]]; then
                echo $_pri_pkg_name"|compute|ERROR:Failed to re-enable node switching for the primary package." \
                                             >> $error_file
                echo $_pri_pkg_name"|compute|ERROR:Node switching has to be manually enabled using cmmodpkg." \
                                             >> $error_file
                _ret=1
            fi
        elif [[ $_switching_type == "disable" ]]; then
            $SGSBIN/cmmodpkg -r -d -n $_node $_pri_pkg_name >> $rehearsal_dir/cmmodpkg_disable.log
            if [[ $? -ne 0 ]]; then
                echo $_pri_pkg_name"|compute|ERROR:Failed to disable node switching using cmmodpkg." \
                                             >> $error_file
                _ret=1
            fi
        fi
    done
    if [[ $_switching_type == "disable" ]] && [[ $_ret -ne 0 ]]; then
        for package in ${packagelist[*]}
        do            
            # We need to mark only the package that failed as Bad. Not all packages
            # and also reenable switching only for those bad package
            sed -i "s/\<Good:$package\>/Bad:$package/" $rehearsal_dir/packages
            echo $package"|compute|ERROR:Failed to disable node switching for one or more primary packages." \
                                              >> $error_file
        done
    fi
    return $_ret
}

function halt_script
{
    switching_primary_package_on_target_nodes $rehearsal_id "enable"
    if (( $type_e_option == 1 )); then
        exit 2
    fi
    rm -f $tmp_dir/$date_prefix* > /dev/null 2>&1
    $SGSBIN/cmdo "rm -rf $rehearsal_dir" &> /dev/null
    $SGSBIN/cmdo "rm -f $start_reh_file" &> /dev/null
    exit 2
}

#############################
#       MAIN ROUTINE
#############################

typeset -i type_i_option=0
typeset -i type_e_option=0
typeset -i type_r_option=0

trap halt_script SIGTERM SIGINT

while [[ $# -ge 1 ]]
do
    key="$1"
    case $key in
    -i)
        type_i_option=1
        input_file="$2"
        if [[ "X$input_file" == "X" ]]; then
            echo "The Input file is missing"
            exit 1
        fi
        if [ ! -f $input_file ]; then
            echo "The Input file $input_file does not exist"
            exit 1
        fi
        shift
    ;;
    -e)
        type_e_option=1
    ;;
    -r)
        type_r_option=1
        rehearsal_id="$2"
        if [[ "X$rehearsal_id" == "X" ]]; then
            echo "Operation is missing"
        fi
        shift
    ;;
    *)
        echo "Unknown Option :: $key"
        exit 1
    ;;
    esac
    shift
done


if (( $type_e_option == 1 )); then
    switching_primary_package_on_target_nodes $rehearsal_id "enable"
    if [[ $? -ne 0 ]]; then
        exit 1
    else
        exit 0
    fi
fi

rehearsal_id=`grep "rehearsal_id" $input_file | cut -d ":" -f 2`
rehearsal_dir=${SGRUN}/$magic/$rehearsal_id
start_reh_file=${SGRUN}/$magic/.starting.$rehearsal_id
error_file=$rehearsal_dir/.prep_error_file
gr_name="genres_rehearsal_$rehearsal_id"

packagelist=(`grep "package:" $input_file | cut -d ":" -f 2`)
$SGSBIN/cmdo "mkdir -p $rehearsal_dir" > /dev/null
$SGSBIN/cmdo "touch $start_reh_file" > /dev/null
vfline_output=$rehearsal_dir/cmviewclvfline
cmeval_output=$rehearsal_dir/cmeval_output

packagelist=(`grep "package:" $input_file | cut -d ":" -f 2`)

for package in ${packagelist[*]}
do
    echo "Good:$package" >> $rehearsal_dir/packages
done    

cache_cmviewclvfline_output
if [[ $? -ne 0 ]]
then
    sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
    for package in ${packagelist[*]}
    do
        echo $package"|compute|ERROR:Failed to run cmviewcl" \
                                 >> $error_file
    done
    cleanup_before_exit 0
fi

tgt_node_list=""
# Get the owner nodes of the packages marked for rehearsal.
pri_pkg_list=(`grep "package:" $input_file | cut -d ":" -f 2`)
pri_node_list=""
for package in ${pri_pkg_list[*]}
do
    pri_node_list+=`awk -F= '/package:'$package'\|owner=/ {printf "%s \n", $2}' $vfline_output`
done
    
# Identify the target DC nodes and the eligible nodes to perform rehearsal
find_target_nodes_for_packages 
if [[ $? -ne 0 ]]
then
    cleanup_before_exit 0
fi

# perform cluster verification on primary packages
perform_configuration_check

packagelist=(`grep "Good:" $rehearsal_dir/packages | cut -d ":" -f 2`)
if [ -z $packagelist ]
then
    cleanup_before_exit 0
fi

# prepare configuration file for all packages
for package in ${packagelist[*]}
do
    make_rehearsal_package $package
done

# perform cmcheckconf on rehearsal packages
packagelist=(`grep "Good:" $rehearsal_dir/packages | cut -d ":" -f 2`)
if [ -z $packagelist ]
then
    cleanup_before_exit 0
fi
check_rehearsal_package

# Disable switching of primary packages
packagelist=(`grep "Good:" $rehearsal_dir/packages | cut -d ":" -f 2`)
if [ -z $packagelist ]
then
    cleanup_before_exit 0
fi

create_file_and_distribute_for_node_switching

switching_primary_package_on_target_nodes $rehearsal_id "disable"
if [[ $? -ne 0 ]]
then
    switching_primary_package_on_target_nodes $rehearsal_id "enable"
    cleanup_before_exit 0
fi

# Check if for any package for which rehearsal was triggered, is there any
# change in the owner node. If yes, stop the rehearsal.
index=0
_nodelist=(`printf '%s\n' ${pri_node_list[*]}`)
while [[ $index -lt ${#pri_pkg_list[*]} ]]
do
    _primary_node=`$SGSBIN/cmviewcl -fline | awk -F= '/package:'${pri_pkg_list[$index]}'\|owner=/ {print \$2}'`
    if [[ "$_primary_node" != "${_nodelist[$index]}" ]]; then
        sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
        for package in ${packagelist[*]}
        do
            echo $package"|compute|ERROR:Source node for package ${pri_pkg_list[$index]} has changed." \
                                 >> $error_file
        done
        switching_primary_package_on_target_nodes $rehearsal_id "enable"
        cleanup_before_exit 0
    fi
    ((index=index+1))
done

# Check if all the source and target nodes are in "up" state.
# if not, stop the rehearsal. 
index=0
final_node_list=("${tgt_node_list[@]}" "${pri_node_list[@]}")
_nodelist=(`printf '%s\n' ${final_node_list[*]} | sort -u`)
while [[ $index -lt ${#_nodelist[*]} ]]
do
    node_status=`$SGSBIN/cmviewcl -fline -n ${_nodelist[$index]} | grep "^status=" | cut -d "=" -f 2`
    if [[ "$node_status" != "up" ]]
    then
        sed -i "s/Good:/Bad:/" $rehearsal_dir/packages
        for package in ${packagelist[*]}
        do
            echo $package"|compute|ERROR:Either the source node or the target node is not in running state" \
                                 >> $error_file
        done
        switching_primary_package_on_target_nodes $rehearsal_id "enable"
        cleanup_before_exit 0
    fi
    ((index=index+1))
done

# Updating filelist with ascii files of Good packages only
# The same file can be used with cmapplyconf later
awk -F: '/Good:/ {print "'$rehearsal_dir'/"$2".ascii"}' \
    $rehearsal_dir/packages > $rehearsal_dir/filelist

cleanup_before_exit 0
