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