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