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