#!/usr/bin/env bash
# set -x
# version 1.00

# Initialize the dir variable to the default directory which contains the discovery file and log file.
log_dir=/var/cpq

# Get time in seconds.
seconds=$(date +%s)

temp_component_log_file=component_log_"$seconds".log
temp_log_file1=temp1_log_"$seconds".log
temp_log_file2=temp2_log_"$seconds".log

temp_verbose_log_file1=temp1_verbose_log_"$seconds".log
temp_verbose_log_file2=temp2_verbose_log_"$seconds".log
temp_verbose_log_file3=temp3_verbose_log_"$seconds".log
temp_verbose_log_file4=temp4_verbose_log_"$seconds".log
temp_verbose_log_file5=temp5_verbose_log_"$seconds".log
temp_verbose_log_file6=temp6_verbose_log_"$seconds".log

#Variables
##########
silentflag=false
discovery_file=
discovery_flag=false
discovery_file_flag=false
downgrade_flag=false
rewrite_flag=false
force_flag=false
force_ignore_bad_dev_status_flag=false
log_dir_flag=false
usexml_flag=false
usexml_file_flag=false
usexml_file=
pd_controller_id=
pd_EID=
pd_drive_bay=
internal_disc_flag=false
non_storcli_drives=true
total_strocli_drives_flashed=0
total_strocli_drives_user_skipped=0
total_strocli_drives_comp_skipped=0
final_comp_opt_count=0
final_user_opt_count=0
final_comp_act_count=0
drive_found=false
#Command line Argument Check
############################
for arg in "$@"
do
    case $arg in
        -s|--silent)
            silentFlag=true
            #echo "silent flag enabled"
            shift
        ;;
        -f|--force)
            force_flag=true
            #echo "force flag enabled"
            shift
        ;;
        -g|--downgrade)
            downgrade_flag=true
            #echo "downgrade flag enabled"
            shift
        ;;
        -e|--rewrite)
            rewrite_flag=true
            #echo "rewrite flag enabled"
            shift
        ;;
        -z)
            internal_disc_flag=true
            discovery_flag=true
            discovery_file="$2"
            diccovery_file_flag=true
            shift
        ;;
        -d|--discovery)
            discovery_flag=true
            discovery_file="$2"
            diccovery_file_flag=true
            #echo "Discovery flag enabled"
            #echo "Discovery file Path: $discovery_file"
            shift
        ;;
        -u|--usexml)
            usexml_flag=true
            usexml_file="$2"
            usexml_file_flag=true
            #echo "Use XML flage enabled"
            #echo "Use XML file path: $usexml_file"
            shift
        ;;
        --default)
          echo "Invalid argument: $1"
        ;;
    esac
done



# Initialize the return value to "Installation not attempted".
ret_value=3

createTimeStamp() {
  timestamp=$(date +"%b %-d %T")
}

createSupplementalLogFile() {
  # Created an alternate log file if the primary log file cannot be located.
  # Exit with a status of "Installation not attempted, unmet dependence or tool failure".
  component_log=/var/cpq/Component.log
  echo Program exiting...
  echo See log at: $component_log
  createTimeStamp
  printf "[ $timestamp ] Error: The Smart Component log file could not be found.\n""[ $timestamp ] Program exiting...\n" > $component_log
}

# Write information to stdout and the log file.
output() {
  if [[ ! $1 =~ "Warning: No drives are connected to the controller in slot" && ! $1 == "Warning: The Smart Component did not find any supported hard drives." ]]; then
    echo $1
  fi
  if [[ $1 =~ "Warning:" || $1 =~ "Error:" ]]; then
    warning_message=$(echo $1 | sed 's/Warning: //')
    echo $warning_message >> ${temp_log_file1}
    printf "[ $timestamp ] $warning_message\n" >> ${temp_verbose_log_file4}
  fi
  if [[ $1 =~ "Error:" ]]; then
    if [[ ! -s ${temp_verbose_log_file4} ]]; then
      printf "Program exiting...\n" >> ${temp_log_file1}
      printf "[ $timestamp ] Program exiting...\n" >> ${temp_verbose_log_file4}
    else
      createSupplementalLogFile
    fi
    exit 6
  fi
}

# This function checks to see if the file is readable.
isFileReadable() {
  if [[ ! -r $1 ]]; then
    output "Error: unable to read $2 file."
  fi
}

isFileWritable() {
  if [[ ! -w $1 ]]; then
    output "Error: $2 file is not writable."
  fi
}

getXMLFileName() {
  # Initialize the variable xml_file to the Smart Component's XML file name.
  xml_file=$(ls $PWD | grep -e CP[0-9]*.xml)
  if [ -z $xml_file ]; then
    output "Error: No Smart Component XML file found."
  fi
  isFileReadable $xml_file "Smart Component XML"
}

getFirmwareVersionFromXML() {
  # Read from the smart component's xml file and obtain the firmware version.
  xml_file_firmware_version=$(grep 'version value=' "$xml_file" | head -1 | awk '{print $2}' | sed 's/value=//' | sed 's/"//g')
  if [ -z "$xml_file_firmware_version" ]; then
    output "Warning: Unable to obtain the drive firmware version from the $xml_file file."
  fi
}

getFirmwareImageFileNameFromPayloadFile() {
  # Read from the smart component's firmware image filename from the payload.json file.
  firmware_binary=$(grep -o -E "\"FileName\":(.*)" payload.json | sed 's/FileName//' | sed 's/"//g' | sed 's/://' | sed 's/,//' | sed 's/ //g' | head -1)
  #echo "firmware Binary name:$firmware_binary"
  # THE 3 FOLLOWING STATEMENTS SHOULD BE REMOVED IN THE FINAL VERSION!!!!!!!!!!!!!!!!!!!!!!!
  # Remove the ".fw" from the end of the firmware image's file name.
  #firmware_binary=${firmware_binary%.*}
  # Remove the ".REL" from the end of the firmware image's file name.
  #firmware_binary=${firmware_binary%.*}
  # Add the lowercase ".rel" file extension.
  #firmware_binary=${firmware_binary}.rel
  #echo "firmware Binary name:$firmware_binary"
}

# This function checks to see if the file exists.
doesFileExist() {
  if [ ! -f $1 ]; then
    output "Error: The $2 file is missing from the current Smart Component."
  fi
}

# Check to see if a directory exists.
doesDirectoryExist() {
  if [ ! -d $1 ]; then
    output "Error: The $1 directory does not exist."
  fi
}

#Copying shasta logs into temp logs for manipulation
doesDirectoryExist ${log_dir}
log_file_name=$(ls -t ${log_dir} | grep -e "$xml_prefix"_[0-9][0-9][0-9][0-9]_ | head -n1)
verbose_log_file=$log_dir/$log_file_name
if [ ! -f $verbose_log_file ]; then
  # If the specified log file cannot be found, create a supplemental log file and exit.
  createSupplementalLogFile
  exit 6
fi
isFileReadable ${verbose_log_file} "Smart Component verbose log"
# Initialize the component_log_file to the Smart Component's Component.log file
component_log_file=${log_dir}/Component.log
# Check to see if the Component log file is readable.
isFileReadable ${component_log_file} "Smart Component log"
# Make a temporary copy of the Component Log file, this is needed because the OS will not allow file appends.
cp ${component_log_file} ${temp_component_log_file}
isFileReadable ${temp_component_log_file} "Temporary Smart Component log"

determineCourseOfAction() {
  if [ "$drive_firmware_version" \< "$xml_file_firmware_version" ]; then
     perform_action="upgrade"
   elif [ "$drive_firmware_version" \> "$xml_file_firmware_version" ]; then
     perform_action="downgrade"
   else
     perform_action="rewrite"
   fi
}

printDivider() {
  printf "[ $timestamp ] ===========================================================\n" >> ${temp_verbose_log_file4}
}

componentLogDriveFlashInfo() {
  # Write information to the temporary Component Log file.
  printf "Component Version:     $xml_file_firmware_version\n" >> ${temp_log_file1}
  printf "Device:          Drive $drive_location ($controller_name in Slot $controller_slot_number)\n" >> ${temp_log_file1}
  printf "Image Version:         $drive_firmware_version\n" >> ${temp_log_file1}
}

LogDriveInfo() {
  # Write Drives information found in the system  to the Verbose Log file.
  createTimeStamp
  printDivider
  printf "[ $timestamp ] $1    Drive: $drive_location ($controller_name in Slot $controller_slot_number)\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tEID: $EID\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tModel: $drive_model_name\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tType: $drive_protocol\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tFirmware Revision: $drive_firmware_version\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tDrive Serial Number: $drive_serial_number\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tDrive State: $drive_state\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tController Name: $controller_name\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tController Serial Number: $controller_serial_number\n" >> ${temp_verbose_log_file4}
  printDivider
}

verboseLogDriveFlashInfo() {
  createTimeStamp
  printDivider
  printf "[ $timestamp ] $1 device: Drive $drive_location ($controller_name in Slot $controller_slot_number)\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tID:            AC:$controller_serial_number,PD:$physical_drive_id\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tWWID:          $wwid\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tModel:         $drive_model_name\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tType:          $drive_protocol\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tFirmware:      $drive_firmware_version\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tSerial Number: $drive_serial_number\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tStatus:        $drive_status_scs\n" >> ${temp_verbose_log_file4}
  printf "[ $timestamp ] \tController:    $controller_name in Slot $controller_slot_number\n" >> ${temp_verbose_log_file4}
  if [[ ! -n "${2/[ ]*\n/}" ]]; then
    printf "[ $timestamp ]\n" >> ${temp_verbose_log_file4}
  else
    printf "[ $timestamp ] $flash_status_flag\n" >> ${temp_verbose_log_file4}
  fi
  printDivider
}

