1*** Settings *** 2Documentation This module is for IPMI client for copying ipmitool to 3... openbmc box and execute ipmitool IPMI standard 4... command. IPMI raw command will use dbus-send command 5Resource ../lib/resource.robot 6Resource ../lib/connection_client.robot 7Resource ../lib/utils.robot 8Resource ../lib/state_manager.robot 9 10Library String 11Library ipmi_client.py 12 13*** Variables *** 14${dbusHostIpmicmd1}= dbus-send --system ${OPENBMC_BASE_URI}HostIpmi/1 15${dbusHostIpmiCmdReceivedMsg}= ${OPENBMC_BASE_DBUS}.HostIpmi.ReceivedMessage 16${netfnByte}= ${EMPTY} 17${cmdByte}= ${EMPTY} 18${arrayByte}= array:byte: 19${IPMI_USER_OPTIONS} ${EMPTY} 20${IPMI_INBAND_CMD}= ipmitool -C ${IPMI_CIPHER_LEVEL} 21${HOST}= -H 22${RAW}= raw 23 24*** Keywords *** 25 26Run IPMI Command 27 [Documentation] Run the raw IPMI command. 28 [Arguments] ${command} ${fail_on_err}=${1} &{options} 29 30 # Description of argument(s): 31 # command The IPMI command string to be executed 32 # (e.g. "power status"). 33 # fail_on_err Fail if the IPMI command execution fails. 34 # options Additional ipmitool command options (e.g. 35 # -C=3, -I=lanplus, etc.). Currently, only 36 # used for external IPMI commands. 37 38 ${resp}= Run Keyword If '${IPMI_COMMAND}' == 'External' 39 ... Run External IPMI Raw Command ${command} ${fail_on_err} &{options} 40 ... ELSE IF '${IPMI_COMMAND}' == 'Inband' 41 ... Run Inband IPMI Raw Command ${command} 42 ... ELSE IF '${IPMI_COMMAND}' == 'Dbus' 43 ... Run Dbus IPMI RAW Command ${command} 44 ... ELSE Fail msg=Invalid IPMI Command type provided: ${IPMI_COMMAND} 45 [Return] ${resp} 46 47 48Run IPMI Standard Command 49 [Documentation] Run the standard IPMI command. 50 [Arguments] ${command} ${fail_on_err}=${1} ${expected_rc}=${0} &{options} 51 52 # Description of argument(s): 53 # command The IPMI command string to be executed 54 # (e.g. "0x06 0x36"). 55 # fail_on_err Fail if the IPMI command execution fails. 56 # expected_rc The expected return code from the ipmi 57 # command (e.g. ${0}, ${1}, etc.). 58 # options Additional ipmitool command options (e.g. 59 # -C=3, -I=lanplus, etc.). Currently, only 60 # used for external IPMI commands. 61 62 ${resp}= Run Keyword If '${IPMI_COMMAND}' == 'External' 63 ... Run External IPMI Standard Command ${command} ${fail_on_err} ${expected_rc} &{options} 64 ... ELSE IF '${IPMI_COMMAND}' == 'Inband' 65 ... Run Inband IPMI Standard Command ${command} ${fail_on_err} 66 ... ELSE IF '${IPMI_COMMAND}' == 'Dbus' 67 ... Run Dbus IPMI Standard Command ${command} 68 ... ELSE Fail msg=Invalid IPMI Command type provided : ${IPMI_COMMAND} 69 70 [Return] ${resp} 71 72 73Run Dbus IPMI RAW Command 74 [Documentation] Run the raw IPMI command through dbus. 75 [Arguments] ${command} 76 ${valueinBytes}= Byte Conversion ${command} 77 ${cmd}= Catenate ${dbushostipmicmd1} ${dbusHostIpmiCmdReceivedMsg} 78 ${cmd}= Catenate ${cmd} ${valueinBytes} 79 ${output} ${stderr}= Execute Command ${cmd} return_stderr=True 80 Should Be Empty ${stderr} 81 set test variable ${OUTPUT} "${output}" 82 83 84Run Dbus IPMI Standard Command 85 [Documentation] Run the standard IPMI command through dbus. 86 [Arguments] ${command} 87 Copy ipmitool 88 ${stdout} ${stderr} ${output}= Execute Command 89 ... /tmp/ipmitool -I dbus ${command} return_stdout=True 90 ... return_stderr= True return_rc=True 91 Should Be Equal ${output} ${0} msg=${stderr} 92 [Return] ${stdout} 93 94 95Run Inband IPMI Raw Command 96 [Documentation] Run the raw IPMI command in-band. 97 [Arguments] ${command} ${os_host}=${OS_HOST} ${os_username}=${OS_USERNAME} 98 ... ${os_password}=${OS_PASSWORD} 99 100 # Description of argument(s): 101 # command The IPMI command string to be executed 102 # (e.g. "0x06 0x36"). 103 # os_host The host name or IP address of the OS Host. 104 # os_username The OS host user name. 105 # os_password The OS host passwrd. 106 107 Login To OS Host ${os_host} ${os_username} ${os_password} 108 Check If IPMI Tool Exist 109 110 ${ipmi_cmd}= Catenate ${IPMI_INBAND_CMD} ${RAW} ${command} 111 Qprint Issuing ${ipmi_cmd} 112 ${stdout} ${stderr}= Execute Command ${ipmi_cmd} return_stderr=True 113 Should Be Empty ${stderr} msg=${stdout} 114 [Return] ${stdout} 115 116 117Run Inband IPMI Standard Command 118 [Documentation] Run the standard IPMI command in-band. 119 [Arguments] ${command} ${fail_on_err}=${1} ${os_host}=${OS_HOST} 120 ... ${os_username}=${OS_USERNAME} ${os_password}=${OS_PASSWORD} 121 122 # Description of argument(s): 123 # command The IPMI command string to be executed 124 # (e.g. "power status"). 125 # os_host The host name or IP address of the OS Host. 126 # os_username The OS host user name. 127 # os_password The OS host passwrd. 128 129 Login To OS Host ${os_host} ${os_username} ${os_password} 130 Check If IPMI Tool Exist 131 132 ${ipmi_cmd}= Catenate ${IPMI_INBAND_CMD} ${command} 133 Qprint Issuing ${ipmi_cmd} 134 ${stdout} ${stderr}= Execute Command ${ipmi_cmd} return_stderr=True 135 Return From Keyword If ${fail_on_err} == ${0} ${stderr} 136 Should Be Empty ${stderr} msg=${stdout} 137 [Return] ${stdout} 138 139 140Run External IPMI Standard Command 141 [Documentation] Run the external IPMI standard command. 142 [Arguments] ${command} ${fail_on_err}=${1} ${expected_rc}=${0} &{options} 143 144 # Description of argument(s): 145 # command The IPMI command string to be executed 146 # (e.g. "power status"). Note that if 147 # ${IPMI_USER_OPTIONS} has a value (e.g. 148 # "-vvv"), it will be pre-pended to this 149 # command string. 150 # fail_on_err Fail if the IPMI command execution fails. 151 # expected_rc The expected return code from the ipmi 152 # command (e.g. ${0}, ${1}, etc.). 153 # options Additional ipmitool command options (e.g. 154 # -C=3, -I=lanplus, etc.). 155 156 ${command_string}= Process IPMI User Options ${command} 157 ${ipmi_cmd}= Create IPMI Ext Command String ${command_string} &{options} 158 Qprint Issuing ${ipmi_cmd} 159 ${rc} ${output}= Run And Return RC and Output ${ipmi_cmd} 160 Return From Keyword If ${fail_on_err} == ${0} ${output} 161 Should Be Equal ${rc} ${expected_rc} msg=${output} 162 [Return] ${output} 163 164 165Run External IPMI Raw Command 166 [Documentation] Run the external IPMI raw command. 167 [Arguments] ${command} ${fail_on_err}=${1} &{options} 168 169 # This keyword is a wrapper for 'Run External IPMI Standard Command'. See 170 # that keyword's prolog for argument details. This keyword will pre-pend 171 # the word "raw" plus a space to command prior to calling 'Run External 172 # IPMI Standard Command'. 173 174 ${output}= Run External IPMI Standard Command 175 ... raw ${command} ${fail_on_err} &{options} 176 [Return] ${output} 177 178 179Check If IPMI Tool Exist 180 [Documentation] Check if IPMI Tool installed or not. 181 ${output}= Execute Command which ipmitool 182 Should Not Be Empty ${output} msg=ipmitool not installed. 183 184 185Activate SOL Via IPMI 186 [Documentation] Start SOL using IPMI and route output to a file. 187 [Arguments] ${file_path}=/tmp/sol_${OPENBMC_HOST} 188 189 # Description of argument(s): 190 # file_path The file path on the local machine (vs. 191 # OBMC) to collect SOL output. By default 192 # SOL output is collected at 193 # /tmp/sol_<BMC_IP> else user input location. 194 195 ${ipmi_cmd}= Create IPMI Ext Command String sol activate usesolkeepalive 196 Qprint Issuing ${ipmi_cmd} 197 Start Process ${ipmi_cmd} shell=True stdout=${file_path} 198 ... alias=sol_proc 199 200 201Deactivate SOL Via IPMI 202 [Documentation] Stop SOL using IPMI and return SOL output. 203 [Arguments] ${file_path}=/tmp/sol_${OPENBMC_HOST} 204 205 # Description of argument(s): 206 # file_path The file path on the local machine to copy 207 # SOL output collected by above "Activate 208 # SOL Via IPMI" keyword. By default it 209 # copies log from /tmp/sol_<BMC_IP>. 210 211 ${ipmi_cmd}= Create IPMI Ext Command String sol deactivate 212 Qprint Issuing ${ipmi_cmd} 213 ${rc} ${output}= Run and Return RC and Output ${ipmi_cmd} 214 Run Keyword If ${rc} > 0 Run Keywords 215 ... Run Keyword And Ignore Error Terminate Process sol_proc 216 ... AND Return From Keyword ${output} 217 218 ${rc} ${output}= Run and Return RC and Output cat ${file_path} 219 Should Be Equal ${rc} ${0} msg=${output} 220 221 # Logging SOL output for debug purpose. 222 Log ${output} 223 224 [Return] ${output} 225 226 227Byte Conversion 228 [Documentation] Byte Conversion method receives IPMI RAW commands as 229 ... argument in string format. 230 ... Sample argument is as follows 231 ... "0x04 0x30 9 0x01 0x00 0x35 0x00 0x00 0x00 0x00 0x00 232 ... 0x00" 233 ... IPMI RAW command format is as follows 234 ... <netfn Byte> <cmd Byte> <Data Bytes..> 235 ... This method converts IPMI command format into 236 ... dbus command format as follows 237 ... <byte:seq-id> <byte:netfn> <byte:lun> <byte:cmd> 238 ... <array:byte:data> 239 ... Sample dbus Host IPMI Received Message argument 240 ... byte:0x00 byte:0x04 byte:0x00 byte:0x30 241 ... array:byte:9,0x01,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00 242 [Arguments] ${args} 243 ${argLength}= Get Length ${args} 244 Set Global Variable ${arrayByte} array:byte: 245 @{listargs}= Split String ${args} 246 ${index}= Set Variable ${0} 247 :FOR ${word} IN @{listargs} 248 \ Run Keyword if ${index} == 0 Set NetFn Byte ${word} 249 \ Run Keyword if ${index} == 1 Set Cmd Byte ${word} 250 \ Run Keyword if ${index} > 1 Set Array Byte ${word} 251 \ ${index}= Set Variable ${index + 1} 252 ${length}= Get Length ${arrayByte} 253 ${length}= Evaluate ${length} - 1 254 ${arrayByteLocal}= Get Substring ${arrayByte} 0 ${length} 255 Set Global Variable ${arrayByte} ${arrayByteLocal} 256 ${valueinBytesWithArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 257 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${cmdByte} 258 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${arrayByte} 259 ${valueinBytesWithoutArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 260 ${valueinBytesWithoutArray}= Catenate ${valueinBytesWithoutArray} ${cmdByte} 261 # To Check scenario for smaller IPMI raw commands with only 2 arguments 262 # instead of usual 12 arguments. 263 # Sample small IPMI raw command: Run IPMI command 0x06 0x36 264 # If IPMI raw argument length is only 9 then return value in bytes without 265 # array population. 266 # Equivalent dbus-send argument for smaller IPMI raw command: 267 # byte:0x00 byte:0x06 byte:0x00 byte:0x36 268 Run Keyword if ${argLength} == 9 Return from Keyword ${valueinBytesWithoutArray} 269 [Return] ${valueinBytesWithArray} 270 271 272Set NetFn Byte 273 [Documentation] Set the network function byte. 274 [Arguments] ${word} 275 ${netfnByteLocal}= Catenate byte:${word} 276 Set Global Variable ${netfnByte} ${netfnByteLocal} 277 278 279Set Cmd Byte 280 [Documentation] Set the command byte. 281 [Arguments] ${word} 282 ${cmdByteLocal}= Catenate byte:${word} 283 Set Global Variable ${cmdByte} ${cmdByteLocal} 284 285 286Set Array Byte 287 [Documentation] Set the array byte. 288 [Arguments] ${word} 289 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByte} ${word} 290 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByteLocal} , 291 Set Global Variable ${arrayByte} ${arrayByteLocal} 292 293 294Copy ipmitool 295 [Documentation] Copy the ipmitool to the BMC. 296 ${ipmitool_error}= Catenate The ipmitool program could not be found in the tools directory. 297 ... It is not part of the automation code by default. You must manually copy or link the correct openbmc 298 ... version of the tool in to the tools directory in order to run this test suite. 299 300 OperatingSystem.File Should Exist tools/ipmitool msg=${ipmitool_error} 301 302 Import Library SCPLibrary WITH NAME scp 303 scp.Open connection ${OPENBMC_HOST} username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD} 304 scp.Put File tools/ipmitool /tmp 305 SSHLibrary.Open Connection ${OPENBMC_HOST} 306 Login ${OPENBMC_USERNAME} ${OPENBMC_PASSWORD} 307 Execute Command chmod +x /tmp/ipmitool 308 309 310Initiate Host Boot Via External IPMI 311 [Documentation] Initiate host power on using external IPMI. 312 [Arguments] ${wait}=${1} 313 314 # Description of argument(s): 315 # wait Indicates that this keyword should wait 316 # for host running state. 317 318 ${output}= Run External IPMI Standard Command chassis power on 319 Should Not Contain ${output} Error 320 321 Run Keyword If '${wait}' == '${0}' Return From Keyword 322 Wait Until Keyword Succeeds 10 min 10 sec Is Host Running 323 324 325Initiate Host PowerOff Via External IPMI 326 [Documentation] Initiate host power off using external IPMI. 327 [Arguments] ${wait}=${1} 328 329 # Description of argument(s): 330 # wait Indicates that this keyword should wait 331 # for host off state. 332 333 ${output}= Run External IPMI Standard Command chassis power off 334 Should Not Contain ${output} Error 335 336 Run Keyword If '${wait}' == '${0}' Return From Keyword 337 Wait Until Keyword Succeeds 3 min 10 sec Is Host Off 338 339 340Get Host State Via External IPMI 341 [Documentation] Returns host state using external IPMI. 342 343 ${output}= Run External IPMI Standard Command chassis power status 344 Should Not Contain ${output} Error 345 ${output}= Fetch From Right ${output} ${SPACE} 346 347 [Return] ${output} 348 349 350Set BMC Network From Host 351 [Documentation] Set BMC network from host. 352 [Arguments] ${nw_info} 353 354 # Description of argument(s): 355 # nw_info A dictionary containing the network 356 # information to apply. 357 358 Run Inband IPMI Standard Command 359 ... lan set 1 ipaddr ${nw_info['IP Address']} 360 361 Run Inband IPMI Standard Command 362 ... lan set 1 netmask ${nw_info['Subnet Mask']} 363 364 Run Inband IPMI Standard Command 365 ... lan set 1 defgw ipaddr ${nw_info['Default Gateway IP']} 366 367 368Verify IPMI Username And Password 369 [Documentation] Verify that user is able to run IPMI command 370 ... with given username and password. 371 [Arguments] ${username} ${password} 372 373 # Description of argument(s): 374 # username The user name (e.g. "root", "robert", etc.). 375 # password The user password (e.g. "0penBmc", "0penBmc1", etc.). 376 377 ${output}= Run External IPMI Standard Command 378 ... sel info U=${username} P=${password} 379 Should Contain ${output} SEL Information msg=SEL information not present 380 381 382IPMI Create User 383 [Documentation] Create IPMI user with given userid and username. 384 [Arguments] ${userid} ${username} 385 386 # Description of argument(s): 387 # userid The user ID (e.g. "1", "2", etc.). 388 # username The user name (e.g. "root", "robert", etc.). 389 390 ${ipmi_cmd}= Catenate user set name ${userid} ${username} 391 ${resp}= Run IPMI Standard Command ${ipmi_cmd} 392 ${user_info}= Get User Info ${userid} 393 Should Be Equal ${user_info['user_name']} ${username} 394 395 396Set Channel Access 397 [Documentation] Verify that user is able to run IPMI command 398 ... with given username and password. 399 [Arguments] ${userid} ${options} ${channel}=1 400 401 # Description of argument(s): 402 # userid The user ID (e.g. "1", "2", etc.). 403 # options Set channel command options (e.g. 404 # "link=on", "ipmi=on", etc.). 405 # channel_number The user's channel number (e.g. "1"). 406 407 ${ipmi_cmd}= Catenate SEPARATOR= 408 ... channel setaccess${SPACE}${channel}${SPACE}${userid} 409 ... ${SPACE}${options} 410 Run IPMI Standard Command ${ipmi_cmd} 411 412 413Delete All Non Root IPMI User 414 [Documentation] Delete all non-root IPMI user. 415 416 FOR ${userid} IN RANGE 2 16 417 ${user_info}= Get User Info ${userid} 418 Run Keyword If "${user_info['user_name']}" != "" 419 ... Run IPMI Standard Command user set name ${userid} "" 420 END 421