blob: 20618d59ead255d6d8fdd6b87c67ce1bc8c55ca3 [file] [log] [blame]
*** Settings ***
Documentation This module is for IPMI client for copying ipmitool to
... openbmc box and execute ipmitool IPMI standard
... command. IPMI raw command will use dbus-send command
Resource ../lib/resource.robot
Resource ../lib/connection_client.robot
Resource ../lib/utils.robot
Resource ../lib/state_manager.robot
Library String
Library var_funcs.py
Library ipmi_client.py
*** Variables ***
${dbusHostIpmicmd1}= dbus-send --system ${OPENBMC_BASE_URI}HostIpmi/1
${dbusHostIpmiCmdReceivedMsg}= ${OPENBMC_BASE_DBUS}.HostIpmi.ReceivedMessage
${netfnByte}= ${EMPTY}
${cmdByte}= ${EMPTY}
${arrayByte}= array:byte:
${IPMI_USER_OPTIONS} ${EMPTY}
${IPMI_INBAND_CMD}= ipmitool -C ${IPMI_CIPHER_LEVEL} -p ${IPMI_PORT}
${HOST}= -H
${RAW}= raw
*** Keywords ***
Run IPMI Command
[Documentation] Run the raw IPMI command.
[Arguments] ${command} ${fail_on_err}=${1} &{options}
# Description of argument(s):
# command The IPMI command string to be executed
# (e.g. "power status").
# fail_on_err Fail if the IPMI command execution fails.
# options Additional ipmitool command options (e.g.
# -C=3, -I=lanplus, etc.). Currently, only
# used for external IPMI commands.
${resp}= Run Keyword If '${IPMI_COMMAND}' == 'External'
... Run External IPMI Raw Command ${command} ${fail_on_err} &{options}
... ELSE IF '${IPMI_COMMAND}' == 'Inband'
... Run Inband IPMI Raw Command ${command}
... ELSE IF '${IPMI_COMMAND}' == 'Dbus'
... Run Dbus IPMI RAW Command ${command}
... ELSE Fail msg=Invalid IPMI Command type provided: ${IPMI_COMMAND}
[Return] ${resp}
Run IPMI Standard Command
[Documentation] Run the standard IPMI command.
[Arguments] ${command} ${fail_on_err}=${1} ${expected_rc}=${0} &{options}
# Description of argument(s):
# command The IPMI command string to be executed
# (e.g. "0x06 0x36").
# fail_on_err Fail if the IPMI command execution fails.
# expected_rc The expected return code from the ipmi
# command (e.g. ${0}, ${1}, etc.).
# options Additional ipmitool command options (e.g.
# -C=3, -I=lanplus, etc.). Currently, only
# used for external IPMI commands.
${resp}= Run Keyword If '${IPMI_COMMAND}' == 'External'
... Run External IPMI Standard Command ${command} ${fail_on_err} ${expected_rc} &{options}
... ELSE IF '${IPMI_COMMAND}' == 'Inband'
... Run Inband IPMI Standard Command ${command} ${fail_on_err}
... ELSE IF '${IPMI_COMMAND}' == 'Dbus'
... Run Dbus IPMI Standard Command ${command}
... ELSE Fail msg=Invalid IPMI Command type provided : ${IPMI_COMMAND}
[Return] ${resp}
Run Dbus IPMI RAW Command
[Documentation] Run the raw IPMI command through dbus.
[Arguments] ${command}
${valueinBytes}= Byte Conversion ${command}
${cmd}= Catenate ${dbushostipmicmd1} ${dbusHostIpmiCmdReceivedMsg}
${cmd}= Catenate ${cmd} ${valueinBytes}
${output} ${stderr}= Execute Command ${cmd} return_stderr=True
Should Be Empty ${stderr}
set test variable ${OUTPUT} "${output}"
Run Dbus IPMI Standard Command
[Documentation] Run the standard IPMI command through dbus.
[Arguments] ${command}
Copy ipmitool
${stdout} ${stderr} ${output}= Execute Command
... /tmp/ipmitool -I dbus ${command} return_stdout=True
... return_stderr= True return_rc=True
Should Be Equal ${output} ${0} msg=${stderr}
[Return] ${stdout}
Run Inband IPMI Raw Command
[Documentation] Run the raw IPMI command in-band.
[Arguments] ${command} ${os_host}=${OS_HOST} ${os_username}=${OS_USERNAME}
... ${os_password}=${OS_PASSWORD}
# Description of argument(s):
# command The IPMI command string to be executed
# (e.g. "0x06 0x36").
# os_host The host name or IP address of the OS Host.
# os_username The OS host user name.
# os_password The OS host passwrd.
Login To OS Host ${os_host} ${os_username} ${os_password}
Check If IPMI Tool Exist
${ipmi_cmd}= Catenate ${IPMI_INBAND_CMD} ${RAW} ${command}
Qprint Issuing ${ipmi_cmd}
${stdout} ${stderr}= Execute Command ${ipmi_cmd} return_stderr=True
Should Be Empty ${stderr} msg=${stdout}
[Return] ${stdout}
Run Inband IPMI Standard Command
[Documentation] Run the standard IPMI command in-band.
[Arguments] ${command} ${fail_on_err}=${1} ${os_host}=${OS_HOST}
... ${os_username}=${OS_USERNAME} ${os_password}=${OS_PASSWORD}
... ${login_host}=${1}
# Description of argument(s):
# command The IPMI command string to be executed
# (e.g. "power status").
# os_host The host name or IP address of the OS Host.
# os_username The OS host user name.
# os_password The OS host passwrd.
# login_host Indicates that this keyword should login to host OS.
Run Keyword If ${login_host} == ${1}
... Login To OS Host ${os_host} ${os_username} ${os_password}
Check If IPMI Tool Exist
${ipmi_cmd}= Catenate ${IPMI_INBAND_CMD} ${command}
Qprint Issuing ${ipmi_cmd}
${stdout} ${stderr}= Execute Command ${ipmi_cmd} return_stderr=True
Return From Keyword If ${fail_on_err} == ${0} ${stderr}
Should Be Empty ${stderr} msg=${stdout}
[Return] ${stdout}
Run External IPMI Standard Command
[Documentation] Run the external IPMI standard command.
[Arguments] ${command} ${fail_on_err}=${1} ${expected_rc}=${0} &{options}
# Description of argument(s):
# command The IPMI command string to be executed
# (e.g. "power status"). Note that if
# ${IPMI_USER_OPTIONS} has a value (e.g.
# "-vvv"), it will be pre-pended to this
# command string.
# fail_on_err Fail if the IPMI command execution fails.
# expected_rc The expected return code from the ipmi
# command (e.g. ${0}, ${1}, etc.).
# options Additional ipmitool command options (e.g.
# -C=3, -I=lanplus, etc.).
${command_string}= Process IPMI User Options ${command}
${ipmi_cmd}= Create IPMI Ext Command String ${command_string} &{options}
Qprint Issuing ${ipmi_cmd}
${rc} ${output}= Run And Return RC and Output ${ipmi_cmd}
Return From Keyword If ${fail_on_err} == ${0} ${output}
Should Be Equal ${rc} ${expected_rc} msg=${output}
[Return] ${output}
Run External IPMI Raw Command
[Documentation] Run the external IPMI raw command.
[Arguments] ${command} ${fail_on_err}=${1} &{options}
# This keyword is a wrapper for 'Run External IPMI Standard Command'. See
# that keyword's prolog for argument details. This keyword will pre-pend
# the word "raw" plus a space to command prior to calling 'Run External
# IPMI Standard Command'.
${output}= Run External IPMI Standard Command
... raw ${command} ${fail_on_err} &{options}
[Return] ${output}
Check If IPMI Tool Exist
[Documentation] Check if IPMI Tool installed or not.
${output}= Execute Command which ipmitool
Should Not Be Empty ${output} msg=ipmitool not installed.
Activate SOL Via IPMI
[Documentation] Start SOL using IPMI and route output to a file.
[Arguments] ${file_path}=/tmp/sol_${OPENBMC_HOST}
# Description of argument(s):
# file_path The file path on the local machine (vs.
# OBMC) to collect SOL output. By default
# SOL output is collected at
# /tmp/sol_<BMC_IP> else user input location.
${ipmi_cmd}= Create IPMI Ext Command String sol activate usesolkeepalive
Qprint Issuing ${ipmi_cmd}
Start Process ${ipmi_cmd} shell=True stdout=${file_path}
... alias=sol_proc
Deactivate SOL Via IPMI
[Documentation] Stop SOL using IPMI and return SOL output.
[Arguments] ${file_path}=/tmp/sol_${OPENBMC_HOST}
# Description of argument(s):
# file_path The file path on the local machine to copy
# SOL output collected by above "Activate
# SOL Via IPMI" keyword. By default it
# copies log from /tmp/sol_<BMC_IP>.
${ipmi_cmd}= Create IPMI Ext Command String sol deactivate
Qprint Issuing ${ipmi_cmd}
${rc} ${output}= Run and Return RC and Output ${ipmi_cmd}
Run Keyword If ${rc} > 0 Run Keywords
... Run Keyword And Ignore Error Terminate Process sol_proc
... AND Return From Keyword ${output}
${output}= OperatingSystem.Get File ${file_path} encoding_errors=ignore
# Logging SOL output for debug purpose.
Log ${output}
[Return] ${output}
Byte Conversion
[Documentation] Byte Conversion method receives IPMI RAW commands as
... argument in string format.
... Sample argument is as follows
... "0x04 0x30 9 0x01 0x00 0x35 0x00 0x00 0x00 0x00 0x00
... 0x00"
... IPMI RAW command format is as follows
... <netfn Byte> <cmd Byte> <Data Bytes..>
... This method converts IPMI command format into
... dbus command format as follows
... <byte:seq-id> <byte:netfn> <byte:lun> <byte:cmd>
... <array:byte:data>
... Sample dbus Host IPMI Received Message argument
... byte:0x00 byte:0x04 byte:0x00 byte:0x30
... array:byte:9,0x01,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00
[Arguments] ${args}
${argLength}= Get Length ${args}
Set Global Variable ${arrayByte} array:byte:
@{listargs}= Split String ${args}
${index}= Set Variable ${0}
:FOR ${word} IN @{listargs}
\ Run Keyword if ${index} == 0 Set NetFn Byte ${word}
\ Run Keyword if ${index} == 1 Set Cmd Byte ${word}
\ Run Keyword if ${index} > 1 Set Array Byte ${word}
\ ${index}= Set Variable ${index + 1}
${length}= Get Length ${arrayByte}
${length}= Evaluate ${length} - 1
${arrayByteLocal}= Get Substring ${arrayByte} 0 ${length}
Set Global Variable ${arrayByte} ${arrayByteLocal}
${valueinBytesWithArray}= Catenate byte:0x00 ${netfnByte} byte:0x00
${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${cmdByte}
${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${arrayByte}
${valueinBytesWithoutArray}= Catenate byte:0x00 ${netfnByte} byte:0x00
${valueinBytesWithoutArray}= Catenate ${valueinBytesWithoutArray} ${cmdByte}
# To Check scenario for smaller IPMI raw commands with only 2 arguments
# instead of usual 12 arguments.
# Sample small IPMI raw command: Run IPMI command 0x06 0x36
# If IPMI raw argument length is only 9 then return value in bytes without
# array population.
# Equivalent dbus-send argument for smaller IPMI raw command:
# byte:0x00 byte:0x06 byte:0x00 byte:0x36
Run Keyword if ${argLength} == 9 Return from Keyword ${valueinBytesWithoutArray}
[Return] ${valueinBytesWithArray}
Set NetFn Byte
[Documentation] Set the network function byte.
[Arguments] ${word}
${netfnByteLocal}= Catenate byte:${word}
Set Global Variable ${netfnByte} ${netfnByteLocal}
Set Cmd Byte
[Documentation] Set the command byte.
[Arguments] ${word}
${cmdByteLocal}= Catenate byte:${word}
Set Global Variable ${cmdByte} ${cmdByteLocal}
Set Array Byte
[Documentation] Set the array byte.
[Arguments] ${word}
${arrayByteLocal}= Catenate SEPARATOR= ${arrayByte} ${word}
${arrayByteLocal}= Catenate SEPARATOR= ${arrayByteLocal} ,
Set Global Variable ${arrayByte} ${arrayByteLocal}
Copy ipmitool
[Documentation] Copy the ipmitool to the BMC.
${ipmitool_error}= Catenate The ipmitool program could not be found in the tools directory.
... It is not part of the automation code by default. You must manually copy or link the correct openbmc
... version of the tool in to the tools directory in order to run this test suite.
OperatingSystem.File Should Exist tools/ipmitool msg=${ipmitool_error}
Import Library SCPLibrary WITH NAME scp
scp.Open connection ${OPENBMC_HOST} username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD}
scp.Put File tools/ipmitool /tmp
SSHLibrary.Open Connection ${OPENBMC_HOST}
Login ${OPENBMC_USERNAME} ${OPENBMC_PASSWORD}
Execute Command chmod +x /tmp/ipmitool
Initiate Host Boot Via External IPMI
[Documentation] Initiate host power on using external IPMI.
[Arguments] ${wait}=${1}
# Description of argument(s):
# wait Indicates that this keyword should wait
# for host running state.
${output}= Run External IPMI Standard Command chassis power on
Should Not Contain ${output} Error
Run Keyword If '${wait}' == '${0}' Return From Keyword
Wait Until Keyword Succeeds 10 min 10 sec Is Host Running
Initiate Host PowerOff Via External IPMI
[Documentation] Initiate host power off using external IPMI.
[Arguments] ${wait}=${1}
# Description of argument(s):
# wait Indicates that this keyword should wait
# for host off state.
${output}= Run External IPMI Standard Command chassis power off
Should Not Contain ${output} Error
Run Keyword If '${wait}' == '${0}' Return From Keyword
Wait Until Keyword Succeeds 3 min 10 sec Is Host Off
Get Host State Via External IPMI
[Documentation] Returns host state using external IPMI.
${output}= Run External IPMI Standard Command chassis power status
Should Not Contain ${output} Error
${output}= Fetch From Right ${output} ${SPACE}
[Return] ${output}
Set BMC Network From Host
[Documentation] Set BMC network from host.
[Arguments] ${nw_info}
# Description of argument(s):
# nw_info A dictionary containing the network
# information to apply.
Run Inband IPMI Standard Command
... lan set 1 ipaddr ${nw_info['IP Address']}
Run Inband IPMI Standard Command
... lan set 1 netmask ${nw_info['Subnet Mask']}
Run Inband IPMI Standard Command
... lan set 1 defgw ipaddr ${nw_info['Default Gateway IP']}
Verify IPMI Username And Password
[Documentation] Verify that user is able to run IPMI command
... with given username and password.
[Arguments] ${username} ${password}
# Description of argument(s):
# username The user name (e.g. "root", "robert", etc.).
# password The user password (e.g. "0penBmc", "0penBmc1", etc.).
${output}= Run External IPMI Standard Command
... sel info U=${username} P=${password}
Should Contain ${output} SEL Information msg=SEL information not present
IPMI Create User
[Documentation] Create IPMI user with given userid and username.
[Arguments] ${userid} ${username}
# Description of argument(s):
# userid The user ID (e.g. "1", "2", etc.).
# username The user name (e.g. "root", "robert", etc.).
${ipmi_cmd}= Catenate user set name ${userid} ${username}
${resp}= Run IPMI Standard Command ${ipmi_cmd}
${user_info}= Get User Info ${userid}
Should Be Equal ${user_info['user_name']} ${username}
Set Channel Access
[Documentation] Verify that user is able to run IPMI command
... with given username and password.
[Arguments] ${userid} ${options} ${channel_number}=${CHANNEL_NUMBER}
# Description of argument(s):
# userid The user ID (e.g. "1", "2", etc.).
# options Set channel command options (e.g.
# "link=on", "ipmi=on", etc.).
# channel_number The user's channel number (e.g. "1").
${ipmi_cmd}= Catenate SEPARATOR=
... channel setaccess${SPACE}${channel_number}${SPACE}${userid}
... ${SPACE}${options}
Run IPMI Standard Command ${ipmi_cmd}
Delete All Non Root IPMI User
[Documentation] Delete all non-root IPMI user.
# Get complete list of user info records.
${user_info}= Get User Info ${EMPTY}
# Remove header record.
${user_info}= Filter Struct ${user_info} [('user_name', None)] invert=1
${non_empty_user_info}= Filter Struct ${user_info} [('user_name', '')] invert=1
${non_root_user_info}= Filter Struct ${non_empty_user_info} [('user_name', 'root')] invert=1
FOR ${user_record} IN @{non_root_user_info}
Run IPMI Standard Command user set name ${user_record['user_id']} ""
Sleep 5s
END