home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
public_html
/
cudocs
/
ilosetup-1.07
< prev
next >
Wrap
Text File
|
2020-01-01
|
21KB
|
587 lines
#!/p/sy/subsys/scripts/wermit +
#!/p/kd/fdc/solaris9/wermit +
#!/p/kd/fdc/RHEL4/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
#
.version = 1.07
.date = 20091113
# Created:
# 1.01 20090428
# Modified:
# 1.02 20090916: Prompt for username if not in environment.
# 1.03 20091028: Remove IF WRITEABLE check for log directory
# 1.04 20091103: Handle console login failure more gracefully;
# Allow empty password in serials file.
# 1.05 20091104: Add 'usepassword' and 'nopassword' options;
# Try both in specified order.
# 1.06 20091104: Handle login failure on Telnet connections.
# 1.07 20091113: Enable remote console acquire
#
# Usage: [ ilo_username=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)
# 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 p (same as poweroff)
# ilosetup fillmore p 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.)
#
# The binary used to execute the script is the one shown above in the
# "kerbang line". Of course you can move the binary to anywhere you want,
# or rename it, but then you have to change the kerbang line.
#
# 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
# (if there is no password, the 6th field should be empty).
#
###############################################################################
if < \v(version) 800212 { # Check Kermit version
exit 1 "\m(myname): C-Kermit 8.0.212 or later required"
}
# Operating parameters and defaults (that can be changed)...
.dodebug = 0
if def \$(DEBUG) .dodebug = 1
if \m(dodebug) {
echo DEBUGGING ON
echo ILO_USERID=[\$(ilo_userid)]
echo ILO_USERPASS=[\$(ilo_userpass)]
}
set quiet off # Allow messages (for foreground use)
# "Constant" definitions (that can be changed)...
.iloprompt = ">hpiLO-> " # HP iLO console prompt
.logdirectory = /var/log/ilosetup # Directory for session log
.outputpacing = 30 # Intercharter pacing for OUTPUT (msec)
.poweroff = 0 # Whether to power off at end
.connect = 0 # Make in interactive connection
.reset = 1 # Reset at end
.dopassword = 1 # Use password from serials file
.serialsfile = /p/sy/subsys/HP/serials # Path of blade serial numbers file
.hostsuffix = -console.cc.columbia.edu # Hostname suffix
.loginname = Administrator # iLO login name
if equ "\v(user)" "fdc" { # Development / testing
.logdirectory = ~/net/shrimp # (dev/test)
# if \m(dodebug) .serialsfile = ./serials
}
.myname := \fbasename(\v(cmdfile)) # Name of this script without path
if \m(dodebug) { # dev/test
show args
}
# Define command-line option keywords
dcl \&k[] = poweroff nopoweroff verbose quiet -
connect debug reset noreset usepassword nopassword
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"
echo -
"Usage: [ ilo_username=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"
echo "Default options: \m(verbose) \m(turnoff) \m(doreset) \m(usepass)"
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...
set flag off # No debugging unless requested
if def \m(dodebug) set flag on # Can request with environment var
while defined \%2 { # While we still have trailing args...
.tmp := \%2
.\%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
:debug # Debug
set flag on
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
: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
}
shift # Shift argument list to the left
}
# 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 message { # Print and log a progress message
if not quiet echo # To avoid mixing up screen text
echo "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 getiloprompt { # Get iLO prompt
if not def \%1 .\%1 = 30 # 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 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
getiloprompt \%2 # Get response and next iLO prompt
# The "power on/off" and "vsp" commands give no response...
if not equ "\%1" "power" { # But "power" by itself does...
if ( equ "\m(cmd)" "power" || equ "\m(cmd)" "vsp" ) 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
for i 1 lines 1 { # Loop through lines
void \fkwval(\&a[i]) # to get status and message values...
}
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" && equ "\&a[5]" "Duplicate login name." ) {
end 0 # This is not an error
}
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)"
message "BEGIN ilosetup \m(version) \m(date)"
# Open the connection and log in
.protocol = "none" # No protocol yet
message "TRYING TELNET..."
set host \m(fullhost) # Try Telnet (port 23) first
if success { # Telnet OK - send user name
input 10 "Login Name: "
if fail fatal "Telnet Login Name timeout"
lineout \m(loginname)
input 10 "password: "
if fail fatal "Telnet password timeout"
.protocol = telnet
message "PROTOCOL TELNET"
} else { # No telnet - try SSH
message "TELNET FAILED - TRYING SSH..."
set host /pty ssh -e none -l \m(loginname) \m(fullhost)
if fail fatal "SSH \m(fullhost) failed."
# Watch out for RSA key fingerprint complaint and "are you sure?" prompt...
minput 20 "password: " "continue connecting (yes/no)? "
if fail fatal "No response on SSH connection to \m(fullhost)"
if == \v(minput) 2 {
lineout "yes"
input 20 "password: "
if fail fatal "SSH password timeout"
}
.protocol = "ssh"
message "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) {
message "Password from serials file failed - trying empty password..."
} else {
message "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"
# 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
}
# 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
askq 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: "
}
# Send iLO commands...
.state = iLO
ilocommand "create /map1/accounts1 username=\m(userid) -
password=\m(userpass) group=admin,config,oemhp_vm,oemhp_rc,oemhp_power"
ilocommand "set /map1/config1 oemhp_telnetenable=yes"
ilocommand "set /system1 oemhp_server_name=\m(hostname)"
ilocommand "set /map1/config1 oemhp_rc_acquire=yes" # 1.07
lineout "power" # Check power state
minput 20 {server power is currently: On} {server power is currently: Off}
if fail fatal "No response to power command"
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 {server power is currently: On} {server power is currently: Off}
if fail fatal "No response to power command"
if == \v(minput) 1 break
xsleep 10
getiloprompt
lineout "power on"
getiloprompt
}
if >= \m(i) \m(max) fatal "POWER ON DIDN'T TURN POWER ON"
# Enter VSP [virtual serial port]...
message "Attempting to enter VSP..."
if flag {
set debug timestamps on
log debug \m(hostname)-debug.log
}
ilocommand "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.
while true {
minput 300 -
{Press "ESC+0" for System Maintenance Menu} -
{\27[5n} -
{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
message "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) break # What we want...
if == 2 \v(minput) { # Device Status Report Request
output \27[0n # Send Device Status Report (I'm OK)
continue
}
getiloprompt # Soak up rest of message
lineout "exit" # Exit from iLO
fatal "VSP service unavailable"
.rc = 1
forward DONE
}
if flag if open debug-log close debug-log
output \{27}0 # Send ESC and 0
input 60 "MMenu> " # Get MMenu> prompt
if fail fatal "Timed out waiting for MMenu> prompt"
.state = MMenu
lineout RBSU # Enter RBSU
input 30 "rbsu> " # Wait for rbsu> prompt
if fail fatal "Timed out waiting for first rbsu> prompt"
.state = rbsu
set output pacing \m(outputpacing) # Throttle output speed
# 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) message "LEAVING POWER ON" # No...
forward DONE
}
message "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
message "HARD RESET AND CLOSE"
ilocommand "cd /Map1"
lineout "reset"
sleep 5
close connection # Close our end of the connection
} else {
if not \m(rc) {
message "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
message "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: