#!/bin/bash
#*****************************************************************************
# Copyright 2004-2007 Engenio Information Technologies, Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation,  version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#*****************************************************************************
#
#  Script %name:    mppUpdate26p %
#  Instance:        WIC_1
#  %version:        3 %
#  Description:        This script is used to update the entries in the device mapping file. Either
#  all or specific entries can be deleted or entries can be made to match what the driver can 
#  currently see.        
#  %created_by:        bmoger %
#  %date_created:    Thu Jan 31 20:21:30 2008 %

# Get all the options from the command line

. /opt/mpp/mppMkInitrdHelper;

while getopts cvd: op 2>/dev/null
do
    case "$op" in
        c) CLEAR_ALL=TRUE;;
        d) MODULE="$OPTARG";;
        v) VERBOSE=TRUE;;
        \?) echo "Usage: $0: [-c] [-v] [-d storageArrayName]"
            exit 2;;
    esac
done


DEVICE_MAP_FILE=/var/mpp/devicemapping
MPP_UTIL_FILE=/usr/sbin/mppUtil
TEMP_DEVICE_MAP_FILE=/tmp/devicemapping.$$
TEMP_DEVICE_LIST=/tmp/deviceList.$$
TEMP_MODULE_LIST=/tmp/moduleList.$$
UNAME=`uname -r`


#check if a module name has been given as input

if [ -n "$MODULE" ]
then
    if [ ! -e $DEVICE_MAP_FILE ]
    then
        echo "Error, No Devicemapping ($DEVICE_MAP_FILE) file found." >&2
        exit
    fi
    MODULE_FOUND=`/bin/grep ":$MODULE$" $DEVICE_MAP_FILE`
    # search for the module name in the device mapping file
    if [ -z "${MODULE_FOUND}" ]
    then
        echo "The module "$MODULE" is not present in the MPP persistence mapping list ($DEVICE_MAP_FILE). "
        exit
    else
        # Remove the entry from the device mapping file
        /bin/sed -n "/:$MODULE$/ !p"  $DEVICE_MAP_FILE >>  $TEMP_DEVICE_MAP_FILE
        /bin/mv -f $TEMP_DEVICE_MAP_FILE $DEVICE_MAP_FILE
        echo "The module "$MODULE" was removed from the MPP persistence mapping list ($DEVICE_MAP_FILE)."
        # do not exit here. Makeinitrd image and exit
    fi
elif [ -n "$CLEAR_ALL" ]
then
    if [ ! -e $DEVICE_MAP_FILE ]
    then
        echo "Error, No Devicemapping ($DEVICE_MAP_FILE) file found." >&2
        exit
    fi
    # Remove all the entries from the device mapping file
    /bin/sed '1,$ d' $DEVICE_MAP_FILE >> $TEMP_DEVICE_MAP_FILE
    /bin/mv -f $TEMP_DEVICE_MAP_FILE $DEVICE_MAP_FILE
    echo "All entries have been cleared from the MPP persistence mapping list ($DEVICE_MAP_FILE)."
    # do not exit here. Makeinitrd image and exit
else
    # If the -c or -d option have not been used, need to update the devicemapping file
    if [ ! -e $MPP_UTIL_FILE ]
    then
        echo "Error, No mppUtil ($MPP_UTIL_FILE) found." >&2
        exit
    fi

    # get the maximum virtual target Id supported by our driver
    MAX_VIRTUAL_TARGET_IDS=`$MPP_UTIL_FILE -m 2>/dev/null | cut -d= -f2`
    if [ -z $MAX_VIRTUAL_TARGET_IDS  ]
    then
        echo "Error, MaxVirtualTargets=0. Cannot update Devicemapping ($DEVICE_MAP_FILE) file." >&2
        exit
    fi

    if [ -e $DEVICE_MAP_FILE ]
    then
        /bin/cp $DEVICE_MAP_FILE $TEMP_DEVICE_LIST
    else
        /bin/touch $TEMP_DEVICE_LIST
    fi

    if [ ! -e $TEMP_MODULE_LIST ]
    then
        /bin/touch $TEMP_MODULE_LIST
    fi
   

    i=0
    # Loop through all the virtual target Ids
    while [ $i -lt "$MAX_VIRTUAL_TARGET_IDS" ]
    do
        # call mppUtil to see if there exists an array corresponding to this virtual target id  
        MODULE_NAME=`$MPP_UTIL_FILE -g $i 2>/dev/null`
    
        MODULE_PRESENT=`echo $MODULE_NAME | /bin/grep "WWN: "`
        if [ -z "$MODULE_PRESENT" ]
        then
           # echo "No array at this virtual target ID "
            i=`expr $i + 1`
            continue
    fi
        ARRAY_NOT_LABELED_TAG=`echo "$MODULE_NAME" | /bin/grep Array_Module_`
        if [ -n "$ARRAY_NOT_LABELED_TAG" ]
        then
            # The array doesn't have a defined storage array name
            # do nothing
            echo "The storage array corresponding to virtual target ID "$i" does not have"
        echo " a user assigned label."
        else
            # Parse the storage array name from the mppUtil info
            # and place in the module list temp file
            ARRAY_ENTRY=`echo "$MODULE_NAME" | /bin/sed  -n 's/^      ModuleName: //
                   s/SingleController: .*//p ' | /bin/sed 's/  *// '`
            echo "$i:$ARRAY_ENTRY"  >> $TEMP_MODULE_LIST
        fi
        i=`expr $i + 1`
    done

    if [ ! -e $DEVICE_MAP_FILE ]
    then
        /bin/cp $TEMP_MODULE_LIST $DEVICE_MAP_FILE
        echo "New Devicemapping ( $DEVICE_MAP_FILE ) file has been created with latest array entries."
    fi

    # Start nawk script to read storage array names we have discovered using mppUtil
    # and compare to the list already in devicemapping file 
    /bin/gawk -v numElements="$MAX_VIRTUAL_TARGET_IDS" -v tmpList="$TEMP_MODULE_LIST"  -v tmpFile="$TEMP_DEVICE_LIST" -v uname="$UNAME" -v devmapfile="$DEVICE_MAP_FILE" -v verbose="$VERBOSE" '
        BEGIN {
            # read elements from temporary storage array name file
            contentsChanged=0;
            FS=":"
            while ( getline < tmpList > 0) {
                arrayIndex[$1] = $2;
                arrayName[$2] = $1;
                #printf( "array name %d %s", $1, arrayIndex[$1] )
            }
        }
    
    
        END {
            for ( x in arrayIndex ) {
                contentsChanged=1;
                if ( arrayIndex[x] != "" )
                    printf ("%d:%s\n",x, arrayIndex[x])  >>tmpFile;
    
            }
        }
    
        {
            FS = ":"
            if ($1 >= numElements)  {
                # nothing to do as the virtual target id is off the range we support
                print "Found a virtual Target ID off limits."
                next;
            }
                # see if there is a match
            if ( $1 in arrayIndex || $2 in arrayName ) {
                # index is present in devicemapping file and in array 
                # found a match, get rid of entries in arrays
                if( $1 == arrayName[$2] && $2 == arrayIndex[$1] ) { 
                    print "Found match for array name",$1":"$2,arrayName[$2]":"arrayIndex[$1]"."
                    delete arrayIndex[arrayName[$2]] ;
                    delete arrayName[$2];
                    next;
                }
                else {
                    if ( $1 in arrayIndex) {
                        if ($2 !=  arrayIndex[$1] && arrayIndex[$1] != "")  {
                            if (verbose) {
                                print "INFO: The array name "arrayIndex[$1]" found corresponding "
                                print "to Virtual Target ID "$1" is different from that present "
                                print "in the Devicemapping (" devmapfile ") file.\n"
                            }
    
                            # delete entry from array so it is not added to devicemapping file
                            delete arrayName[arrayIndex[$1]];
                            delete arrayIndex[$1] ;
                            if ( $2 in arrayName) {
                                delete arrayIndex[arrayName[$2]] ;
                                delete arrayName[$2];
                            }
                            next; 
                        }
                    }
                    if ( $2 in arrayName) {
                        if ($1 != arrayName[$2] && arrayName[$2] != "" ) {
                            if (verbose) {
                                print "INFO: The array index "arrayName[$2]" found corresponding "
                                print "to array name "$2" is different from that present "
                                print "in the Devicemapping (" devmapfile ") file.\n"
                            }
    
                            # delete entry from array so it is not added to devicemapping file
                            delete arrayIndex[arrayName[$2]] ;
                            delete arrayName[$2];
                            if ( $1 in arrayIndex) {
                                delete arrayName[arrayIndex[$1]];
                                delete arrayIndex[$1] ;
                            }
                            next;
                        }
                    }
                }
    
            }
            else  {
                # This means the name is in the devicemapping file but mppUtil did not find the array  
                print "Spurious Entry "$1":"$2", found in Devicemapping (" devmapfile ") file."
                print "If it is not needed, delete this old entry for which the array was not found.\n"
                next;
            }
    
        } ' $TEMP_DEVICE_LIST 
    
    /bin/cp $TEMP_DEVICE_LIST $DEVICE_MAP_FILE
fi

identifyOSAndHBAVendor
checkHBAConfig ;
ModuleNameCheck;
createModDep;
makeMPPInitrdImage

/bin/rm -f $TEMP_DEVICE_LIST
/bin/rm -f $TEMP_MODULE_LIST
exit 0;
