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} ${fail_on_err}=${1} ${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 Return From Keyword If ${fail_on_err} == ${0} ${stderr} 114 Should Be Empty ${stderr} msg=${stdout} 115 [Return] ${stdout} 116 117 118Run Inband IPMI Standard Command 119 [Documentation] Run the standard IPMI command in-band. 120 [Arguments] ${command} ${fail_on_err}=${1} ${os_host}=${OS_HOST} 121 ... ${os_username}=${OS_USERNAME} ${os_password}=${OS_PASSWORD} 122 ... ${login_host}=${1} 123 124 # Description of argument(s): 125 # command The IPMI command string to be executed 126 # (e.g. "power status"). 127 # os_host The host name or IP address of the OS Host. 128 # os_username The OS host user name. 129 # os_password The OS host passwrd. 130 # login_host Indicates that this keyword should login to host OS. 131 132 Run Keyword If ${login_host} == ${1} 133 ... Login To OS Host ${os_host} ${os_username} ${os_password} 134 Check If IPMI Tool Exist 135 136 ${ipmi_cmd}= Catenate ${IPMI_INBAND_CMD} ${command} 137 Qprint Issuing ${ipmi_cmd} 138 ${stdout} ${stderr}= Execute Command ${ipmi_cmd} return_stderr=True 139 Return From Keyword If ${fail_on_err} == ${0} ${stderr} 140 Should Be Empty ${stderr} msg=${stdout} 141 [Return] ${stdout} 142 143 144Run External IPMI Standard Command 145 [Documentation] Run the external IPMI standard command. 146 [Arguments] ${command} ${fail_on_err}=${1} ${expected_rc}=${0} &{options} 147 148 # Description of argument(s): 149 # command The IPMI command string to be executed 150 # (e.g. "power status"). Note that if 151 # ${IPMI_USER_OPTIONS} has a value (e.g. 152 # "-vvv"), it will be pre-pended to this 153 # command string. 154 # fail_on_err Fail if the IPMI command execution fails. 155 # expected_rc The expected return code from the ipmi 156 # command (e.g. ${0}, ${1}, etc.). 157 # options Additional ipmitool command options (e.g. 158 # -C=3, -I=lanplus, etc.). 159 160 ${command_string}= Process IPMI User Options ${command} 161 ${ipmi_cmd}= Create IPMI Ext Command String ${command_string} &{options} 162 Qprint Issuing ${ipmi_cmd} 163 ${rc} ${output}= Run And Return RC and Output ${ipmi_cmd} 164 Return From Keyword If ${fail_on_err} == ${0} ${output} 165 Should Be Equal ${rc} ${expected_rc} msg=${output} 166 [Return] ${output} 167 168 169Run External IPMI Raw Command 170 [Documentation] Run the external IPMI raw command. 171 [Arguments] ${command} ${fail_on_err}=${1} &{options} 172 173 # This keyword is a wrapper for 'Run External IPMI Standard Command'. See 174 # that keyword's prolog for argument details. This keyword will pre-pend 175 # the word "raw" plus a space to command prior to calling 'Run External 176 # IPMI Standard Command'. 177 178 ${output}= Run External IPMI Standard Command 179 ... raw ${command} ${fail_on_err} &{options} 180 [Return] ${output} 181 182 183Check If IPMI Tool Exist 184 [Documentation] Check if IPMI Tool installed or not. 185 ${output}= Execute Command which ipmitool 186 Should Not Be Empty ${output} msg=ipmitool not installed. 187 188 189Activate SOL Via IPMI 190 [Documentation] Start SOL using IPMI and route output to a file. 191 [Arguments] ${file_path}=${IPMI_SOL_LOG_FILE} 192 193 # Description of argument(s): 194 # file_path The file path on the local machine (vs. 195 # OBMC) to collect SOL output. By default 196 # SOL output is collected at 197 # logs/sol_<BMC_IP> else user input location. 198 199 ${ipmi_cmd}= Create IPMI Ext Command String sol activate usesolkeepalive 200 Qprint Issuing ${ipmi_cmd} 201 Start Process ${ipmi_cmd} shell=True stdout=${file_path} 202 ... alias=sol_proc 203 204 205Deactivate SOL Via IPMI 206 [Documentation] Stop SOL using IPMI and return SOL output. 207 [Arguments] ${file_path}=${IPMI_SOL_LOG_FILE} 208 209 # Description of argument(s): 210 # file_path The file path on the local machine to copy 211 # SOL output collected by above "Activate 212 # SOL Via IPMI" keyword. By default it 213 # copies log from logs/sol_<BMC_IP>. 214 215 ${ipmi_cmd}= Create IPMI Ext Command String sol deactivate 216 Qprint Issuing ${ipmi_cmd} 217 ${rc} ${output}= Run and Return RC and Output ${ipmi_cmd} 218 Run Keyword If ${rc} > 0 Run Keywords 219 ... Run Keyword And Ignore Error Terminate Process sol_proc 220 ... AND Return From Keyword ${output} 221 222 ${output}= OperatingSystem.Get File ${file_path} encoding_errors=ignore 223 224 # Logging SOL output for debug purpose. 225 Log ${output} 226 227 [Return] ${output} 228 229 230Byte Conversion 231 [Documentation] Byte Conversion method receives IPMI RAW commands as 232 ... argument in string format. 233 ... Sample argument is as follows 234 ... "0x04 0x30 9 0x01 0x00 0x35 0x00 0x00 0x00 0x00 0x00 235 ... 0x00" 236 ... IPMI RAW command format is as follows 237 ... <netfn Byte> <cmd Byte> <Data Bytes..> 238 ... This method converts IPMI command format into 239 ... dbus command format as follows 240 ... <byte:seq-id> <byte:netfn> <byte:lun> <byte:cmd> 241 ... <array:byte:data> 242 ... Sample dbus Host IPMI Received Message argument 243 ... byte:0x00 byte:0x04 byte:0x00 byte:0x30 244 ... array:byte:9,0x01,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00 245 [Arguments] ${args} 246 ${argLength}= Get Length ${args} 247 Set Global Variable ${arrayByte} array:byte: 248 @{listargs}= Split String ${args} 249 ${index}= Set Variable ${0} 250 FOR ${word} IN @{listargs} 251 Run Keyword if ${index} == 0 Set NetFn Byte ${word} 252 Run Keyword if ${index} == 1 Set Cmd Byte ${word} 253 Run Keyword if ${index} > 1 Set Array Byte ${word} 254 ${index}= Set Variable ${index + 1} 255 END 256 ${length}= Get Length ${arrayByte} 257 ${length}= Evaluate ${length} - 1 258 ${arrayByteLocal}= Get Substring ${arrayByte} 0 ${length} 259 Set Global Variable ${arrayByte} ${arrayByteLocal} 260 ${valueinBytesWithArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 261 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${cmdByte} 262 ${valueinBytesWithArray}= Catenate ${valueinBytesWithArray} ${arrayByte} 263 ${valueinBytesWithoutArray}= Catenate byte:0x00 ${netfnByte} byte:0x00 264 ${valueinBytesWithoutArray}= Catenate ${valueinBytesWithoutArray} ${cmdByte} 265 # To Check scenario for smaller IPMI raw commands with only 2 arguments 266 # instead of usual 12 arguments. 267 # Sample small IPMI raw command: Run IPMI command 0x06 0x36 268 # If IPMI raw argument length is only 9 then return value in bytes without 269 # array population. 270 # Equivalent dbus-send argument for smaller IPMI raw command: 271 # byte:0x00 byte:0x06 byte:0x00 byte:0x36 272 Run Keyword if ${argLength} == 9 Return from Keyword ${valueinBytesWithoutArray} 273 [Return] ${valueinBytesWithArray} 274 275 276Set NetFn Byte 277 [Documentation] Set the network function byte. 278 [Arguments] ${word} 279 ${netfnByteLocal}= Catenate byte:${word} 280 Set Global Variable ${netfnByte} ${netfnByteLocal} 281 282 283Set Cmd Byte 284 [Documentation] Set the command byte. 285 [Arguments] ${word} 286 ${cmdByteLocal}= Catenate byte:${word} 287 Set Global Variable ${cmdByte} ${cmdByteLocal} 288 289 290Set Array Byte 291 [Documentation] Set the array byte. 292 [Arguments] ${word} 293 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByte} ${word} 294 ${arrayByteLocal}= Catenate SEPARATOR= ${arrayByteLocal} , 295 Set Global Variable ${arrayByte} ${arrayByteLocal} 296 297 298Copy ipmitool 299 [Documentation] Copy the ipmitool to the BMC. 300 ${ipmitool_error}= Catenate The ipmitool program could not be found in the tools directory. 301 ... It is not part of the automation code by default. You must manually copy or link the correct openbmc 302 ... version of the tool in to the tools directory in order to run this test suite. 303 304 OperatingSystem.File Should Exist tools/ipmitool msg=${ipmitool_error} 305 306 Import Library SCPLibrary WITH NAME scp 307 scp.Open connection ${OPENBMC_HOST} username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD} 308 scp.Put File tools/ipmitool /tmp 309 SSHLibrary.Open Connection ${OPENBMC_HOST} 310 SSHLibrary.Login ${OPENBMC_USERNAME} ${OPENBMC_PASSWORD} 311 Execute Command chmod +x /tmp/ipmitool 312 313 314Initiate Host Boot Via External IPMI 315 [Documentation] Initiate host power on using external IPMI. 316 [Arguments] ${wait}=${1} 317 318 # Description of argument(s): 319 # wait Indicates that this keyword should wait 320 # for host running state. 321 322 ${output}= Run External IPMI Standard Command chassis power on 323 Should Not Contain ${output} Error 324 325 Run Keyword If '${wait}' == '${0}' Return From Keyword 326 Wait Until Keyword Succeeds 10 min 10 sec Is Host Running 327 328 329Initiate Host PowerOff Via External IPMI 330 [Documentation] Initiate host power off using external IPMI. 331 [Arguments] ${wait}=${1} 332 333 # Description of argument(s): 334 # wait Indicates that this keyword should wait 335 # for host off state. 336 337 ${output}= Run External IPMI Standard Command chassis power off 338 Should Not Contain ${output} Error 339 340 Run Keyword If '${wait}' == '${0}' Return From Keyword 341 Wait Until Keyword Succeeds 3 min 10 sec Is Host Off 342 343 344Is Host Off Via IPMI 345 [Documentation] Verify if the Host is off using IPMI command. 346 347 ${status}= Run External IPMI Standard Command chassis power status 348 Should Contain ${status} off 349 350 351Get Host State Via External IPMI 352 [Documentation] Returns host state using external IPMI. 353 354 ${output}= Run External IPMI Standard Command chassis power status 355 Should Not Contain ${output} Error 356 ${output}= Fetch From Right ${output} ${SPACE} 357 358 [Return] ${output} 359 360 361Set BMC Network From Host 362 [Documentation] Set BMC network from host. 363 [Arguments] ${nw_info} 364 365 # Description of argument(s): 366 # nw_info A dictionary containing the network 367 # information to apply. 368 369 Run Inband IPMI Standard Command 370 ... lan set 1 ipaddr ${nw_info['IP Address']} 371 372 Run Inband IPMI Standard Command 373 ... lan set 1 netmask ${nw_info['Subnet Mask']} 374 375 Run Inband IPMI Standard Command 376 ... lan set 1 defgw ipaddr ${nw_info['Default Gateway IP']} 377 378 379Verify IPMI Username And Password 380 [Documentation] Verify that user is able to run IPMI command 381 ... with given username and password. 382 [Arguments] ${username} ${password} 383 384 # Description of argument(s): 385 # username The user name (e.g. "root", "robert", etc.). 386 # password The user password (e.g. "0penBmc", "0penBmc1", etc.). 387 388 ${output}= Wait Until Keyword Succeeds 15 sec 5 sec Run External IPMI Standard Command 389 ... sel info U=${username} P=${password} 390 Should Contain ${output} SEL Information msg=SEL information not present 391 392 393IPMI Create User 394 [Documentation] Create IPMI user with given userid and username. 395 [Arguments] ${userid} ${username} 396 397 # Description of argument(s): 398 # userid The user ID (e.g. "1", "2", etc.). 399 # username The user name (e.g. "root", "robert", etc.). 400 401 ${ipmi_cmd}= Catenate user set name ${userid} ${username} 402 ${resp}= Run IPMI Standard Command ${ipmi_cmd} 403 ${user_info}= Get User Info ${userid} 404 Should Be Equal ${user_info['user_name']} ${username} 405 406 407Set Channel Access 408 [Documentation] Verify that user is able to run IPMI command 409 ... with given username and password. 410 [Arguments] ${userid} ${options} ${channel_number}=${CHANNEL_NUMBER} 411 412 # Description of argument(s): 413 # userid The user ID (e.g. "1", "2", etc.). 414 # options Set channel command options (e.g. 415 # "link=on", "ipmi=on", etc.). 416 # channel_number The user's channel number (e.g. "1"). 417 418 ${ipmi_cmd}= Catenate SEPARATOR= 419 ... channel setaccess${SPACE}${channel_number}${SPACE}${userid} 420 ... ${SPACE}${options} 421 Run IPMI Standard Command ${ipmi_cmd} 422 423 424Delete All Non Root IPMI User 425 [Documentation] Delete all non-root IPMI user. 426 427 # Get complete list of user info records. 428 ${user_info}= Get User Info ${EMPTY} 429 # Remove header record. 430 ${user_info}= Filter Struct ${user_info} [('user_name', None)] invert=1 431 ${non_empty_user_info}= Filter Struct ${user_info} [('user_name', '')] invert=1 432 ${non_root_user_info}= Filter Struct ${non_empty_user_info} [('user_name', 'root')] invert=1 433 434 FOR ${user_record} IN @{non_root_user_info} 435 Run IPMI Standard Command user set name ${user_record['user_id']} "" 436 Sleep 5s 437 END 438 439 440Create SEL 441 [Documentation] Create a SEL. 442 [Arguments] ${sensor_type} ${sensor_number} 443 444 # Create a SEL. 445 # Example: 446 # a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 | | Asserted 447 448 # Description of argument(s): 449 # ${sensor_type} Type of the sensor used in hexadecimal (can be fan, temp etc.,), 450 # obtained from Sensor Type field in - ipmitool sdr get "sensor_name". 451 # Example: Sensor Type (Threshold) : Fan (0x04), here 0xHH is sensor type. 452 453 # ${sensor_number} Sensor number of the sensor in hexadecimal. 454 # obtained from Sensor ID field in - ipmitool sdr get "sensor_name". 455 # Example: Sensor ID : SENSOR_1 (0xHH), here 0xHH is sensor number. 456 457 ${resp}= Run IPMI Command 458 ... ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][0]} 0x${sensor_type} 0x${sensor_number} ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][1]} 459 460 Should Not Contain ${resp} 00 00 msg=SEL not created. 461 462 [Return] ${resp} 463 464 465Fetch One Threshold Sensor From Sensor List 466 [Documentation] Fetch one threshold sensor randomly from Sensor list. 467 468 @{sensor_name_list}= Create List 469 470 ${resp}= Run IPMI Standard Command sensor 471 @{sensor_list}= Split To Lines ${resp} 472 473 # Omit the discrete sensor and create an threshold sensor name list 474 FOR ${sensor} IN @{sensor_list} 475 ${discrete_sensor_status}= Run Keyword And Return Status Should Contain ${sensor} discrete 476 Continue For Loop If '${discrete_sensor_status}' == 'True' 477 ${sensor_details}= Split String ${sensor} | 478 ${get_sensor_name}= Get From List ${sensor_details} 0 479 ${sensor_name}= Set Variable ${get_sensor_name.strip()} 480 Append To List ${sensor_name_list} ${sensor_name} 481 END 482 483 ${random_sensor_name}= Evaluate random.choice(${sensor_name_list}) random 484 485 [Return] ${random_sensor_name} 486 487Fetch Sensor Details From SDR 488 [Documentation] Identify the sensors from sdr get and fetch sensor details required. 489 [Arguments] ${sensor_name} ${setting} 490 491 # Description of argument(s): 492 # ${sensor_number} Sensor number of the sensor in hexadecimal. 493 # obtained sensor name from - 'ipmitool sensor' command. 494 # Example: a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 | | Asserted 495 # here, a is the sensor name. 496 497 # ${setting} Field to fetch data. Example : Sensor ID, Sensor Type (Threshold), etc,. 498 499 ${resp}= Run IPMI Standard Command sdr get "${sensor_name}" 500 501 ${setting_line}= Get Lines Containing String ${resp} ${setting} 502 ... case-insensitive 503 ${setting_status}= Fetch From Right ${setting_line} :${SPACE} 504 505 [Return] ${setting_status} 506 507 508Get Data And Byte From SDR Sensor 509 [Documentation] Fetch the Field Data and hexadecimal values from given details. 510 [Arguments] ${sensor_detail} 511 512 # Description of argument(s): 513 # ${sensor_detail} Requested field and the value from the sdr get ipmi command. 514 # Example : if Sensor ID is the requesting setting, then, 515 # ${sensor_detail} will be "Sensor ID : SENSOR_1 (0xHH)" 516 517 ${sensor_detail}= Split String ${sensor_detail} (0x 518 ${field_data}= Set Variable ${sensor_detail[0]} 519 ${field_data}= Remove Whitespace ${field_data} 520 ${sensor_hex}= Replace String ${sensor_detail[1]} ) ${EMPTY} 521 ${sensor_hex}= Zfill Data ${sensor_hex} 2 522 523 [Return] ${field_data} ${sensor_hex} 524 525 526Get Current Date from BMC 527 [Documentation] Runs the date command from BMC and returns current date and time 528 529 # Get Current Date from BMC 530 ${date} ${stderr} ${rc}= BMC Execute Command date 531 532 # Split the string and remove first and 2nd last value from the list and join to form %d %b %H:%M:%S %Y date format 533 ${date}= Split String ${date} 534 Remove From List ${date} 0 535 Remove From List ${date} -2 536 ${date}= Evaluate " ".join(${date}) 537 538 # Convert the date format to %m/%d/%Y %H:%M:%S 539 ${date}= Convert Date ${date} date_format=%b %d %H:%M:%S %Y result_format=%m/%d/%Y %H:%M:%S exclude_millis=True 540 541 [Return] ${date} 542 543 544Get SEL Info Via IPMI 545 [Documentation] Get the SEL Info via IPMI raw command 546 547 # Get SEL Info response consist of 14 bytes of hexadecimal data. 548 549 # Byte 1 - SEL Version, 550 # Byte 2 & 3 - Entry bytes - LSB MSB, 551 # Byte 4 & 5 - Free Space in bytes, LS Byte first. 552 # Byte 6 - 9 - Most recent addition timestamp, 553 # Byte 10-13 - Most recent erase timestamp, 554 # Byte 14 - Operation Support 555 556 # Example: ${resp} will be "51 XX XX XX XX ff ff ff ff ff ff ff ff XX" 557 558 ${resp}= Run IPMI Standard Command 559 ... raw ${IPMI_RAW_CMD['SEL_entry']['SEL_info'][0]} 560 ${resp}= Split String ${resp} 561 562 [Return] ${resp} 563