1*** Settings ***
2Documentation   BMC and host redfish utility keywords.
3
4Resource        resource.robot
5Resource        bmc_redfish_resource.robot
6
7
8*** Keywords ***
9
10Redfish Power Operation
11    [Documentation]  Do Redfish host power operation.
12    [Arguments]      ${reset_type}
13
14    # Description of arguments:
15    # reset_type     Type of power operation.
16    #                (e.g. On/ForceOff/GracefulRestart/GracefulShutdown)
17
18    # Example:
19    # "Actions": {
20    # "#ComputerSystem.Reset": {
21    #  "ResetType@Redfish.AllowableValues": [
22    #    "On",
23    #    "ForceOff",
24    #    "ForceOn",
25    #    "ForceRestart",
26    #    "GracefulRestart",
27    #    "GracefulShutdown"
28    #    "PowerCycle",
29    #    "Nmi"
30    #  ],
31    #  "target": "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"
32    #  }
33    # }
34
35    ${target}=  Wait Until Keyword Succeeds  1 min  20 sec
36    ...  redfish_utils.Get Target Actions  /redfish/v1/Systems/${SYSTEM_ID}/  ComputerSystem.Reset
37    ${payload}=  Create Dictionary  ResetType=${reset_type}
38    ${resp}=  Redfish.Post  ${target}  body=&{payload}
39    ...  valid_status_codes=[${HTTP_OK}, ${HTTP_NO_CONTENT}]
40
41
42Redfish BMC Reset Operation
43    [Documentation]  Do Redfish BMC reset operation.
44    [Arguments]  ${reset_type}=GracefulRestart
45
46    # Example:
47    # "Actions": {
48    # "#Manager.Reset": {
49    #  "ResetType@Redfish.AllowableValues": [
50    #    "GracefulRestart",
51    #    "ForceRestart"
52    #  ],
53    #  "target": "/redfish/v1/Managers/${MANAGER_ID}/Actions/Manager.Reset"
54    # }
55
56    ${target}=  Wait Until Keyword Succeeds  1 min  20 sec
57    ...  redfish_utils.Get Target Actions  /redfish/v1/Managers/${MANAGER_ID}/  Manager.Reset
58    ${payload}=  Create Dictionary  ResetType=${reset_type}
59    Redfish.Post  ${target}  body=&{payload}
60
61
62Reset BIOS Via Redfish
63    [Documentation]  Do BIOS reset through Redfish.
64
65    ${target}=  redfish_utils.Get Target Actions  /redfish/v1/Systems/${SYSTEM_ID}/Bios/  Bios.ResetBios
66    Redfish.Post  ${target}  valid_status_codes=[${HTTP_OK}]
67
68
69Set Redfish Delete Session Flag
70    [Documentation]  Disable or enable delete redfish while performing the power operation keyword.
71    [Arguments]  ${set_flag}
72
73    # Description of argument(s):
74    # set_flag    Set user specified enable(1) or disable(0).
75
76    Set Suite Variable  ${REDFISH_DELETE_SESSIONS}  ${set_flag}
77
78
79Redfish Delete Session
80    [Documentation]  Redfish delete session.
81    [Arguments]  ${session_info}
82
83    # Description of argument(s):
84    # session_info      Session information are stored in dictionary.
85
86    # ${session_info} = {
87    #     'SessionIDs': 'XXXXXXXXX',
88    #     'ClientID': 'XXXXXX',
89    #     'SessionToken': 'XXXXXXXXX',
90    #     'SessionResp': session response from redfish login
91    # }
92
93    # SessionIDs   : Session IDs
94    # ClientID     : Client ID
95    # SessionToken : Session token
96    # SessionResp  : Response of creating an redfish login session
97
98    Redfish.Delete  /redfish/v1/SessionService/Sessions/${session_info["SessionIDs"]}
99
100
101Redfish Delete List Of Session
102    [Documentation]  Redfish delete session from list of session records, individual session information
103    ...              are stored in dictionary.
104    [Arguments]  ${session_info_list}
105
106    # Description of argument(s):
107    # session_info_list    List contains individual session record are stored in dictionary.
108
109    # ${session_info_list} = [{
110    #     'SessionIDs': 'XXXXXXXXX',
111    #     'ClientID': 'XXXXXX',
112    #     'SessionToken': 'XXXXXXXXX',
113    #     'SessionResp': session response from redfish login
114    # }]
115
116    # SessionIDs   : Session IDs
117    # ClientID     : Client ID
118    # SessionToken : Session token
119    # SessionResp  : Response of creating an redfish login session
120
121    FOR  ${session_record}  IN  @{session_info_list}
122      Redfish.Delete  /redfish/v1/SessionService/Sessions/${session_record["SessionIDs"]}
123    END
124
125
126Delete All Redfish Sessions
127    [Documentation]  Delete all active redfish sessions.
128
129    ${saved_session_info}=  Redfish_Utils.Get Redfish Session Info
130
131    ${resp_list}=  Redfish_Utils.Get Member List
132    ...  /redfish/v1/SessionService/Sessions
133
134    # Remove the current login session from the list.
135    Remove Values From List  ${resp_list}  ${saved_session_info["location"]}
136
137    # Remove session with client_id populated from the list.
138    ${client_id_list}=  Get Session With Client Id  ${resp_list}
139    Log To Console  Client sessions skip list: ${client_id_list}
140    FOR  ${client_session}  IN  @{client_id_list}
141        Remove Values From List  ${resp_list}  ${client_session}
142    END
143
144    FOR  ${session}  IN  @{resp_list}
145        Run Keyword And Ignore Error  Redfish.Delete  ${session}
146    END
147
148
149Get Session With Client Id
150    [Documentation]  Iterate through the active sessions and return sessions
151    ...              populated with Context.
152    [Arguments]  ${session_list}
153
154    # Description of argument(s):
155    # session_list   Active session list from SessionService.
156
157    # "@odata.type": "#Session.v1_5_0.Session",
158    # "ClientOriginIPAddress": "xx.xx.xx.xx",
159    # "Context": "MYID-01"
160
161    ${client_id_sessions}=  Create List
162    FOR  ${session}  IN  @{session_list}
163        ${resp}=  Redfish.Get  ${session}   valid_status_codes=[200,404]
164        # This prevents dictionary KeyError exception when the Context
165        # attribute is not populated in generic session response.
166        ${context_var}=  Get Variable Value  ${resp.dict["Context"]}  ${EMPTY}
167        # Handle backward compatibility for OEM.
168        ${oem_var}=  Get Variable Value  ${resp.dict["Oem"]["OpenBMC"]["ClientID"]}  ${EMPTY}
169        Run Keyword If  '${context_var}' != '${EMPTY}'
170        ...    Append To List  ${client_id_sessions}  ${session}
171        Run Keyword If  '${oem_var}' != '${EMPTY}'
172        ...    Append To List  ${client_id_sessions}  ${session}
173    END
174
175    RETURN  ${client_id_sessions}
176
177
178Get Valid FRUs
179    [Documentation]  Return a dictionary containing all of the valid FRU records for the given fru_type.
180    [Arguments]  ${fru_type}
181
182    # NOTE: A valid FRU record will have a "State" key of "Enabled" and a "Health" key of "OK".
183
184    # Description of argument(s):
185    # fru_type  The type of fru (e.g. "Processors", "Memory", etc.).
186
187    ${fru_records}=  Redfish_Utils.Enumerate Request
188    ...  /redfish/v1/Systems/${SYSTEM_ID}/${fru_type}  return_json=0
189    ${fru_records}=  Filter Struct  ${fru_records}  [('State', 'Enabled'), ('Health', 'OK')]
190
191    RETURN  ${fru_records}
192
193
194Get Num Valid FRUs
195    [Documentation]  Return the number of valid FRU records for the given fru_type.
196    [Arguments]  ${fru_type}
197
198    # Description of argument(s):
199    # fru_type  The type of fru (e.g. "Processors", "Memory", etc.).
200
201    ${fru_records}=  Get Valid FRUs  ${fru_type}
202    ${num_valid_frus}=  Get length  ${fru_records}
203
204    RETURN  ${num_valid_frus}
205
206
207Verify Valid Records
208    [Documentation]  Verify all records retrieved with the given arguments are valid.
209    [Arguments]  ${record_type}  ${redfish_uri}  ${reading_type}
210
211    # Description of Argument(s):
212    # record_type    The sensor record type (e.g. "PowerSupplies")
213    # redfish_uri    The power supply URI (e.g. /redfish/v1/Chassis/chassis/Power)
214    # reading_type   The power watt readings (e.g. "PowerInputWatts")
215
216    # A valid record will have "State" key "Enabled" and "Health" key "OK".
217    ${records}=  Redfish.Get Attribute  ${redfish_uri}  ${record_type}
218
219    Rprint Vars  records
220
221    # Example output:
222    # records:
223    #   [0]:
224    #     [@odata.id]:                 /redfish/v1/Chassis/chassis/Power#/PowerControl/0
225    #     [@odata.type]:               #Power.v1_0_0.PowerControl
226    #     [MemberId]:                  0
227    #     [Name]:                      Chassis Power Control
228    #     [PowerConsumedWatts]:        264.0
229    #     [PowerLimit]:
230    #       [LimitInWatts]:            None
231    #     [PowerMetrics]:
232    #       [AverageConsumedWatts]:    325
233    #       [IntervalInMin]:           3
234    #       [MaxConsumedWatts]:        538
235    #     [Status]:
236    #       [Health]:                  OK
237    #       [State]:                   Enabled
238
239    ${invalid_records}=  Filter Struct  ${records}
240    ...  [('Health', '^OK$'), ('State', '^Enabled$'), ('${reading_type}', '')]  regex=1  invert=1
241    Valid Length  invalid_records  max_length=0
242
243    RETURN  ${records}
244
245
246Redfish Create User
247    [Documentation]  Redfish create user.
248    [Arguments]   ${user_name}  ${password}  ${role_id}  ${enabled}  ${force}=${False}
249
250    # Description of argument(s):
251    # user_name           The user name to be created.
252    # password            The password to be assigned.
253    # role_id             The role ID of the user to be created.
254    #                     (e.g. "Administrator", "Operator", etc.).
255    # enabled             Indicates whether the username being created.
256    #                     should be enabled (${True}, ${False}).
257    # force               Delete user account and re-create if force is True.
258
259    ${curr_role}=  Run Keyword And Ignore Error  Get User Role  ${user_name}
260    # Ex: ${curr_role} = ('PASS', 'Administrator')
261
262    ${user_exists}=  Run Keyword And Return Status  Should Be Equal As Strings  ${curr_role}[0]  PASS
263
264    # Delete user account when force is True.
265    Run Keyword If  ${force} == ${True}  Redfish.Delete  ${REDFISH_ACCOUNTS_URI}${user_name}
266    ...  valid_status_codes=[${HTTP_OK}, ${HTTP_NOT_FOUND}]
267
268    # Create specified user when force is True or User does not exist.
269    ${payload}=  Create Dictionary
270    ...  UserName=${user_name}  Password=${password}  RoleId=${role_id}  Enabled=${enabled}
271
272    Run Keyword If  ${force} == ${True} or ${user_exists} == ${False}
273    ...  Redfish.Post  ${REDFISH_ACCOUNTS_URI}  body=&{payload}
274    ...  valid_status_codes=[${HTTP_CREATED}]
275
276
277Get User Role
278    [Documentation]  Get User Role.
279    [Arguments]  ${user_name}
280
281    # Description of argument(s):
282    # user_name    User name to get it's role.
283
284    ${role_config}=  Redfish_Utils.Get Attribute
285    ...  ${REDFISH_ACCOUNTS_URI}${user_name}  RoleId
286
287    RETURN  ${role_config}
288
289
290Create Users With Different Roles
291    [Documentation]  Create users with different roles.
292    [Arguments]  ${users}  ${force}=${False}
293
294    # Description of argument(s):
295    # users    Dictionary of roles and user credentials to be created.
296    #          Ex:  {'Administrator': '[admin_user, TestPwd123]', 'Operator': '[operator_user, TestPwd123]'}
297    # force    Delete given user account if already exists when force is True.
298
299    FOR  ${role}  IN  @{users}
300      Redfish Create User  ${users['${role}'][0]}  ${users['${role}']}[1]  ${role}  ${True}  ${force}
301    END
302
303
304Delete BMC Users Via Redfish
305    [Documentation]  Delete BMC users via redfish.
306    [Arguments]  ${users}
307
308    # Description of argument(s):
309    # users    Dictionary of roles and user credentials to be deleted.
310
311    FOR  ${role}  IN  @{users}
312        Redfish.Delete  /redfish/v1/AccountService/Accounts/${users['${role}'][0]}
313        ...  valid_status_codes=[${HTTP_OK}, ${HTTP_NOT_FOUND}]
314    END
315
316
317Expire And Update New Password Via Redfish
318    [Documentation]  Expire and change password and verify using password.
319    [Arguments]  ${username}  ${password}  ${new_password}
320
321    # Description of argument(s):
322    # username        The username to be used to login to the BMC.
323    # password        The password to be used to login to the BMC.
324    # new_password    The new password to be used to update password.
325
326    # Expire admin password using ssh.
327    Open Connection And Log In  ${OPENBMC_USERNAME}  ${OPENBMC_PASSWORD}
328    ${output}  ${stderr}  ${rc}=  BMC Execute Command  passwd --expire ${username}
329    Should Contain Any  ${output}  password expiry information changed
330    ...  password changed
331
332    # Verify user password expired using Redfish
333    Verify User Password Expired Using Redfish  ${username}  ${password}
334
335    # Change user password.
336    Redfish.Patch  /redfish/v1/AccountService/Accounts/${username}
337    ...  body={'Password': '${new_password}'}
338    Redfish.Logout
339
340
341Verify User Password Expired Using Redfish
342    [Documentation]  Checking whether user password expired or not using redfish.
343    [Arguments]  ${username}  ${password}  ${expected_result}=${True}
344
345    # Description of argument(s):
346    # username        The username to be used to login to the BMC.
347    # password        The password to be used to login to the BMC.
348
349    Redfish.Login  ${username}  ${password}
350    ${resp}=  Redfish.Get  /redfish/v1/AccountService/Accounts/${username}
351    Should Be Equal  ${resp.dict["PasswordChangeRequired"]}  ${expected_result}
352
353
354Is BMC LastResetTime Changed
355    [Documentation]  Return fail if BMC last reset time is not changed.
356    [Arguments]  ${reset_time}
357
358    # Description of argument(s):
359    # reset_time  Last BMC reset time.
360
361    ${last_reset_time}=  Get BMC Last Reset Time
362    Should Not Be Equal  ${last_reset_time}  ${reset_time}
363
364
365Redfish BMC Reboot
366    [Documentation]  Use Redfish API reboot BMC and wait for BMC ready.
367
368    #  Get BMC last reset time for compare
369    ${last_reset_time}=  Get BMC Last Reset Time
370
371    # Reboot BMC by Redfish API
372    Redfish BMC Reset Operation
373
374    # Wait for BMC real reboot and Redfish API ready
375    Wait Until Keyword Succeeds  3 min  10 sec  Is BMC LastResetTime Changed  ${last_reset_time}
376
377
378Get BMC Last Reset Time
379    [Documentation]  Return BMC LastResetTime.
380
381    ${last_reset_time}=  Redfish.Get Attribute  /redfish/v1/Managers/${MANAGER_ID}  LastResetTime
382
383    RETURN  ${last_reset_time}
384