|  | #!/usr/bin/env python | 
|  |  | 
|  | r""" | 
|  | BMC redfish utility functions. | 
|  | """ | 
|  |  | 
|  | import json | 
|  | from robot.libraries.BuiltIn import BuiltIn | 
|  | import gen_print as gp | 
|  |  | 
|  |  | 
|  | class bmc_redfish_utils(object): | 
|  |  | 
|  | def __init__(self): | 
|  | r""" | 
|  | Initialize the bmc_redfish_utils object. | 
|  | """ | 
|  | # Obtain a reference to the global redfish object. | 
|  | self._redfish_ = BuiltIn().get_library_instance('redfish') | 
|  |  | 
|  | def get_redfish_session_info(self): | 
|  | r""" | 
|  | Returns redfish sessions info dictionary. | 
|  |  | 
|  | { | 
|  | 'key': 'yLXotJnrh5nDhXj5lLiH' , | 
|  | 'location': '/redfish/v1/SessionService/Sessions/nblYY4wlz0' | 
|  | } | 
|  | """ | 
|  | session_dict = { | 
|  | "key": self._redfish_.get_session_key(), | 
|  | "location": self._redfish_.get_session_location() | 
|  | } | 
|  | return session_dict | 
|  |  | 
|  | def get_attribute(self, resource_path, attribute): | 
|  | r""" | 
|  | Get resource attribute. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path               URI resource absolute path (e.g. | 
|  | "/redfish/v1/Systems/1"). | 
|  | attribute                   Name of the attribute (e.g. 'PowerState'). | 
|  | """ | 
|  |  | 
|  | resp = self._redfish_.get(resource_path) | 
|  | if attribute in resp.dict: | 
|  | return resp.dict[attribute] | 
|  |  | 
|  | return None | 
|  |  | 
|  | def get_properties(self, resource_path): | 
|  | r""" | 
|  | Returns dictionary of attributes for the resource. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path               URI resource absolute path (e.g. | 
|  | "/redfish/v1/Systems/1"). | 
|  | """ | 
|  |  | 
|  | resp = self._redfish_.get(resource_path) | 
|  | return resp.dict | 
|  |  | 
|  | def get_target_actions(self, resource_path, target_attribute): | 
|  | r""" | 
|  | Returns resource target entry of the searched target attribute. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path      URI resource absolute path | 
|  | (e.g. "/redfish/v1/Systems/system"). | 
|  | target_attribute   Name of the attribute (e.g. 'ComputerSystem.Reset'). | 
|  |  | 
|  | Example: | 
|  | "Actions": { | 
|  | "#ComputerSystem.Reset": { | 
|  | "ResetType@Redfish.AllowableValues": [ | 
|  | "On", | 
|  | "ForceOff", | 
|  | "GracefulRestart", | 
|  | "GracefulShutdown" | 
|  | ], | 
|  | "target": "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset" | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | global target_list | 
|  | target_list = [] | 
|  |  | 
|  | resp_dict = self.get_attribute(resource_path, "Actions") | 
|  | if resp_dict is None: | 
|  | return None | 
|  |  | 
|  | # Recursively search the "target" key in the nested dictionary. | 
|  | # Populate the target_list of target entries. | 
|  | self.get_key_value_nested_dict(resp_dict, "target") | 
|  |  | 
|  | # Return the matching target URL entry. | 
|  | for target in target_list: | 
|  | # target "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset" | 
|  | if target_attribute in target: | 
|  | return target | 
|  |  | 
|  | return None | 
|  |  | 
|  | def get_member_list(self, resource_path): | 
|  | r""" | 
|  | Perform a GET list request and return available members entries. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path  URI resource absolute path | 
|  | (e.g. "/redfish/v1/SessionService/Sessions"). | 
|  |  | 
|  | "Members": [ | 
|  | { | 
|  | "@odata.id": "/redfish/v1/SessionService/Sessions/Z5HummWPZ7" | 
|  | } | 
|  | { | 
|  | "@odata.id": "/redfish/v1/SessionService/Sessions/46CmQmEL7H" | 
|  | } | 
|  | ], | 
|  | """ | 
|  |  | 
|  | member_list = [] | 
|  | resp_list_dict = self.get_attribute(resource_path, "Members") | 
|  | if resp_list_dict is None: | 
|  | return member_list | 
|  |  | 
|  | for member_id in range(0, len(resp_list_dict)): | 
|  | member_list.append(resp_list_dict[member_id]["@odata.id"]) | 
|  |  | 
|  | return member_list | 
|  |  | 
|  | def list_request(self, resource_path): | 
|  | r""" | 
|  | Perform a GET list request and return available resource paths. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path  URI resource absolute path | 
|  | (e.g. "/redfish/v1/SessionService/Sessions"). | 
|  | """ | 
|  |  | 
|  | gp.qprint_executing(style=gp.func_line_style_short) | 
|  |  | 
|  | # Set quiet variable to keep subordinate get() calls quiet. | 
|  | quiet = 1 | 
|  |  | 
|  | global resource_list | 
|  | resource_list = [] | 
|  | self._rest_response_ = \ | 
|  | self._redfish_.get(resource_path, | 
|  | valid_status_codes=[200, 404, 500]) | 
|  |  | 
|  | # Return empty list. | 
|  | if self._rest_response_.status != 200: | 
|  | return resource_list | 
|  |  | 
|  | self.walk_nested_dict(self._rest_response_.dict) | 
|  |  | 
|  | if not resource_list: | 
|  | return uri_path | 
|  |  | 
|  | for resource in resource_list: | 
|  | self._rest_response_ = \ | 
|  | self._redfish_.get(resource, | 
|  | valid_status_codes=[200, 404, 500]) | 
|  | if self._rest_response_.status != 200: | 
|  | continue | 
|  | self.walk_nested_dict(self._rest_response_.dict) | 
|  |  | 
|  | resource_list.sort() | 
|  | return resource_list | 
|  |  | 
|  | def enumerate_request(self, resource_path): | 
|  | r""" | 
|  | Perform a GET enumerate request and return available resource paths. | 
|  |  | 
|  | Description of argument(s): | 
|  | resource_path  URI resource absolute path | 
|  | (e.g. "/redfish/v1/SessionService/Sessions"). | 
|  | """ | 
|  |  | 
|  | gp.qprint_executing(style=gp.func_line_style_short) | 
|  |  | 
|  | # Set quiet variable to keep subordinate get() calls quiet. | 
|  | quiet = 1 | 
|  |  | 
|  | url_list = self.list_request(resource_path) | 
|  |  | 
|  | resource_dict = {} | 
|  |  | 
|  | # Return empty dict. | 
|  | if not url_list: | 
|  | return resource_dict | 
|  |  | 
|  | for resource in url_list: | 
|  | # JsonSchemas data are not required in enumeration. | 
|  | # Example: '/redfish/v1/JsonSchemas/' and sub resources. | 
|  | if 'JsonSchemas' in resource: | 
|  | continue | 
|  | self._rest_response_ = \ | 
|  | self._redfish_.get(resource, | 
|  | valid_status_codes=[200, 404, 500]) | 
|  | if self._rest_response_.status != 200: | 
|  | continue | 
|  | resource_dict[resource] = self._rest_response_.dict | 
|  |  | 
|  | return json.dumps(resource_dict, sort_keys=True, | 
|  | indent=4, separators=(',', ': ')) | 
|  |  | 
|  | def walk_nested_dict(self, data): | 
|  | r""" | 
|  | Parse through the nested dictionary and get the resource id paths. | 
|  |  | 
|  | Description of argument(s): | 
|  | data    Nested dictionary data from response message. | 
|  | """ | 
|  |  | 
|  | for key, value in data.items(): | 
|  | if isinstance(value, dict): | 
|  | self.walk_nested_dict(value) | 
|  | else: | 
|  | if 'Members' == key: | 
|  | if isinstance(value, list): | 
|  | for index in value: | 
|  | if index['@odata.id'] not in resource_list: | 
|  | resource_list.append(index['@odata.id']) | 
|  | if '@odata.id' == key: | 
|  | if value not in resource_list and not value.endswith('/'): | 
|  | resource_list.append(value) | 
|  |  | 
|  | def get_key_value_nested_dict(self, data, key): | 
|  | r""" | 
|  | Parse through the nested dictionary and get the searched key value. | 
|  |  | 
|  | Description of argument(s): | 
|  | data    Nested dictionary data from response message. | 
|  | key     Search dictionary key element. | 
|  | """ | 
|  |  | 
|  | for k, v in data.items(): | 
|  | if isinstance(v, dict): | 
|  | self.get_key_value_nested_dict(v, key) | 
|  |  | 
|  | if k == key: | 
|  | target_list.append(v) |