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

  1. #!/p/kd/fdc/RHEL4/wermit +
  2. #!/p/kd/fdc/solaris9/wermit +
  3. #!/p/sy/subsys/scripts/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. .scriptversion = 1.10
  14. .scriptdate = 20100322
  15. #
  16. #   Created:  
  17. #    1.01 20090428
  18. #
  19. #   Modified:
  20. #    1.10 20100322: Allow hyphens in host names;
  21. #    1.09 20091221: Added raid / noraid option to configure RAID (or not);
  22. #                   added telnet and ssh options to specify which to try first;
  23. #                   added iloonly option to only do iLO commands.
  24. #    1.08 20091123: Undo 1.07 because the command doesn't work on all models.
  25. #                   Fix echoing of username when typed in manually.
  26. #                   Capture iLO firmware version and record in log.
  27. #                   Don't produce a debug.log unless asked.
  28. #    1.07 20091113: Enable remote console acquire (spelled "aquire")
  29. #    1.06 20091104: Handle login failure on Telnet connections.
  30. #    1.05 20091104: Add 'usepassword' and 'nopassword' options;
  31. #                   Try both in specified order.
  32. #    1.04 20091103: Handle console login failure more gracefully;
  33. #                   Allow empty password in serials file.
  34. #    1.03 20091028: Remove IF WRITEABLE check for log directory
  35. #    1.02 20090916: Prompt for username if not in environment.
  36. # Usage: [ ilo_username=x ] [ ilo_userpass=y ] ilosetup hostname [ keywords ]
  37. #
  38. # After the hostname you can put zero or more of these keywords:
  39. #
  40. #   connect - make an interactive connection after logging in
  41. #   debug - create a debug log (very big, only for Frank)
  42. #   usepassword - try to log in first with a serials file password
  43. #   nopassword - try to log in first with a blank password
  44. #   nopoweroff - don't power the host machine off at the end
  45. #   noreset - no reset at end
  46. #   poweroff - power the host machine off at the end (default)
  47. #   raid - set Logical Drive 1 to RAID 1
  48. #   noraid - Don't mess with RAID configuration (default)
  49. #   iloonly - Only do iLO commands and don't reset or power off the server
  50. #   quiet - only show error, warning, or status messages on the screen
  51. #   reset - reset at end (default)
  52. #   verbose - watch the script play on the screen (default)
  53. #
  54. # The keywords can be abbreviated to any unique left substring.
  55. #
  56. # Examples for host fillmore:
  57. #   ilosetup fillmore
  58. #   ilosetup fillmore poweroff
  59. #   ilosetup fillmore p (same as poweroff)
  60. #   ilosetup fillmore p q (poweroff and run quietly)
  61. #
  62. # The hostname should match (case independently) a hostname in the HP
  63. # serials file, which is just the first part of the first field of the
  64. # IP hostname, e.g. fillmore instead of fillmore-console.cc.columbia.edu.
  65. # But if you do include the extra fields, the script allows for it.
  66. #
  67. # Exit status:
  68. #   0 on success; 1 on failure.
  69. #
  70. # Creates in the log directory (logdirectory defined below):
  71. #   A session log file xxx-session.log (xxx is the hostname)
  72. #  (the log directory itself is created if it doesn't exist)
  73. #
  74. # Requires: C-Kermit 8.0.212 or later because it uses some recent features.
  75. # Version 8.0.211 or earlier lack at least the following, which are used in
  76. # this script:
  77. #  . FSEEK /FIND:string
  78. #  . The \fkwval() function
  79. # (The script could be recoded at some effort to use older ways of doing
  80. #  the same things.)
  81. #
  82. # If this script is run directly as if it were a shell command, the C-Kermit
  83. # binary that executes it is the one in the "kerbang line" (the first line in
  84. # the file).  Of course you can move the binary anywhere you want, or rename
  85. # it, but then you have to change the kerbang line to match.
  86. #
  87. # Other dependencies:
  88. #  . The HP serial numbers file (path defined a few lines down)
  89. #  . That the first field in a serials file record is the simple hostname
  90. #    (e.g. FILLMORE, not FILLMORE-CONSOLE or FILLMORE-CONSOLE.CC.COLUMBIA.EDU)
  91. #  . That the corresponding iLO console password is the 6th field.
  92. #
  93. # Documentation: http://www.columbia.edu/~fdc/net/ilosetup.html
  94. #
  95. ###############################################################################
  96.  
  97. if < \v(version) 800212 {               # Check Kermit version
  98.     exit 1 "\m(myname): C-Kermit 8.0.212 or later required"
  99. }
  100. # Debugging
  101.  
  102. .dodebug = 0
  103. if > 0 \flen(\$(DEBUG)) if numeric \$(DEBUG) if \$(DEBUG) .dodebug = 1
  104. if \m(dodebug) {
  105.     echo DEBUGGING ON
  106.     echo ILO_USERID=[\$(ilo_userid)]
  107.     echo ILO_USERPASS=[\$(ilo_userpass)]
  108. }
  109. if not background set quiet off         # Allow messages (for foreground use)
  110. set session-log text            # filter out escape sequences
  111. set session-log timestamp               # Put timestamps in session log
  112.  
  113. # "Constant" definitions (that can be changed)...
  114.  
  115. .iloprompt = ">hpiLO-> "                # HP iLO console prompt
  116. .logdirectory = /var/log/ilosetup       # Directory for session log
  117. .outputpacing = 100                     # Intercharter pacing for OUTPUT (msec)
  118. .poweroff = 0                           # Whether to power off at end
  119. .connect = 0                            # Make an interactive connection
  120. .telnet = 1                             # Default connection method is Telnet
  121. .iloonly = 0                            # Only do iLO commands
  122. .ssh = 0                                # and is not SSH
  123. .reset = 1                              # Reset at end
  124. .dopassword = 1                         # Use password from serials file
  125. .doingraid = 0                          # Don't configure RAID unless asked
  126. .serialsfile = /p/sy/subsys/HP/serials  # Path of blade serial numbers file
  127. .hostsuffix = -console.cc.columbia.edu  # Hostname suffix
  128. .loginname = Administrator              # iLO login name
  129.  
  130. if equ "\v(user)" "fdc" {               # Development / testing
  131.     .logdirectory = ~/net/shrimp # (dev/test)
  132.     # if \m(dodebug) .serialsfile = ./serials
  133. }
  134. .myname := \fbasename(\v(cmdfile))      # Name of this script without path
  135.  
  136. if \m(dodebug) show args                # development/test  
  137.  
  138. # Define command-line option keywords
  139.  
  140. dcl \&k[] = poweroff nopoweroff verbose quiet telnet ssh help iloonly -
  141.             connect debug reset noreset usepassword nopassword raid noraid
  142. array sort &k                           # Alphabetize them for table lookup
  143.  
  144. # If command line is invalid give usage message and exit
  145.  
  146. def usage {                             # Give usage message and exit
  147.     .verbose = "verbose"
  148.     .turnoff = "nopoweroff"
  149.     .doreset = "noreset"
  150.     .usepass = "nopassword"
  151.     .doraid = "raid"
  152.     .dotelnet = "telnet"
  153.     if not \m(telnet) .dotelnet = "ssh"
  154.     echo -
  155. "Usage: [ ilo_username=x ] [ ilo_userpass=y ] \m(myname) hostname [ options ]"
  156.     echo "Options:"
  157.     show array k
  158.     if quiet .verbose = "quiet"
  159.     if \m(poweroff) .turnoff = "poweroff"
  160.     if \m(reset) .doreset = "reset"
  161.     if \m(dopassword) .usepass = "usepassword"
  162.     xecho "Default options: \m(verbose) \m(turnoff)"
  163.     echo " \m(dotelnet) \m(doreset) \m(usepass) \m(doraid)"
  164.     echo "Optional environment variables:"
  165.     echo " ilo_userid:   user ID to create"
  166.     echo " ilo_userpass: password for user ID"
  167.     echo " DEBUG=1: turn on debugging"
  168.     echo "If created user ID and password are not found in the environment,"
  169.     echo "you are prompted for them."
  170.     echo
  171.     exit 1
  172. }
  173. # Parse and validate command line
  174.  
  175. if not def \%1 {
  176.     echo "FATAL - A hostname is required"
  177.     usage                               # A hostname is required
  178. }
  179. .hostname := \flower(\fword(\%1,1,.))   # First field of hostname argument
  180. .\%t := \findex(-console,\m(hostname))  # If "-console" found in hostname...
  181. if \%t .hostname := \s(hostname[1:\%t-1]) # remove it.
  182. .fullhost := \m(hostname)\m(hostsuffix) # Make full IP hostname
  183.  
  184. # Parse optional command-line keywords...
  185.  
  186. while defined \%2 {                     # While we still have trailing args...
  187.     .tmp := \%2
  188.     .\%2 := \ftablelook(\%2,&k)         # Look up this keyword and get index
  189.     if < \%2 1 {                        # Not found or ambiguous
  190.         echo "Invalid command-line option: '\m(tmp)'"
  191.         usage                   
  192.     }
  193.     .\%2 := \&k[\%2]                    # Resolve index to keyword itself
  194.     switch \%2 {                        # Handle the keyword
  195.       :iloonly                          # Do iLO commands only
  196.         .iloonly = 1
  197.         break
  198.       :help                             # Help
  199.         dousage                         # (exits)
  200.       :debug                            # Debug
  201.         .dodebug = 1
  202.         break 
  203.       :connect                          # Connect (interactive session)
  204.         .connect = 1
  205.         break
  206.       :poweroff                         # Leave power off at end
  207.         .poweroff = 1
  208.         break
  209.       :nopoweroff                       # Leave power on at end
  210.         .poweroff = 0
  211.         break
  212.       :quiet                            # Silent running (don't watch session)
  213.         set quiet on
  214.         set input echo off
  215.         break
  216.       :verbose                          # Show session on screen
  217.         set quiet off
  218.         set input echo on
  219.         break
  220.       :reset                            # Reset at end (default)
  221.         .reset = 1
  222.         break
  223.       :noreset                          # No reset at end
  224.         .reset = 0
  225.         break
  226.       :usepassword                      # Use password from serials file
  227.         .dopassword = 1
  228.         break
  229.       :nopassword                       # Use empty password
  230.         .dopassword = 0
  231.         break
  232.       :raid                             # Configure RAID 1 if RAID 0
  233.         .doingraid = 1
  234.         break
  235.       :noraid                           # Don't do anything with RAID
  236.         .doingraid = 0
  237.         break
  238.       :telnet                           # Try Telnet first
  239.         .telnet = 1
  240.         break
  241.       :ssh                              # Try ssh first
  242.         .telnet = 0
  243.     }
  244.     shift                               # Shift argument list to the left
  245. }
  246. # Macro definitions...
  247.  
  248. define logit {                          # Write a message to session log
  249.     if not open session-log end 0
  250.     .\%1 := \frpad(\%1,7,.)             # Make fields line up
  251.     writeln session                     # Make sure we're on a new line
  252.     writeln session "%% \%1 - \m(myname): \v(timestamp) [\m(hostname)] - \%2"
  253. }
  254. define message {                        # Print and log a progress message
  255.     if not quiet echo                   # To avoid mixing up screen text
  256.     echo "MESSAGE - \%1"                # Write message to screen (stdout)
  257.     logit MESSAGE "\%1"                 # and to session log
  258. }
  259. define warn {                           # Print and log warning message
  260.     if not quiet echo                   # To avoid mixing up screen text
  261.     echo "WARNING - \%1"                # Write it to to stdout
  262.     logit WARNING "\%1"                 # and to session log
  263. }
  264. define fatal {                          # Fatal error
  265.     .rc = 1                             # Failure exit code
  266.     echo "FATAL - \%1"                  # Write error message to screen
  267.     if \m(haveconnection) {             # If we have a connection
  268.         if not equ "\m(state)" "iLO" {  # but w're not in iLO...
  269.             output \{27}\{40}           # ESC+( - Escape back to iLO 
  270.             input 8 \m(iloprompt)       # and wait 8 sec for the prompt
  271.         }
  272.     }
  273.     logit FATAL "\%1"                   # write message to session log
  274.     logit INFO  "Most recent error: \v(errstring)"
  275.     goto DONE
  276. }
  277. define dotelnet {
  278.     set login user                      # Force a login prompt
  279.     set host \m(fullhost)               # Try Telnet (port 23)
  280.     if fail end 1                       # Return failure code if no go
  281.     input 10 "Login Name: "             # Wait for login prompt
  282.     if fail end 1 "Telnet Login Name timeout"
  283.     lineout \m(loginname)               # Send user ID
  284.     input 10 "password: "               # Wait for password prompt
  285.     if fail end 1 "Telnet password timeout"
  286.     end 0
  287. }
  288. define dossh {
  289.     set host /pty ssh -e none -l \m(loginname) \m(fullhost)
  290.     if fail end 1
  291.     # Watch out for RSA key fingerprint complaint and "are you sure?" prompt...
  292.     minput 20 "password: " "continue connecting (yes/no)? "
  293.     if fail end 1 "No response on SSH connection to \m(fullhost)"
  294.     if == \v(minput) 2 {
  295.         lineout "yes"
  296.         input 20 "password: "
  297.         if fail end 1 "SSH password timeout"
  298.     }
  299.     end 0
  300. }
  301. define getiloprompt {                   # Get iLO prompt
  302.     if not def \%1 .\%1 = 30            # Default timeout (secs)
  303.     if not numeric \%1 fatal "Non-numeric INPUT timeout"
  304.     input \%1 \m(iloprompt)             # Wait for the prompt
  305.     if fail fatal "Timed out waiting for iLO CLI prompt."
  306. }
  307. define ilocommand {                     # Send an iLO command and get response
  308.     local cmd                           # Local (stack) variable
  309.     .cmd := \fword(\%1,1)               # First word of command
  310.     msleep 10                           # Pause 10 msec just in case
  311.     lineout \%1                         # Send the full command
  312.     if fail fatal "Output failed"       # Check for i/o error
  313.     clear input                         # Empty the INPUT result buffer
  314.     getiloprompt \%2                    # Get response and next iLO prompt
  315.     # The "power on/off" and "vsp" commands give no response...
  316.     if not equ "\%1" "power" {          # But "power" by itself does...
  317.         if ( equ "\m(cmd)" "power" || equ "\m(cmd)" "vsp" ) end 0
  318.     }
  319.     .status = 9                         # Dummy inital status value
  320.     .tmp := \freplace(\v(input),\13,)   # Strip carriage returns (but not LFs)
  321.     .lines := \fsplit(\m(tmp),&a,\10)   # Split captured text into lines
  322.     undef iloversion                    # iLO firmware version
  323.     for i 1 lines 1 {                   # Loop through lines
  324.         void \fkwval(\&a[i])            # to get status and message values...
  325.     }     
  326.     if equ "\m(cmd)" "show" {
  327.         if def version .iloversion := \m(version) [\m(date)]
  328.         if def iloversion message "iLO Firmware \m(iloversion)"
  329.     }
  330.     if not numeric \m(status) .status = 9 # Just in case
  331.     if == \m(status) 0 end 0            # If status was 0 then OK
  332.     if ( equ "\m(cmd)" "create" && equ "\&a[5]" "Duplicate login name." ) {
  333.         end 0                           # This is not an error
  334.     }
  335.     fatal "ILO COMMAND \%1: \m(error_tag)" # Fail with nonzero status
  336. }
  337. define rbsucommand {  # Send a command to RBSU and get next rbsu> prompt.
  338.     local i sleep pacing max
  339.     msleep 10                           # Pause 10 msec just in case
  340.     lineout \%1                         # Send the command
  341.     # Check for error response or next rbsu> prompt.
  342.     # Note: RBSU commands have no consistent error indication;
  343.     # There may be some error responses that are not caught here...
  344.     minput 30 {rbsu>} {Invalid Command} {Incomplete Command} {Invalid Option}
  345.     if fail fatal "RBSU: Timeout after [\%1]"
  346.     if == \v(minput) 1 end 0            # No error message - done.
  347.     warn "RBSU COMMAND FAILURE [\%1]"
  348.     .max = 10
  349.     for i 1 \m(max) 1 {                 # Try again this many times.
  350.         increment pacing 40             # Slower pacing each time.
  351.         warn "RETRYING WITH PACING = \m(pacing) msec..."
  352.         msleep 10*i                     # Pause a little longer each time
  353.         lineout \%1                     # Send the command
  354.         minput 30 {rbsu>} -
  355. {Invalid Command} {Incomplete Command} {Invalid Option}
  356.         if fail fatal "RBSU: Timeout [\%1]"
  357.         if == \v(minput) 1 break        # No error message - done.
  358.     }
  359.     if > \m(i) \m(max) fatal "RBSU command error"
  360.     warn "RBSU COMMAND RECOVERY OK"
  361. }
  362. def xsleep {                            # (for debugging display)
  363.     if not def \%1 .\%1 = 1
  364.     if quiet {
  365.         sleep \%1 
  366.     } else {
  367.         local i
  368.         for i 1 \%1 1 { sleep 1, xecho . }
  369.         echo
  370.     }
  371. }
  372.  
  373. # Execution begins here: Get host password from HP serial numbers file...
  374.  
  375. .haveconnection = 0                     # No connection yet
  376. set input cancellation off              # Essential because of Esc sequences
  377. set exit warning off                    # Allow exit without warning
  378.  
  379. if \m(dodebug) directory \m(serialsfile) # Check and open serials file
  380. if not exist \m(serialsfile) exit 1 "\m(serialsfile) not found"
  381. if not readable \m(serialsfile) exit 1 "\m(serialsfile) not readable"
  382.  
  383. fopen /read \%c \m(serialsfile)         # Open serials file
  384. if fail fatal                           # Check for failure
  385. # Seek to line with this hostname
  386. fseek /find:"^\fupper(\m(hostname))[\9\32]" \%c 0
  387. if fail fatal "Hostname [\m(hostname)] not found in HP serials file"
  388. fread /line \%c line                    # Read the line
  389. fclose \%c                              # Close the file
  390.  
  391. .\%n := \fsplit(\m(line),&a,,-)         # Split the line into words
  392. .pass := \&a[6]                         # The sixth word is the host password
  393.  
  394. if \m(dopassword) {                     # 2-element password array
  395.     dcl \&p[2] = \m(pass) ""            # Try serials file password first
  396. } else {
  397.     dcl \&p[2] =  "" \m(pass)           # Try blank password first
  398. }
  399. if \m(dodebug) show array p
  400.  
  401. # If this is a configuration run open the log file
  402.  
  403. if not \m(connect) {
  404.     if not directory \m(logdirectory) { # Check if log directory exists
  405.         fatal "Log directory \m(logdirectory) not found or not a directory"
  406.     }
  407.     cd \m(logdirectory)                 # cd to the log directory
  408.     if fail fatal "cd \m(logdirectory)" # failure is fatal
  409.  
  410.     .sessionlog := \m(logdirectory)/\m(hostname)-session.log # Session log name
  411.     log session \m(sessionlog)          # Open and start the session log
  412. } else {
  413.     # Make session log in current directory
  414.     log session \m(hostname)-connect.log
  415. }
  416. if fail warn "FAILURE TO OPEN \m(sessionlog)"
  417. message "BEGIN ilosetup \m(scriptversion) \m(scriptdate)"
  418.  
  419. # Open the connection and log in
  420.  
  421. .protocol = "none"                      # No protocol yet
  422.  
  423. if \m(telnet) {                         # Try telnet first
  424.     message "TRYING TELNET..."
  425.     dotelnet
  426.     if fail {                           # If it fails try ssh
  427.         hangup                          # First close Telnet connection
  428.         message "TELNET FAILED - TRYING SSH..."
  429.         dossh
  430.         if fail fatal "SSH \m(fullhost) failed."
  431.         .protocol = "ssh"
  432.     }
  433.     .protocol = telnet
  434. } else {                                # Try ssh first
  435.     message "TRYING SSH..."
  436.     dossh
  437.     if fail {                           # If it fails try Telnet
  438.         hangup                          # First close ssh connection
  439.         message "SSH FAILED - TRYING TELNET..."
  440.         dotelnet
  441.         if fail fatal "TELNET \m(fullhost) failed."
  442.         .protocol = telnet
  443.     }
  444.     .protocol = "ssh"
  445. }
  446.  
  447. # If we arrive here we should have the password prompt.
  448. # NOTE: This logic will need to be changed if it is possible to log in
  449. # via SSH (or some secure form of Telnet) without a password.
  450.  
  451. .haveiloprompt = 0
  452. for i 1 2 1 {
  453.     lineout \&p[i]                      # Send console password
  454.     if fail fatal "Output password to \m(fullhost) failed."
  455.     minput 30 \m(iloprompt) "Permission denied" "Invalid login."
  456.     if fail fatal "Timed out waiting for iLO CLI prompt."
  457.     if == \v(minput) 1 {
  458.         .haveiloprompt = 1
  459.         break 
  460.     }
  461.     if \m(dopassword) {
  462.         message "Password from serials file failed - trying empty password..."
  463.     } else {
  464.         message "Empty password failed - trying password from serials file..."
  465.     }
  466.     # After bad password Telnet prompts again for the username - ssh does not.
  467.     if eq "\m(protocol)" "telnet" {
  468.         input 10 "Login Name: "
  469.         if fail fatal "Telnet Login Name timeout"
  470.         lineout \m(loginname)
  471.     }
  472.     input 2 "password: "
  473.     if not quiet echo
  474.     if == \m(i) 2 fatal "Password not accepted"
  475.     if quiet continue
  476. }
  477. if not \m(haveiloprompt) fatal "iLO console login failure"
  478.  
  479. # CONNECT - Go interactive and do not execute the rest of the script.
  480.  
  481. .haveconnection = 1                     # Have connection
  482.  
  483. if \m(connect) {                        # Interactive session requested
  484.     lineout                             # Send a carriage return
  485.     connect                             # Connect to remote
  486.     if not open connection exit         # Exit from Kermit if connection closed
  487.     stop                                # Otherwise don't exit
  488. }
  489.  
  490. # Automated configuration run...
  491.  
  492. # Prompt for created-user ID if it wasn't in the environment
  493. .userid := \$(ilo_userid)
  494. .userpass := \$(ilo_userpass)
  495. while not defined userid {              # Prompt for created user ID
  496.     ask userid "User ID for created account: "
  497. }
  498. # Prompt for created-user password if it wasn't in the environment
  499. while not defined userpass {    
  500.     askq /echo:* userpass "Password for created account: "
  501. }
  502. if \m(dodebug) {
  503.     set debug timestamps on
  504.     log debug \m(hostname)-debug.log
  505. }
  506.  
  507. # Send iLO commands...
  508.  
  509. .state = iLO
  510. ilocommand "show /system1/firmware1"    # Get iLO firmware version
  511. ilocommand "create /map1/accounts1 username=\m(userid) -
  512.  password=\m(userpass) group=admin,config,oemhp_vm,oemhp_rc,oemhp_power"
  513. ilocommand "set /map1/config1 oemhp_telnetenable=yes"
  514. ilocommand "set /map1/config1 oemhp_shared_console_enable=yes"
  515. ilocommand "set /system1 oemhp_server_name=\m(hostname)"
  516. # ilocommand "set /map1/config1 oemhp_rc_aquire=yes"
  517.  
  518. if \m(iloonly) {                        # Skip the rest if iloonly
  519.     .rc = 0                             # Set a good return code
  520.     forward done                        # and finish up
  521. }
  522. lineout "power"                         # Check power state
  523. minput 20 {server power is currently: On} {server power is currently: Off} 
  524. if fail fatal "No response to power command"
  525. switch \v(minput) {
  526.   :1, getiloprompt, lineout "reset /system1 hard", break
  527.   :2, getiloprompt, lineout "power on", break
  528. }
  529. .max = 10
  530. for i 1 \m(max) 1 {                     # Wait for power to come on
  531.     lineout "power"
  532.     minput 20 {server power is currently: On} {server power is currently: Off} 
  533.     if fail fatal "No response to power command"
  534.     if == \v(minput) 1 break
  535.     xsleep 10
  536.     getiloprompt
  537.     lineout "power on"
  538.     getiloprompt
  539. }
  540. if >= \m(i) \m(max) fatal "POWER ON DIDN'T TURN POWER ON"
  541.  
  542. # Enter VSP [virtual serial port]...
  543.  
  544. :dovsp
  545.  
  546. message "Attempting to enter VSP..."
  547. ilocommand "vsp"
  548.  
  549. # Here we have to allow for many prompts and responses
  550. # including a Device Status Request escape sequence from the host
  551. # (ESC [ 5 n) which must be replied to.
  552.  
  553. while true { 
  554.     minput 300 -
  555.      {Press "ESC+0" for System Maintenance Menu} -
  556.      {\27[5n} -
  557.      {Press <F8> to run the Option ROM Configuration for Arrays Utility} -
  558.      {Requested service is unavailable\, it is already in use} -
  559.      {The server is not powered on} -
  560.      {The Virtual Serial Port is not available}
  561.     if fail {                           # If INPUT fails
  562.         output \{27}\{40}               # Escape back to iLO prompt
  563.         message "INPUT: \v(inmessage)"  # and back out from there.
  564.         if open connection {            # Is the connection still open?
  565.             fatal "INPUT FAILED WITH CONNECTION STILL OPEN"
  566.         } else {
  567.             fatal "CONNECTION CLOSED BY SERVER"
  568.         }
  569.     }
  570.     if == 1 \v(minput) break            # What we want...
  571.     if == 2 \v(minput) {                # Device Status Report Request
  572.         output \27[0n                   # Send Device Status Report (I'm OK)
  573.         continue
  574.     } 
  575.     if == 3 \v(minput) {                # If we are configuring RAID
  576.         if not \m(doingraid) continue
  577.         output \{27}8                   # Send Esc 8
  578.         break                           # and quit this loop
  579.     }
  580.     getiloprompt                        # Soak up rest of message
  581.     lineout "exit"                      # Exit from iLO
  582.     fatal "VSP service unavailable" 
  583.     .rc = 1
  584.     forward DONE
  585. }
  586. if not \m(doingraid) goto dorbsu        # If not doing RAID skip to next part
  587.  
  588. .havecli = 0                            # Flag for have CLI prompt
  589. input 20 "CLI> "                        # Wait for CLI prompt
  590. if fail {
  591.     message "Arrays CLI> prompt did not appear - skipping..."
  592.     forward dorbsu
  593. }
  594. .havecli = 1
  595. set output pacing 200                   # Can't blast characters at CLI prompt
  596. clear input                             # Clear INPUT buffer
  597. lineout "physicaldrive * show"          # Show physical arrays
  598. input 30 "CLI> "                        # Wait for next CLI prompt
  599.  
  600. # Count the drives - \v(input) contains the results of the SHOW command"
  601.  
  602. .drives = 0              
  603. if \findex({Unknown Command},\v(input)) {
  604.     message "Command 'physicaldrive * show' garbled - increase OUTPUT PACING"
  605.     forward dorbsu
  606. }
  607. if \findex({Invalid physical drive number specified},\v(input)) {
  608.     message "Arrays CLI Invalid drive number specified - skipping"
  609.     forward dorbsu
  610. }
  611. .xx := \freplace(\v(input),\32,_)       # This solves a slight syntax problem
  612. if \findex(Physical_Drive_#_1,\m(xx)) incr drives
  613. if \findex(Physical_Drive_#_2,\m(xx)) incr drives
  614. if \findex(Physical_Drive_#_3,\m(xx)) incr drives
  615. if \findex(Physical_Drive_#_4,\m(xx)) incr drives
  616. if \findex(Physical_Drive_#_5,\m(xx)) incr drives
  617. if \findex(Physical_Drive_#_6,\m(xx)) incr drives
  618. if \findex(Physical_Drive_#_7,\m(xx)) incr drives
  619. if \findex(Physical_Drive_#_8,\m(xx)) incr drives
  620. if < \m(drives) 2 {
  621.     message "Physical Drives: \m(drives) - skipping..."
  622.     forward dorbsu
  623. }
  624. message "Physical Drives: \m(drives) - OK"
  625. set output pacing 250                   # Can't blast characters at CLI prompt
  626. clear input                             # Erase \v(input) again
  627. lineout "logicaldrive * show"           # Show logical drives
  628. input 30 "CLI> "                        # Wait for next CLI prompt
  629. if fail {
  630.     message "No CLI prompt after 'logicaldrive * show' after \v(inwait) secs"
  631.     .havecli = 0
  632.     forward dorbsu
  633. }
  634. .raid = -1
  635. if \findex({Unknown Command},\v(input)) {
  636.     message "Command 'logicaldrive * show' garbled - increase OUTPUT PACING"
  637.     forward dorbsu
  638. }
  639. .xx := \fsubstitute(\v(input),\32\44,_:) # Another syntax trick
  640. if \findex({Logical_Drive_#_1:RAID_0},\m(xx)) .raid = 0
  641. if \findex({Logical_Drive_#_1:RAID_1},\m(xx)) .raid = 1
  642. if < \m(raid) 0 {
  643.     message "Unexpected response to 'logicaldrives * show'"
  644.     forward dorbsu
  645. }
  646. if == \m(raid) 1 {
  647.     message "Logical Drive \# 1 RAID 1 - skipping..."
  648.     forward dorbsu
  649. }
  650. message "Logical Drive \# 1 RAID 0 - Changing to RAID 1..."
  651.  
  652. lineout "logicaldrive 1 delete"
  653. minput 20 "Are you sure? (y/n):" "Unknown Command"
  654. if fail {
  655.     message "Timeout after 'logical drive 1 delete' dialog - skipping...'"
  656.     forward dorbsu
  657. }
  658. if == \v(minput) 2 {
  659.     message "Command 'logicaldrive 1 delete' garbled - increase OUTPUT PACING"
  660.     forward dorbsu
  661. }
  662. output y                                # Just the letter 'y', no CR.
  663. message "Creating logicaldrive 1 RAID 1 mirrored..."
  664. input 10 "CLI> "                        # Wait for next CLI prompt
  665. if fail {
  666.     message "No CLI prompt after 'logicaldrive 1 delete' after \v(inwait) secs"
  667.     .havecli = 0
  668.     forward dorbsu
  669. }
  670. clear input                             # In case we want to collect text
  671. lineout "controller create type=logicaldrive raid=1 drives=1,2"
  672.  
  673. # Note: when this succeeds there is no message at all.
  674. # It takes about 20 seconds.  I don't know that any error messages would be.
  675.  
  676. input 30 "CLI> "                        # Wait for next CLI prompt
  677.  
  678. :dorbsu
  679.  
  680. if \m(havecli) {                        # Exit from CLI if we were in it
  681.     lineout exit                        # and wait for another menu
  682.     input 30 {Press "ESC+0" for System Maintenance Menu}
  683. }
  684. output \{27}0                           # Send ESC and 0
  685. input 60 "MMenu> "                      # Get MMenu> prompt
  686. if fail fatal "Timed out waiting for MMenu> prompt"
  687. .state = MMenu
  688. lineout RBSU                            # Enter RBSU
  689. input 30 "rbsu> "                       # Wait for rbsu> prompt
  690. if fail fatal "Timed out waiting for first rbsu> prompt"
  691. .state = rbsu
  692.  
  693. set output pacing \m(outputpacing)      # Throttle output speed
  694.  
  695. # Send the RBSU commands.
  696. # Here we could give a SHOW CONFIG VIRTUAL SERIAL PORT command and parse the
  697. # BIOS Serial Console Port menu choices in case the menu ever changes.
  698.  
  699. rbsucommand "SET CONFIG VIRTUAL SERIAL PORT 2"
  700. rbsucommand "SET CONFIG BIOS SERIAL CONSOLE PORT 4"
  701. rbsucommand "SET CONFIG BIOS SERIAL CONSOLE BAUD RATE 4"
  702. rbsucommand "SET CONFIG EMS CONSOLE 3"
  703.  
  704. lineout EXIT                            # Exit from RBSU
  705. pause 1                                 # Wait a sec and...
  706. output \27(                             # Escape back to iLO
  707. getiloprompt                            # Get iLO prompt
  708. .state = iLO
  709.  
  710. .rc = 0                                 # Our return code - assume success.
  711. if not \m(poweroff) {                   # Turn power off now?
  712.     
  713.     if not \m(reset) message "LEAVING POWER ON" # No...
  714.     forward DONE
  715. }
  716. message "TURNING POWER OFF"             # Yes...
  717. .max = 10                               # How many times to try.
  718. for i 1 \m(max) 1 {                     # Loop for each try.
  719.     lineout "power off"                 # Send power off command.
  720.     sleep 15                            # Give it a little time
  721.     getiloprompt                        # Get iLO prompt    
  722.     lineout "power"                     # Send "power" command to check
  723.     minput 30 {server power is currently: Off} {server power is currently: On} 
  724.     if == \v(minput) 1 {                # Power is off
  725.         getiloprompt                    # Read next iLO prompt
  726.         forward DONE                    # Exit loop and skip ahead
  727.     }
  728.     sleep 2*i                           # Sleep more each time
  729.     warn "RETRYING POWER OFF [\m(i)]..."
  730.     getiloprompt
  731. }
  732. warn "WARNING: POWER OFF FAILED AFTER \m(max) TRIES"
  733. .rc = 1
  734.  
  735. :DONE
  736. define fatal end 0                      # No fatal errors from now on
  737. if \m(haveconnection) {                 # If we have a connection...
  738.     if \m(reset) {                      # Reset the machine
  739.         .reset = 0                      # Prevent recursion in case of error
  740.         message "HARD RESET AND CLOSE"
  741.         ilocommand "cd /Map1"
  742.         lineout "reset"
  743.         sleep 5
  744.         close connection                # Close our end of the connection
  745.     } else {
  746.         if not \m(rc) {
  747.             message "EXIT WITHOUT RESET"
  748.             lineout "exit"              # Exit from iLO
  749.             input 30 "CLI session stopped" # Wait for final gasp
  750.         }
  751.         if open connection hangup       # Close our end too just in case
  752.     }
  753. }
  754. .haveconnection = 0
  755. message "END: STATUS: \m(rc)"
  756. if open session-log close session-log   # Close log
  757. exit \m(rc)                             # Exit from script and Kermit
  758.  
  759. ; Local Variables:
  760. ; comment-column:40
  761. ; comment-start:"# "
  762. ; End:
  763.