blob: 178a207f548662a44f329265acffb1428e4994ee [file] [log] [blame]
George Keishinge62d8b02018-11-29 12:01:56 -06001#!/usr/bin/env python
2
3r"""
4Using python based redfish library.
5Refer: https://github.com/DMTF/python-redfish-library
6"""
7
8import redfish
9import json
George Keishing2296e8c2019-02-01 05:49:58 -060010from robot.libraries.BuiltIn import BuiltIn
George Keishinge62d8b02018-11-29 12:01:56 -060011
12
13class HTTPSBadRequestError(Exception):
14 r"""
15 BMC redfish generic raised method for error(s).
16 """
17 pass
18
19
20class bmc_redfish(object):
21
22 ROBOT_LIBRARY_SCOPE = "GLOBAL"
23
24 def __init__(self, hostname, username, password, *args, **kwargs):
25 r"""
26 Establish session connection to host.
27
28 Description of argument(s):
29 hostname The host name or IP address of the server.
30 username The username to be used to connect to the server.
31 password The password to be used to connect to the server.
32 args/kwargs Additional parms which are passed directly
33 to the redfish_client function.
34 """
35
36 self._base_url_ = "https://" + hostname
37 self._username_ = username
38 self._password_ = password
39 self._default_prefix_ = "/redfish/v1"
40 self._robj_ = \
41 redfish.redfish_client(base_url=self._base_url_,
42 username=self._username_,
43 password=self._password_,
44 default_prefix=self._default_prefix_,
45 *args, **kwargs)
46 self._robj_.login(auth=redfish.AuthMethod.SESSION)
47 self._session_location_ = self._robj_.get_session_location()
48
49 def __enter__(self):
50 return self
51
52 def __exit__(self, exception_type, exception_value, traceback):
53 self._robj_.logout()
54
55 def login(self, *args, **kwargs):
56 r"""
57 Call the corresponding RestClientBase method and return the result.
58
59 Description of argument(s):
60 args/kwargs These are passed directly to the corresponding
61 RestClientBase method.
62 """
63 self._robj_.__init__(self._base_url_, self._username_, self._password_)
64 self._robj_.login(auth=redfish.AuthMethod.SESSION)
65
66 def get(self, resource_path, *args, **kwargs):
67 r"""
68 Perform a GET request and return response.
69
70 Description of argument(s):
George Keishing6510cfb2019-01-31 12:28:36 -060071 resource_path URI resource absolute path (e.g. "/redfish/v1/Systems/1").
George Keishinge62d8b02018-11-29 12:01:56 -060072 args/kwargs These are passed directly to the corresponding
73 RestClientBase method.
74 """
George Keishing6510cfb2019-01-31 12:28:36 -060075 self._rest_response_ = self._robj_.get(resource_path, *args, **kwargs)
George Keishinge62d8b02018-11-29 12:01:56 -060076 return self._rest_response_
77
78 def post(self, resource_path, *args, **kwargs):
79 r"""
80 Perform a POST request.
81
82 Description of argument(s):
83 resource_path URI resource relative path
84 (e.g. "Systems/1/Actions/ComputerSystem.Reset").
85 args/kwargs These are passed directly to the corresponding
86 RestClientBase method.
87 """
88 self._rest_response_ = self._robj_.post('/redfish/v1/' + resource_path,
89 *args, **kwargs)
George Keishinge62d8b02018-11-29 12:01:56 -060090 return self._rest_response_
91
92 def patch(self, resource_path, *args, **kwargs):
93 r"""
94 Perform a POST request.
95
96 Description of argument(s):
97 resource_path URI resource relative path
98 args/kwargs These are passed directly to the corresponding
99 RestClientBase method.
100 """
101 self._rest_response_ = self._robj_.patch('/redfish/v1/' + resource_path,
102 *args, **kwargs)
George Keishinge62d8b02018-11-29 12:01:56 -0600103 return self._rest_response_
104
105 def put(self, resource_path, actions, attr_data):
106 r"""
107 Perform a PUT request.
108
109 Description of argument(s):
110 resource_path URI resource relative path.
111 args/kwargs These are passed directly to the corresponding
112 RestClientBase method.
113 """
114 self._rest_response_ = self._robj_.put('/redfish/v1/' + resource_path,
115 *args, **kwargs)
George Keishinge62d8b02018-11-29 12:01:56 -0600116 return self._rest_response_
117
118 def delete(self, resource_path):
119 r"""
120 Perform a DELETE request.
121
122 Description of argument(s):
123 resource_path URI resource absoulute path
124 (e.g. "/redfish/v1/SessionService/Sessions/8d1a9wiiNL").
125 """
126 self._rest_response_ = self._robj_.delete(resource_path)
George Keishinge62d8b02018-11-29 12:01:56 -0600127 return self._rest_response_
128
129 def logout(self):
130 r"""
131 Logout redfish connection session.
132 """
133 self._robj_.logout()
134
135 def list_request(self, resource_path):
136 r"""
137 Perform a GET list request and return available resource paths.
138
139 Description of argument(s):
140 resource_path URI resource relative path (e.g. "Systems/1").
141 """
142
George Keishinge62d8b02018-11-29 12:01:56 -0600143 global resource_list
144 resource_list = []
George Keishing2296e8c2019-02-01 05:49:58 -0600145
146 self._rest_response_ = self._robj_.get('/redfish/v1/' + resource_path)
147
148 # Return empty list.
149 if self._rest_response_.status != 200:
150 return resource_list
151
George Keishinge62d8b02018-11-29 12:01:56 -0600152 self.walk_nested_dict(self._rest_response_.dict)
153
154 if not resource_list:
155 return uri_path
156
157 for resource in resource_list:
158 self._rest_response_ = self._robj_.get(resource)
159 if self._rest_response_.status != 200:
160 continue
161 self.walk_nested_dict(self._rest_response_.dict)
162
163 resource_list.sort()
George Keishing5a73ee02019-01-28 08:21:47 -0600164 return resource_list
George Keishinge62d8b02018-11-29 12:01:56 -0600165
166 def enumerate_request(self, resource_path):
167 r"""
168 Perform a GET enumerate request and return available resource paths.
169
170 Description of argument(s):
171 resource_path URI resource relative path (e.g. "Systems/1").
172 """
173
George Keishing2296e8c2019-02-01 05:49:58 -0600174 url_list = self.list_request(resource_path)
George Keishinge62d8b02018-11-29 12:01:56 -0600175
176 resource_dict = {}
George Keishing2296e8c2019-02-01 05:49:58 -0600177
178 # Return empty dict.
179 if not url_list:
180 return resource_dict
181
182 for resource in url_list:
George Keishinge62d8b02018-11-29 12:01:56 -0600183 self._rest_response_ = self._robj_.get(resource)
184 if self._rest_response_.status != 200:
185 continue
186 resource_dict[resource] = self._rest_response_.dict
187
188 return json.dumps(resource_dict, sort_keys=True,
189 indent=4, separators=(',', ': '))
190
191 def walk_nested_dict(self, data):
192 r"""
193 Parse through the nested dictionary and get the resource id paths.
194
195 Description of argument(s):
196 data Nested dictionary data from response message.
197 """
198
199 for key, value in data.items():
200 if isinstance(value, dict):
201 self.walk_nested_dict(value)
202 else:
203 if 'Members' == key:
204 if isinstance(value, list):
205 for index in value:
206 if index['@odata.id'] not in resource_list:
207 resource_list.append(index['@odata.id'])
208 if '@odata.id' == key:
209 if value not in resource_list and not value.endswith('/'):
210 resource_list.append(value)