flashDrive() {
  echo "Flashing Drive $drive_location ($controller_name in $controller_slot_number) [ $drive_firmware_version -> $xml_file_firmware_version ]"
  echo This could take several minutes...
  flash_execution=true
  createTimeStamp
  host_name=$(uname -n)
  # Report the drive location in the messages file.
  echo "$timestamp $host_name setup: Location of Drive $drive_location ($controller_name in $controller_slot_number)" >> /var/log/messages
  # Report that a drive is having its firmware updated/modified.
  echo "$timestamp $host_name setup: Updating $drive_model_name drive Model from current firmware $drive_firmware_version to $xml_file_firmware_version firmware version" >> /var/log/messages
  # Report in the temporary Component Log file that the drive flash process has just begun.
  echo "$timestamp Begin flash" >> ${temp_log_file1}
  # Report the drive model name in the temporary Component Log file.
  echo "Model: $drive_model_name" >> ${temp_log_file1}
  # Report the drive location in the temporary Component Log file.
  echo "Location: Drive $drive_location ($controller_name in $controller_slot_number)" >> ${temp_log_file1}
  # Report what the drive is being flashed to or from in the temporary Component Log file.
  echo "Current firmware $drive_firmware_version flashing to $xml_file_firmware_version" >> ${temp_log_file1}
  # Flash the drive and capture its flash status.
  if [[ $usexml_flag == "true" ]]; then
    flash_status=$("$storcli" /c$1/e$2/s$3 download src=$4)
    #echo "Flash Status"
    #echo $flash_status
  else
    flash_status=$("$storcli" /c"$controller_id"/e"$EID"/s"$drive_bay" download src=$1)
  fi
}

printReasonForNotFlashing() {
  printf "[ $timestamp ] The following device will not be updated\n" >>  ${temp_verbose_log_file3}
  printf "The following device will not be updated\n" >>  ${temp_log_file1}
  printf "[ $timestamp ] * Drive $drive_location ($controller_name in Slot $controller_slot_number)\n" >> ${temp_verbose_log_file3}
  printf "* Drive $drive_location ($controller_name in Slot $controller_slot_number)\n" >> ${temp_log_file1}
  printf "[ $timestamp ] Reason:\n" >> ${temp_verbose_log_file3}
  printf "Reason:\n" >> ${temp_log_file1}
  printf "[ $timestamp ] Device(s) are up-to-date and can only be updated with --force or $1\n" >> ${temp_verbose_log_file3}
  printf "Device(s) are up-to-date and can only be updated with --force or $1\n" >> ${temp_log_file1}
  printf "[ $timestamp ]\n" >> ${temp_verbose_log_file3}
}

# Flash the drive.
flash() {
   getFirmwareVersionFromXML
   # Remove unwanted characters from both the beginning of the firmware version string and trailing characters.
   firmware_filename=$(echo $1 | sed 's@.*/@@')
   # Deside whether to do a rewrite, upgrade or downgrade.
   determineCourseOfAction
   if [[ $drive_status = "UGood" || $drive_status = "JBOD" ]]; then
     drive_status_scs=ATTR_VALUE_STATUS_OK
   else
     drive_status_scs=ATTR_VALUE_STATUS_FAILURE
   fi
   verboseLogDriveFlashInfo "Supported"
   flash_flag="failed"
   flash_status="unknown"
   # Perform the firmware flash.
   flash_execution=false
   if [[ "true" == $usexml_flag && "true" == $force_flag ]]; then
     flashDrive $1 $2 $3 $4
   elif [[ "true" == $usexml_flag && "true" == $downgrade_flag &&  "downgrade" == $perform_action ]]; then
     flashDrive  $1 $2 $3 $4
   elif [[ "true" == $usexml_flag && "true" == $rewrite_flag &&  "rewrite" == $perform_action ]]; then
     flashDrive  $1 $2 $3 $4
   elif [[ "true" == $usexml_flag && "false" == $downgrade_flag &&  "downgrade" == $perform_action &&  "false" == $force_flag ]]; then
     total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
     printReasonForNotFlashing "--downgrade"
   elif [[ "true" == $usexml_flag && "true" == $rewrite_flag && "downgrade" == $perform_action ]]; then
     total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
     printReasonForNotFlashing "--downgrade"
   elif [[ "true" == $usexml_flag && "false" == $force_flag && "false" == $rewrite_flag && "rewrite" == $perform_action ]]; then
     total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
     printReasonForNotFlashing "--rewrite"
     ret_value=2
   elif [[ "true" == $usexml_flag && "upgrade" == $perform_action && "true" == $rewrite_flag ]]; then
     total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
     printReasonForNotFlashing "--upgrade"
   elif [[ "true" == $usexml_flag && "upgrade" == $perform_action && "false" == $rewrite_flag ]]; then
     flashDrive  $1 $2 $3 $4
   fi
   
   # Set variable to true in order to verify that at least one supported hard drive was found.
   at_least_one_drive_found=true
   if [[ "true" == $flash_execution ]]; then
     # Verify that the variable is not empty.
     if [[ -z $flash_status ]]; then
       output "Error: Could not obtain the flash results for $target"
     fi
     for status in $flash_status
     do
       if [[ $status == "Success" ]]; then
         flash_flag="succeeded"
       fi
     done
     if [[ $flash_flag =~ "succeeded" ]]; then
       counter=0
       total_strocli_drives_flashed=`expr ${total_strocli_drives_flashed} + 1`
       while [[ "$drive_firmware_version" != "$xml_file_firmware_version" && $counter -ne 10 ]]
       do
         # Update the drive information (including the drive firmware version)
         getAllDriveInfo
         getDriveFirmwareVersion
         counter=$(($counter + 1))
         sleep 1
       done
       echo "$timestamp Complete flash, status Success" >> ${temp_log_file1}
       if [ "$drive_firmware_version" != "$xml_file_firmware_version" ]; then
         flash_status_flag="Deferred flashes will be performed on next system reboot"
         # Installation successful, however a reboot is required.
         ret_value=1
       else
         flash_status_flag="NDU flashing completed successfully"
         # Installation successful, no reboot required.
         ret_value=0
       fi
       echo $flash_status_flag
       if [[ "true" = $force_flag || "true" = $downgrade_flag && "downgrade" = $perform_action ]]; then
         performed_action="downgraded"
       elif [[ "true" = $force_flag || "true" = $rewrite_flag && "rewrite" = $perform_action ]]; then
         performed_action="re-wrote"
       elif [[ "upgrade" = $perform_action ]]; then
         performed_action="upgraded"
       fi
     else
       total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
       # Write status to the temporary Component Log file.
       echo "$timestamp Complete flash, status Failed" >> ${temp_log_file1}
       # Write status to the Verbose Log file.
       output "Warning: Failed to flash $target"
       # Installation attempted, but failed.
       ret_value=7
     fi
     # Report to the temporary Component Log file whether an NDU or deferred flash has occurred.
     echo "$flash_status_flag" >> ${temp_log_file1}
     # Report to the Verbose Log file whether an NDU or deferred flash has occurred.
     verboseLogDriveFlashInfo "Flashing" $flash_status_flag
   fi
}

# Get controller info.
getControllerInfo() {
  controller_info=$("$storcli" /c"$controller_id" show)
}

# Get controller name.
getControllerName() {
  controller_name=$(echo "$controller_info" | grep 'Product Name =' | sed 's/Product Name = //')
}

# Get controller slot number.
getControllerSlotNumber() {
  controller_slot_number=$(echo "$controller_info" | grep 'PCI Slot Number =' | sed 's/PCI Slot Number = //')
}

getCtrlSerialNumber() {
  controller_serial_number=$(echo "$controller_info" | grep -e '^Serial Number =' | sed 's/Serial Number = //')
}

# Get detailed drive information.
getAllDriveInfo() {
  if [[ $usexml_flag == "true" ]]; then
    drive_info_all=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show all)
  else
    drive_info_all=$("$storcli" /c"$controller_id"/e"$EID"/s"$drive_bay" show all)
  fi
}

# Get World Wide ID for the hard drive.
getWWID() {
  wwid=$(echo "$drive_info_all" | grep 'WWN =' | sed 's/WWN = //')
}

#Trims last 4 char from actual firmware version
firmwareTrim(){
        temp=$1
        len="${#temp}"
        if [[ len -gt 4 ]]; then
          pos=`expr $len - 4`
          version="${temp:$pos}"
          drive_firmware_version=$version
        else
          drive_firmware_version=$temp
        fi
}
# Get the target drive's firmware version.
getDriveFirmwareVersion() {
  drive_firmware=$(echo "$drive_info_all" | grep 'Firmware Revision =' | awk '{print $4}')
  #Trimming last four digit firmware version in standard format
  firmwareTrim "$drive_firmware"
  # Verify that the variable is not empty.
  if [ -z $drive_firmware_version ]; then
    output "Error: Could not obtain the current firmware version for the drive at $drive_address"
  fi
}
getDriveInfo(){
  if [[ $usexml_flag == "true" ]]; then
    drive_info=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show | grep [0-9] | grep -v '=')
  else
    drive_info=$("$storcli" /c"$controller_id"/e"$EID"/s"$drive_bay" show | grep [0-9] | grep -v '=')
  fi
}

getDriveSerialNumber() {
   if [[ $usexml_flag == "true" ]]; then
     drive_serial_number=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show all | grep 'SN = ' | sed 's/SN = //' | sed 's/ //g')
   else
     drive_serial_number=$("$storcli" /c"$controller_id"/e"$EID"/s"$drive_bay" show all | grep 'SN = ' | sed 's/SN = //' | sed 's/ //g')
   fi  
}

