#!/usr/bin/expect --
################################################################################
#
# File: GetState 
# RCS:	   @(#) $Header: $
#
# Description:  Connect to the iLO virtual serial console, send a carriage
#               return as a stimulus and print the detected state as soon
#               as it can be determined.
#
# Notes:
#    Possible states are
#      OTL         -> off, or not responding
#      LOGIN       -> At linux login prompt
#      LINUX       -> At root or user prompt ("#" or "$")
#      ILO         -> At iLO prompt
#      OA          -> At OA prompt
#      BOOTING     -> In the process of booting
#      SHUTDOWN    -> In the process of shutting down
#         
# 
#    The output will be "state is $state"
#
# Authors:  jana@fc.hp.com
# Revision History:
#
#
################################################################################

# Get the name of this script.
set MyName [lindex [split $argv0 {/}] end]
set caller "$MyName"

################################################################################
#                                 Subroutines
################################################################################

#*******************************************************************************
# SetLibraryPath: Sets the library path for common libraries
# Input: none
# Output: exits with value 0
#*******************************************************************************
proc SetLibraryPath {argv0} {
   global basepath locpath
   global env
   global VERBOSE

   if {![info exists VERBOSE]} {
      set VERBOSE 0
   }
   set libDir "tests/hisv/lib"
    # Get the path to the our libraries
    if {$VERBOSE} {
       send_user "\n\[SM] SetLibraryPath:\n"
       send_user "\targv0 = $argv0\n"
    }
    set pathToMe $argv0
     # If the path to this tool is relative to this directory,
     #   substitute $PWD.
    regsub {^./[^/]+} $pathToMe $env(PWD) pathToMe
     # set locpath to this directory
    regsub {/[^/]+$} $pathToMe "" locpath

    if {$VERBOSE} {
       send_user "\tpathToMe = $pathToMe\n"
       send_user "\tlocpath  = $locpath\n"
    }
    if [info exists env(BASEPATH)] {
        # Use the environment variable BASEPATH if set:
       set basepath "$env(BASEPATH)"
    } \
    else {
           set pathDirs [split $locpath /]
           set pLen [expr [llength $pathDirs] - 1]

            # Work backwards through the path to try to
            #  find the path to the library directory
           for {set i $pLen} {$i > 0 } {incr i -1} {

               if {$i == $pLen} {
                  set dummyPath $pathToMe
               }
               regsub {/[^/]+$} $dummyPath "" dummyPath
               if {[file exists $dummyPath/libsm]} {
                  set basepath $dummyPath
                  break
               } \
               elseif {[file exists $dummyPath/lib/libsm]} {
                  set basepath $dummyPath/lib
                  break
               }
           }

           if {![info exists basepath]} {
               send_user "ERROR: Can't find common library directory $libDir\n"
               exit 2
           }
    }

    if {$VERBOSE} {send_user "\tFound library path $basepath\n"}
}

#*******************************************************************************
# Usage: Print usage message
# Input: none
# Output: exits with value 0
#*******************************************************************************
proc Usage {} {
   global MyName
   global domain
   global ilo_user ilo_passwd
   global user passwd

   puts "\nUsage: $MyName -sut=<ilo_hostname> \[optional]"
   puts "    Required options:"
   puts "\t-sut=<ilo_hostname>"
   puts "\t    hostname is the hostname of the system under test."
   puts ""
   puts "    Test-related options:"
   puts "\t-state=<expected_state>"
   puts "\t    expected_state is the state the system should be in."
   puts "\t    Possible states are"
   puts "\t      OTL         -> off, or not responding"
   puts "\t      LOGIN       -> At linux login prompt"
   puts "\t      LINUX       -> At root or user prompt (\"#\" or \"$\")"
   puts "\t      ILO         -> At iLO prompt"
   puts "\t      OA          -> At OA prompt"
   puts "\t      BOOTING     -> In the process of booting"
   puts "\t      SHUTDOWN    -> In the process of shutting down"
   puts ""
   puts "    Other options:"
   puts "\t-ilo_passwd=<ilo_admin_passwd>"
   puts "\t    ilo_admin_passwd is the administrator password on the system under test."
   puts "\t    (default: $passwd)."
   puts "\t-ilo_user=<administrator>"
   puts "\t    user_name to log into iLO virtual serial console as"
   puts "\t    (default: $user)."
   puts ""
   puts "    Login-related options:"
   puts "\t-user=<root_user>"
   puts "\t    root_user is the login name for a user with root privileges."
   puts "\t    default: $user."
   puts "\t-password=<root_user_password>"
   puts "\t    The password for the user specified above."
   puts ""
   exit 0
} ;# End Usage

