| *** 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 | 
 | Library         ../lib/bmc_ssh_utils.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} -N ${IPMI_TIMEOUT} -p ${IPMI_PORT} | 
 | ${HOST}=               -H | 
 | ${RAW}=                raw | 
 | ${IPMITOOL_PATH}       /tmp/ipmitool | 
 | ${expected_max_ids}    15 | 
 | ${empty_name_pattern}  ^User Name\\s.*\\s:\\s$ | 
 |  | 
 | *** 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 | 
 |     ...    ${IPMITOOL_PATH} -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}  ${fail_on_err}=${1}  ${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 | 
 |     Return From Keyword If  ${fail_on_err} == ${0}  ${stderr} | 
 |     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}=${IPMI_SOL_LOG_FILE} | 
 |  | 
 |     # 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 | 
 |     #                               logs/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}=${IPMI_SOL_LOG_FILE} | 
 |  | 
 |     # 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 logs/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} | 
 |     END | 
 |     ${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. | 
 |  | 
 |     ${response}  ${stderr}  ${rc}=  BMC Execute Command | 
 |     ...  which ipmitool  ignore_err=${1} | 
 |     ${installed}=  Get Regexp Matches  ${response}  ipmitool | 
 |     Run Keyword If  ${installed} == ['ipmitool'] | 
 |     ...  Run Keywords  Set Suite Variable  ${IPMITOOL_PATH}  ${response} | 
 |     ...  AND  SSHLibrary.Open Connection     ${OPENBMC_HOST} | 
 |     ...  AND  SSHLibrary.Login   ${OPENBMC_USERNAME}    ${OPENBMC_PASSWORD} | 
 |     ...  AND  Return From Keyword | 
 |  | 
 |     OperatingSystem.File Should Exist  tools/ipmitool  msg=${ipmitool_error} | 
 |     Import Library      SCPLibrary      AS       scp | 
 |     scp.Open connection     ${OPENBMC_HOST}     username=${OPENBMC_USERNAME}      password=${OPENBMC_PASSWORD} | 
 |     scp.Put File    tools/ipmitool   /tmp | 
 |     SSHLibrary.Open Connection     ${OPENBMC_HOST} | 
 |     SSHLibrary.Login   ${OPENBMC_USERNAME}    ${OPENBMC_PASSWORD} | 
 |     Execute Command     chmod +x ${IPMITOOL_PATH} | 
 |  | 
 |  | 
 | 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 | 
 |  | 
 |  | 
 | Is Host Off Via IPMI | 
 |     [Documentation]  Verify if the Host is off using IPMI command. | 
 |  | 
 |     ${status}=  Run External IPMI Standard Command  chassis power status | 
 |     Should Contain  ${status}  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. | 
 |  | 
 |     ${output}=  Wait Until Keyword Succeeds  15 sec  5 sec  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}  ${CHANNEL_NUMBER} | 
 |     Should Be Equal  ${user_info['user_name']}  ${username} | 
 |  | 
 |  | 
 | Enable IPMI User And Verify | 
 |     [Documentation]  Enable the userid and verify that it has been enabled. | 
 |     [Arguments]  ${userid} | 
 |  | 
 |     # Description of argument(s): | 
 |     # userid   A numeric userid (e.g. "4"). | 
 |  | 
 |     Run IPMI Standard Command  user enable ${userid} | 
 |     ${user_info}=  Get User Info  ${userid}  ${CHANNEL_NUMBER} | 
 |     Valid Value  user_info['enable_status']  ['enabled'] | 
 |  | 
 |  | 
 | Create Random IPMI User | 
 |     [Documentation]  Create IPMI user with random username and userid and return those fields. | 
 |  | 
 |     ${random_username}=  Generate Random String  8  [LETTERS] | 
 |     ${random_userid}=  Find Free User Id | 
 |     IPMI Create User  ${random_userid}  ${random_username} | 
 |     Wait And Confirm New User Entry  ${random_username} | 
 |     RETURN  ${random_userid}  ${random_username} | 
 |  | 
 |  | 
 | Find Free User Id | 
 |     [Documentation]  Find a userid that is not being used. | 
 |  | 
 |     Check Enabled User Count | 
 |     FOR    ${num}    IN RANGE    300 | 
 |         ${random_userid}=  Evaluate  random.randint(1, ${expected_max_ids})  modules=random | 
 |         ${access}=  Run IPMI Standard Command  channel getaccess ${CHANNEL_NUMBER} ${random_userid} | 
 |  | 
 |         ${name_line}=  Get Lines Containing String  ${access}  User Name | 
 |         Log To Console  For ID ${random_userid}: ${name_line} | 
 |         ${is_empty}=  Run Keyword And Return Status | 
 |         ...  Should Match Regexp  ${name_line}  ${empty_name_pattern} | 
 |  | 
 |         Exit For Loop If  ${is_empty} == ${True} | 
 |     END | 
 |     RETURN  ${random_userid} | 
 |  | 
 |  | 
 | Check Enabled User Count | 
 |     [Documentation]  Ensure that there are available user IDs. | 
 |  | 
 |     # Check for the enabled user count | 
 |     ${resp}=  Run IPMI Standard Command  user summary ${CHANNEL_NUMBER} | 
 |     ${enabled_user_count}= | 
 |     ...  Get Lines Containing String  ${resp}  Enabled User Count | 
 |  | 
 |     Should not contain  ${enabled_user_count}  ${expected_max_ids} | 
 |     ...  msg=IPMI has reached maximum user count | 
 |  | 
 |  | 
 | Wait And Confirm New User Entry | 
 |     [Documentation]  Wait in loop until new user appears with given username. | 
 |     [Arguments]  ${username} | 
 |  | 
 |     # Description of argument(s): | 
 |     # username         The user name (e.g. "root", "robert", etc.). | 
 |  | 
 |     Wait Until Keyword Succeeds  45 sec  1 sec  Verify IPMI Username Visible | 
 |     ...  ${username} | 
 |  | 
 |  | 
 | Verify IPMI Username Visible | 
 |     [Documentation]  Confirm that username is present in user list. | 
 |     [Arguments]  ${username} | 
 |  | 
 |     # Description of argument(s): | 
 |     # username         The user name (e.g. "root", "robert", etc.). | 
 |  | 
 |     ${resp}=  Run IPMI Standard Command  user list | 
 |     Should Contain  ${resp}  ${username} | 
 |  | 
 |  | 
 | Delete Created User | 
 |     [Documentation]  Delete created IPMI user. | 
 |     [Arguments]  ${userid} | 
 |     # Description of argument(s): | 
 |     # userid  The user ID (e.g. "1", "2", etc.). | 
 |  | 
 |     Run IPMI Standard Command  user set name ${userid} "" | 
 |     Sleep  5s | 
 |  | 
 |  | 
 | 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}  ${CHANNEL_NUMBER} | 
 |     # 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 | 
 |  | 
 |  | 
 | Create SEL | 
 |     [Documentation]  Create a SEL. | 
 |     [Arguments]  ${sensor_type}  ${sensor_number} | 
 |  | 
 |     # Create a SEL. | 
 |     # Example: | 
 |     # a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted | 
 |     # Description of argument(s): | 
 |     #    ${sensor_type}            Type of the sensor used in hexadecimal (can be fan, temp etc.,), | 
 |     #                              obtained from Sensor Type field in - ipmitool sdr get "sensor_name". | 
 |     #                              Example: Sensor Type (Threshold) : Fan (0x04), here 0xHH is sensor type. | 
 |  | 
 |     #    ${sensor_number}          Sensor number of the sensor in hexadecimal. | 
 |     #                              obtained from Sensor ID field in - ipmitool sdr get "sensor_name". | 
 |     #                              Example: Sensor ID : SENSOR_1 (0xHH), here 0xHH is sensor number. | 
 |  | 
 |     ${cmd}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][0]} 0x${GEN_ID_BYTE_1} 0x${GEN_ID_BYTE_2} | 
 |     ...  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][1]} 0x${sensor_type} 0x${sensor_number} | 
 |     ...  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][2]} | 
 |  | 
 |     ${resp}=  Run IPMI Command  ${cmd} | 
 |  | 
 |     Should Not Contain  ${resp}  00 00  msg=SEL not created. | 
 |  | 
 |     Sleep  5s | 
 |  | 
 |     RETURN  ${resp} | 
 |  | 
 |  | 
 | Fetch One Threshold Sensor From Sensor List | 
 |     [Documentation]  Fetch one threshold sensor randomly from Sensor list. | 
 |  | 
 |     @{sensor_name_list}=  Create List | 
 |  | 
 |     ${resp}=  Run IPMI Standard Command  sensor | 
 |     @{sensor_list}=  Split To Lines  ${resp} | 
 |  | 
 |     # Omit the discrete sensor and create an threshold sensor name list | 
 |     FOR  ${sensor}  IN  @{sensor_list} | 
 |       ${discrete_sensor_status}=  Run Keyword And Return Status  Should Contain  ${sensor}  discrete | 
 |       Continue For Loop If  '${discrete_sensor_status}' == 'True' | 
 |       ${sensor_details}=  Split String  ${sensor}  | | 
 |       ${get_sensor_name}=  Get From List  ${sensor_details}  0 | 
 |       ${sensor_name}=  Set Variable  ${get_sensor_name.strip()} | 
 |       Append To List  ${sensor_name_list}  ${sensor_name} | 
 |     END | 
 |  | 
 |     ${random_sensor_name}=  Evaluate  random.choice(${sensor_name_list})  random | 
 |  | 
 |     RETURN  ${random_sensor_name} | 
 |  | 
 | Fetch Sensor Details From SDR | 
 |     [Documentation]  Identify the sensors from sdr get and fetch sensor details required. | 
 |     [Arguments]  ${sensor_name}  ${setting} | 
 |  | 
 |     # Description of argument(s): | 
 |     #    ${sensor_number}        Sensor number of the sensor in hexadecimal. | 
 |     #                            obtained sensor name from - 'ipmitool sensor' command. | 
 |     #                            Example: a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted | 
 |     #                            here, a is the sensor name. | 
 |  | 
 |     #    ${setting}              Field to fetch data. Example : Sensor ID, Sensor Type (Threshold), etc,. | 
 |  | 
 |     ${resp}=  Run IPMI Standard Command  sdr get "${sensor_name}" | 
 |  | 
 |     ${setting_line}=  Get Lines Containing String  ${resp}  ${setting} | 
 |     ...  case-insensitive | 
 |     ${setting_status}=  Fetch From Right  ${setting_line}  :${SPACE} | 
 |  | 
 |     RETURN  ${setting_status} | 
 |  | 
 |  | 
 | Get Bytes From SDR Sensor | 
 |     [Documentation]  Fetch the Field Data and hexadecimal values from given details. | 
 |     [Arguments]  ${sensor_detail} | 
 |  | 
 |     # Description of argument(s): | 
 |     #    ${sensor_detail}      Requested field and the value from the sdr get ipmi command. | 
 |     #                          Example : if Sensor ID is the requesting setting, then, | 
 |     #                          ${sensor_detail} will be "Sensor ID : SENSOR_1 (0xHH)" | 
 |  | 
 |     ${sensor_detail}=  Split String  ${sensor_detail}  (0x | 
 |     ${sensor_hex}=  Replace String  ${sensor_detail[1]}  )  ${EMPTY} | 
 |     ${sensor_hex}=  Zfill Data  ${sensor_hex}  2 | 
 |  | 
 |     RETURN  ${sensor_hex} | 
 |  | 
 |  | 
 | Get Current Date from BMC | 
 |     [Documentation]  Runs the date command from BMC and returns current date and time | 
 |     [Arguments]  ${date_format}=%m/%d/%Y %H:%M:%S | 
 |  | 
 |     # Description of argument(s): | 
 |     # date_format    Date format of the result. E.g. %Y-%m-%d %H:%M:%S etc. | 
 |  | 
 |     # Get Current Date from BMC | 
 |     ${date}  ${stderr}  ${rc}=  BMC Execute Command   date | 
 |  | 
 |     # Split the string and remove first and 2nd last value from the list and join to form %d %b %H:%M:%S %Y date format | 
 |     ${date}=  Split String  ${date} | 
 |     Remove From List  ${date}  0 | 
 |     Remove From List  ${date}  -2 | 
 |     ${date}=  Evaluate  " ".join(${date}) | 
 |  | 
 |     # Convert the date to specified format, default:%m/%d/%Y %H:%M:%S | 
 |     ${date}=  Convert Date  ${date}  date_format=%b %d %H:%M:%S %Y  result_format=${date_format}  exclude_millis=True | 
 |  | 
 |     RETURN   ${date} | 
 |  | 
 |  | 
 | Get SEL Info Via IPMI | 
 |     [Documentation]  Get the SEL Info via IPMI raw command | 
 |  | 
 |     # Get SEL Info response consist of 14 bytes of hexadecimal data. | 
 |  | 
 |     # Byte 1 - SEL Version, | 
 |     # Byte 2 & 3 - Entry bytes - LSB MSB, | 
 |     # Byte 4 & 5 - Free Space in bytes, LS Byte first. | 
 |     # Byte 6 - 9 - Most recent addition timestamp, | 
 |     # Byte 10-13 - Most recent erase timestamp, | 
 |     # Byte 14 - Operation Support | 
 |  | 
 |     # Example: ${resp} will be "51 XX XX XX XX ff ff ff ff ff ff ff ff XX" | 
 |  | 
 |     ${resp}=  Run IPMI Command | 
 |     ...  ${IPMI_RAW_CMD['SEL_entry']['SEL_info'][0]} | 
 |     ${resp}=  Split String  ${resp} | 
 |  | 
 |     RETURN  ${resp} | 
 |  | 
 |  | 
 | Verify Invalid IPMI Command | 
 |     [Documentation]  Execute invalid IPMI command and verify with given response code. | 
 |     [Arguments]  ${ipmi_cmd}  ${error_code}=0xc9 | 
 |  | 
 |     #  Description Of Arguments. | 
 |     #  ${ipmi_cmd}   - IPMI raw cmd with invalid data length. | 
 |     #  ${error_code} - Expected error code e.g 0xc7, 0xcc. | 
 |  | 
 |     ${resp}=  Run IPMI Command  ${ipmi_cmd}  fail_on_err=0 | 
 |  | 
 |     Should Contain  ${resp}  rsp=${error_code} | 
 |  | 
 |  | 
 | Identify Request Data | 
 |     [Documentation]  Convert text from variable declared to request data. | 
 |     [Arguments]  ${string} | 
 |  | 
 |     # Convert string to hexadecimal data for each character. | 
 |     # Return the hex data with prefix of 0x as string and list of hex data. | 
 |     # Description of argument(s): | 
 |     #    string             Any string to be converted to hex. | 
 |  | 
 |     # Given a string, convert to hexadecimal and prefix with 0x | 
 |     ${hex1}=  Create List | 
 |     ${hex2}=  Create List | 
 |     ${resp_data}=  Split String With Index  ${string}  1 | 
 |     FOR  ${data}  IN  @{resp_data} | 
 |         # prefixes 0x by default | 
 |         ${hex_value}=  Evaluate  hex(ord("${data}")) | 
 |         # prefixes string with bytes prefixed 0x by default | 
 |         Append To List  ${hex1}  ${hex_value} | 
 |         # provides only hexadecimal bytes | 
 |         ${hex}=  Evaluate  hex(ord("${data}"))[2:] | 
 |         # provides string with only hexadecimal bytes | 
 |         Append To List  ${hex2}  ${hex} | 
 |     END | 
 |     ${hex1}=  Evaluate  " ".join(${hex1}) | 
 |  | 
 |     # ${hex1} will contains the data to write for fru in list. | 
 |     # ${hex2} will contains the data to verify fru after write operation completed. | 
 |  | 
 |     RETURN  ${hex1}  ${hex2} |