1*** Settings ***
2Documentation  Open power domain keywords.
3
4Variables      ../data/variables.py
5Resource       ../lib/utils.robot
6Resource       ../lib/connection_client.robot
7
8*** Variables ***
9${functional_cpu_count}       ${0}
10${active_occ_count}           ${0}
11${OCC_WAIT_TIMEOUT}           2 min
12
13*** Keywords ***
14
15Get OCC Objects
16    [Documentation]  Get the OCC objects and return as a list.
17
18    # Example:
19    # {
20    #     "/org/open_power/control/occ0": {
21    #          "OccActive": 0
22    # },
23    #     "/org/open_power/control/occ1": {
24    #          "OccActive": 1
25    # }
26
27    ${occ_list}=  Get Endpoint Paths  ${OPENPOWER_CONTROL}  occ*
28
29    [Return]  ${occ_list}
30
31
32Get OCC Active State
33    [Documentation]  Get the OCC "OccActive" and return the attribute value.
34    [Arguments]  ${value}
35
36    # Description of argument(s):
37    # value       CPU position (e.g. "0, 1, 2").
38
39    ${cmd}=  Catenate  busctl get-property org.open_power.OCC.Control
40    ...   /org/open_power/control/occ${value} org.open_power.OCC.Status OccActive
41
42    ${cmd_output}  ${stderr}  ${rc} =  BMC Execute Command  ${cmd}
43    ...  print_out=1  print_err=1  ignore_err=1
44
45    # The command returns format  'b true'
46    Return From Keyword If  '${cmd_output.split(' ')[-1]}' == 'true'  ${1}
47
48    [Return]  ${0}
49
50
51Count Object Entries
52    [Documentation]  Count the occurrence number of a given object.
53    [Arguments]  ${object_base_uri_path}  ${object_name}
54
55    # Description of argument(s):
56    # object_base_uri_path    Object base path
57    #                         (e.g. "/org/open_power/control/").
58    # object_name             Object name (e.g. "occ", "cpu" etc).
59
60    ${object_list}=  Get Endpoint Paths
61    ...  ${object_base_uri_path}  ${object_name}
62    ${list_count}=  Get Length  ${object_list}
63    [Return]  ${list_count}
64
65
66Read Object Attribute
67    [Documentation]  Return object attribute data.
68    [Arguments]  ${object_base_uri_path}  ${attribute_name}
69
70    # Description of argument(s):
71    # object_base_uri_path       Object path.
72    #                   (e.g. "/org/open_power/control/occ0").
73    # attribute_name    Object attribute name.
74
75    ${resp}=  OpenBMC Get Request
76    ...  ${object_base_uri_path}/attr/${attribute_name}  quiet=${1}
77    Return From Keyword If  ${resp.status_code} != ${HTTP_OK}
78    ${content}=  To JSON  ${resp.content}
79    [Return]  ${content["data"]}
80
81
82Get Functional Processor Count
83    [Documentation]  Get functional processor count.
84
85    ${cpu_list}=  Redfish.Get Members List  /redfish/v1/Systems/system/Processors/  *cpu*
86
87    FOR  ${endpoint_path}  IN  @{cpu_list}
88       # {'Health': 'OK', 'State': 'Enabled'} get only matching status good.
89       ${cpu_status}=  Redfish.Get Attribute  ${endpoint_path}  Status
90       Continue For Loop If  '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled'
91       ${functional_cpu_count} =  Evaluate   ${functional_cpu_count} + 1
92    END
93
94    [Return]  ${functional_cpu_count}
95
96
97Get Active OCC State Count
98    [Documentation]  Get active OCC state count.
99
100    ${cpu_list}=  Redfish.Get Members List  /redfish/v1/Systems/system/Processors/  *cpu*
101
102    FOR  ${endpoint_path}  IN  @{cpu_list}
103       ${num}=  Set Variable  ${endpoint_path[-1]}
104       ${cmd}=  Catenate  busctl get-property org.open_power.OCC.Control
105       ...   /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive
106
107       ${cmd_output}  ${stderr}  ${rc} =  BMC Execute Command  ${cmd}
108       ...  print_out=1  print_err=1  ignore_err=1
109
110       # The command returns format  'b true'
111       Continue For Loop If   '${cmd_output.split(' ')[-1]}' != 'true'
112       ${active_occ_count} =  Evaluate   ${active_occ_count} + 1
113    END
114
115    [Return]  ${active_occ_count}
116
117
118Match OCC And CPU State Count
119    [Documentation]  Get CPU functional count and verify OCC count active matches.
120
121    ${cpu_count}=  Get Functional Processor Count
122    Log To Console  Functional Processor count: ${cpu_count}
123
124    FOR  ${num}  IN RANGE  ${0}  ${cpu_count}
125       ${cmd}=  Catenate  busctl get-property org.open_power.OCC.Control
126       ...   /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive
127
128       ${cmd_output}  ${stderr}  ${rc} =  BMC Execute Command  ${cmd}
129       ...  print_out=1  print_err=1  ignore_err=1
130
131       # The command returns format  'b true'
132       Continue For Loop If   '${cmd_output.split(' ')[-1]}' != 'true'
133       ${active_occ_count} =  Evaluate   ${active_occ_count} + 1
134    END
135
136    Log To Console  OCC Active count: ${active_occ_count}
137
138    Should Be Equal  ${active_occ_count}  ${cpu_count}
139    ...  msg=OCC count ${active_occ_count} and CPU Count ${cpu_count} mismatched.
140
141
142Verify OCC State
143    [Documentation]  Check OCC active state.
144    [Arguments]  ${expected_occ_active}=${1}
145    # Description of Argument(s):
146    # expected_occ_active  The expected occ_active value (i.e. 1/0).
147
148    # Example cpu_list data output:
149    #  /redfish/v1/Systems/system/Processors/cpu0
150    #  /redfish/v1/Systems/system/Processors/cpu1
151
152    ${cpu_list}=  Redfish.Get Members List  /redfish/v1/Systems/system/Processors/  cpu*
153
154    FOR  ${endpoint_path}  IN  @{cpu_list}
155       # {'Health': 'OK', 'State': 'Enabled'} get only matching status good.
156       ${cpu_status}=  Redfish.Get Attribute  ${endpoint_path}  Status
157       Continue For Loop If  '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled'
158       Log To Console  ${cpu_status}
159       ${num}=  Set Variable  ${endpoint_path[-1]}
160       ${occ_active}=  Get OCC Active State  ${num}
161       Should Be Equal  ${occ_active}  ${expected_occ_active}
162       ...  msg=OCC not in right state
163    END
164
165
166Get Sensors Aggregation Data
167    [Documentation]  Return open power sensors aggregation value list.
168    [Arguments]  ${object_base_uri_path}
169
170    # Description of argument(s):
171    # object_base_uri_path  An object path such as one of the elements
172    #                       returned by 'Get Sensors Aggregation URL List'
173    #                       (e.g. "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average").
174
175    # Example of aggregation [epoch,time] data:
176    # "Values": [
177    #    [
178    #        1517815708479,  <-- EPOCH
179    #        282             <-- Power value in watts
180    #    ],
181    #    [
182    #        1517815678238,
183    #        282
184    #    ],
185    #    [
186    #        1517815648102,
187    #        282
188    #    ],
189    # ],
190
191    ${resp}=  Read Attribute  ${object_base_uri_path}  Values  quiet=${1}
192    ${power_sensors_value_list}=  Create List
193    FOR  ${entry}  IN  @{resp}
194       Append To List  ${power_sensors_value_list}  ${entry[1]}
195    END
196    [Return]  ${power_sensors_value_list}
197
198
199Get Sensors Aggregation URL List
200    [Documentation]  Return the open power aggregation maximum list and the
201    ...  average list URIs.
202    [Arguments]  ${object_base_uri_path}
203
204    # Example of the 2 lists returned by this keyword:
205    # avgs:
206    #   avgs[0]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/average
207    #   avgs[1]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/average
208    # maxs:
209    #   maxs[0]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum
210    #   maxs[1]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum
211
212    # Description of argument(s):
213    # object_base_uri_path  Object path.
214    #                       base path "/org/open_power/sensors/"
215    #        (e.g. "base path + aggregation/per_30s/ps0_input_power/average")
216
217    # Example of open power sensor aggregation data as returned by the get
218    # request:
219    # /org/open_power/sensors/list
220    # [
221    #    "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average",
222    #    "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum",
223    #    "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum",
224    #    "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/average"
225    # ]
226
227    ${resp}=  OpenBMC Get Request  ${object_base_uri_path}list  quiet=${1}
228    ${content}=  To JSON  ${resp.content}
229
230    ${power_supply_avg_list}=  Create List
231    ${power_supply_max_list}=  Create List
232
233    FOR  ${entry}  IN  @{content["data"]}
234        Run Keyword If  'average' in '${entry}'  Append To List  ${power_supply_avg_list}  ${entry}
235        Run Keyword If  'maximum' in '${entry}'  Append To List  ${power_supply_max_list}  ${entry}
236    END
237
238    [Return]  ${power_supply_avg_list}  ${power_supply_max_list}
239
240
241REST Verify No Gard Records
242    [Documentation]  Verify no gard records are present.
243
244    ${resp}=  Read Properties  ${OPENPOWER_CONTROL}gard/enumerate
245    Log Dictionary  ${resp}
246    Should Be Empty  ${resp}  msg=Found gard records.
247
248
249Inject OPAL TI
250    [Documentation]  OPAL terminate immediate procedure.
251    [Arguments]      ${stable_branch}=master
252    ...              ${repo_dir_path}=/tmp/repository
253    ...              ${repo_github_url}=https://github.com/open-power/op-test
254
255    # Description of arguments:
256    # stable_branch    Git branch to clone. (default: master)
257    # repo_dir_path    Directory path for repo tool (e.g. "op-test").
258    # repo_github_url  Github URL link (e.g. "https://github.com/open-power/op-test").
259
260    ${value}=  Generate Random String  4  [NUMBERS]
261
262    ${cmd_buf}=  Catenate  git clone --branch ${stable_branch} ${repo_github_url} ${repo_dir_path}/${value}
263    Shell Cmd  ${cmd_buf}
264
265    Open Connection for SCP
266    scp.Put File  ${repo_dir_path}/${value}/test_binaries/deadbeef  /tmp
267    Pdbg  -a putmem 0x300000f8 < /tmp/deadbeef
268
269    # Clean up the repo once done.
270    ${cmd_buf}=  Catenate  rm -rf ${repo_dir_path}${/}${value}
271    Shell Cmd  ${cmd_buf}
272
273
274Trigger OCC Reset
275    [Documentation]  Trigger OCC reset request on an active OCC.
276    [Arguments]  ${occ_target}=${0}
277
278    # Description of Argument(s):
279    # occ_target   Target a valid given OCC number 0,1, etc.
280
281    Log To Console   OCC Reset Triggered on OCC ${occ_target}
282
283    ${cmd}=  Catenate  busctl call org.open_power.OCC.Control
284    ...  /org/open_power/control/occ${occ_target} org.open_power.OCC.PassThrough
285    ...  Send ai 8 64 0 5 20 82 83 84 0
286
287    ${cmd_output}  ${stderr}  ${rc} =  BMC Execute Command  ${cmd}  print_out=1  print_err=1
288
289    Log To Console  OCC wait check for disabled state.
290    Wait Until Keyword Succeeds  30 sec  5 sec  Verify OCC Target State  ${occ_target}
291
292
293Verify OCC Target State
294    [Documentation]  Verify that the user given state matches th current OCC state.
295    [Arguments]  ${occ_target}=${0}  ${expected_state}=${0}
296
297    # Description of Argument(s):
298    # occ_target       Target a valid given OCC number 0,1, etc.
299    # expected_state   For OCC either 0 or 1. Default is 0.
300
301    ${occ_active}=  Get OCC Active State  ${occ_target}
302    Should Be Equal  ${occ_active}  ${expected_state}
303    Log To Console  Target OCC ${occ_target} state is ${occ_active}.
304
305
306Trigger OCC Reset And Wait For OCC Active State
307    [Documentation]  Trigger OCC reset request and wait for OCC to reset back to active state.
308
309    Trigger OCC Reset
310
311    Log To Console  OCC wait check for active state.
312    Wait Until Keyword Succeeds  ${OCC_WAIT_TIMEOUT}  20 sec   Match OCC And CPU State Count
313