|  | *** Settings *** | 
|  | Documentation   BMC and host redfish utility keywords. | 
|  |  | 
|  | Resource        resource.robot | 
|  | Resource        bmc_redfish_resource.robot | 
|  |  | 
|  |  | 
|  | *** Keywords *** | 
|  |  | 
|  | Redfish Power Operation | 
|  | [Documentation]  Do Redfish host power operation. | 
|  | [Arguments]      ${reset_type} | 
|  |  | 
|  | # Description of arguments: | 
|  | # reset_type     Type of power operation. | 
|  | #                (e.g. On/ForceOff/GracefulRestart/GracefulShutdown) | 
|  |  | 
|  | # Example: | 
|  | # "Actions": { | 
|  | # "#ComputerSystem.Reset": { | 
|  | #  "ResetType@Redfish.AllowableValues": [ | 
|  | #    "On", | 
|  | #    "ForceOff", | 
|  | #    "ForceOn", | 
|  | #    "ForceRestart", | 
|  | #    "GracefulRestart", | 
|  | #    "GracefulShutdown" | 
|  | #    "PowerCycle", | 
|  | #    "Nmi" | 
|  | #  ], | 
|  | #  "target": "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset" | 
|  | #  } | 
|  | # } | 
|  |  | 
|  | ${target}=  redfish_utils.Get Target Actions  /redfish/v1/Systems/system/  ComputerSystem.Reset | 
|  | ${payload}=  Create Dictionary  ResetType=${reset_type} | 
|  | ${resp}=  Redfish.Post  ${target}  body=&{payload} | 
|  |  | 
|  |  | 
|  | Redfish BMC Reset Operation | 
|  | [Documentation]  Do Redfish BMC reset operation. | 
|  | [Arguments]  ${reset_type}=GracefulRestart | 
|  |  | 
|  | # Example: | 
|  | # "Actions": { | 
|  | # "#Manager.Reset": { | 
|  | #  "ResetType@Redfish.AllowableValues": [ | 
|  | #    "GracefulRestart", | 
|  | #    "ForceRestart" | 
|  | #  ], | 
|  | #  "target": "/redfish/v1/Managers/bmc/Actions/Manager.Reset" | 
|  | # } | 
|  |  | 
|  | ${target}=  redfish_utils.Get Target Actions  /redfish/v1/Managers/bmc/  Manager.Reset | 
|  | ${payload}=  Create Dictionary  ResetType=${reset_type} | 
|  | Redfish.Post  ${target}  body=&{payload} | 
|  |  | 
|  |  | 
|  | Reset BIOS Via Redfish | 
|  | [Documentation]  Do BIOS reset through Redfish. | 
|  |  | 
|  | ${target}=  redfish_utils.Get Target Actions  /redfish/v1/Systems/system/Bios/  Bios.ResetBios | 
|  | Redfish.Post  ${target}  valid_status_codes=[${HTTP_OK}] | 
|  |  | 
|  |  | 
|  | Redfish Delete Session | 
|  | [Documentation]  Redfish delete session. | 
|  | [Arguments]  ${session_info} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # session_info      Session information are stored in dictionary. | 
|  |  | 
|  | # ${session_info} = { | 
|  | #     'SessionIDs': 'XXXXXXXXX', | 
|  | #     'ClientID': 'XXXXXX', | 
|  | #     'SessionToken': 'XXXXXXXXX', | 
|  | #     'SessionResp': session response from redfish login | 
|  | # } | 
|  |  | 
|  | # SessionIDs   : Session IDs | 
|  | # ClientID     : Client ID | 
|  | # SessionToken : Session token | 
|  | # SessionResp  : Response of creating an redfish login session | 
|  |  | 
|  | Redfish.Delete  /redfish/v1/SessionService/Sessions/${session_info["SessionIDs"]} | 
|  |  | 
|  |  | 
|  | Redfish Delete List Of Session | 
|  | [Documentation]  Redfish delete session from list of session records, individual session information | 
|  | ...              are stored in dictionary. | 
|  | [Arguments]  ${session_info_list} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # session_info_list    List contains individual session record are stored in dictionary. | 
|  |  | 
|  | # ${session_info_list} = [{ | 
|  | #     'SessionIDs': 'XXXXXXXXX', | 
|  | #     'ClientID': 'XXXXXX', | 
|  | #     'SessionToken': 'XXXXXXXXX', | 
|  | #     'SessionResp': session response from redfish login | 
|  | # }] | 
|  |  | 
|  | # SessionIDs   : Session IDs | 
|  | # ClientID     : Client ID | 
|  | # SessionToken : Session token | 
|  | # SessionResp  : Response of creating an redfish login session | 
|  |  | 
|  | FOR  ${session_record}  IN  @{session_info_list} | 
|  | Redfish.Delete  /redfish/v1/SessionService/Sessions/${session_record["SessionIDs"]} | 
|  | END | 
|  |  | 
|  |  | 
|  | Delete All Redfish Sessions | 
|  | [Documentation]  Delete all active redfish sessions. | 
|  |  | 
|  | ${saved_session_info}=  Get Redfish Session Info | 
|  |  | 
|  | ${resp_list}=  Redfish_Utils.Get Member List | 
|  | ...  /redfish/v1/SessionService/Sessions | 
|  |  | 
|  | # Remove the current login session from the list. | 
|  | Remove Values From List  ${resp_list}  ${saved_session_info["location"]} | 
|  |  | 
|  | # Remove session with client_id populated from the list. | 
|  | ${client_id_list}=  Get Session With Client Id  ${resp_list} | 
|  | Log To Console  Client sessions skip list: ${client_id_list} | 
|  | FOR  ${client_session}  IN  @{client_id_list} | 
|  | Remove Values From List  ${resp_list}  ${client_session} | 
|  | END | 
|  |  | 
|  | FOR  ${session}  IN  @{resp_list} | 
|  | Run Keyword And Ignore Error  Redfish.Delete  ${session} | 
|  | END | 
|  |  | 
|  |  | 
|  | Get Session With Client Id | 
|  | [Documentation]  Iterate through the active sessions and return sessions populated with client id. | 
|  | [Arguments]  ${session_list} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # session_list   Active session list from SessionService. | 
|  |  | 
|  | #  "Oem": { | 
|  | #    "OpenBMC": { | 
|  | #        "@odata.type": "#OemSession.v1_0_0.Session", | 
|  | #        "ClientID": "MYID=Vd57f62*2811504" | 
|  | #    } | 
|  |  | 
|  | ${client_id_sessions}=  Create List | 
|  | FOR  ${session}  IN  @{session_list} | 
|  | ${resp}=  Redfish.Get  ${session}   valid_status_codes=[200,404] | 
|  | Run Keyword If  '${resp.dict["Oem"]["OpenBMC"]["ClientID"]}' != '${EMPTY}' | 
|  | ...    Append To List  ${client_id_sessions}  ${session} | 
|  | END | 
|  |  | 
|  | [Return]  ${client_id_sessions} | 
|  |  | 
|  |  | 
|  | Get Valid FRUs | 
|  | [Documentation]  Return a dictionary containing all of the valid FRU records for the given fru_type. | 
|  | [Arguments]  ${fru_type} | 
|  |  | 
|  | # NOTE: A valid FRU record will have a "State" key of "Enabled" and a "Health" key of "OK". | 
|  |  | 
|  | # Description of argument(s): | 
|  | # fru_type  The type of fru (e.g. "Processors", "Memory", etc.). | 
|  |  | 
|  | ${fru_records}=  Redfish_Utils.Enumerate Request | 
|  | ...  /redfish/v1/Systems/system/${fru_type}  return_json=0 | 
|  | ${fru_records}=  Filter Struct  ${fru_records}  [('State', 'Enabled'), ('Health', 'OK')] | 
|  |  | 
|  | [Return]  ${fru_records} | 
|  |  | 
|  |  | 
|  | Get Num Valid FRUs | 
|  | [Documentation]  Return the number of valid FRU records for the given fru_type. | 
|  | [Arguments]  ${fru_type} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # fru_type  The type of fru (e.g. "Processors", "Memory", etc.). | 
|  |  | 
|  | ${fru_records}=  Get Valid FRUs  ${fru_type} | 
|  | ${num_valid_frus}=  Get length  ${fru_records} | 
|  |  | 
|  | [Return]  ${num_valid_frus} | 
|  |  | 
|  |  | 
|  | Verify Valid Records | 
|  | [Documentation]  Verify all records retrieved with the given arguments are valid. | 
|  | [Arguments]  ${record_type}  ${redfish_uri}  ${reading_type} | 
|  |  | 
|  | # Description of Argument(s): | 
|  | # record_type    The sensor record type (e.g. "PowerSupplies") | 
|  | # redfish_uri    The power supply URI (e.g. /redfish/v1/Chassis/chassis/Power) | 
|  | # reading_type   The power watt readings (e.g. "PowerInputWatts") | 
|  |  | 
|  | # A valid record will have "State" key "Enabled" and "Health" key "OK". | 
|  | ${records}=  Redfish.Get Attribute  ${redfish_uri}  ${record_type} | 
|  |  | 
|  | Rprint Vars  records | 
|  |  | 
|  | # Example output: | 
|  | # records: | 
|  | #   [0]: | 
|  | #     [@odata.id]:                 /redfish/v1/Chassis/chassis/Power#/PowerControl/0 | 
|  | #     [@odata.type]:               #Power.v1_0_0.PowerControl | 
|  | #     [MemberId]:                  0 | 
|  | #     [Name]:                      Chassis Power Control | 
|  | #     [PowerConsumedWatts]:        264.0 | 
|  | #     [PowerLimit]: | 
|  | #       [LimitInWatts]:            None | 
|  | #     [PowerMetrics]: | 
|  | #       [AverageConsumedWatts]:    325 | 
|  | #       [IntervalInMin]:           3 | 
|  | #       [MaxConsumedWatts]:        538 | 
|  | #     [Status]: | 
|  | #       [Health]:                  OK | 
|  | #       [State]:                   Enabled | 
|  |  | 
|  | ${invalid_records}=  Filter Struct  ${records} | 
|  | ...  [('Health', '^OK$'), ('State', '^Enabled$'), ('${reading_type}', '')]  regex=1  invert=1 | 
|  | Valid Length  invalid_records  max_length=0 | 
|  |  | 
|  | [Return]  ${records} | 
|  |  | 
|  |  | 
|  | Redfish Create User | 
|  | [Documentation]  Redfish create user. | 
|  | [Arguments]   ${user_name}  ${password}  ${role_id}  ${enabled}  ${force}=${False} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # user_name           The user name to be created. | 
|  | # password            The password to be assigned. | 
|  | # role_id             The role ID of the user to be created. | 
|  | #                     (e.g. "Administrator", "Operator", etc.). | 
|  | # enabled             Indicates whether the username being created. | 
|  | #                     should be enabled (${True}, ${False}). | 
|  | # force               Delete user account and re-create if force is True. | 
|  |  | 
|  | ${curr_role}=  Run Keyword And Ignore Error  Get User Role  ${user_name} | 
|  | # Ex: ${curr_role} = ('PASS', 'Administrator') | 
|  |  | 
|  | ${user_exists}=  Run Keyword And Return Status  Should Be Equal As Strings  ${curr_role}[0]  PASS | 
|  |  | 
|  | # Delete user account when force is True. | 
|  | Run Keyword If  ${force} == ${True}  Redfish.Delete  ${REDFISH_ACCOUNTS_URI}${user_name} | 
|  | ...  valid_status_codes=[${HTTP_OK}, ${HTTP_NOT_FOUND}] | 
|  |  | 
|  | # Create specified user when force is True or User does not exist. | 
|  | ${payload}=  Create Dictionary | 
|  | ...  UserName=${user_name}  Password=${password}  RoleId=${role_id}  Enabled=${enabled} | 
|  |  | 
|  | Run Keyword If  ${force} == ${True} or ${user_exists} == ${False} | 
|  | ...  Redfish.Post  ${REDFISH_ACCOUNTS_URI}  body=&{payload} | 
|  | ...  valid_status_codes=[${HTTP_CREATED}] | 
|  |  | 
|  |  | 
|  | Get User Role | 
|  | [Documentation]  Get User Role. | 
|  | [Arguments]  ${user_name} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # user_name    User name to get it's role. | 
|  |  | 
|  | ${role_config}=  Redfish_Utils.Get Attribute | 
|  | ...  ${REDFISH_ACCOUNTS_URI}${user_name}  RoleId | 
|  |  | 
|  | [Return]  ${role_config} | 
|  |  | 
|  |  | 
|  | Create Users With Different Roles | 
|  | [Documentation]  Create users with different roles. | 
|  | [Arguments]  ${users}  ${force}=${False} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # users    Dictionary of roles and user credentails to be created. | 
|  | #          Ex:  {'Administrator': '[admin_user, TestPwd123]', 'Operator': '[operator_user, TestPwd123]'} | 
|  | # force    Delete given user account if already exists when force is True. | 
|  |  | 
|  | FOR  ${role}  IN  @{users} | 
|  | Redfish Create User  ${users['${role}'][0]}  ${users['${role}']}[1]  ${role}  ${True}  ${force} | 
|  | END | 
|  |  | 
|  |  | 
|  | Delete BMC Users Via Redfish | 
|  | [Documentation]  Delete BMC users via redfish. | 
|  | [Arguments]  ${users} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # users    Dictionary of roles and user credentials to be deleted. | 
|  |  | 
|  | FOR  ${role}  IN  @{users} | 
|  | Redfish.Delete  /redfish/v1/AccountService/Accounts/${users['${role}'][0]} | 
|  | ...  valid_status_codes=[${HTTP_OK}, ${HTTP_NOT_FOUND}] | 
|  | END | 
|  |  | 
|  |  | 
|  | Expire And Update New Password Via Redfish | 
|  | [Documentation]  Expire and change password and verify using password. | 
|  | [Arguments]  ${username}  ${password}  ${new_password} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # username        The username to be used to login to the BMC. | 
|  | # password        The password to be used to login to the BMC. | 
|  | # new_password    The new password to be used to update password. | 
|  |  | 
|  | # Expire admin password using ssh. | 
|  | Open Connection And Log In  ${username}  ${password} | 
|  | ${output}  ${stderr}  ${rc}=  BMC Execute Command  passwd --expire ${username} | 
|  | Should Contain Any  ${output}  password expiry information changed | 
|  | ...  password changed | 
|  |  | 
|  | # Verify user password expired using Redfish | 
|  | Verify User Password Expired Using Redfish  ${username}  ${password} | 
|  |  | 
|  | # Change user password. | 
|  | Redfish.Patch  /redfish/v1/AccountService/Accounts/${username} | 
|  | ...  body={'Password': '${new_password}'} | 
|  | Redfish.Logout | 
|  |  | 
|  |  | 
|  | Verify User Password Expired Using Redfish | 
|  | [Documentation]  Checking whether user password expired or not using redfish. | 
|  |  | 
|  | # Description of argument(s): | 
|  | # username        The username to be used to login to the BMC. | 
|  | # password        The password to be used to login to the BMC. | 
|  |  | 
|  | [Arguments]  ${username}  ${password}  ${expected_result}=${True} | 
|  | Redfish.Login  ${username}  ${password} | 
|  | ${resp}=  Redfish.Get  /redfish/v1/AccountService/Accounts/${username} | 
|  | Should Be Equal  ${resp.dict["PasswordChangeRequired"]}  ${expected_result} | 
|  |  |