getDriveState() {
  drive_state=$(echo $drive_info | awk '{print $3}')
}

getDriveProtocol() {
  drive_protocol=$(echo "$drive_info" | awk '{print $7}')
}

getSupportedDriveModels() {
  supported_drives=$(grep 'alt_name_xlate lang="en"' "$xml_file" | head -1 | awk -F">" '{print $2}' | awk -F"<" '{print $1}')
  if [ -z "$supported_drives" ]; then
    output "Warning: Could not find any supported drives attached to controller in slot $controller_slot_number on port $port_id"
  fi
  # Get a string containing the supported drive models from the xml file.
  supported_drive_models=$(echo $supported_drives | sed 's/and/ /gI' | sed 's/drives/ /gI' | sed 's/\,/ /g')
  if [ -z "$supported_drive_models" ]; then
    output "Warning: Could not find any supported drives models attached to controller in slot $controller_slot_number on port $port_id"
  fi
}

getEIDs() {
  attached_EIDS=$("$storcli" /c"$controller_id"/eall show | grep [0-9] | grep -v '=' | awk '{print $1}')
  # Verify that the variable is not empty.
  if [ -z "$attached_EIDS" ]; then
    output "Warning: No drives are connected to the controller in slot $controller_slot_number"
    no_drive_found=true
  fi
}

getPortID() {
  port_id=$("$storcli" /c"$controller_id"/e"$EID" show | grep [0-9] | grep -v '=' | awk '{print $12}')
  # Verify that the variable is not empty.
  if [ -z "$port_id" ]; then
    output "Error: Could not acquire the port id which is connected to EID $EID on the controller in slot $controller_slot_number"
  fi
}

getDriveBayIDs() {
  drive_bay_numbers=$("$storcli" /c"$controller_id"/e"$EID"/sall show | grep [0-9] | grep -v '=' | awk '{print $1}')
  # Verify that the variable is not empty.
  if [ -z "$drive_bay_numbers" ]; then
    output "Error: Could not obtain a list of attached drives for port $port_id on controller in slot $controller_slot_number"
  fi
  drive_bay_ids=
  # Find the drive bay number for each drive under the currently selected EID.
  for drive_id in $drive_bay_numbers
  do
    temp=$(echo $drive_id | sed 's/.*://')
    drive_bay_ids=$temp" "$drive_bay_ids
  done
  if [ -z "$drive_bay_ids" ]; then
    output "Error: Could not find any drive bay numbers for controller in slot $controller_slot_number on port $port_id"
  fi
}

getBoxNumber() {
  box_field=$(echo "$drive_info_all" | grep 'Box =')
  box_number=$(echo $box_field | sed 's/Box = //')
  # Verify that the variable is not empty.
  if [ -z "$box_number" ]; then
    output "Error: Could not obtain the Box number for the box connected to port $port_id for the controller in slot $controller_slot_number"
  fi
}

getFwVerFromDiscoveryXML() {
 discovery_drive_fw_version=$(cat $discovery_file | grep -e '^\s*<version value=' | head -1)
}

getProtocolFromDiscoveryXML() {
 discovery_drive_protocol=$(cat $discovery_file | grep -e '^\s*<type value=' | head -1 | sed 's/<type value="firmware:sd://' | sed 's/" \/>//' | tr -d '[:space:]')
}

getTakesEffectFromDiscoveryXML() {
 discovery_when_takes_effect=$(cat $discovery_file | grep -e '^\s*<takes_effect value=' | head -1 | sed 's/<takes_effect value="//' | sed 's/" \/>//' | tr -d '[:space:]')
}

getDriveModelName() {
  drive_model_name=$(echo "$drive_info" | awk '{print $12}')
}

getDurationValue() {
  # This while loop locates and captures the duration value from the discovery XML file.
  while read -r a_line_from_discovery_file
  do
    if [[ $a_line_from_discovery_file =~ "<duration value=" ]]; then
      duration_value=$(echo $a_line_from_discovery_file | sed 's/<duration value=//' | sed 's/"//g' | sed 's/>//g' | sed 's/\///g' | sed 's/ //g')
      break
    fi
  done < $discovery_file
}

