home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / pub / public_html / cudocs / ilosetup-1.07 < prev    next >
Text File  |  2020-01-01  |  21KB  |  587 lines

  1. #!/p/sy/subsys/scripts/wermit +
  2. #!/p/kd/fdc/solaris9/wermit +
  3. #!/p/kd/fdc/RHEL4/wermit +
  4. #
  5. # IMPORTANT: The first line must indicate the path to C-Kermit 8.0.212 or 9.0
  6. #  and there must be a + sign after the path, separated by a space.
  7. #
  8. # ilosetup: C-Kermit Script to configure an HP server through its
  9. #            iLO management interface.
  10. #
  11. # author: Frank da Cruz, Columbia University, 2009
  12. #
  13. .version = 1.07
  14. .date = 20091113
  15. #   Created:  
  16. #    1.01 20090428
  17. #   Modified:
  18. #    1.02 20090916: Prompt for username if not in environment.
  19. #    1.03 20091028: Remove IF WRITEABLE check for log directory
  20. #    1.04 20091103: Handle console login failure more gracefully;
  21. #                   Allow empty password in serials file.
  22. #    1.05 20091104: Add 'usepassword' and 'nopassword' options;
  23. #                   Try both in specified order.
  24. #    1.06 20091104: Handle login failure on Telnet connections.
  25. #    1.07 20091113: Enable remote console acquire
  26. # Usage: [ ilo_username=x ] [ ilo_userpass=y ] ilosetup hostname [ keywords ]
  27. #
  28. # After the hostname you can put zero or more of these keywords:
  29. #
  30. #   connect - make an interactive connection after logging in
  31. #   debug - create a debug log (very big, only for Frank)
  32. #   usepassword - try to log in first with a serials file password
  33. #   nopassword - try to log in first with a blank password
  34. #   nopoweroff - don't power the host machine off at the end
  35. #   noreset - no reset at end
  36. #   poweroff - power the host machine off at the end (default)
  37. #   quiet - only show error, warning, or status messages on the screen
  38. #   reset - reset at end (default)
  39. #   verbose - watch the script play on the screen (default)
  40. #
  41. # The keywords can be abbreviated to any unique left substring.
  42. #
  43. # Examples for host fillmore:
  44. #   ilosetup fillmore
  45. #   ilosetup fillmore poweroff
  46. #   ilosetup fillmore p (same as poweroff)
  47. #   ilosetup fillmore p q (poweroff and run quietly)
  48. #
  49. # The hostname should match (case independently) a hostname in the HP
  50. # serials file, which is just the first part of the first field of the
  51. # IP hostname, e.g. fillmore instead of fillmore-console.cc.columbia.edu.
  52. # But if you do include the extra fields, the script allows for it.
  53. #
  54. # Exit status:
  55. #   0 on success; 1 on failure.
  56. #
  57. # Creates in the log directory (logdirectory defined below):
  58. #   A session log file xxx-session.log (xxx is the hostname)
  59. #  (the log directory itself is created if it doesn't exist)
  60. #
  61. # Requires: C-Kermit 8.0.212 or later because it uses some recent features.
  62. # Version 8.0.211 or earlier lack at least the following, which are used in
  63. # this script:
  64. #  . FSEEK /FIND:string
  65. #  . The \fkwval() function
  66. # (The script could be recoded at some effort to use older ways of doing
  67. #  the same things.)
  68. #
  69. # The binary used to execute the script is the one shown above in the
  70. # "kerbang line".  Of course you can move the binary to anywhere you want, 
  71. # or rename it, but then you have to change the kerbang line.
  72. #
  73. # Other dependencies:
  74. #  . The HP serial numbers file (path defined a few lines down)
  75. #  . That the first field in a serials file record is the simple hostname
  76. #    (e.g. FILLMORE, not FILLMORE-CONSOLE or FILLMORE-CONSOLE.CC.COLUMBIA.EDU)
  77. #  . That the corresponding iLO console password is the 6th field
  78. #    (if there is no password, the 6th field should be empty).
  79. #
  80. ###############################################################################
  81.  
  82. if < \v(version) 800212 {        # Check Kermit version
  83.     exit 1 "\m(myname): C-Kermit 8.0.212 or later required"
  84. }
  85. # Operating parameters and defaults (that can be changed)...
  86.  
  87. .dodebug = 0
  88. if def \$(DEBUG) .dodebug = 1
  89. if \m(dodebug) {
  90.     echo DEBUGGING ON
  91.     echo ILO_USERID=[\$(ilo_userid)]
  92.     echo ILO_USERPASS=[\$(ilo_userpass)]
  93. }
  94. set quiet off                # Allow messages (for foreground use)
  95.  
  96. # "Constant" definitions (that can be changed)...
  97.  
  98. .iloprompt = ">hpiLO-> "        # HP iLO console prompt
  99. .logdirectory = /var/log/ilosetup    # Directory for session log
  100. .outputpacing = 30            # Intercharter pacing for OUTPUT (msec)
  101. .poweroff = 0                # Whether to power off at end
  102. .connect = 0                # Make in interactive connection
  103. .reset = 1                # Reset at end
  104. .dopassword = 1                # Use password from serials file
  105. .serialsfile = /p/sy/subsys/HP/serials    # Path of blade serial numbers file
  106. .hostsuffix = -console.cc.columbia.edu    # Hostname suffix
  107. .loginname = Administrator        # iLO login name
  108.  
  109. if equ "\v(user)" "fdc" {        # Development / testing
  110.     .logdirectory = ~/net/shrimp # (dev/test)
  111.     # if \m(dodebug) .serialsfile = ./serials
  112. }
  113. .myname := \fbasename(\v(cmdfile))    # Name of this script without path
  114.  
  115. if \m(dodebug) {            # dev/test
  116.     show args     
  117. }
  118. # Define command-line option keywords
  119.  
  120. dcl \&k[] = poweroff nopoweroff verbose quiet -
  121.             connect debug reset noreset usepassword nopassword
  122. array sort &k                # Alphabetize them for table lookup
  123.  
  124. # If command line is invalid give usage message and exit
  125.  
  126. def usage {                # Give usage message and exit
  127.     .verbose = "verbose"
  128.     .turnoff = "nopoweroff"
  129.     .doreset = "noreset"
  130.     .usepass = "nopassword"
  131.     echo -
  132. "Usage: [ ilo_username=x ] [ ilo_userpass=y ] \m(myname) hostname [ options ]"
  133.     echo "Options:"
  134.     show array k
  135.     if quiet .verbose = "quiet"
  136.     if \m(poweroff) .turnoff = "poweroff"
  137.     if \m(reset) .doreset = "reset"
  138.     if \m(dopassword) .usepass = "usepassword"
  139.     echo "Default options: \m(verbose) \m(turnoff) \m(doreset) \m(usepass)"
  140.     echo "Optional environment variables:"
  141.     echo " ilo_userid:   user ID to create"
  142.     echo " ilo_userpass: password for user ID"
  143.     echo " DEBUG=1: turn on debugging"
  144.     echo "If created user ID and password are not found in the environment,"
  145.     echo "you are prompted for them."
  146.     echo
  147.     exit 1
  148. }
  149. # Parse and validate command line
  150.  
  151. if not def \%1 {
  152.     echo "FATAL - A hostname is required"
  153.     usage                # A hostname is required
  154. }
  155. .hostname := \flower(\fword(\%1,1,.))    # First field of hostname argument
  156. .\%t := \findex(-console,\m(hostname))    # If "-console" found in hostname...
  157. if \%t .hostname := \s(hostname[1:\%t-1]) # remove it.
  158. .fullhost := \m(hostname)\m(hostsuffix) # Make full IP hostname
  159.  
  160. # Parse optional command-line keywords...
  161.  
  162. set flag off                # No debugging unless requested
  163. if def \m(dodebug) set flag on        # Can request with environment var
  164.  
  165. while defined \%2 {            # While we still have trailing args...
  166.     .tmp := \%2
  167.     .\%2 := \ftablelook(\%2,&k)        # Look up this keyword and get index
  168.     if < \%2 1 {            # Not found or ambiguous
  169.     echo "Invalid command-line option: '\m(tmp)'"
  170.     usage            
  171.     }
  172.     .\%2 := \&k[\%2]            # Resolve index to keyword itself
  173.     switch \%2 {            # Handle the keyword
  174.       :debug                # Debug
  175.     set flag on
  176.     break 
  177.       :connect                # Connect (interactive session)
  178.     .connect = 1
  179.     break
  180.       :poweroff                # Leave power off at end
  181.     .poweroff = 1
  182.     break
  183.       :nopoweroff            # Leave power on at end
  184.     .poweroff = 0
  185.     break
  186.       :quiet                # Silent running (don't watch session)
  187.     set quiet on
  188.     set input echo off
  189.     break
  190.       :verbose                # Show session on screen
  191.     set quiet off
  192.     set input echo on
  193.       :reset                # Reset at end (default)
  194.     .reset = 1
  195.     break
  196.       :noreset                # No reset at end
  197.     .reset = 0
  198.     break
  199.       :usepassword            # Use password from serials file
  200.         .dopassword = 1
  201.     break
  202.       :nopassword            # Use empty password
  203.         .dopassword = 0
  204.     }
  205.     shift                # Shift argument list to the left
  206. }
  207. # Macro definitions...
  208.  
  209. define logit {                # Write a message to session log
  210.     if not open session-log end 0
  211.     .\%1 := \frpad(\%1,7,.)        # Make fields line up
  212.     writeln session            # Make sure we're on a new line
  213.     writeln session "%% \%1 - \m(myname): \v(timestamp) [\m(hostname)] - \%2"
  214. }
  215. define message {            # Print and log a progress message
  216.     if not quiet echo            # To avoid mixing up screen text
  217.     echo "MESSAGE - \%1"        # Write message to screen (stdout)
  218.     logit MESSAGE "\%1"            # and to session log
  219. }
  220. define warn {                # Print and log warning message
  221.     if not quiet echo            # To avoid mixing up screen text
  222.     echo "WARNING - \%1"        # Write it to to stdout
  223.     logit WARNING "\%1"            # and to session log
  224. }
  225. define fatal {                # Fatal error
  226.     .rc = 1                # Failure exit code
  227.     echo "FATAL - \%1"            # Write error message to screen
  228.     if \m(haveconnection) {        # If we have a connection
  229.     if not equ "\m(state)" "iLO" {    # but w're not in iLO...
  230.         output \{27}\{40}        # ESC+( - Escape back to iLO 
  231.         input 8 \m(iloprompt)    # and wait 8 sec for the prompt
  232.     }
  233.     }
  234.     logit FATAL "\%1"            # write message to session log
  235.     logit INFO    "Most recent error: \v(errstring)"
  236.     goto DONE
  237. }
  238. define getiloprompt {            # Get iLO prompt
  239.     if not def \%1 .\%1 = 30        # Default timeout (secs)
  240.     if not numeric \%1 fatal "Non-numeric INPUT timeout"
  241.     input \%1 \m(iloprompt)        # Wait for the prompt
  242.     if fail fatal "Timed out waiting for iLO CLI prompt."
  243. }
  244. define ilocommand {            # Send an iLO command and get response
  245.     local cmd                # Local (stack) variable
  246.     .cmd := \fword(\%1,1)        # First word of command
  247.     msleep 10                # Pause 10 msec just in case
  248.     lineout \%1                # Send the full command
  249.     if fail fatal "Output failed"    # Check for i/o error
  250.     clear input                # Empty the INPUT result buffer
  251.     getiloprompt \%2            # Get response and next iLO prompt
  252.     # The "power on/off" and "vsp" commands give no response...
  253.     if not equ "\%1" "power" {        # But "power" by itself does...
  254.     if ( equ "\m(cmd)" "power" || equ "\m(cmd)" "vsp" ) end 0
  255.     }
  256.     .status = 9                # Dummy inital status value
  257.     .tmp := \freplace(\v(input),\13,)    # Strip carriage returns (but not LFs)
  258.     .lines := \fsplit(\m(tmp),&a,\10)    # Split captured text into lines
  259.     for i 1 lines 1 {            # Loop through lines
  260.        void \fkwval(\&a[i])        # to get status and message values...
  261.     }      
  262.     if not numeric \m(status) .status = 9 # Just in case
  263.     if == \m(status) 0 end 0        # If status was 0 then OK
  264.     if ( equ "\m(cmd)" "create" && equ "\&a[5]" "Duplicate login name." ) {
  265.     end 0                # This is not an error
  266.     }
  267.     fatal "ILO COMMAND \%1: \m(error_tag)" # Fail with nonzero status
  268. }
  269. define rbsucommand {  # Send a command to RBSU and get next rbsu> prompt.
  270.     local i sleep pacing max
  271.     msleep 10                # Pause 10 msec just in case
  272.     lineout \%1                # Send the command
  273.     # Check for error response or next rbsu> prompt.
  274.     # Note: RBSU commands have no consistent error indication;
  275.     # There may be some error responses that are not caught here...
  276.     minput 30 {rbsu>} {Invalid Command} {Incomplete Command} {Invalid Option}
  277.     if fail fatal "RBSU: Timeout after [\%1]"
  278.     if == \v(minput) 1 end 0        # No error message - done.
  279.     warn "RBSU COMMAND FAILURE [\%1]"
  280.     .max = 10
  281.     for i 1 \m(max) 1 {            # Try again this many times.
  282.     increment pacing 40        # Slower pacing each time.
  283.     warn "RETRYING WITH PACING = \m(pacing) msec..."
  284.     msleep 10*i            # Pause a little longer each time
  285.     lineout \%1            # Send the command
  286.     minput 30 {rbsu>} -
  287. {Invalid Command} {Incomplete Command} {Invalid Option}
  288.     if fail fatal "RBSU: Timeout [\%1]"
  289.     if == \v(minput) 1 break    # No error message - done.
  290.     }
  291.     if > \m(i) \m(max) fatal "RBSU command error"
  292.     warn "RBSU COMMAND RECOVERY OK"
  293. }
  294. def xsleep {                # (for debugging display)
  295.     if not def \%1 .\%1 = 1
  296.     if quiet {
  297.     sleep \%1 
  298.     } else {
  299.     local i
  300.     for i 1 \%1 1 { sleep 1, xecho . }
  301.     echo
  302.     }
  303. }
  304.  
  305. # Execution begins here: Get host password from HP serial numbers file...
  306.  
  307. .haveconnection = 0            # No connection yet
  308. set input cancellation off        # Essential because of Esc sequences
  309. set exit warning off            # Allow exit without warning
  310.  
  311. if \m(dodebug) directory \m(serialsfile)    # Check and open serials file
  312. if not exist \m(serialsfile) exit 1 "\m(serialsfile) not found"
  313. if not readable \m(serialsfile) exit 1 "\m(serialsfile) not readable"
  314.  
  315. fopen /read \%c \m(serialsfile)        # Open serials file
  316. if fail fatal                # Check for failure
  317. # Seek to line with this hostname
  318. fseek /find:"^\fupper(\m(hostname))[\9\32]" \%c 0
  319. if fail fatal "Hostname [\m(hostname)] not found in HP serials file"
  320. fread /line \%c line            # Read the line
  321. fclose \%c                # Close the file
  322.  
  323. .\%n := \fsplit(\m(line),&a,)        # Split the line into words
  324. .pass := \&a[6]                # The sixth word is the host password
  325.  
  326. if \m(dopassword) {            # 2-element password array
  327.     dcl \&p[2] = \m(pass) ""        # Try serials file password first
  328. } else {
  329.     dcl \&p[2] =  "" \m(pass)        # Try blank password first
  330. }
  331. if \m(dodebug) show array p
  332.  
  333. # If this is a configuration run open the log file
  334.  
  335. if not \m(connect) {
  336.     if not directory \m(logdirectory) {    # Check if log directory exists
  337.     fatal "Log directory \m(logdirectory) not found or not a directory"
  338.     }
  339.     cd \m(logdirectory)            # cd to the log directory
  340.     if fail fatal "cd \m(logdirectory)"    # failure is fatal
  341.  
  342.     .sessionlog := \m(logdirectory)/\m(hostname)-session.log # Session log name
  343.     log session \m(sessionlog)        # Open and start the session log
  344. } else {
  345.     # Make session log in current directory
  346.     log session \m(hostname)-connect.log
  347. }
  348. if fail warn "FAILURE TO OPEN \m(sessionlog)"
  349. message "BEGIN ilosetup \m(version) \m(date)"
  350.  
  351. # Open the connection and log in
  352.  
  353. .protocol = "none"            # No protocol yet
  354.  
  355. message "TRYING TELNET..."
  356. set host \m(fullhost)            # Try Telnet (port 23) first
  357. if success {                # Telnet OK - send user name
  358.     input 10 "Login Name: "
  359.     if fail fatal "Telnet Login Name timeout"
  360.     lineout \m(loginname)
  361.     input 10 "password: "
  362.     if fail fatal "Telnet password timeout"
  363.     .protocol = telnet
  364.     message "PROTOCOL TELNET"
  365. } else {                # No telnet - try SSH
  366.     message "TELNET FAILED - TRYING SSH..."
  367.     set host /pty ssh -e none -l \m(loginname) \m(fullhost)
  368.     if fail fatal "SSH \m(fullhost) failed."
  369.     # Watch out for RSA key fingerprint complaint and "are you sure?" prompt...
  370.     minput 20 "password: " "continue connecting (yes/no)? "
  371.     if fail fatal "No response on SSH connection to \m(fullhost)"
  372.     if == \v(minput) 2 {
  373.     lineout "yes"
  374.     input 20 "password: "
  375.     if fail fatal "SSH password timeout"
  376.     }
  377.     .protocol = "ssh"
  378.     message "PROTOCOL SSH"
  379. }
  380. # If we arrive here we should have the password prompt.
  381. # NOTE: This logic will need to be changed if it is possible to log in
  382. # via SSH (or some secure form of Telnet) without a password.
  383.  
  384. .haveiloprompt = 0
  385. for i 1 2 1 {
  386.     lineout \&p[i]            # Send console password
  387.     if fail fatal "Output password to \m(fullhost) failed."
  388.     minput 30 \m(iloprompt) "Permission denied" "Invalid login."
  389.     if fail fatal "Timed out waiting for iLO CLI prompt."
  390.     if == \v(minput) 1 {
  391.         .haveiloprompt = 1
  392.         break 
  393.     }
  394.     if \m(dopassword) {
  395.         message "Password from serials file failed - trying empty password..."
  396.     } else {
  397.         message "Empty password failed - trying password from serials file..."
  398.     }
  399.     # After bad password Telnet prompts again for the username - ssh does not.
  400.     if eq "\m(protocol)" "telnet" {
  401.         input 10 "Login Name: "
  402.     if fail fatal "Telnet Login Name timeout"
  403.     lineout \m(loginname)
  404.     }
  405.     input 2 "password: "
  406.     if not quiet echo
  407.     if == \m(i) 2 fatal "Password not accepted"
  408.     if quiet continue
  409. }
  410. if not \m(haveiloprompt) fatal "iLO console login failure"
  411.  
  412. # CONNECT - Go interactive and do not execute the rest of the script.
  413.  
  414. .haveconnection = 1            # Have connection
  415.  
  416. if \m(connect) {            # Interactive session requested
  417.     lineout                # Send a carriage return
  418.     connect                # Connect to remote
  419.     if not open connection exit        # Exit from Kermit if connection closed
  420.     stop                # Otherwise don't exit
  421. }
  422.  
  423. # Automated configuration run...
  424.  
  425. # Prompt for created-user ID if it wasn't in the environment
  426. .userid := \$(ilo_userid)
  427. .userpass := \$(ilo_userpass)
  428. while not defined userid {        # Prompt for created user ID
  429.     askq userid "User ID for created account: "
  430. }
  431. # Prompt for created-user password if it wasn't in the environment
  432. while not defined userpass {    
  433.     askq /echo:* userpass "Password for created account: "
  434. }
  435.  
  436. # Send iLO commands...
  437.  
  438. .state = iLO
  439. ilocommand "create /map1/accounts1 username=\m(userid) -
  440.  password=\m(userpass) group=admin,config,oemhp_vm,oemhp_rc,oemhp_power"
  441. ilocommand "set /map1/config1 oemhp_telnetenable=yes"
  442. ilocommand "set /system1 oemhp_server_name=\m(hostname)"
  443. ilocommand "set /map1/config1 oemhp_rc_acquire=yes" # 1.07
  444.  
  445. lineout "power"                # Check power state
  446. minput 20 {server power is currently: On} {server power is currently: Off} 
  447. if fail fatal "No response to power command"
  448. switch \v(minput) {
  449.   :1, getiloprompt, lineout "reset /system1 hard", break
  450.   :2, getiloprompt, lineout "power on", break
  451. }
  452. .max = 10
  453. for i 1 \m(max) 1 {            # Wait for power to come on
  454.     lineout "power"
  455.     minput 20 {server power is currently: On} {server power is currently: Off} 
  456.     if fail fatal "No response to power command"
  457.     if == \v(minput) 1 break
  458.     xsleep 10
  459.     getiloprompt
  460.     lineout "power on"
  461.     getiloprompt
  462. }
  463. if >= \m(i) \m(max) fatal "POWER ON DIDN'T TURN POWER ON"
  464.  
  465. # Enter VSP [virtual serial port]...
  466.  
  467. message "Attempting to enter VSP..."
  468. if flag {
  469.     set debug timestamps on
  470.     log debug \m(hostname)-debug.log
  471. }
  472. ilocommand "vsp"
  473.  
  474. # Here we have to allow for many prompts and responses
  475. # including a Device Status Request escape sequence from the host
  476. # (ESC [ 5 n) which must be replied to.
  477.  
  478. while true { 
  479.     minput 300 -
  480.      {Press "ESC+0" for System Maintenance Menu} -
  481.      {\27[5n} -
  482.      {Requested service is unavailable\, it is already in use} -
  483.      {The server is not powered on} -
  484.      {The Virtual Serial Port is not available}
  485.     if fail {                # If INPUT fails
  486.     output \{27}\{40}        # Escape back to iLO prompt
  487.     message "INPUT: \v(inmessage)"    # and back out from there.
  488.     if open connection {        # Is the connection still open?
  489.         fatal "INPUT FAILED WITH CONNECTION STILL OPEN"
  490.     } else {
  491.         fatal "CONNECTION CLOSED BY SERVER"
  492.     }
  493.     }
  494.     if == 1 \v(minput) break        # What we want...
  495.     if == 2 \v(minput) {        # Device Status Report Request
  496.     output \27[0n            # Send Device Status Report (I'm OK)
  497.     continue
  498.     } 
  499.     getiloprompt            # Soak up rest of message
  500.     lineout "exit"            # Exit from iLO
  501.     fatal "VSP service unavailable" 
  502.     .rc = 1
  503.     forward DONE
  504. }
  505. if flag if open debug-log close debug-log
  506.  
  507. output \{27}0                # Send ESC and 0
  508. input 60 "MMenu> "            # Get MMenu> prompt
  509. if fail fatal "Timed out waiting for MMenu> prompt"
  510. .state = MMenu
  511. lineout RBSU                # Enter RBSU
  512. input 30 "rbsu> "            # Wait for rbsu> prompt
  513. if fail fatal "Timed out waiting for first rbsu> prompt"
  514. .state = rbsu
  515.  
  516. set output pacing \m(outputpacing)    # Throttle output speed
  517.  
  518. # Send the RBSU commands.
  519. # Here we could give a SHOW CONFIG VIRTUAL SERIAL PORT command and parse the
  520. # BIOS Serial Console Port menu choices in case the menu ever changes.
  521.  
  522. rbsucommand "SET CONFIG VIRTUAL SERIAL PORT 2"
  523. rbsucommand "SET CONFIG BIOS SERIAL CONSOLE PORT 4"
  524. rbsucommand "SET CONFIG BIOS SERIAL CONSOLE BAUD RATE 4"
  525. rbsucommand "SET CONFIG EMS CONSOLE 3"
  526.  
  527. lineout EXIT                # Exit from RBSU
  528. pause 1                    # Wait a sec and...
  529. output \27(                # Escape back to iLO
  530. getiloprompt                # Get iLO prompt
  531. .state = iLO
  532.  
  533. .rc = 0                    # Our return code - assume success.
  534. if not \m(poweroff) {            # Turn power off now?
  535.     
  536.     if not \m(reset) message "LEAVING POWER ON"    # No...
  537.     forward DONE
  538. }
  539. message "TURNING POWER OFF"        # Yes...
  540. .max = 10                # How many times to try.
  541. for i 1 \m(max) 1 {            # Loop for each try.
  542.     lineout "power off"            # Send power off command.
  543.     sleep 15                # Give it a little time
  544.     getiloprompt            # Get iLO prompt    
  545.     lineout "power"            # Send "power" command to check
  546.     minput 30 {server power is currently: Off} {server power is currently: On} 
  547.     if == \v(minput) 1 {        # Power is off
  548.     getiloprompt            # Read next iLO prompt
  549.     forward DONE            # Exit loop and skip ahead
  550.     }
  551.     sleep 2*i                # Sleep more each time
  552.     warn "RETRYING POWER OFF [\m(i)]..."
  553.     getiloprompt
  554. }
  555. warn "WARNING: POWER OFF FAILED AFTER \m(max) TRIES"
  556. .rc = 1
  557.  
  558. :DONE
  559. define fatal end 0            # No fatal errors from now on
  560. if \m(haveconnection) {            # If we have a connection...
  561.     if \m(reset) {            # Reset the machine
  562.     .reset = 0            # Prevent recursion in case of error
  563.     message "HARD RESET AND CLOSE"
  564.     ilocommand "cd /Map1"
  565.     lineout "reset"
  566.     sleep 5
  567.     close connection        # Close our end of the connection
  568.     } else {
  569.     if not \m(rc) {
  570.         message "EXIT WITHOUT RESET"
  571.         lineout "exit"        # Exit from iLO
  572.         input 30 "CLI session stopped" # Wait for final gasp
  573.     }
  574.     if open connection hangup    # Close our end too just in case
  575.     }
  576. }
  577. .haveconnection = 0
  578. message "END: STATUS: \m(rc)"
  579. if open session-log close session-log    # Close log
  580. exit \m(rc)                # Exit from script and Kermit
  581.  
  582. ; Local Variables:
  583. ; comment-column:40
  584. ; comment-start:"# "
  585. ; End:
  586.