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} -N ${IPMI_TIMEOUT} -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}=${IPMI_SOL_LOG_FILE} 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 # logs/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}=${IPMI_SOL_LOG_FILE} 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 logs/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 END 255 ${length}= Get Length ${arrayByte} 256 ${length}= Evaluate ${length} - 1 257 ${arrayByteLocal}= Get Substring ${arrayByte} 0 ${length} 258 Set Global Variable ${arrayByte} ${arrayByteLocal} 259 ${valueinBytesWithArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 260 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${cmdByte} 261 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${arrayByte} 262 ${valueinBytesWithoutArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 263 ${valueinBytesWithoutArray}= Catenate ${valueinBytesWithoutArray} ${cmdByte} 264 # To Check scenario for smaller IPMI raw commands with only 2 arguments 265 # instead of usual 12 arguments. 266 # Sample small IPMI raw command: Run IPMI command 0x06 0x36 267 # If IPMI raw argument length is only 9 then return value in bytes without 268 # array population. 269 # Equivalent dbus-send argument for smaller IPMI raw command: 270 # byte:0x00 byte:0x06 byte:0x00 byte:0x36 271 Run Keyword if ${argLength} == 9 Return from Keyword ${valueinBytesWithoutArray} 272 [Return] ${valueinBytesWithArray} 273 274 275Set NetFn Byte 276 [Documentation] Set the network function byte. 277 [Arguments] ${word} 278 ${netfnByteLocal}= Catenate byte:${word} 279 Set Global Variable ${netfnByte} ${netfnByteLocal} 280 281 282Set Cmd Byte 283 [Documentation] Set the command byte. 284 [Arguments] ${word} 285 ${cmdByteLocal}= Catenate byte:${word} 286 Set Global Variable ${cmdByte} ${cmdByteLocal} 287 288 289Set Array Byte 290 [Documentation] Set the array byte. 291 [Arguments] ${word} 292 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByte} ${word} 293 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByteLocal} , 294 Set Global Variable ${arrayByte} ${arrayByteLocal} 295 296 297Copy ipmitool 298 [Documentation] Copy the ipmitool to the BMC. 299 ${ipmitool_error}= Catenate The ipmitool program could not be found in the tools directory. 300 ... It is not part of the automation code by default. You must manually copy or link the correct openbmc 301 ... version of the tool in to the tools directory in order to run this test suite. 302 303 OperatingSystem.File Should Exist tools/ipmitool msg=${ipmitool_error} 304 305 Import Library SCPLibrary WITH NAME scp 306 scp.Open connection ${OPENBMC_HOST} username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD} 307 scp.Put File tools/ipmitool /tmp 308 SSHLibrary.Open Connection ${OPENBMC_HOST} 309 SSHLibrary.Login ${OPENBMC_USERNAME} ${OPENBMC_PASSWORD} 310 Execute Command chmod +x /tmp/ipmitool 311 312 313Initiate Host Boot Via External IPMI 314 [Documentation] Initiate host power on using external IPMI. 315 [Arguments] ${wait}=${1} 316 317 # Description of argument(s): 318 # wait Indicates that this keyword should wait 319 # for host running state. 320 321 ${output}= Run External IPMI Standard Command chassis power on 322 Should Not Contain ${output} Error 323 324 Run Keyword If '${wait}' == '${0}' Return From Keyword 325 Wait Until Keyword Succeeds 10 min 10 sec Is Host Running 326 327 328Initiate Host PowerOff Via External IPMI 329 [Documentation] Initiate host power off using external IPMI. 330 [Arguments] ${wait}=${1} 331 332 # Description of argument(s): 333 # wait Indicates that this keyword should wait 334 # for host off state. 335 336 ${output}= Run External IPMI Standard Command chassis power off 337 Should Not Contain ${output} Error 338 339 Run Keyword If '${wait}' == '${0}' Return From Keyword 340 Wait Until Keyword Succeeds 3 min 10 sec Is Host Off 341 342 343Is Host Off Via IPMI 344 [Documentation] Verify if the Host is off using IPMI command. 345 346 ${status}= Run External IPMI Standard Command chassis power status 347 Should Contain ${status} off 348 349 350Get Host State Via External IPMI 351 [Documentation] Returns host state using external IPMI. 352 353 ${output}= Run External IPMI Standard Command chassis power status 354 Should Not Contain ${output} Error 355 ${output}= Fetch From Right ${output} ${SPACE} 356 357 [Return] ${output} 358 359 360Set BMC Network From Host 361 [Documentation] Set BMC network from host. 362 [Arguments] ${nw_info} 363 364 # Description of argument(s): 365 # nw_info A dictionary containing the network 366 # information to apply. 367 368 Run Inband IPMI Standard Command 369 ... lan set 1 ipaddr ${nw_info['IP Address']} 370 371 Run Inband IPMI Standard Command 372 ... lan set 1 netmask ${nw_info['Subnet Mask']} 373 374 Run Inband IPMI Standard Command 375 ... lan set 1 defgw ipaddr ${nw_info['Default Gateway IP']} 376 377 378Verify IPMI Username And Password 379 [Documentation] Verify that user is able to run IPMI command 380 ... with given username and password. 381 [Arguments] ${username} ${password} 382 383 # Description of argument(s): 384 # username The user name (e.g. "root", "robert", etc.). 385 # password The user password (e.g. "0penBmc", "0penBmc1", etc.). 386 387 ${output}= Wait Until Keyword Succeeds 15 sec 5 sec Run External IPMI Standard Command 388 ... sel info U=${username} P=${password} 389 Should Contain ${output} SEL Information msg=SEL information not present 390 391 392IPMI Create User 393 [Documentation] Create IPMI user with given userid and username. 394 [Arguments] ${userid} ${username} 395 396 # Description of argument(s): 397 # userid The user ID (e.g. "1", "2", etc.). 398 # username The user name (e.g. "root", "robert", etc.). 399 400 ${ipmi_cmd}= Catenate user set name ${userid} ${username} 401 ${resp}= Run IPMI Standard Command ${ipmi_cmd} 402 ${user_info}= Get User Info ${userid} 403 Should Be Equal ${user_info['user_name']} ${username} 404 405 406Set Channel Access 407 [Documentation] Verify that user is able to run IPMI command 408 ... with given username and password. 409 [Arguments] ${userid} ${options} ${channel_number}=${CHANNEL_NUMBER} 410 411 # Description of argument(s): 412 # userid The user ID (e.g. "1", "2", etc.). 413 # options Set channel command options (e.g. 414 # "link=on", "ipmi=on", etc.). 415 # channel_number The user's channel number (e.g. "1"). 416 417 ${ipmi_cmd}= Catenate SEPARATOR= 418 ... channel setaccess${SPACE}${channel_number}${SPACE}${userid} 419 ... ${SPACE}${options} 420 Run IPMI Standard Command ${ipmi_cmd} 421 422 423Delete All Non Root IPMI User 424 [Documentation] Delete all non-root IPMI user. 425 426 # Get complete list of user info records. 427 ${user_info}= Get User Info ${EMPTY} 428 # Remove header record. 429 ${user_info}= Filter Struct ${user_info} [('user_name', None)] invert=1 430 ${non_empty_user_info}= Filter Struct ${user_info} [('user_name', '')] invert=1 431 ${non_root_user_info}= Filter Struct ${non_empty_user_info} [('user_name', 'root')] invert=1 432 433 FOR ${user_record} IN @{non_root_user_info} 434 Run IPMI Standard Command user set name ${user_record['user_id']} "" 435 Sleep 5s 436 END 437