buildDiscoveryXML() {
  # Create an array that will contain a minimal amount of information for each supported drive.
  driveArray=()
  # Initialize the discovery_file variable to the actual discovery XML file.
  # If the discovery XML file is empty, exit.
  if [ -z $discovery_file ]; then
    output "Error: The $discovery_file does not contain any data."
  fi
  # Remove the last 2 lines of the discovery XML file.
  sed -i '$ d' $discovery_file
  sed -i '$ d' $discovery_file
  # Find the number of supported controllers in the server.
  getNumberOfControllers
  # The following while loop iterates over each supported attached controller.
  controller_id=0
  while [ "$controller_id" -le $(($num_controllers-1)) ]
  do
    physical_drive_id=0
    # Get the currently selected controller's information.
    getControllerInfo
    # Get the currently selected controller name.
    getControllerName
    # Get the currently selected controller slot number.
    getControllerSlotNumber
    # Get a list of the EIDs that are connected to the currently selected controller.
    getEIDs
    # Initialize the no_drive_found_flag to false, this flag is used to report if a controller has no drives connencted.
    no_drive_found_flag=false
    # The following for loop iterates over each EID that is connected to the currently selected controller.
    for EID in $attached_EIDS
    do
      # Get the Port ID.
      getPortID
      # Get a list of the drive bay IDs for currently have EID installed.
      getDriveBayIDs
      # The following loop iterates over each drive bay that contains a drive under the currently selected EID.
      for drive_bay in $drive_bay_ids
      do
        # Get all of the details for the currently selected hard drive.
        getAllDriveInfo
        # Get the Box Number of the box that is connected to the currently selected port on the currently selected controller.
        getBoxNumber
        drive_location="$port_id:$box_number:$drive_bay"
        drive_address="(Controller-Slot:$controller_slot_number Port:$port_id Box:$box_number Bay:$drive_bay)"
        # Get all of the informatoin for the currently selected hard drive.
        getDriveInfo
        # Verify that the variable is not empty.
        if [ -z "$drive_info" ]; then
          output "Error: Could not obtain information for the drive at $drive_address"
          continue
        fi
        # Continue looping through the remainder of the drive bays, if the target drive is not found.
        if [[ $drive_info =~ "Drive not found" ]]; then
          continue
        fi
        # Get the drive model name from the drive itself.
        getDriveModelName
        # Get the version of firmware that is currently on the drive.
        getDriveFirmwareVersion
        # Read from the smart component's xml file and obtain the supported drive models.
        getSupportedDriveModels
        # Get the currently selected controller's serial number
        getCtrlSerialNumber
        # Get the currently selected drive serial number
        getDriveSerialNumber
        # Get the currently selected drive protocol : SAS, SATA, NVME
        getDriveProtocol
        # Get the currently selected drive state : JBOD, UGood
        getDriveState
        #Log drives information to the Verbose Log file
        LogDriveInfo
        if [[ $supported_drive_models =~ $drive_model_name ]]; then
          # Log firmware and drive information to the Component Log file
          componentLogDriveFlashInfo
          # Get the currently selected controller's information.
          getControllerInfo
          # Get the currently selected controller's serial number.
          getCtrlSerialNumber
          # Get the hard drive firmware version from the discovery XML file.
          getFwVerFromDiscoveryXML
          # Find out when the flash takes effect.
          getTakesEffectFromDiscoveryXML
          # Get the drive's protocol (i.e. SAS/SATA) from the discovery XML file.
          getProtocolFromDiscoveryXML
          # Add the currently targeted drive to the array of drives.
          driveArray+=("* Drive $drive_location ($controller_name in Slot $controller_slot_number)")
          line_counter=1
	  temp_drive_id="$controller_id:$EID:$drive_bay"
          
          if [[ $internal_disc_flag == "false" ]]; then #Actual Discovery
            while read -r a_line_from_discovery_file
            do
              if [[ $a_line_from_discovery_file =~ "/user_options" ]]; then
                last_line=$(tail -n1 $discovery_file)
                if [ "</user_options>" = $last_line ]; then
                  # Add the <devices> tag to the discovery XML file, if it is missing.
                  printf "\t<devices>\n" >> $discovery_file
                fi
                while read -r xml_tag_line
                do
                  # If the drive is SATA, change the discovery XML's type value to SATA.
                  if [ "SAS" != "$discovery_drive_protocol" ]; then
                    if [[ $xml_tag_line =~ "<type value=" ]]; then
                      xml_tag_line="<type value=\"SATA\" />"
                    fi
                  fi
                  # Modify the discovery XML's Takes Effect tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<takes_effect value=" ]]; then
                    xml_tag_line=("<takes_effect value=\"$discovery_when_takes_effect\" />")
                  fi
                  # Modify the discovery XML's Smart Component hard drive firmware ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<version value=" ]]; then
                    xml_tag_line=("<version value=\"$xml_file_firmware_version\" />")
                  fi
                  # Modify the discovery XML's device ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<device id=" ]]; then
                    xml_tag_line=("<device id=\"AC:$controller_serial_number,PD:$temp_drive_id\">")
                  fi
                  # Modify the discovery XML's controller ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<controller_id value=" ]]; then
                    xml_tag_line=("<controller_id value=\"AC:$controller_serial_number\" />")
                  fi
                  # Modify the discovery XML's drive Model Name tag to match the
                  # drive model name of the currently targeted drive.
                  if [[ $xml_tag_line =~ "<product_id value=" ]]; then
                    xml_tag_line=("<product_id value=\"$drive_model_name\" />")
                  fi
                  # Modify the discovery XML's hard drive firmware version tag
                  # so that it matches the firmware version that is currently on the target drive.
                  if [[ $xml_tag_line =~ "<active_version value=" ]]; then
                    xml_tag_line=("<active_version value=\"$drive_firmware_version\" />")
                  fi
                  # Deside whether to do a rewrite, upgrade or downgrade.
                  determineCourseOfAction
                  # Modify the discovery XML's flash action tag so that the discovery XML
                  # file will correctly reflect whether HPSUM should perform a rewrite, upgrade or downgrade.
                  if [[ $xml_tag_line =~ "<action value=" ]]; then
                    xml_tag_line=("<action value=\"$perform_action\" />")
                  fi
                  # If no drives are found in the discovery XML file, use the default duration value.
                  duration_value="unknown"
                  getDurationValue
                  if [ "unknown" != $duration_value ]; then
                    # Modify the discovery XML's duration value tag so that the discovery XML
                    # file will correctly reflect the duration value.
                    if [[ $xml_tag_line =~ "<duration value=" ]]; then
                      xml_tag_line=("<duration value=\"$duration_value\" />")
                    fi
                  fi
                  # Insert the currently selected drive's information into the discovery XML file.
                  if [[ 1 == $line_counter || 14 == $line_counter ]]; then
                    printf "\t\t$xml_tag_line\n" >> $discovery_file
                  elif [[ 1 -lt $line_counter && $line_counter -lt 5 || 13 == $line_counter ]]; then
                    printf "\t\t\t$xml_tag_line\n" >> $discovery_file
                  elif [[ 4 -lt $line_counter && $line_counter -lt 13 ]]; then
                    printf "\t\t\t\t$xml_tag_line\n" >> $discovery_file
                  fi
                  line_counter=$(($line_counter + 1))
                done < <(cat << DRIVEINFO
                  <device id="AC:539369777,PD:6">
                          <controller_id value="AC:539369777" />
                          <product_id value="MB2000FBZPN" />
                          <fw_item>
                                  <type value="SAS" />
                                  <firmware_id value="" />
                                  <takes_effect value="deferred" />
                                  <version value="HPG4" />
                                  <active_version value="HPG4" />
                                  <action value="downgrade" />
                                  <duration value="9" />
                                  <shared value="no" />
                          </fw_item>
                  </device>
DRIVEINFO
)
              fi
            done < $discovery_file
          else # internal Discovery 
            while read -r a_line_from_discovery_file
            do
              if [[ $a_line_from_discovery_file =~ "/user_options" ]]; then
                last_line=$(tail -n1 $discovery_file)
                if [ "</user_options>" = $last_line ]; then
                  # Add the <devices> tag to the discovery XML file, if it is missing.
                  printf "\t<devices>\n" >> $discovery_file
                fi
                while read -r xml_tag_line
                do
                  # If the drive is SATA, change the discovery XML's type value to SATA.
                  if [ "SAS" != "$discovery_drive_protocol" ]; then
                    if [[ $xml_tag_line =~ "<type value=" ]]; then
                      xml_tag_line="<type value=\"SATA\" />"
                    fi
                  fi
                  # Modify the discovery XML's Takes Effect tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<takes_effect value=" ]]; then
                    xml_tag_line=("<takes_effect value=\"$discovery_when_takes_effect\" />")
                  fi
                  # Modify the discovery XML's Smart Component hard drive firmware ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<version value=" ]]; then
                    xml_tag_line=("<version value=\"$xml_file_firmware_version\" />")
                  fi
                  # Modify the discovery XML's device ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<device id=" ]]; then
                    xml_tag_line=("<device id=\"AC:$controller_serial_number,PD:$controller_id\">")
                  fi
                  # Modify the discovery XML's controller ID tag for the currently selected drive.
                  if [[ $xml_tag_line =~ "<controller_id value=" ]]; then
                    xml_tag_line=("<controller_id value=\"AC:$controller_serial_number\" />")
                  fi
                  # Modify the discovery XML's drive Model Name tag to match the
                  # drive model name of the currently targeted drive.
                  if [[ $xml_tag_line =~ "<product_id value=" ]]; then
                    xml_tag_line=("<product_id value=\"$drive_model_name\" />")
                  fi
                  # Modify the discovery XML's Physical location tag to match the
                  if [[ $xml_tag_line =~ "<physical_location value=" ]]; then
                    xml_tag_line=("<physical_location value=\"$temp_drive_id\" />")
                  fi
                  # Modify the discovery XML's drive Serial Number tag to match the
                  if [[ $xml_tag_line =~ "<drive_serialnumber value=" ]]; then
                    xml_tag_line=("<drive_serialnumber value=\"$drive_serial_number\" />")
                  fi
                  # Modify the discovery XML's hard drive firmware version tag
                  # so that it matches the firmware version that is currently on the target drive.
                  if [[ $xml_tag_line =~ "<active_version value=" ]]; then
                    xml_tag_line=("<active_version value=\"$drive_firmware_version\" />")
                  fi
                  # Deside whether to do a rewrite, upgrade or downgrade.
                  determineCourseOfAction
                  # Modify the discovery XML's flash action tag so that the discovery XML
                  # file will correctly reflect whether HPSUM should perform a rewrite, upgrade or downgrade.
                  if [[ $xml_tag_line =~ "<action value=" ]]; then
                    xml_tag_line=("<action value=\"$perform_action\" />")
                  fi
                  # If no drives are found in the discovery XML file, use the default duration value.
                  duration_value="unknown"
                  getDurationValue
                  if [ "unknown" != $duration_value ]; then
                    # Modify the discovery XML's duration value tag so that the discovery XML
                    # file will correctly reflect the duration value.
                    if [[ $xml_tag_line =~ "<duration value=" ]]; then
                      xml_tag_line=("<duration value=\"$duration_value\" />")
                    fi
                  fi
                  # Insert the currently selected drive's information into the discovery XML file.
                  if [[ 1 == $line_counter || 16 == $line_counter ]]; then
                    printf "\t\t$xml_tag_line\n" >> $discovery_file
                  elif [[ 1 -lt $line_counter && $line_counter -lt 7|| 15 == $line_counter ]]; then
                    printf "\t\t\t$xml_tag_line\n" >> $discovery_file
                  elif [[ 6 -lt $line_counter && $line_counter -lt 15 ]]; then
                    printf "\t\t\t\t$xml_tag_line\n" >> $discovery_file
                  fi
                  line_counter=$(($line_counter + 1))
                done < <(cat << DRIVEINFO
                  <device id="AC:539369777,PD:6">
                          <controller_id value="AC:539369777" />
                          <product_id value="MB2000FBZPN" />
                          <physical_location value="0:222:0" />
                          <drive_serialnumber value="41V0385X" />
                          <fw_item>
                                  <type value="SAS" />
                                  <firmware_id value="" />
                                  <takes_effect value="deferred" />
                                  <version value="HPG4" />
                                  <active_version value="HPG4" />
                                  <action value="downgrade" />
                                  <duration value="9" />
                                  <shared value="no" />
                          </fw_item>
                  </device>
DRIVEINFO
)
              fi
            done < $discovery_file
            fi
          physical_drive_id=$(($physical_drive_id + 1))
        fi
      done
    done
    controller_id=$(($controller_id + 1))
  done
  printf "\t</devices>\n" >> $discovery_file
  printf "</hp_rom_discovery>\n" >> $discovery_file
}

