#!/p/kd/fdc/RHEL4/wermit + #!/p/kd/fdc/solaris9/wermit + #!/p/sy/subsys/scripts/wermit + # # IMPORTANT: The first line must indicate the path to C-Kermit 8.0.212 or 9.0 # and there must be a + sign after the path, separated by a space. # # ilosetup: C-Kermit Script to configure an HP server through its # iLO management interface. # # Author: Frank da Cruz, Columbia University, 2009-2011 # .scriptversion = 1.15 .scriptdate = 20110207 # # Created: # 1.01 20090428 # # Modified: # 1.15 20110207: Get to RBSU directly with ESC+9 in iLO3, which # avoids infinite DHCP query loop when machine is # not registered. # 1.14 20101217: Add notelnet option meaning don't even try to # connect to iLO with telnet. # 1.13 20101216: Allow for different response messages when attempting # to create an account that already exists and also # to power commands; fix usage message to say ilo_userid # instead of ilo_username. # 1.12 20101215: Get iLO version number. If 3 or higher do not attempt # certain oemhp configurations that have been discontinued. # Renamed MESSAGE macro to PMSG to avoid conflict. # 1.11 20100621: Added BIOS and POWERMODE:n options. # 1.10 20100322: Allow hyphens in host names; # 1.09 20091221: Added raid / noraid option to configure RAID (or not); # added telnet and ssh options to specify which to try first; # added iloonly option to only do iLO commands. # 1.08 20091123: Undo 1.07 because the command doesn't work on all models. # Fix echoing of username when typed in manually. # Capture iLO firmware version and record in log. # Don't produce a debug.log unless asked. # 1.07 20091113: Enable remote console acquire (spelled "aquire") # 1.06 20091104: Handle login failure on Telnet connections. # 1.05 20091104: Add 'usepassword' and 'nopassword' options; # Try both in specified order. # 1.04 20091103: Handle console login failure more gracefully; # Allow empty password in serials file. # 1.03 20091028: Remove IF WRITEABLE check for log directory # 1.02 20090916: Prompt for username if not in environment. # # Usage: [ ilo_userid=x ] [ ilo_userpass=y ] ilosetup hostname [ keywords ] # # After the hostname you can put zero or more of these keywords: # # connect - make an interactive connection after logging in # debug - create a debug log (very big, only for Frank) # usepassword - try to log in first with a serials file password # nopassword - try to log in first with a blank password # nopoweroff - don't power the host machine off at the end # noreset - no reset at end # poweroff - power the host machine off at the end (default) # pwrmode:n - set power regulator mode to n (1-4) # raid - set Logical Drive 1 to RAID 1 # bios - go straight to the BIOS prompt without doing anything else # noraid - Don't mess with RAID configuration (default) # iloonly - Only do iLO commands and don't reset or power off the server # quiet - only show error, warning, or status messages on the screen # reset - reset at end (default) # verbose - watch the script play on the screen (default) # # The keywords can be abbreviated to any unique left substring. # # Examples for host fillmore: # ilosetup fillmore # ilosetup fillmore poweroff # ilosetup fillmore pow (same as poweroff) # ilosetup fillmore pow q (poweroff and run quietly) # # The hostname should match (case independently) a hostname in the HP # serials file, which is just the first part of the first field of the # IP hostname, e.g. fillmore instead of fillmore-console.cc.columbia.edu. # But if you do include the extra fields, the script allows for it. # # Exit status: # 0 on success; 1 on failure. # # Creates in the log directory (logdirectory defined below): # A session log file xxx-session.log (xxx is the hostname) # (the log directory itself is created if it doesn't exist) # # Requires: C-Kermit 8.0.212 or later because it uses some recent features. # Version 8.0.211 or earlier lack at least the following, which are used in # this script: # . FSEEK /FIND:string # . The \fkwval() function # (The script could be recoded at some effort to use older ways of doing # the same things.) # # If this script is run directly as if it were a shell command, the C-Kermit # binary that executes it is the one in the "kerbang line" (the first line in # the file). Of course you can move the binary anywhere you want, or rename # it, but then you have to change the kerbang line to match. # # Other dependencies: # . The HP serial numbers file (path defined a few lines down) # . That the first field in a serials file record is the simple hostname # (e.g. FILLMORE, not FILLMORE-CONSOLE or FILLMORE-CONSOLE.CC.COLUMBIA.EDU) # . That the corresponding iLO console password is the 6th field. # # Documentation: http://kermit.columbia.edu/cudocs/ilosetup.html # ############################################################################### .myname := \fbasename(\v(cmdfile)) # Name of this script without path if < \v(version) 800212 { # Check Kermit version exit 1 "\m(myname): C-Kermit 8.0.212 or later required" } # Debugging .dodebug = 0 if > 0 \flen(\$(DEBUG)) if numeric \$(DEBUG) if \$(DEBUG) .dodebug = 1 if \m(dodebug) { echo DEBUGGING ON echo ILO_USERID=[\$(ilo_userid)] echo ILO_USERPASS=[\$(ilo_userpass)] } if not background set quiet off # Allow messages (for foreground use) set session-log text # filter out escape sequences set session-log timestamp # Put timestamps in session log # "Constant" definitions (that can be changed)... .iloprompt = ">hpiLO-> " # HP iLO console prompt .logdirectory = /var/log/ilosetup # Directory for session log .outputpacing = 100 # Intercharter pacing for OUTPUT (msec) .poweroff = 0 # Whether to power off at end .connect = 0 # Make an interactive connection .telnet = 1 # Default connection method is Telnet .notelnet = 0 # Nonzero means there is no Telnet .iloonly = 0 # Only do iLO commands .ssh = 0 # and is not SSH .reset = 1 # Reset at end .dopassword = 1 # Use password from serials file .doingraid = 0 # Don't configure RAID unless asked .serialsfile = /p/sy/subsys/HP/serials # Path of blade serial numbers file .hostsuffix = -console.cc.columbia.edu # Hostname suffix .loginname = Administrator # iLO login name .bios = 0 # Go straight to BIOS .pwrmode = 0 # Change power mode value .saidpwrmode = 0 # For checking power mode value if equ "\v(user)" "fdc" { # Development / testing .logdirectory = ~/net/shrimp # (dev/test) # if \m(dodebug) .serialsfile = ./serials } if \m(dodebug) show args # development/test # COMMAND TABLE: Define command-line option keywords dcl \&k[] = bios poweroff nopoweroff verbose quiet telnet ssh help iloonly - connect debug reset noreset usepassword nopassword raid noraid pwrmode - notelnet array sort &k # Alphabetize them for table lookup # If command line is invalid give usage message and exit def usage { # Give usage message and exit .verbose = "verbose" .turnoff = "nopoweroff" .doreset = "noreset" .usepass = "nopassword" .doraid = "raid" if \m(notelnet) .telnet = 0 .dotelnet = "telnet" if not \m(telnet) .dotelnet = "ssh" echo - "Usage: [ ilo_userid=x ] [ ilo_userpass=y ] \m(myname) hostname [ options ]" echo "Options:" show array k if quiet .verbose = "quiet" if \m(poweroff) .turnoff = "poweroff" if \m(reset) .doreset = "reset" if \m(dopassword) .usepass = "usepassword" xecho "Default options: \m(verbose) \m(turnoff)" echo " \m(dotelnet) \m(doreset) \m(usepass) \m(doraid)" echo "Optional environment variables:" echo " ilo_userid: user ID to create" echo " ilo_userpass: password for user ID" echo " DEBUG=1: turn on debugging" echo "If created user ID and password are not found in the environment," echo "you are prompted for them." echo exit 1 } # Parse and validate command line if not def \%1 { echo "FATAL - A hostname is required" usage # A hostname is required } .hostname := \flower(\fword(\%1,1,.)) # First field of hostname argument .\%t := \findex(-console,\m(hostname)) # If "-console" found in hostname... if \%t .hostname := \s(hostname[1:\%t-1]) # remove it. .fullhost := \m(hostname)\m(hostsuffix) # Make full IP hostname # Parse optional command-line keywords... while defined \%2 { # While we still have trailing commands .tmp := \%2 # Get the next one void \fkwval(\%2,=:) # Split it in case it has an arg .\%2 := \v(lastkwval) # This is the command without the arg if not def \%2 .\%2 := \v(tmp) # Just in case... .\%2 := \ftablelook(\%2,&k) # Look up this keyword and get index if < \%2 1 { # Not found or ambiguous echo "Invalid command-line option: '\m(tmp)'" usage } .\%2 := \&k[\%2] # Resolve index to keyword itself switch \%2 { # Handle the keyword :bios # Go straight to BIOS .bios = 1 break :iloonly # Do iLO commands only .iloonly = 1 break :help # Help usage # (exits) :debug # Debug .dodebug = 1 break :connect # Connect (interactive session) .connect = 1 break :poweroff # Leave power off at end .poweroff = 1 break :nopoweroff # Leave power on at end .poweroff = 0 break :quiet # Silent running (don't watch session) set quiet on set input echo off break :verbose # Show session on screen set quiet off set input echo on break :reset # Reset at end (default) .reset = 1 break :noreset # No reset at end .reset = 0 break :usepassword # Use password from serials file .dopassword = 1 break :nopassword # Use empty password .dopassword = 0 break :raid # Configure RAID 1 if RAID 0 .doingraid = 1 break :noraid # Don't do anything with RAID .doingraid = 0 break :telnet # Try Telnet first .telnet = 1 break :ssh # Try ssh first .telnet = 0 break :notelnet # Telnet is not allowed .notelnet = 1 .telnet = 0 break :pwrmode # Change power mode .saidpwrmode = 1 # Remember they said to do this .bios = 1 # Go straight to BIOS for this } shift # Shift argument list to the left } if \m(saidpwrmode) { # If they said "pwrmode" .\%9 = 0 # validate powermode argument if not defined pwrmode exit 1 "FATAL - pwrmode requires numeric argument" if not numeric \m(pwrmode) exit 1 "FATAL - pwrmode nonnumeric argument" if < \m(pwrmode) 1 exit 1 "FATAL - pwrmode argument must be 1..4" if > \m(pwrmode) 4 exit 1 "FATAL - pwrmode argument must be 1..4" } if \m(bios) .doingraid = 0 # Avoid conflicts - BIOS wins # Macro definitions... define logit { # Write a message to session log if not open session-log end 0 .\%1 := \frpad(\%1,7,.) # Make fields line up writeln session # Make sure we're on a new line writeln session "%% \%1 - \m(myname): \v(timestamp) [\m(hostname)] - \%2" } define pmsg { # Print and log a progress message if not quiet echo # To avoid mixing up screen text echo "[\v(timestamp)] MESSAGE - \%1" # Write message to screen (stdout) logit MESSAGE "\%1" # and to session log } define warn { # Print and log warning message if not quiet echo # To avoid mixing up screen text echo "WARNING - \%1" # Write it to to stdout logit WARNING "\%1" # and to session log } define fatal { # Fatal error .rc = 1 # Failure exit code echo "FATAL - \%1" # Write error message to screen if \m(haveconnection) { # If we have a connection if not equ "\m(state)" "iLO" { # but w're not in iLO... output \{27}\{40} # ESC+( - Escape back to iLO input 8 \m(iloprompt) # and wait 8 sec for the prompt } } logit FATAL "\%1" # write message to session log logit INFO "Most recent error: \v(errstring)" goto DONE } define dotelnet { set login user # Force a login prompt set host \m(fullhost) # Try Telnet (port 23) if fail end 1 # Return failure code if no go input 10 "Login Name: " # Wait for login prompt if fail end 1 "Telnet Login Name timeout" lineout \m(loginname) # Send user ID input 10 "password: " # Wait for password prompt if fail end 1 "Telnet password timeout" end 0 } define dossh { set host /pty ssh -e none -l \m(loginname) \m(fullhost) if fail end 1 # Watch out for RSA key fingerprint complaint and "are you sure?" prompt... minput 20 "password: " "continue connecting (yes/no)? " if fail end 1 "No response on SSH connection to \m(fullhost)" if == \v(minput) 2 { lineout "yes" input 20 "password: " if fail end 1 "SSH password timeout" } end 0 } define getiloprompt { # Get iLO prompt if not def \%1 .\%1 = 40 # Default timeout (secs) if not numeric \%1 fatal "Non-numeric INPUT timeout" input \%1 \m(iloprompt) # Wait for the prompt if fail fatal "Timed out waiting for iLO CLI prompt." } define getiloversion { # Sets global iloversion local s &a # from login herald .\%9 := \findex({\{10}iLO },\v(input)) # Call this right after .s := \fsubstring(\v(input),\%9+1,32) # sending the login password void \fsplit(\m(s),&a) # and getting the first iLO prompt. .iloversion = 0 if ( equ "\&a[1]" "iLO" && match "\&a[3]" "{Standard,Advanced}" ) { if float \&a[2] .iloversion := \&a[2] } pmsg "iLO VERSION = \m(iloversion)" } define ilocommand { # Send an iLO command and get response local cmd # Local (stack) variable .cmd := \fword(\%1,1) # First word of command msleep 10 # Pause 10 msec just in case lineout \%1 # Send the full command if fail fatal "Output failed" # Check for i/o error clear input # Empty the INPUT result buffer if equ "\m(cmd)" "vsp" { clear input end 0 } getiloprompt \%2 # Get response and next iLO prompt # The "power on/off" commands give no response... if not equ "\%1" "power" { # But "power" by itself does... if equ "\m(cmd)" "power" end 0 } .status = 9 # Dummy inital status value .tmp := \freplace(\v(input),\13,) # Strip carriage returns (but not LFs) .lines := \fsplit(\m(tmp),&a,\10) # Split captured text into lines undef ilofirmware # iLO firmware version for i 1 lines 1 { # Loop through lines void \fkwval(\&a[i]) # to get status and message values... } if equ "\m(cmd)" "show" { if def version .ilofirmware := \m(version) [\m(date)] if def ilofirmware pmsg "iLO Firmware \m(ilofirmware)" } if not numeric \m(status) .status = 9 # Just in case if == \m(status) 0 end 0 # If status was 0 then OK if ( equ "\m(cmd)" "create" ) { # In iLO 3 there is an extra blank line in the response. if match "\&a[5]\&a[6]" "*Duplicate {login,user} name.*" { end 0 # This is not an error } } if ( equ "\m(cmd)" "set" && \findex(shared_console,\%1) ) { if match "\&a[5]\&a[6]" "*Advanced License required*" { pmsg "WARNING: HOST LACKS LICENSE for Shared Console" # Change PMSG to FATAL if Advanced License should be there # or if anything that follows depends on shared console. end 0 } } if >= \m(iloversion) 3 { if ( equ "\m(cmd)" "set" ) { if \findex(oemhp_server_name,\%1) end 0 } } fatal "ILO COMMAND \%1: \m(error_tag)" # Fail with nonzero status } define rbsucommand { # Send a command to RBSU and get next rbsu> prompt. local i sleep pacing max msleep 10 # Pause 10 msec just in case lineout \%1 # Send the command # Check for error response or next rbsu> prompt. # Note: RBSU commands have no consistent error indication; # There may be some error responses that are not caught here... minput 30 {rbsu>} {Invalid Command} {Incomplete Command} {Invalid Option} if fail fatal "RBSU: Timeout after [\%1]" if == \v(minput) 1 end 0 # No error message - done. warn "RBSU COMMAND FAILURE [\%1]" .max = 10 for i 1 \m(max) 1 { # Try again this many times. increment pacing 40 # Slower pacing each time. warn "RETRYING WITH PACING = \m(pacing) msec..." msleep 10*i # Pause a little longer each time lineout \%1 # Send the command minput 30 {rbsu>} - {Invalid Command} {Incomplete Command} {Invalid Option} if fail fatal "RBSU: Timeout [\%1]" if == \v(minput) 1 break # No error message - done. } if > \m(i) \m(max) fatal "RBSU command error" warn "RBSU COMMAND RECOVERY OK" } def xsleep { # (for debugging display) if not def \%1 .\%1 = 1 if quiet { sleep \%1 } else { local i for i 1 \%1 1 { sleep 1, xecho . } echo } } # Execution begins here: Get host password from HP serial numbers file... .haveconnection = 0 # No connection yet set input cancellation off # Essential because of Esc sequences set exit warning off # Allow exit without warning if \m(dodebug) directory \m(serialsfile) # Check and open serials file if not exist \m(serialsfile) exit 1 "\m(serialsfile) not found" if not readable \m(serialsfile) exit 1 "\m(serialsfile) not readable" fopen /read \%c \m(serialsfile) # Open serials file if fail fatal # Check for failure # Seek to line with this hostname fseek /find:"^\fupper(\m(hostname))[\9\32]" \%c 0 if fail fatal "Hostname [\m(hostname)] not found in HP serials file" fread /line \%c line # Read the line fclose \%c # Close the file .\%n := \fsplit(\m(line),&a,,-) # Split the line into words .pass := \&a[6] # The sixth word is the host password if \m(dopassword) { # 2-element password array dcl \&p[2] = \m(pass) "" # Try serials file password first } else { dcl \&p[2] = "" \m(pass) # Try blank password first } if \m(dodebug) show array p # If this is a configuration run open the log file if not \m(connect) { if not directory \m(logdirectory) { # Check if log directory exists fatal "Log directory \m(logdirectory) not found or not a directory" } cd \m(logdirectory) # cd to the log directory if fail fatal "cd \m(logdirectory)" # failure is fatal .sessionlog := \m(logdirectory)/\m(hostname)-session.log # Session log name log session \m(sessionlog) # Open and start the session log } else { # Make session log in current directory log session \m(hostname)-connect.log } if fail warn "FAILURE TO OPEN \m(sessionlog)" pmsg "BEGIN ilosetup \m(scriptversion) \m(scriptdate)" # Open the connection and log in .protocol = "none" # No protocol yet if \m(telnet) { # Try telnet first pmsg "TRYING TELNET..." dotelnet if fail { # If it fails try ssh hangup # First close Telnet connection pmsg "TELNET FAILED - TRYING SSH..." dossh if fail fatal "SSH \m(fullhost) failed." .protocol = "ssh" } .protocol = telnet } else { # Try ssh first pmsg "TRYING SSH..." dossh if fail { # If it fails try Telnet hangup # First close ssh connection if \m(notelnet) "SSH \m(fullhost) failed." pmsg "SSH FAILED - TRYING TELNET..." dotelnet if fail fatal "TELNET \m(fullhost) failed." .protocol = telnet } .protocol = "ssh" } # If we arrive here we should have the password prompt. # NOTE: This logic will need to be changed if it is possible to log in # via SSH (or some secure form of Telnet) without a password. .haveiloprompt = 0 for i 1 2 1 { lineout \&p[i] # Send console password if fail fatal "Output password to \m(fullhost) failed." minput 30 \m(iloprompt) "Permission denied" "Invalid login." if fail fatal "Timed out waiting for iLO CLI prompt." if == \v(minput) 1 { .haveiloprompt = 1 break } if \m(dopassword) { pmsg "Password from serials file failed - trying empty password..." } else { pmsg "Empty password failed - trying password from serials file..." } # After bad password Telnet prompts again for the username - ssh does not. if eq "\m(protocol)" "telnet" { input 10 "Login Name: " if fail fatal "Telnet Login Name timeout" lineout \m(loginname) } input 2 "password: " if not quiet echo if == \m(i) 2 fatal "Password not accepted" if quiet continue } if not \m(haveiloprompt) fatal "iLO console login failure" getiloversion # Get iLO version number # CONNECT - Go interactive and do not execute the rest of the script. .haveconnection = 1 # Have connection if \m(connect) { # Interactive session requested lineout # Send a carriage return connect # Connect to remote if not open connection exit # Exit from Kermit if connection closed stop # Otherwise don't exit } if \m(bios) forward skipilocommands # If "go to Bios" jump ahead # Automated configuration run... # Prompt for created-user ID if it wasn't in the environment .userid := \$(ilo_userid) .userpass := \$(ilo_userpass) while not defined userid { # Prompt for created user ID ask userid "User ID for created account: " } # Prompt for created-user password if it wasn't in the environment while not defined userpass { askq /echo:* userpass "Password for created account: " } if \m(dodebug) { set debug timestamps on log debug \m(hostname)-debug.log } # Send iLO commands... .state = iLO ilocommand "show /system1/firmware1" # Get iLO firmware version ilocommand "create /map1/accounts1 username=\m(userid) - password=\m(userpass) group=admin,config,oemhp_vm,oemhp_rc,oemhp_power" if < \m(iloversion) 3 { if not notelnet ilocommand "set /map1/config1 oemhp_telnetenable=yes" ilocommand "set /map1/config1 oemhp_shared_console_enable=yes" } ilocommand "set /system1 oemhp_server_name=\m(hostname)" # ilocommand "set /map1/config1 oemhp_rc_aquire=yes" if \m(iloonly) { # Skip the rest if iloonly .rc = 0 # Set a good return code forward done # and finish up } :skipilocommands lineout "power" # Check power state minput 60 {server power is currently: On} {server power is currently: Off} if fail fatal "No response to power command MINPUT=\v(minput)" switch \v(minput) { :1, getiloprompt, lineout "reset /system1 hard", break :2, getiloprompt, lineout "power on", break } .max = 10 for i 1 \m(max) 1 { # Wait for power to come on lineout "power" minput 20+3*i - {server power is currently: On} {server power is currently: Off} if == \v(minput) 1 break if == \v(minput) 0 { if == \v(instatus) 1 { continue } else { fatal "\v(inmessage)" } } xsleep \m(i) getiloprompt lineout "power on" getiloprompt } if >= \m(i) \m(max) fatal "POWER ON DIDN'T TURN POWER ON" # Enter VSP [virtual serial port]... :dovsp pmsg "Attempting to enter VSP..." ilocommand "vsp" input 30 "Virtual Serial Port Active" if fail fatal "FAILURE TO ENTER VSP" # Here we have to allow for many prompts and responses # including a Device Status Request escape sequence from the host # (ESC [ 5 n) which must be replied to. (NOTE: doublequotes in # the MINPUT text arguments have to be escaped as \{34}). .sendesc9 = 0 while true { minput 300 - {Press \{34}ESC+9\{34} for ROM-Based Setup Utility} - {Press \{34}ESC+0\{34} for System Maintenance Menu} - {\27[5n} - {Press to run the Option ROM Configuration for Arrays Utility} - {Requested service is unavailable\, it is already in use} - {The server is not powered on} - {The Virtual Serial Port is not available} if fail { # If INPUT fails output \{27}\{40} # Escape back to iLO prompt pmsg "INPUT: \v(inmessage)" # and back out from there. if open connection { # Is the connection still open? fatal "INPUT FAILED WITH CONNECTION STILL OPEN" } else { fatal "CONNECTION CLOSED BY SERVER" } } if == 1 \v(minput) { # What we want in iLO 3 .sendesc9 = 1 # Remember that we did this break } if == 2 \v(minput) break # What we want in iLO 2... if == 3 \v(minput) { # Device Status Report Request output \27[0n # Send Device Status Report (I'm OK) if \m(dodebug) echo SENT ESC [0n continue } if == 4 \v(minput) { # If we are configuring RAID if not \m(doingraid) continue output \{27}8 # Send Esc 8 break # and quit this loop } getiloprompt # Soak up rest of message lineout "exit" # Exit from iLO fatal "VSP service unavailable" .rc = 1 forward DONE } if not \m(doingraid) goto dorbsu # If not doing RAID skip to next part .havecli = 0 # Flag for have CLI prompt input 20 "CLI> " # Wait for CLI prompt if fail { pmsg "Arrays CLI> prompt did not appear - skipping..." forward dorbsu } .havecli = 1 set output pacing 200 # Can't blast characters at CLI prompt clear input # Clear INPUT buffer lineout "physicaldrive * show" # Show physical arrays input 30 "CLI> " # Wait for next CLI prompt # Count the drives - \v(input) contains the results of the SHOW command" .drives = 0 if \findex({Unknown Command},\v(input)) { pmsg "Command 'physicaldrive * show' garbled - increase OUTPUT PACING" forward dorbsu } if \findex({Invalid physical drive number specified},\v(input)) { pmsg "Arrays CLI Invalid drive number specified - skipping" forward dorbsu } .xx := \freplace(\v(input),\32,_) # This solves a slight syntax problem if \findex(Physical_Drive_#_1,\m(xx)) incr drives if \findex(Physical_Drive_#_2,\m(xx)) incr drives if \findex(Physical_Drive_#_3,\m(xx)) incr drives if \findex(Physical_Drive_#_4,\m(xx)) incr drives if \findex(Physical_Drive_#_5,\m(xx)) incr drives if \findex(Physical_Drive_#_6,\m(xx)) incr drives if \findex(Physical_Drive_#_7,\m(xx)) incr drives if \findex(Physical_Drive_#_8,\m(xx)) incr drives if < \m(drives) 2 { pmsg "Physical Drives: \m(drives) - skipping..." forward dorbsu } pmsg "Physical Drives: \m(drives) - OK" set output pacing 250 # Can't blast characters at CLI prompt clear input # Erase \v(input) again lineout "logicaldrive * show" # Show logical drives input 30 "CLI> " # Wait for next CLI prompt if fail { pmsg "No CLI prompt after 'logicaldrive * show' after \v(inwait) secs" .havecli = 0 forward dorbsu } .raid = -1 if \findex({Unknown Command},\v(input)) { pmsg "Command 'logicaldrive * show' garbled - increase OUTPUT PACING" forward dorbsu } .xx := \fsubstitute(\v(input),\32\44,_:) # Another syntax trick if \findex({Logical_Drive_#_1:RAID_0},\m(xx)) .raid = 0 if \findex({Logical_Drive_#_1:RAID_1},\m(xx)) .raid = 1 if < \m(raid) 0 { pmsg "Unexpected response to 'logicaldrives * show'" forward dorbsu } if == \m(raid) 1 { pmsg "Logical Drive \# 1 RAID 1 - skipping..." forward dorbsu } pmsg "Logical Drive \# 1 RAID 0 - Changing to RAID 1..." lineout "logicaldrive 1 delete" minput 20 "Are you sure? (y/n):" "Unknown Command" if fail { pmsg "Timeout after 'logical drive 1 delete' dialog - skipping...'" forward dorbsu } if == \v(minput) 2 { pmsg "Command 'logicaldrive 1 delete' garbled - increase OUTPUT PACING" forward dorbsu } output y # Just the letter 'y', no CR. pmsg "Creating logicaldrive 1 RAID 1 mirrored..." input 10 "CLI> " # Wait for next CLI prompt if fail { pmsg "No CLI prompt after 'logicaldrive 1 delete' after \v(inwait) secs" .havecli = 0 forward dorbsu } clear input # In case we want to collect text lineout "controller create type=logicaldrive raid=1 drives=1,2" w # Note: when this succeeds there is no message at all. # It takes about 20 seconds. I don't know what any error messages would be. input 30 "CLI> " # Wait for next CLI prompt :dorbsu if \m(havecli) { # Exit from CLI if we were in it lineout exit # and wait for another menu input 30 {Press "ESC+0" for System Maintenance Menu} } if \m(sendesc9) { # In iLO 3 we can go straight to RBSU input 30 {for Network Boot} # (wait for this...) pause 1 # (wait a bit more...) output \{27}9 # by "pressing" Esc (27) and 9 forward getrbsuprompt } output \{27}0 # Send ESC and 0 # Here it is waiting for a DHCP response which might never come. input 120 "MMenu> " # Get MMenu> prompt if fail { fatal "Timed out waiting for MMenu> prompt" } .state = MMenu # Have MMenu> prompt # Send the RBSU command one char at a time because this prompt is VERY LOSSY .sentrbsu = 0 clear input # Clear the input buffer for \%9 1 4 1 { # Echoplex loop - try this four times output R # R input 2*\%9 R # Wait for the echo if fail { lineout, continue } # On failure send CR and start over output B # B... input 2*\%9 B if fail { lineout, continue } output S # S... input 2*\%9 S if fail { lineout, continue } output U # U... input 2*\%9 U if fail { lineout, continue } lineout # Send carriage return clear input .sentrbsu = 1 break } if not \m(sentrbsu) fatal "Failure to send RBSU Command" :getrbsuprompt input 30 "rbsu> " # Wait for rbsu> prompt if fail fatal "Timed out waiting for first rbsu> prompt" :inrbsu .state = rbsu if ( \m(bios) && NOT \m(pwrmode) ) { # Go interactive to RBSU prompt pmsg "Attempting to access BIOS..." connect # Go interactive forward DONE # Upon return skip the rest } set output pacing \m(outputpacing) # Throttle output speed if \m(pwrmode) { # Change power mode rbsucommand "SHOW CONFIG HP POWER REGULATOR" rbsucommand "SET CONFIG HP POWER REGULATOR \m(pwrmode)" } else { # Send the RBSU commands. # Here we could give a SHOW CONFIG VIRTUAL SERIAL PORT command and parse # the BIOS Serial Console Port menu choices in case the menu ever changes. rbsucommand "SET CONFIG VIRTUAL SERIAL PORT 2" rbsucommand "SET CONFIG BIOS SERIAL CONSOLE PORT 4" rbsucommand "SET CONFIG BIOS SERIAL CONSOLE BAUD RATE 4" rbsucommand "SET CONFIG EMS CONSOLE 3" } lineout EXIT # Exit from RBSU pause 1 # Wait a sec and... output \27( # Escape back to iLO getiloprompt # Get iLO prompt .state = iLO .rc = 0 # Our return code - assume success. if not \m(poweroff) { # Turn power off now? if not \m(reset) pmsg "LEAVING POWER ON" # No... forward DONE } pmsg "TURNING POWER OFF" # Yes... .max = 10 # How many times to try. for i 1 \m(max) 1 { # Loop for each try. lineout "power off" # Send power off command. sleep 15 # Give it a little time getiloprompt # Get iLO prompt lineout "power" # Send "power" command to check minput 30 {server power is currently: Off} {server power is currently: On} if == \v(minput) 1 { # Power is off getiloprompt # Read next iLO prompt forward DONE # Exit loop and skip ahead } sleep 2*i # Sleep more each time warn "RETRYING POWER OFF [\m(i)]..." getiloprompt } warn "WARNING: POWER OFF FAILED AFTER \m(max) TRIES" .rc = 1 :DONE define fatal end 0 # No fatal errors from now on if \m(haveconnection) { # If we have a connection... if \m(reset) { # Reset the machine .reset = 0 # Prevent recursion in case of error pmsg "HARD RESET AND CLOSE" ilocommand "cd /Map1" lineout "reset" sleep 5 close connection # Close our end of the connection } else { if not \m(rc) { pmsg "EXIT WITHOUT RESET" lineout "exit" # Exit from iLO input 30 "CLI session stopped" # Wait for final gasp } if open connection hangup # Close our end too just in case } } .haveconnection = 0 pmsg "END: STATUS: \m(rc)" if open session-log close session-log # Close log exit \m(rc) # Exit from script and Kermit ; Local Variables: ; comment-column:40 ; comment-start:"# " ; End: