1#!/usr/bin/env python 2 3r""" 4BMC redfish utility functions. 5""" 6 7import json 8from robot.libraries.BuiltIn import BuiltIn 9 10 11class bmc_redfish_utils(object): 12 13 def __init__(self): 14 r""" 15 Initialize the bmc_redfish_utils object. 16 """ 17 # Obtain a reference to the global redfish object. 18 self._redfish_ = BuiltIn().get_library_instance('redfish') 19 20 def get_redfish_session_info(self): 21 r""" 22 Returns redfish sessions info dictionary. 23 24 { 25 'key': 'yLXotJnrh5nDhXj5lLiH' , 26 'location': '/redfish/v1/SessionService/Sessions/nblYY4wlz0' 27 } 28 """ 29 session_dict = { 30 "key": self._redfish_.get_session_key(), 31 "location": self._redfish_.get_session_location() 32 } 33 return session_dict 34 35 def get_attribute(self, resource_path, attribute): 36 r""" 37 Get resource attribute. 38 39 Description of argument(s): 40 resource_path URI resource absolute path (e.g. "/redfish/v1/Systems/1"). 41 attribute Name of the attribute (e.g. 'PowerState'). 42 """ 43 44 resp = self._redfish_.get(resource_path) 45 if attribute in resp.dict: 46 return resp.dict[attribute] 47 48 return None 49 50 def get_properties(self, resource_path): 51 r""" 52 Returns dictionary of attributes for the resource. 53 54 Description of argument(s): 55 resource_path URI resource absolute path (e.g. "/redfish/v1/Systems/1"). 56 """ 57 58 resp = self._redfish_.get(resource_path) 59 return resp.dict 60 61 def get_target_actions(self, resource_path, target_attribute): 62 r""" 63 Returns resource target entry of the searched target attribute. 64 65 Description of argument(s): 66 resource_path URI resource absolute path 67 (e.g. "/redfish/v1/Systems/system"). 68 target_attribute Name of the attribute (e.g. 'ComputerSystem.Reset'). 69 70 Example: 71 "Actions": { 72 "#ComputerSystem.Reset": { 73 "ResetType@Redfish.AllowableValues": [ 74 "On", 75 "ForceOff", 76 "GracefulRestart", 77 "GracefulShutdown" 78 ], 79 "target": "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset" 80 } 81 } 82 """ 83 84 global target_list 85 target_list = [] 86 87 resp_dict = self.get_attribute(resource_path, "Actions") 88 if resp_dict is None: 89 return None 90 91 # Recursively search the "target" key in the nested dictionary. 92 # Populate the target_list of target entries. 93 self.get_key_value_nested_dict(resp_dict, "target") 94 95 # Return the matching target URL entry. 96 for target in target_list: 97 # target "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset" 98 if target_attribute in target: 99 return target 100 101 return None 102 103 def get_member_list(self, resource_path): 104 r""" 105 Perform a GET list request and return available members entries. 106 107 Description of argument(s): 108 resource_path URI resource absolute path 109 (e.g. "/redfish/v1/SessionService/Sessions"). 110 111 "Members": [ 112 { 113 "@odata.id": "/redfish/v1/SessionService/Sessions/Z5HummWPZ7" 114 } 115 { 116 "@odata.id": "/redfish/v1/SessionService/Sessions/46CmQmEL7H" 117 } 118 ], 119 """ 120 121 member_list = [] 122 resp_list_dict = self.get_attribute(resource_path, "Members") 123 if resp_list_dict is None: 124 return member_list 125 126 for member_id in range(0, len(resp_list_dict)): 127 member_list.append(resp_list_dict[member_id]["@odata.id"]) 128 129 return member_list 130 131 def list_request(self, resource_path): 132 r""" 133 Perform a GET list request and return available resource paths. 134 135 Description of argument(s): 136 resource_path URI resource absolute path 137 (e.g. "/redfish/v1/SessionService/Sessions"). 138 """ 139 140 global resource_list 141 resource_list = [] 142 self._rest_response_ = self._redfish_.get(resource_path, valid_status_codes=[200, 404, 500]) 143 144 # Return empty list. 145 if self._rest_response_.status != 200: 146 return resource_list 147 148 self.walk_nested_dict(self._rest_response_.dict) 149 150 if not resource_list: 151 return uri_path 152 153 for resource in resource_list: 154 self._rest_response_ = self._redfish_.get(resource, valid_status_codes=[200, 404, 500]) 155 if self._rest_response_.status != 200: 156 continue 157 self.walk_nested_dict(self._rest_response_.dict) 158 159 resource_list.sort() 160 return resource_list 161 162 def enumerate_request(self, resource_path): 163 r""" 164 Perform a GET enumerate request and return available resource paths. 165 166 Description of argument(s): 167 resource_path URI resource absolute path 168 (e.g. "/redfish/v1/SessionService/Sessions"). 169 """ 170 171 url_list = self.list_request(resource_path) 172 173 resource_dict = {} 174 175 # Return empty dict. 176 if not url_list: 177 return resource_dict 178 179 for resource in url_list: 180 # JsonSchemas data are not required in enumeration. 181 # Example: '/redfish/v1/JsonSchemas/' and sub resources. 182 if 'JsonSchemas' in resource: 183 continue 184 self._rest_response_ = self._redfish_.get(resource, valid_status_codes=[200, 404, 500]) 185 if self._rest_response_.status != 200: 186 continue 187 resource_dict[resource] = self._rest_response_.dict 188 189 return json.dumps(resource_dict, sort_keys=True, 190 indent=4, separators=(',', ': ')) 191 192 def walk_nested_dict(self, data): 193 r""" 194 Parse through the nested dictionary and get the resource id paths. 195 196 Description of argument(s): 197 data Nested dictionary data from response message. 198 """ 199 200 for key, value in data.items(): 201 if isinstance(value, dict): 202 self.walk_nested_dict(value) 203 else: 204 if 'Members' == key: 205 if isinstance(value, list): 206 for index in value: 207 if index['@odata.id'] not in resource_list: 208 resource_list.append(index['@odata.id']) 209 if '@odata.id' == key: 210 if value not in resource_list and not value.endswith('/'): 211 resource_list.append(value) 212 213 def get_key_value_nested_dict(self, data, key): 214 r""" 215 Parse through the nested dictionary and get the searched key value. 216 217 Description of argument(s): 218 data Nested dictionary data from response message. 219 key Search dictionary key element. 220 """ 221 222 for k, v in data.items(): 223 if isinstance(v, dict): 224 self.get_key_value_nested_dict(v, key) 225 226 if k == key: 227 target_list.append(v) 228