# Verify that the volume (if any) and drive are in a good state and then Flash the drive.
flashUserSelectionDrives() {
  controller_id=0
  # This loop locates supported storcli hard drives.
  while read -r a_line_from_xml_file
  do
    if [[ $a_line_from_xml_file =~ "PD:" ]]; then
        pd_serial_number=$(echo $a_line_from_xml_file | sed 's/<device id="AC://' | sed 's/,.*//' | sed 's/<device id=AC://')
        pd_controller_id=$(echo $a_line_from_xml_file | sed 's/.*,//' | sed 's/>//' | sed 's/PD://' | sed 's/"//' | cut -d : -f 1)
        pd_EID=$(echo $a_line_from_xml_file | sed 's/.*,//' | sed 's/>//' | sed 's/PD://' | sed 's/"//' | cut -d : -f 2)
        pd_drive_bay=$(echo $a_line_from_xml_file | sed 's/.*,//' | sed 's/>//' | sed 's/PD://' | sed 's/"//' | cut -d : -f 3)
    fi
    if [[ $a_line_from_xml_file =~ "physical_location" ]]; then
        pd_controller_id=$(echo $a_line_from_xml_file | sed 's/<physical_location value="//' | sed 's/<physical_location value=//' | sed 's/\/>//' | sed 's/"//' | cut -d : -f 1)
        pd_EID=$(echo $a_line_from_xml_file | sed 's/<physical_location value="//' | sed 's/<physical_location value=//' | sed 's/\/>//' | sed 's/"//' | cut -d : -f 2)
        pd_drive_bay=$(echo $a_line_from_xml_file | sed 's/<physical_location value="//' | sed 's/<physical_location value=//' | sed 's/\/>//' | sed 's/"//' | cut -d : -f 3)
    elif [[ $a_line_from_xml_file =~ "action value=" ]]; then
      action_item=$(echo $a_line_from_xml_file | sed 's/<action value=//' | sed 's/ //g' | sed 's/\/>//' | sed 's/"//g' | sed 's/"//g' )
      #verify the Drives from the XML and using storecli are good
      drive_status=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show | grep 'Status =' | sed 's/.*=//' | sed 's/ //g' )
      success_item="Success"
      if [[ $drive_status == $success_item ]]; then
        #echo "Drive is in GOOD state"
        #go for flashing the drive
        controller_info=$("$storcli" /c"$pd_controller_id" show)
        controller_name=$(echo "$controller_info" | grep 'Product Name =' | sed 's/Product Name = //')
        controller_slot_number=$(echo "$controller_info" | grep 'PCI Slot Number =' | sed 's/PCI Slot Number = //')
        controller_serial_number=$pd_serial_number
        drive_info_all=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show all)
        drive_location="$pd_controller_id:$pd_EID:$pd_drive_bay"
        drive_address="(Controller-Slot:$controller_slot_number Port:$pd_controller_id Box:$pd_EID Bay:$pd_drive_bay)"
        #drive_info=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show | grep [0-9] | grep -v '=' | sed 's/-//' | sed 's/[\._-]//g' )
        drive_info=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show | grep [0-9] | grep -v '=' )
        #echo $drive_info
        # Verify that the variable is not empty.
        if [ -z "$drive_info" ]; then
          output "Error: Could not obtain information for the drive at $drive_address"
          continue
        fi
        # Continue looping through the remainder of the drive bays, if the target drive is not found.
        if [[ $drive_info =~ "Drive not found" ]]; then
          continue
        fi
        temp_drive_info=$(echo "$drive_info" | sed 's/-//')
        drive_model_name=$(echo "$temp_drive_info" | awk '{print $11}')
        drive_firmware=$(echo "$drive_info_all" | grep 'Firmware Revision =' | awk '{print $4}')
        firmwareTrim "$drive_firmware"
        #Log drive information to Verbose Log file
        #LogDriveInfo
        drive_serial_number=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show all | grep 'SN = ' | sed 's/SN = //' | sed 's/ //g')
        LogDriveInfo
        drive_protocol=$(echo "$drive_info" | awk '{print $7}')
        drive_status=$(echo $drive_info | awk '{print $3}')
        if [ $drive_status = "UBad" ]; then
           total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
           output "Warning: The drive at $drive_address does not have a good status, firmware flash was not attempted."
           # Return value of "Installation not attempted, unmet dependence or tool failure".
           ret_value=6
           continue
        fi
        volume_status=$("$storcli" /c"$pd_controller_id"/e"$pd_EID"/s"$pd_drive_bay" show | grep [0-9] | grep -v "=" | awk '{print $3}')
        if [ -z $volume_status ]; then
          total_strocli_drives_comp_skipped=`expr ${total_strocli_drives_comp_skipped} + 1`
          output "Warning: Could not obtain the volume status for $target"
          # Return value of "Installation not attempted, unmet dependence or tool failure".
          ret_value=6
        fi
        rewrt_item="rewrite"
        upgrd_item="upgrade"
        dwngrd_item="downgrade"
        skip_item="skip"
        if [[ $action_item == $skip_item ]]; then
          total_strocli_drives_user_skipped=`expr ${total_strocli_drives_user_skipped} + 1`
          output "Information : User opted to skip the Drive at  $drive_location ($controller_name in $controller_slot_number) [ $drive_firmware_version ]"
        else
          if [[ $action_item == $upgrd_item ]]; then
            perform_action="upgrade"
          elif [[ $action_item == $dwngrd_item ]]; then
            perform_action="downgrade"
          elif [[ $action_item == $rewrt_item ]]; then
            perform_action="rewrite"
          fi
          #echo "flashing of the Drive"
          flash $pd_controller_id $pd_EID $pd_drive_bay $2	
          #echo "flashing done,check the status"
        fi
      fi
    fi
  done < $usexml_file
}

flashSupportedDrive() {
  # The following while loop iterates over each supported attached controller.
  controller_id=0
  while [ "$controller_id" -le $(($num_controllers-1)) ]
  do
    physical_drive_id=0
    # Get the currently selected controller's information.
    getControllerInfo
    # Get the currently selected controller name.
    getControllerName
    # Get the currently selected controller slot number.
    getControllerSlotNumber
    # Get the currently selected controller's serial number information.
    getCtrlSerialNumber
    # Get a list of the EIDs that are connected to the currently selected controller.
    getEIDs
    # The following for loop iterates over each EID that is connected to the currently selected controller.
    for EID in $attached_EIDS
    do
      # Get the Port ID.
      getPortID
      # Get a list of the drive bay IDs for currently have EID installed.
      getDriveBayIDs
      # The following loop iterates over each drive bay that contains a drive under the currently selected EID.
      for drive_bay in $drive_bay_ids
      do
        # Get all of the details for the currently selected hard drive.
        getAllDriveInfo
        # Get the Box Number of the box that is connected to the currently selected port on the currently selected controller.
        getBoxNumber
        drive_location="$port_id:$box_number:$drive_bay"
        drive_address="(Controller-Slot:$controller_slot_number Port:$port_id Box:$box_number Bay:$drive_bay)"
        # Get all of the informatoin for the currently selected hard drive.
        getDriveInfo
        # Verify that the variable is not empty.
        if [ -z "$drive_info" ]; then
          output "Error: Could not obtain information for the drive at $drive_address"
          continue
        fi
        # Continue looping through the remainder of the drive bays, if the target drive is not found.
        if [[ $drive_info =~ "Drive not found" ]]; then
          continue
        fi
        # Extract the drive model name from the drive_info variable.
        getDriveModelName
        target="Drive Model $drive_model_name at $drive_address"
        # Get the version of firmware that is currently on the currently selected hard drive.
        getDriveFirmwareVersion
        # Get the Drive State of the currently selected hard drive
        getDriveState
        #Log drive information to Verbose Log file
        LogDriveInfo
        # Get the serial number of the currently selected hard drive.
        getDriveSerialNumber
        # Get the protocol of the currently selected hard drive.
        getDriveProtocol
        # Get the world wide ID for the currently selected hard drive.
        getWWID
        drive_status=$(echo $drive_info | awk '{print $3}')
        if [ $drive_status = "UBad" ]; then
          output "Warning: The drive at $drive_address does not have a good status, firmware flash was not attempted."
          # Return value of "Installation not attempted, unmet dependence or tool failure".
          ret_value=6
          continue
        fi
        # Read from the smart component's xml file and obtain the supported drive models.
        getSupportedDriveModels
        # Split the string containing the supported drive models into an array that has a drive model for each of its elements.
        action="unknown"
        if [[ $supported_drive_models =~ $drive_model_name ]]; then
          #Log firmware and drive information to the Component Log file
          componentLogDriveFlashInfo
          # Extract the DG field (i.e. volume) information from the drive_info variable.
          dg=$(echo "$drive_info" | awk '{print $4}')
          # Check to see if the currently selected drive is part of a volume.
          # If the DG field contains an integer, then the selected drive is part of a configured volume.
          # Example: if the DG field contains the integer 1, then the selected drive is part of volume one.
          has_digit=$(echo "$dg" | grep -E ^\-?[0-9]+$)
          if [ ${#has_digit} -gt 0 ]; then
            # Get the status of the volume which is associated with the currently selected hard drive.
            volume_status=$("$storcli" /c"$controller_id"/v"$dg" show | grep [0-9] | grep -v "=" | awk '{print $3}')
            # Verify that the variable is not empty.
            if [ -z $volume_status ]; then
              output "Warning: Could not obtain the volume status for $target"
              # Return value of "Installation not attempted, unmet dependence or tool failure".
              ret_value=6
            fi
            # If the volume status is Optimal, flash the target drive.
            if [[ $volume_status =~ "Optl" || "true" == $force_ignore_bad_dev_status_flag ]]; then
              flash $2
            else
              at_least_one_drive_found=true
              output "Warning: Volume $dg on the controller in slot "$controller_slot_number" is not in an optimal state, no drives assocaited with this volume can be flashed."
              output "Warning: Unable to flash $target because it is assocaited with volume $dg."
              output "Warning: After volume $dg returns to an optimal state, re-run the Smart Component to flash its assocaited drives."
              # Return value of "Installation not attempted, unmet dependence or tool failure".
              ret_value=6
            fi
          else
            # Get the status of the unconfigured target drive.
            drive_status=$("$storcli" /c"$controller_id"/e"$EID"/s"$drive_bay" show | grep [0-9] | grep -v "=" | awk '{print $3}')
            # Verify that the variable is not empty.
            if [ -z $drive_status ]; then
              output "Warning: Could not obtain the drive status for $target"
              # Return value of "Installation not attempted, unmet dependence or tool failure".
              ret_value=6
            fi
            # If the target drive status is UGood, flash the drive.
            if [[ $drive_status != "UBad" || "true" == $force_ignore_bad_dev_status_flag ]]; then
              flash $2
            fi
          fi
        fi
        physical_drive_id=$(($physical_drive_id + 1))
      done
    done
    controller_id=$(($controller_id + 1))
  done
}

getNumberOfControllers() {
  # Find the number of supported controllers.
  controller_count=$("$storcli" show ctrlcount)
  # Verify that at least one supported controller is installed in the server.
  num_controllers=$(echo $controller_count | grep -o -E '[0-9]+' | tail -1)
  if [ 0 -eq $num_controllers ]; then
    # Since no supported controller were found, exit with a status of "Installation not attempted".
    exit 3
  fi
}

getTimeStamp() {
  log_file_time_stamp=$(echo $1 | awk -F "]" '{print $1}')
}

copyDiscoveryFileToLogFile() {
  type_value_flag=false
  version_value_flag=false
  takes_effect_value_flag=false
  while read -r a_line_from_discovery_file
  do
    if [[ $a_line_from_discovery_file =~ "<hp_rom_discovery version=" ]]; then
      printf "$log_file_time_stamp"]" $a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<type value=" && "false" == $type_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
      type_value_flag=true
    elif [[ $a_line_from_discovery_file =~ "<type value=" && "true" == $type_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<alt_name value=" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<version value=" && "false" == $version_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
      version_value_flag=true
    elif [[ $a_line_from_discovery_file =~ "<version value=" && "true" == $version_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<takes_effect value=" && "false" == $takes_effect_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
      takes_effect_value_flag=true
    elif [[ $a_line_from_discovery_file =~ "<takes_effect value=" && "true" == $takes_effect_value_flag ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<enable_device_select>" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<user_options>" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<user_option name=" ]]; then
      printf "$log_file_time_stamp"]"\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "</user_options>" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<devices>" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<device id=" ]]; then
      printf "$log_file_time_stamp"]"\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<controller_id value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<product_id value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<fw_item>" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<firmware_id value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<active_version value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<action value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<duration value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "<shared value=" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "</fw_item>" ]]; then
      printf "$log_file_time_stamp"]"\t\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "</device>" ]]; then
      printf "$log_file_time_stamp"]"\t\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
    if [[ $a_line_from_discovery_file =~ "</devices>" ]]; then
      printf "$log_file_time_stamp"]"\t$a_line_from_discovery_file\n" >> ${temp_verbose_log_file4}
    fi
  done < $discovery_file
  printf "$log_file_time_stamp"]" </hp_rom_discovery>\n" >> ${temp_verbose_log_file4}
}

