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