1*** Settings *** 2Documentation Open power domain keywords. 3 4Variables ../data/variables.py 5Resource ../lib/utils.robot 6Resource ../lib/connection_client.robot 7Library utilities.py 8 9*** Variables *** 10${functional_cpu_count} ${0} 11${active_occ_count} ${0} 12${OCC_WAIT_TIMEOUT} 8 min 13${fan_json_msg} Unable to create dump on non-JSON config based system 14 15*** Keywords *** 16 17Get OCC Objects 18 [Documentation] Get the OCC objects and return as a list. 19 20 # Example: 21 # { 22 # "/org/open_power/control/occ0": { 23 # "OccActive": 0 24 # }, 25 # "/org/open_power/control/occ1": { 26 # "OccActive": 1 27 # } 28 29 ${occ_list}= Get Endpoint Paths ${OPENPOWER_CONTROL} occ* 30 31 RETURN ${occ_list} 32 33 34Get OCC Active State 35 [Documentation] Get the OCC "OccActive" and return the attribute value. 36 [Arguments] ${value} 37 38 # Description of argument(s): 39 # value CPU position (e.g. "0, 1, 2"). 40 41 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control 42 ... /org/open_power/control/occ${value} org.open_power.OCC.Status OccActive 43 44 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} 45 ... print_out=1 print_err=1 ignore_err=1 46 47 # The command returns format 'b true' 48 IF '${cmd_output.split(' ')[-1]}' == 'true' 49 RETURN ${1} 50 END 51 52 RETURN ${0} 53 54 55Count Object Entries 56 [Documentation] Count the occurrence number of a given object. 57 [Arguments] ${object_base_uri_path} ${object_name} 58 59 # Description of argument(s): 60 # object_base_uri_path Object base path 61 # (e.g. "/org/open_power/control/"). 62 # object_name Object name (e.g. "occ", "cpu" etc). 63 64 ${object_list}= Get Endpoint Paths 65 ... ${object_base_uri_path} ${object_name} 66 ${list_count}= Get Length ${object_list} 67 RETURN ${list_count} 68 69 70Read Object Attribute 71 [Documentation] Return object attribute data. 72 [Arguments] ${object_base_uri_path} ${attribute_name} 73 74 # Description of argument(s): 75 # object_base_uri_path Object path. 76 # (e.g. "/org/open_power/control/occ0"). 77 # attribute_name Object attribute name. 78 79 ${resp}= OpenBMC Get Request 80 ... ${object_base_uri_path}/attr/${attribute_name} quiet=${1} 81 82 IF ${resp.status_code} != ${HTTP_OK} 83 RETURN 84 END 85 86 RETURN ${resp.json()["data"]} 87 88 89Get Functional Processor Count 90 [Documentation] Get functional processor count. 91 92 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ *cpu* 93 94 FOR ${endpoint_path} IN @{cpu_list} 95 # {'Health': 'OK', 'State': 'Enabled'} get only matching status good. 96 ${cpu_status}= Redfish.Get Attribute ${endpoint_path} Status 97 98 IF '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled' 99 CONTINUE 100 END 101 ${functional_cpu_count} = Evaluate ${functional_cpu_count} + 1 102 END 103 104 RETURN ${functional_cpu_count} 105 106 107Get Active OCC State Count 108 [Documentation] Get active OCC state count. 109 110 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ *cpu* 111 112 FOR ${endpoint_path} IN @{cpu_list} 113 ${num}= Set Variable ${endpoint_path[-1]} 114 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control 115 ... /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive 116 117 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} 118 ... print_out=1 print_err=1 ignore_err=1 119 120 # The command returns format 'b true' 121 IF '${cmd_output.split(' ')[-1]}' != 'true' CONTINUE 122 ${active_occ_count} = Evaluate ${active_occ_count} + 1 123 END 124 125 RETURN ${active_occ_count} 126 127 128Match OCC And CPU State Count 129 [Documentation] Get CPU functional count and verify OCC count active matches. 130 131 ${cpu_count}= Get Functional Processor Count 132 Log To Console Functional Processor count: ${cpu_count} 133 134 FOR ${num} IN RANGE ${0} ${cpu_count} 135 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control 136 ... /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive 137 138 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} 139 ... print_out=1 print_err=1 ignore_err=1 140 141 # The command returns format 'b true' 142 IF '${cmd_output.split(' ')[-1]}' != 'true' CONTINUE 143 ${active_occ_count} = Evaluate ${active_occ_count} + 1 144 END 145 146 Log To Console OCC Active count: ${active_occ_count} 147 148 Should Be Equal ${active_occ_count} ${cpu_count} 149 ... msg=OCC count ${active_occ_count} and CPU Count ${cpu_count} mismatched. 150 151 152Verify OCC State 153 [Documentation] Check OCC active state. 154 [Arguments] ${expected_occ_active}=${1} 155 # Description of Argument(s): 156 # expected_occ_active The expected occ_active value (i.e. 1/0). 157 158 # Example cpu_list data output: 159 # /redfish/v1/Systems/system/Processors/cpu0 160 # /redfish/v1/Systems/system/Processors/cpu1 161 162 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ cpu* 163 164 FOR ${endpoint_path} IN @{cpu_list} 165 # {'Health': 'OK', 'State': 'Enabled'} get only matching status good. 166 ${cpu_status}= Redfish.Get Attribute ${endpoint_path} Status 167 IF '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled' CONTINUE 168 Log To Console ${cpu_status} 169 ${num}= Set Variable ${endpoint_path[-1]} 170 ${occ_active}= Get OCC Active State ${num} 171 Should Be Equal ${occ_active} ${expected_occ_active} 172 ... msg=OCC not in right state 173 END 174 175 176Get Sensors Aggregation Data 177 [Documentation] Return open power sensors aggregation value list. 178 [Arguments] ${object_base_uri_path} 179 180 # Description of argument(s): 181 # object_base_uri_path An object path such as one of the elements 182 # returned by 'Get Sensors Aggregation URL List' 183 # (e.g. "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average"). 184 185 # Example of aggregation [epoch,time] data: 186 # "Values": [ 187 # [ 188 # 1517815708479, <-- EPOCH 189 # 282 <-- Power value in watts 190 # ], 191 # [ 192 # 1517815678238, 193 # 282 194 # ], 195 # [ 196 # 1517815648102, 197 # 282 198 # ], 199 # ], 200 201 ${resp}= Read Attribute ${object_base_uri_path} Values quiet=${1} 202 ${power_sensors_value_list}= Create List 203 FOR ${entry} IN @{resp} 204 Append To List ${power_sensors_value_list} ${entry[1]} 205 END 206 RETURN ${power_sensors_value_list} 207 208 209Get Sensors Aggregation URL List 210 [Documentation] Return the open power aggregation maximum list and the 211 ... average list URIs. 212 [Arguments] ${object_base_uri_path} 213 214 # Example of the 2 lists returned by this keyword: 215 # avgs: 216 # avgs[0]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/average 217 # avgs[1]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/average 218 # maxs: 219 # maxs[0]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum 220 # maxs[1]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum 221 222 # Description of argument(s): 223 # object_base_uri_path Object path. 224 # base path "/org/open_power/sensors/" 225 # (e.g. "base path + aggregation/per_30s/ps0_input_power/average") 226 227 # Example of open power sensor aggregation data as returned by the get 228 # request: 229 # /org/open_power/sensors/list 230 # [ 231 # "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average", 232 # "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum", 233 # "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum", 234 # "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/average" 235 # ] 236 237 ${resp}= OpenBMC Get Request ${object_base_uri_path}list quiet=${1} 238 239 ${power_supply_avg_list}= Create List 240 ${power_supply_max_list}= Create List 241 242 FOR ${entry} IN @{resp.json()["data"]} 243 IF 'average' in '${entry}' Append To List ${power_supply_avg_list} ${entry} 244 IF 'maximum' in '${entry}' Append To List ${power_supply_max_list} ${entry} 245 END 246 247 RETURN ${power_supply_avg_list} ${power_supply_max_list} 248 249 250REST Verify No Gard Records 251 [Documentation] Verify no gard records are present. 252 253 ${resp}= Read Properties ${OPENPOWER_CONTROL}gard/enumerate 254 Log Dictionary ${resp} 255 Should Be Empty ${resp} msg=Found gard records. 256 257 258Inject OPAL TI 259 [Documentation] OPAL terminate immediate procedure. 260 [Arguments] ${stable_branch}=master 261 ... ${repo_dir_path}=/tmp/repository 262 ... ${repo_github_url}=https://github.com/open-power/op-test 263 264 # Description of arguments: 265 # stable_branch Git branch to clone. (default: master) 266 # repo_dir_path Directory path for repo tool (e.g. "op-test"). 267 # repo_github_url Github URL link (e.g. "https://github.com/open-power/op-test"). 268 269 ${value}= Generate Random String 4 [NUMBERS] 270 271 ${cmd_buf}= Catenate git clone --branch ${stable_branch} ${repo_github_url} ${repo_dir_path}/${value} 272 Shell Cmd ${cmd_buf} 273 274 Open Connection for SCP 275 scp.Put File ${repo_dir_path}/${value}/test_binaries/deadbeef /tmp 276 Pdbg -a putmem 0x300000f8 < /tmp/deadbeef 277 278 # Clean up the repo once done. 279 ${cmd_buf}= Catenate rm -rf ${repo_dir_path}${/}${value} 280 Shell Cmd ${cmd_buf} 281 282 283Trigger OCC Reset 284 [Documentation] Trigger OCC reset request on an active OCC. 285 [Arguments] ${occ_target}=${0} 286 287 # Description of Argument(s): 288 # occ_target Target a valid given OCC number 0,1, etc. 289 290 Log To Console OCC Reset Triggered on OCC ${occ_target} 291 292 ${cmd}= Catenate busctl call org.open_power.OCC.Control 293 ... /org/open_power/control/occ${occ_target} org.open_power.OCC.PassThrough 294 ... Send ai 8 64 0 5 20 82 83 84 0 295 296 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} print_out=1 print_err=1 297 298 Log To Console OCC wait check for disabled state. 299 Wait Until Keyword Succeeds 30 sec 5 sec Verify OCC Target State ${occ_target} 300 301 302Verify OCC Target State 303 [Documentation] Verify that the user given state matches th current OCC state. 304 [Arguments] ${occ_target}=${0} ${expected_state}=${0} 305 306 # Description of Argument(s): 307 # occ_target Target a valid given OCC number 0,1, etc. 308 # expected_state For OCC either 0 or 1. Default is 0. 309 310 ${occ_active}= Get OCC Active State ${occ_target} 311 Should Be Equal ${occ_active} ${expected_state} 312 Log To Console Target OCC ${occ_target} state is ${occ_active}. 313 314 315Trigger OCC Reset And Wait For OCC Active State 316 [Documentation] Trigger OCC reset request and wait for OCC to reset back to active state. 317 318 Trigger OCC Reset 319 320 Log To Console OCC wait check for active state. 321 Wait Until Keyword Succeeds ${OCC_WAIT_TIMEOUT} 20 sec Match OCC And CPU State Count 322 323 324Get Sensors Dbus Tree List 325 [Documentation] Get the list dbus path of the given sensor object and 326 ... return the populatedlist. 327 328 ${dbus_obj_var}= Set Variable 329 ... xyz.openbmc_project.HwmonTempSensor 330 ... xyz.openbmc_project.ADCSensor 331 ... xyz.openbmc_project.VirtualSensor 332 333 # Filter only the dbus paths service by the sensor obj. 334 ${sensors_dbus_tree_dict}= Create Dictionary 335 FOR ${dbus_obj} IN @{dbus_obj_var} 336 ${cmd}= Catenate busctl tree ${dbus_obj} --list | grep /sensors/ 337 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} 338 ... print_out=0 print_err=0 ignore_err=1 339 Set To Dictionary ${sensors_dbus_tree_dict} ${dbus_obj} ${cmd_output.splitlines()} 340 END 341 342 Rprint Vars sensors_dbus_tree_dict 343 # Key Pair: 'sensor obj":[list of obj URI] 344 # Example: 345 # sensors_dbus_tree_dict: 346 # [xyz.openbmc_project.HwmonTempSensor]: 347 # [0]: /xyz/openbmc_project/sensors/temperature/Ambient_0_Temp 348 # [1]: /xyz/openbmc_project/sensors/temperature/PCIE_0_Temp 349 # [xyz.openbmc_project.ADCSensor]: 350 # [0]: /xyz/openbmc_project/sensors/voltage/Battery_Voltage 351 # [xyz.openbmc_project.VirtualSensor]: 352 # [0]: /xyz/openbmc_project/sensors/temperature/Ambient_Virtual_Temp 353 354 RETURN ${sensors_dbus_tree_dict} 355 356 357Get Populated Sensors Dbus List 358 [Documentation] Perform GET operation on the attribute list and confirm it is 359 ... populated and does not error out during GET request.. 360 361 ${sensor_dict}= Get Sensors Dbus Tree List 362 363 # Loop through the dictionary and iterate item entries. 364 ${valid_dbus_list}= Create List 365 FOR ${key} IN @{sensor_dict.keys()} 366 FOR ${val} IN @{sensor_dict["${key}"]} 367 ${cmd}= Catenate 368 ... busctl get-property ${key} ${val} xyz.openbmc_project.Sensor.Value Value 369 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} 370 ... print_out=0 print_err=0 ignore_err=1 371 # Skip failed to get property command on Dbus object. 372 IF ${rc} == 0 Append To List ${valid_dbus_list} ${val} 373 END 374 END 375 376 RETURN ${valid_dbus_list} 377 378 379Verify Runtime Sensors Dbus List 380 [Documentation] Load pre-defined sensor JSON Dbus data and validate against 381 ... runtime sensor list generated. 382 383 # Default path data/sensor_dbus.json else takes 384 # user CLI input -v SENSOR_DBUS_JSON_FILE_PATH:<path> 385 ${SENSOR_DBUS_JSON_FILE_PATH}= 386 ... Get Variable Value ${SENSOR_DBUS_JSON_FILE_PATH} data/sensor_dbus.json 387 388 ${json_data}= OperatingSystem.Get File ${SENSOR_DBUS_JSON_FILE_PATH} 389 ${json_sensor_data}= Evaluate json.loads('''${json_data}''') json 390 391 ${runtime_sensor_list}= Get Populated Sensors Dbus List 392 393 ${system_model}= Get BMC System Model 394 Rprint Vars system_model 395 Rprint Vars runtime_sensor_list 396 397 ${status}= Run Keyword And Return Status 398 ... Dictionary Should Contain Value ${json_sensor_data} ${runtime_sensor_list} 399 400 IF ${status} == ${False} Log And Fail ${json_sensor_data} 401 402 Log To Console Runtime Dbus sensor list matches. 403 404 405Log And Fail 406 [Documentation] Log detailed failure log on the console. 407 [Arguments] ${json_sensor_data} 408 409 # Description of Argument(s): 410 # json_sensor_data Sensor JSON data from data/sensor_dbus.json. 411 412 Rprint Vars json_sensor_data 413 Fail Runtime generated Dbus sensors does not match 414 415 416Dump Fan Control JSON 417 [Documentation] Execute fan control on BMC to dump config with 'fanctl dump', 418 ... which makes it write a /tmp/fan_control_dump.json file. 419 420 ${output} ${stderr} ${rc} = BMC Execute Command test -f /usr/bin/fanctl 421 ... print_err=1 ignore_err=1 422 423 IF ${rc} == 1 RETURN fanctl application doesn't exist. 424 425 # This command will force a fan_control_dump.json file in temp path and 426 # takes few seconds to complete.. 427 BMC Execute Command fanctl dump 428 Sleep 10s 429 430 431Get Fan JSON Data 432 [Documentation] Read the JSON string file from BMC and return. 433 434 # Check for the generated file and return the file data as JSON and fails if 435 # it doesn't find file generated. 436 ${cmd}= Catenate test -f /tmp/fan_control_dump.json; cat /tmp/fan_control_dump.json 437 ${json_string} ${stderr} ${rc} = BMC Execute Command ${cmd} 438 ... print_out=1 print_err=1 ignore_err=1 439 440 Should Be True ${rc} == 0 msg=No Fan control config JSON file is generated. 441 ${fan_json}= Evaluate json.loads('''${json_string}''') json 442 443 RETURN ${fan_json} 444 445 446Get Fan Attribute Value 447 [Documentation] Return the specified value of the matched search key in 448 ... nested dictionary data. 449 [Arguments] ${fan_dict} ${key_value} 450 451 # Description of Argument(s): 452 # key_value User input attribute value in the dictionary. 453 454 ${empty_dicts}= Create Dictionary 455 456 # Check for JSON response data. 457 # { 458 # "msg": "Unable to create dump on non-JSON config based system" 459 # } 460 461 ${status}= Run Keyword And Return Status 462 ... Should Be Equal ${fan_dict["msg"]} ${fan_json_msg} 463 IF ${status} 464 Log To Console Skipping attribute ${key_value} check. 465 Return From Keyword ${empty_dicts} 466 END 467 468 # Python module: get_value_from_nested_dict(key,dict) 469 ${value_list}= utilities.Get Value From Nested Dict ${key_value} ${fan_dict} 470 471 Should Not Be Empty ${value_list} msg=${key_value} key attribute not found. 472 473 RETURN ${value_list[0]} 474