captureLastEntryInComponentLog() {
  lines=$(( ${#file[@]} - 1 ))
  for (( line=$lines, i=${1:-$lines}; (( line >= 0 && i > 0 )); line--, i-- )); do
    # Check to see if the input parameter is an empty string.
    echo -ne "${file[$line]}" >> ${temp_log_file2}
    if [[ ${file[$line]} =~ "=================================================================" ]]; then
      # Break out of the loop when the delimiter is found.
      break
    fi
    #if [[ ${file[$line]} =~ "Exit Status:" ]]; then
      # Get status from the Smart Component log file.
    #  hpsetup1_status_str=$(echo ${file[$line]})
    #  hpsetup1_status=$(echo "${hpsetup1_status_str: -1}")
    #fi
  done
}

trimStaleDataFromComponentLog() {
  discovery_delimiter="Generating discovery file at"
  flash_delimiter="See log at"
  any_non_storcli_drives="Any Supported\?:[[:space:]]+no"
  # Find out which delimiter is being used in this particular Component log.
  lines=$(( ${#file[@]} - 1 ))
  for (( line=$lines, i=${1:-$lines}; (( line >= 0 && i > 0 )); line--, i-- )); do
    if [[ ${file[$line]} =~ $discovery_delimiter ]]; then
      stale_data_delimiter=$discovery_delimiter
    fi
    if [[ ${file[$line]} =~ $flash_delimiter ]]; then
      stale_data_delimiter=$flash_delimiter
    fi
    # Use script return value if supported drives are connected to storcli based controllers only.
    if [[ ${file[$line]} =~ $any_non_storcli_drives ]]; then
      non_storcli_drives=false
    fi
  done
  # Write everyting from the input file up to the point where the delimiter is located.
  lines=$(( ${#file[@]} - 1 ))
  for (( line=$lines, i=${1:-$lines}; (( line >= 0 && i > 0 )); line--, i-- )); do
    if [[ ${file[$line]} =~ $stale_data_delimiter ]]; then
        break
    fi
    echo -ne "${file[$line]}" >> ${temp_log_file1}
  done
  if [[ $stale_data_delimiter == $flash_delimiter ]]; then
    sed -i '$ d' ${temp_log_file1}
  fi
}

removeRedundantLinesFromComponentLog() {
  lines=$(( ${#file[@]} - 1 ))
  for (( line=$lines, i=${1:-$lines}; (( line >= 0 && i > 0 )); line--, i-- )); do
    # Delete every line prior to encountering the delimiter in the Component log.
    sed -i '$ d' ${component_log_file}
    if [[ ${file[$line]} =~ "=================================================================" ]]; then
      # Break out of the loop when the delimiter is found.
      break
    fi
  done
}

getDataFromComponentLog() {
  #readarray file < ${temp_component_log_file} #readarray is not compatiable with Sles11sp4
  #TO-DO partial fix done, component log has to be Fixed for SLES11SP4
  if [[ -f ${temp_component_log_file} ]]; then
    readarray file 2>/dev/null < ${temp_component_log_file} 
  fi
  captureLastEntryInComponentLog
  #readarray file < ${temp_log_file2} #readarray is not compatiable with Sles11sp4
  if [[ -f ${temp_log_file2} ]]; then  
    readarray file 2>/dev/null < ${temp_log_file2}
  fi
  trimStaleDataFromComponentLog
}

appendDataToSmartComponentLog() {
  # Write the Verbose Log file name and location to the temporary Component Log file.
  echo "See log at: $verbose_log_file" >> ${temp_log_file1}
  # Check to see if the Component log file is writable.
  isFileWritable ${component_log_file} "Smart Component log"
  #readarray file < ${component_log_file} #readaray is not compatiable with Sles11sp4
  readarray file 2>/dev/null < ${component_log_file}
  removeRedundantLinesFromComponentLog
  cat ${temp_log_file1} >> ${component_log_file}
  #echo "============ Summary ============" >> ${component_log_file}
}

appendDataToSmartComponentVerboseLogForFlashing() {
  file_delimiter_flag=false
  # Copy the upperr portion of the Smart Component log file to the temp1_verbose_log file
  while read -r a_line_from_verbose_log_file
  do
  #  if [[ ${a_line_from_verbose_log_file} =~ "Generic HBA megaraid_sas in Slot ATTR_VALUE_SLOT_UNKNOWN" ]]; then
  #    file_delimiter_flag=true
  #fi
  #if [[ "false" == ${file_delimiter_flag} ]]; then
    echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file1}
  #fi
  done < ${verbose_log_file}
  #isFileReadable ${temp_verbose_log_file1} "temp1_verbose_log"

  #file_delimiter_flag=false
  # Copy the upperr portion of the Smart Component log file to the temp1_verbose_log file
  #while read -r a_line_from_verbose_log_file
  #do
  #  if [[ ${a_line_from_verbose_log_file} =~ "The following devices are not supported by this component" ]]; then
  #    file_delimiter_flag=true
  #fi
  #if [[ "true" == ${file_delimiter_flag} ]]; then
  #  echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file1}
  #fi
  #done < ${verbose_log_file}
  isFileReadable ${temp_verbose_log_file1} "temp1_verbose_log"

  #file_delimiter_flag=false
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ "Internal Exit Status:" || ${a_line_from_verbose_log_file} =~ "See log at" ]]; then
      if [[ ${a_line_from_verbose_log_file} =~ "Internal Exit Status:" ]]; then
        internal_exit_status=$(echo ${a_line_from_verbose_log_file} | sed 's/.*://' | sed 's/ //g')
      fi
      file_delimiter_flag=true
    fi
    if [[ "false" == ${file_delimiter_flag} ]]; then
      echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file2}
    fi
  done < ${temp_verbose_log_file1}
  isFileReadable ${temp_verbose_log_file1} "temp1_verbose_log"
  cat ${temp_verbose_log_file2} > ${temp_verbose_log_file4}
}

completeSmartComponentLogForFlashing() {
  createTimeStamp
  temp_file_delimiter_flag=false
  while read -r a_line_from_verbose_log
  do
    if [[ ${a_line_from_verbose_log} =~ "Internal Exit Status:" || ${a_line_from_verbose_log_file} =~ "See log at" ]]; then
      temp_file_delimiter_flag=true
    fi
    if [[ "true" == ${temp_file_delimiter_flag} ]]; then
      if [[ ${a_line_from_verbose_log} =~ "new FW image has been activated" ]]; then
        #echo Found: new FW images have been activated
        echo "[ $timestamp ]  new FW images have been activated" >> ${temp_verbose_log_file6}
      else
        a_line_from_verbose_log_minus_timestamp=$(echo "${a_line_from_verbose_log}" | sed 's/.*]//')
        echo "[ $timestamp ] ${a_line_from_verbose_log_minus_timestamp}" >> ${temp_verbose_log_file6}
      fi
    fi
  done < ${verbose_log_file}
  isFileReadable ${temp_verbose_log_file6} "temp6_verbose_log"
  cat ${temp_verbose_log_file6} >> ${temp_verbose_log_file4}
  cp ${temp_verbose_log_file4} ${verbose_log_file}
}

breakUpSmartComponentVerboseLogFileForDiscovery() {
  temp_file_delimiter_flag=false
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ "Generic HBA megaraid_sas in Slot ATTR_VALUE_SLOT_UNKNOWN" || ${a_line_from_verbose_log_file} =~ "The following devices are not supported by this component" ]]; then
      temp_file_delimiter_flag=true
    fi
    if [[ "false" == ${temp_file_delimiter_flag} ]]; then
      echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file1}
    fi
  done < ${verbose_log_file}
  isFileReadable ${temp_verbose_log_file1} "temp1_verbose_log"
  cat ${temp_verbose_log_file1} > ${temp_verbose_log_file4}

  temp_file_delimiter_flag=false
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ "The following devices are not supported by this component" ]]; then
      temp_file_delimiter_flag=true
    fi
    if [[ "true" == ${temp_file_delimiter_flag} ]]; then
      echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file2}
    fi
  done < ${verbose_log_file}
  isFileReadable ${temp_verbose_log_file2} "temp2_verbose_log"
  cat ${temp_verbose_log_file2} >> ${temp_verbose_log_file4}

  temp_file_delimiter_flag=true
  while read -r a_line_from_temp_verbose_log_file4
  do
    if [[ ${a_line_from_temp_verbose_log_file4} =~ "<hp_rom_discovery version=" ]]; then
      temp_file_delimiter_flag=false
    fi
    if [[ "true" == ${temp_file_delimiter_flag} ]]; then
      echo "${a_line_from_temp_verbose_log_file4}" >> ${temp_verbose_log_file3}
    fi
  done < ${temp_verbose_log_file4}
  isFileReadable ${temp_verbose_log_file3} "temp3_verbose_log"
  cat ${temp_verbose_log_file3} > ${temp_verbose_log_file4}
  a_line_from_temp3_file=$(tail -1 ${temp_verbose_log_file3})
  getTimeStamp "${a_line_from_temp3_file}"
}

completeSmartComponentLogFileForDiscovery() {
  regex="The following [[:digit:]]+ devices are supported"
  found_device_delimiter=false
  # Check to see if the device delimiter exists.
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ $regex ]]; then
      found_device_delimiter=true
    fi
  done < ${temp_verbose_log_file4}
  # If device delimiter does not exist, define alternate delimiter.
  if [[ "false" == $found_device_delimiter ]]; then
    regex="Requires ANY of Model/Type:"
  fi
  # Write the drive location ID into the Verbose log file.
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ $regex ]]; then
      getTimeStamp "${a_line_from_verbose_log_file}"
      if [[ "false" == $found_device_delimiter ]]; then
        printf "$log_file_time_stamp"]"\n" >> ${temp_verbose_log_file5}
      fi
      printf "${log_file_time_stamp}] The following devices are supported\n" >> ${temp_verbose_log_file5}
      for drive_location_id in "${driveArray[@]}"
      do
        printf "$log_file_time_stamp"]"  ${drive_location_id}\n" >> ${temp_verbose_log_file5}
      done
      continue
    fi
    echo "${a_line_from_verbose_log_file}" >> ${temp_verbose_log_file5}
  done < ${temp_verbose_log_file4}

  temp_file_delimiter_flag=false
  while read -r a_line_from_verbose_log_file
  do
    if [[ ${a_line_from_verbose_log_file} =~ "Internal Exit Status:" ]]; then
      temp_file_delimiter_flag=true
    fi
    if [ "true" = ${temp_file_delimiter_flag} ]; then
      printf "${a_line_from_verbose_log_file}\n" >> ${temp_verbose_log_file5}
    fi
  done < ${verbose_log_file}
  cp ${temp_verbose_log_file5} ${verbose_log_file}
}

writeExitStatusInComponentLog() {
  echo "Exit Status: $ret_value" >> ${component_log_file}
}

modifyLogFileStatusAndExit() {
  sed -i "s/]  Exit Status: $hpsetup1_status/]  Exit Status: $ret_value/" ${verbose_log_file}
  #writeExitStatusInComponentLog
}

generateOverallSummary(){
	# Generating overall summary message for SA & Mesa installation
	#Calculating overall summary
	final_comp_opt_count=`expr ${sc_opt_count} + ${total_strocli_drives_comp_skipped}`
	final_user_opt_count=`expr ${sc_user_opt_count} + ${total_strocli_drives_user_skipped}`
	final_comp_act_count=`expr ${sc_act_count} + ${total_strocli_drives_flashed}`
	if [[ $final_comp_opt_count > 0 || $final_user_opt_count > 0 || $final_comp_act_count > 0 ]]; then
		echo "===== Overall Flashing Summary =====" | tee -a $component_log_file
		if [[ $final_comp_opt_count > 0 ]]; then
			echo "Smart Component opted to not flash $final_comp_opt_count device(s)" | tee -a $component_log_file
		fi
		if [[ $final_user_opt_count > 0 ]]; then
			echo "User opted to not flash $final_user_opt_count device(s)" | tee -a $component_log_file
		fi
		if [[ $final_comp_act_count > 0 ]]; then
			echo "$final_comp_act_count new FW image has been activated" | tee -a $component_log_file
		fi
	fi
}

setReturnValue() {
  # Determine the correct return value.
  if [[ "true" == $non_storcli_drives && $hpsetup1_status <4 && $ret_value < 4 ]]; then
        if [[ 0 == $hpsetup1_status && $ret_value > 1 ]] || [[ 1 == $hpsetup1_status && $ret_value > 1 ]] || [[ 1 == $hpsetup1_status && 0 == $ret_value ]] ||  [[ 2 == $hpsetup1_status && 3 == $ret_value ]]; then
                ret_value=$hpsetup1_status
        elif [[ $hpsetup1_status > 1 && 0 == $ret_value ]] || [[ $hpsetup1_status > 1 && 0 == $ret_value ]] || [[ 0 == $hpsetup1_status && 1 == $ret_value ]] ||  [[ 3 == $hpsetup1_status && 2 == $ret_value ]]; then
                ret_value=$ret_value
        elif [[ 0 == $hpsetup1_status && 0 == $ret_value ]] || [[ 1 == $hpsetup1_status && 1 == $ret_value ]] || [[ 2 == $hpsetup1_status && 2 == $ret_value ]] || [[ 3 == $hpsetup1_status && 3 == $ret_value ]]; then
                ret_value=$ret_value
        else
                ret_value=$ret_value
        fi
  else
        if [[ $hpsetup1_status > 3 && $ret_value < 4 ]]; then
                ret_value=$hpsetup1_status
        elif [[ $hpsetup1_status < 4 && $ret_value > 4 ]]; then
                ret_value=$ret_value
        elif [[ $hpsetup1_status > 3 && $ret_value > 3 ]]; then
                if [[ 7 == $hpsetup1_status && 6 == $ret_value ]]; then
                        ret_value=$hpsetup1_status
                else
                        ret_value=$ret_value
                fi
        else
                ret_value=$ret_value
        fi
  fi
  if [[ "true" == $drive_found ]]; then
	generateOverallSummary
	modifyLogFileStatusAndExit
  fi
  exit $ret_value
  #if [[ 1 == $ret_value ]]; then
  #  modifyLogFileStatusAndExit
  #  exit $ret_value
  #fi
  #if [[ "true" == $non_storcli_drives && 2 == $hpsetup1_status && 0 == $ret_value ]]; then
  #  modifyLogFileStatusAndExit
  #  exit $ret_value
  #fi
  #if [[ "true" == $non_storcli_drives && 0 == $hpsetup1_status && 2 == $ret_value ]]; then
  #  ret_value=$hpsetup1_status
  #fi
  #if [[ "true" == $non_storcli_drives && 3 == $hpsetup1_status && $ret_value < 3 ]]; then
  #  modifyLogFileStatusAndExit
  #  exit $ret_value
  #fi
  #if [[ "true" == $non_storcli_drives && 3 == $ret_value && $hpsetup1_status < 3 ]]; then
  #  ret_value=$hpsetup1_status
  #fi
  #if [[ "true" == $non_storcli_drives && 1 == $hpsetup1_status || "true" == $non_storcli_drives && 4 < $hpsetup1_status ]]; then
  #  ret_value=$hpsetup1_status
  #fi
  #modifyLogFileStatusAndExit
  #exit $ret_value
}

removeXMLFileExtension() {
  # Remove the file extension from the XML file name.
  xml_prefix=$(echo $xml_file | sed -e 's/\(.xml\)*$//')
  if [ -z "$xml_prefix" ]; then
    output "Error: Could not extract the prefix of the XML file name from the $xml_file file."
  fi
}

removeAllReferencesToMegaRAID() {
  sed -i "/Generic HBA MegaRAID/Id" ${verbose_log_file}
}

getXMLFileName
removeXMLFileExtension

#length=0
#for arg in $@
#do
#  length=$(($length + 1))
#done
#length=$(($length - 1))
#
#arg_counter=0
# This array contains the input parameters for this script.
#for arg in $@
#do
#  arg_counter=$(($arg_counter + 1))
  # Run the Dicovery option using the default file.
#  if [[ "--discovery" == $arg || "--discovery" == $arg && $arg_counter == $length ]]; then
#    discovery_flag=true
#    break
#  fi
  # Set the Log-dir flag to true and use the default directory to hold the log file.
#  if [[ "-b" == $arg && 1 == $length || "-b" == $arg && $arg_counter == $length ]]; then
#    break
#  fi
  # Run the Dicovery option using the default file.
#  if [[ "-d" == $arg && 1 == $length || "-d" == $arg && $arg_counter == $length ]]; then
#    discovery_flag=true
#    break
#  fi
  # Use the file specified by the user as the Discovery file.
#  if [[ $arg =~ "--discovery=" ]]; then
#    discovery_flag=true
#    if [ -r $discovery_file ]; then
#      continue
#    else
#      output "Error: Cannot read the $discovery_file file."
#    fi
#  fi
#  if [[ "--discovery" == $arg || "true" == $discovery_flag ]]; then
#    discovery_flag=true
#    if [[ "true" == $discovery_flag && $arg =~ "/" ]]; then
#      discovery_file=$arg
#    else
#      echo the Discovery flag is set to: $discovery_flag and the ARG variable is: $arg
#      output "Error: Cannot find the discovery file."
#    fi
#    continue
#  fi
  # Run Discovery option and if supplied, use the user supplied directory and file name instead of the default.
#  if [[ "-d" == $arg || "true" == $discovery_file_flag ]]; then
#    discovery_flag=true
#    if [[ "true" == $discovery_file_flag && $arg =~ "/" && ! $arg =~ "--discovery=" && ! $arg =~ "--log-dir=" && ! $arg =~ "--usexml=" && ! $arg =~ "--unpack=" ]]; then
#      discovery_file_flag=false
#      continue
#    fi
#    discovery_file_flag=true
#    continue
#  fi
  # Set the Downgrade flag to true if either of the Downgrade arguments are supplied.
