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