#*******************************************************************************
#  ParseArgs: Customized command-line parsing for this test
#  Input: rargv - reference to the argv string
#  Output: sets variables in caller's scope
#  Note: This parses options that didn't match options in
#        libcmdline::ParseCanonicalCmdline, so if the option
#        is not set properly here, check libcmdline.
#*******************************************************************************
proc ParseArgs {rargv} {
   global VERBOSE
   upvar $rargv argv

   set unusedArgs ""

   if {$VERBOSE} {
       send_user "\n\[SM] ParseArgs:\n"
   }
   if [info exists argv] {
      if {$VERBOSE} { send_user "\targv = $argv\n"}
   } \
   else {
      return
   }
 
   set argv [split $argv { =}]

   while {[llength $argv] > 0} {
       set opt [shift argv]
       switch -- $opt {
           -h -
           -help -
           --help -
           -? {  Usage }
           -s -
           -state { uplevel #0 set EndState [shift argv]; continue }
           default {
              if { $opt != "" } {
                   # The user can specify a console without a -oa or -ilo flag
                 if {![info exists console] || [info exists console] && [regexp {^[0-9]+$} $console]} {
                    set console $opt
                    SmartParse
                 } \
                 else {
                    push unusedArgs $opt
                 }
              }
           }
       }
    }  ;# End while
    set argv $unusedArgs
}   ;# End ParseArgs


################################################################################
#                              End Subroutines
################################################################################
# Set verbose early to get verbose output from search for library
# path and command-line parsing
if {[regexp -- {-v} $argv]} { set VERBOSE 1 }

# Set library path
SetLibraryPath $argv0

#***************************** Global Variables ********************************
source $basepath/defaults
 # Need to reset VERBOSE after loading default variables
if {[regexp -- {-v} $argv]} { set VERBOSE 1 }

# Source libraries.
source "$basepath/libcmdline"
source "$basepath/stdlib"
source "$basepath/libilo"
source "$basepath/libsm"
source "$basepath/liblinux"
source "$basepath/libstate"

# Give 2 minutes to detect something.
set timeout_setting 120
################################################################################
#                           Overloaded Subroutines
################################################################################
#  Add subroutines, e.g., Done, here to override the
#  default action as defined in the libraries above.

################################################################################
#                         End Overloaded Subroutines
################################################################################

# Set interrupt handlers
SetSigTraps


#************************** Configuration Loading ******************************

# Override default settings with command-line options
ParseCanonicalCmdline argv
if {[info exists argv] && [llength $argv]} { ParseArgs argv }
if {![info exists prompt]} { set prompt $root_prompt }

# Show the user what's going on...
log_user 1

# Set the Expect log file if we are in verbose mode.
set log "$MyName"
set log [split $log {.}]
set logfilename "[lindex $log 0].log.[pid]"

if {[info exists env(DRYRUN)] && $env(DRYRUN)} {
   set DRYRUN 1
   set VERBOSE 3
}

#**************************** Start Debug-Logfile ******************************
if { $VERBOSE || [info exists env(DEBUG)] && $env(DEBUG)} {
    exp_internal -f $logfilename 0
    send_user "\n\[SM] Logfile is $logfilename\n"
}

#*************************** Connect to the System *****************************
set timeout $timeout_setting

if {$VERBOSE} {
   send_user "\[SM] $MyName:\n"
   if {[info exists console]} {send_user "\tconsole is $console\n"}
   if {[info exists sut]} {send_user "\tsut is $sut\n"}
   if {[info exists type]} {send_user "\ttype is $type\n"}
}
  # If running in DRYRUN mode, don't connect to the console, 
  #  get 'console' input from the process that we specified on the command
  #  line (this will be anything left over after parse_cmd_line gets
  #  through with the command line).
if { $DRYRUN } {
   if {[info exists argv] && [llength $argv]} {
      eval spawn [lrange $argv 0 end]
      set MainProc $spawn_id
   }
   # To run with simulator, append the following to the command line,
   #    bootsim <logfile> .1 1
} \
else {
     # sut is the system number if connecting from the OA
   if {!$fwConnect} {
       # Connect to the system console
      if {![ConnectConsole $type $console sut]} {
         ErrorMessage "Failed to connect to the system console $console" 2
      }
   } \
   else {
      if {$type == "ilo"} {
         set fw_passwd $iloPasswd
         set fw_user $iloUser
      } \
      else {
         set fw_passwd $oaPasswd
         set fw_user $oaUser
      }
      if {![ConnectFW $console $fw_user $fw_passwd]} {
         ErrorMessage "Failed to connect to $type" 2
      }
   }
}

# Clean out any chassis codes
expect *

#****************************** Start the Test *********************************
set failed 0
set state [DetermineState 1]
if {$DRYRUN} { set state "BOOTING" }
if { [info exists EndState] } {
    if {$EndState != ""} {
       if [info exists state] {
          if [regexp -nocase "^$EndState$" $state] {
             if {$VERBOSE} { send_user "\n\n" }
             send_user "\nSystem has reached $EndState\n"
          } \
          else {
             if {$VERBOSE} { send_user "\n\n" }
             send_user "\nSystem IS $state, NOT '$EndState'\n"
             set failed 1
          }
       } \
       else {
          send_user "\n\nERROR: No state returned from DetermineState\n"
          set failed 1
       }
    }
    Done 0
}
if {[info exists state] && $state != ""} {
   if {$VERBOSE} { send_user "\n\n" }
   send_user -- "--> State=$state\n"
} \
else {
   send_user "\n\nERROR: No state returned from DetermineState\n"
   set failed 1
}

#******************************* End the Test **********************************

set timeout 20
Done $failed

##
# vim: tabstop=4
# -*- tab-width:4 -*-
##