#  if [[ "--downgrade" == $arg || "-g" == $arg ]]; then
#    downgrade_flag=true
#    continue
#  fi
  # Set the Rewrite flag to true if either of the Rewrite arguments are supplied.
#  if [[ "--rewrite" == $arg || "-e" == $arg ]]; then
#    rewrite_flag=true
#    continue
#  fi
  # Set the Force flag to true if either of the Force arguments are supplied.
#  if [[ "--force" == $arg || "-f" == $arg ]]; then
#    force_flag=true
#    continue
#  fi
  # Set the Force-ignore-bad-dev-status flag to true if the Force-ignore-bad-dev-status argument is supplied.
#  if [ "--force-ignore-bad-dev-status" == $arg ]; then
#    force_ignore_bad_dev_status_flag=true
#    continue
#  fi
  # Set the Log-dir flag to true and use the user supplied directory to hold the log file.
#  if [[ $arg =~ "--log-dir=" ]]; then
#    log_dir=$(echo $arg | sed 's/--log-dir=//')
#    continue
#  fi
  # Capture the logging directory if one is provided by the user, otherwise use the default location.
#  if [[ "-b" = $arg || "true" == $log_dir_flag ]]; then
#    if [[ $arg =~ "/" && ! $arg =~ "--discovery=" && ! $arg =~ "--log-dir=" && ! $arg =~ "--usexml=" && ! $arg =~ "--unpack=" ]]; then
#      log_dir=$arg
#      log_dir_flag=false
#      continue
#    fi
#    log_dir_flag=true
#    continue
#  fi
#done

#usexml_flag=false
#arg_counter=0
#for arg in $@
#do
#  arg_counter=$(($arg_counter + 1))
#  if [[ "--usexml" == $arg && 1 == $length || "--usexml" == $arg && $arg_counter == $length ]]; then
#    usexml_file=$log_dir/"$xml_prefix"_disc.xml
#    usexml_flag=true
#    break
#  fi
#  if [[ "-u" == $arg && 1 == $length || "-u" == $arg && $arg_counter == $length ]]; then
#    usexml_file=$log_dir/"$xml_prefix"_disc.xml
#    usexml_flag=true
#    break
#  fi
#  if [[ "--usexml" == $arg || "true" == $usexml_flag ]]; then
#    if [[ "true" == $usexml_flag && $arg =~ "/" ]]; then
#      usexml_file=$arg
#      break
#    fi
#    usexml_flag=true
#    continue
#  fi
#  if [[ $arg =~ "--usexml=" ]]; then
#    usexml_file=$(echo $arg | sed 's/--usexml=//')
#    usexml_flag=true
#    break
#  fi
#  if [[ "-u" == $arg || "true" == $usexml_flag ]]; then
#    if [[ "true" == $usexml_flag && $arg =~ "/" && ! $arg =~ "--discovery=" && ! $arg =~ "--log-dir=" && ! $arg =~ "--usexml=" && ! $arg =~ "--unpack=" ]]; then
#      usexml_file=$arg
#      break
#    fi
#    usexml_flag=true
#    continue
#  fi
#done

drives_to_flash=
if [[ "true" == $usexml_flag ]]; then
  isFileReadable $usexml_file "usexml"
  # This loop locates supported storcli hard drives.
  #drive_found=false
  while read -r a_line_from_xml_file
  do
    if [[ $a_line_from_xml_file =~ "PD:" ]]; then
      pd_serial_number=$(echo $a_line_from_xml_file | sed 's/<device id="AC://' | sed 's/,.*//')
      pd_location=$(echo $a_line_from_xml_file | sed 's/.*n//' | sed 's/\">//' | sed 's/:/-/')
      drives_to_flash=$(echo ${drives_to_flash}$pd_serial_number$pd_location',')
      drive_found=true
    fi
  done < $usexml_file
  if [[ "false" == $drive_found ]]; then
    #output "Error: Could not locate any Storcli supported drives."
    ret_value=3 # No drives found under mesaverde so returning 3
    getDataFromComponentLog
    appendDataToSmartComponentLog
    setReturnValue
  fi
fi

locateStorcli() {
#echo "locateStorcli"
# Locate where the storcli utility is installed.
# Once the installation directory is found, split the string containing the filenames into an array.
storcli_array=$(find / -type f \( -name "storcli64" -o -name "storclio64" -o -name "storcli" \) 2> /dev/null)
# The following for loop iterates over each file, the first executable file that is found will be used as the storcli executable file.
for file_name in $storcli_array
do
  if [ -x "$file_name" ]; then
    storcli=$file_name
  fi
done

# Verify that the variable contains an executable file.
if [ ! -x "$storcli" ]; then
  output_CmpLog "Error: Cannot find the storcli utility, please install either the storcli or storcli64 utility."
  output_CmpLog "Script Exiting."
  output_CmpLog "Exit Status: $INSTALL_NOT_ATTEMPTED"
  exit $INSTALL_NOT_ATTEMPTED
fi
}
locateStorcli
# Initialize the storcli variable to the storcli64 binary file.
#storcli=$PWD/storcli64
# Verify that the storcli64 file is in the current working directory.
#if [ ! -e "$storcli" ]; then
#  output "Error: Cannot find the storcli64 utility."
#fi

# Verify that the variable contains an executable file.
#if [ ! -x "$storcli" ]; then
#  output "Error: The storcli64 utility is not executable."
#fi

#doesDirectoryExist ${log_dir}
# Read in the Smart Component log file and copy the bottom portion of the log file data to the temp.log file.
#log_file_name=$(ls -t ${log_dir} | grep -e "$xml_prefix"_[0-9][0-9][0-9][0-9]_ | head -n1)
#verbose_log_file=$log_dir/$log_file_name
#if [ ! -f $verbose_log_file ]; then
  # If the specified log file cannot be found, create a supplemental log file and exit.
#  createSupplementalLogFile
#  exit 6
#fi
#isFileReadable ${verbose_log_file} "Smart Component verbose log"
# Initialize the component_log_file to the Smart Component's Component.log file
#component_log_file=${log_dir}/Component.log
# Check to see if the Component log file is readable.
#isFileReadable ${component_log_file} "Smart Component log"
# Make a temporary copy of the Component Log file, this is needed because the OS will not allow file appends.
#cp ${component_log_file} ${temp_component_log_file}
#isFileReadable ${temp_component_log_file} "Temporary Smart Component log"
getFirmwareVersionFromXML

list_of_drives=
if [[ "false" == $discovery_flag ]]; then
  # Get information from the Component log file.
  getDataFromComponentLog
  # Add data to Smart Component Verbose Log file.
  appendDataToSmartComponentVerboseLogForFlashing
  getNumberOfControllers
  at_least_one_drive_found=false
  # Extract the name of the firmware binary file from the payload.json file.
  getFirmwareImageFileNameFromPayloadFile
  doesFileExist $PWD/$firmware_binary "Smart Component firmware binary"
  isFileReadable $PWD/$firmware_binary "Smart Component firmware binary"
  # Get the last input parameter and assign it to the user_defined_drive_list variable.
  # user_defined_drive_list=$(echo "${@: -1}")
  #echo  $usexml_flag
  if [[ $usexml_flag == "true" ]]; then
    #echo $firmware_binary
    flashUserSelectionDrives $xml_file  $PWD/$firmware_binary
  else
    flashSupportedDrive $xml_file $PWD/$firmware_binary
  fi
  #echo "Number of Drives Flashed using storcli are : $total_strocli_drives_flashed"
  #echo "Number of Drives skipped by the user using storcli are : $total_strocli_drives_user_skipped"
  #echo "Number of Drives Flashed by the component using storcli are : $total_strocli_drives_comp_skipped"
   #if [[ $user_defined_drive_list =~ "-" ]]; then
   #  output "Warning: Only comma separated drive locations are supported for drives connected to a $controller_name"
   #fi
  # Notify the user that this script did not find any supported hard drives.
  if [ "false" == $at_least_one_drive_found ]; then
    echo " " 
    #output "Warning: The Smart Component did not find any supported hard drives in HPE Smart Array P824i-p MR Gen10 controllers."
    #echo " "
    ret_value=3
  fi
  # Reassemble the Smart Component Verbose Log file.
  completeSmartComponentLogForFlashing
  # Add data to the Smart Component Log file.
  appendDataToSmartComponentLog
  # Remove both the megaraid_sas and the MegaRAID lines from the log file.
  #removeAllReferencesToMegaRAID
  #Generating overall summary
  #generateOverallSummary  
  # Determine the correct return value.
  setReturnValue
else
  # Discovery option is set to true.
  if [ -z $discovery_file ]; then
    removeXMLFileExtension
    discovery_file=$log_dir/"$xml_prefix"_disc.xml
  fi
  isFileReadable $discovery_file "Discovery"
  # Get information from the Component log file.
  getDataFromComponentLog
  # breakUpSmartComponentComponentLog
  breakUpSmartComponentVerboseLogFileForDiscovery
  # Build the Discovery XML file.
  buildDiscoveryXML
  # Copy the contents of the discovery file to the Smart Component Log file.
  copyDiscoveryFileToLogFile
  # Append datat to the Smart Component Log file.
  appendDataToSmartComponentLog
  # completeSmartComponentLog
  # Add information to the lower portion of the Smart Component Verbose Log file.
  completeSmartComponentLogFileForDiscovery
  # Remove both the megaraid_sas and the MegaRAID lines from the log file.
  #removeAllReferencesToMegaRAID
  #Generating overall summary
  #generateOverallSummary
  # Determine the correct return value.
  setReturnValue
fi

exit $ret_value
