blob: 819dd634b36da9b0bc19999faa1f58e1fcdbb676 [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
10
11
12class HTTPSBadRequestError(Exception):
13 r"""
14 BMC redfish generic raised method for error(s).
15 """
16 pass
17
18
19class bmc_redfish(object):
20
21 ROBOT_LIBRARY_SCOPE = "GLOBAL"
22
23 def __init__(self, hostname, username, password, *args, **kwargs):
24 r"""
25 Establish session connection to host.
26
27 Description of argument(s):
28 hostname The host name or IP address of the server.
29 username The username to be used to connect to the server.
30 password The password to be used to connect to the server.
31 args/kwargs Additional parms which are passed directly
32 to the redfish_client function.
33 """
34
35 self._base_url_ = "https://" + hostname
36 self._username_ = username
37 self._password_ = password
38 self._default_prefix_ = "/redfish/v1"
39 self._robj_ = \
40 redfish.redfish_client(base_url=self._base_url_,
41 username=self._username_,
42 password=self._password_,
43 default_prefix=self._default_prefix_,
44 *args, **kwargs)
45 self._robj_.login(auth=redfish.AuthMethod.SESSION)
46 self._session_location_ = self._robj_.get_session_location()
47
48 def __enter__(self):
49 return self
50
51 def __exit__(self, exception_type, exception_value, traceback):
52 self._robj_.logout()
53
54 def login(self, *args, **kwargs):
55 r"""
56 Call the corresponding RestClientBase method and return the result.
57
58 Description of argument(s):
59 args/kwargs These are passed directly to the corresponding
60 RestClientBase method.
61 """
62 self._robj_.__init__(self._base_url_, self._username_, self._password_)
63 self._robj_.login(auth=redfish.AuthMethod.SESSION)
64
65 def get(self, resource_path, *args, **kwargs):
66 r"""
67 Perform a GET request and return response.
68
69 Description of argument(s):
70 resource_path URI resource relative path (e.g. "Systems/1").
71 args/kwargs These are passed directly to the corresponding
72 RestClientBase method.
73 """
74 self._rest_response_ = self._robj_.get('/redfish/v1/' + resource_path,
75 *args, **kwargs)
76 if self._rest_response_.status != 200:
77 raise HTTPSBadRequestError("GET Session location: %s, "
78 "return code: %d"
79 % (self._session_location_,
80 self._rest_response_.status))
81 return self._rest_response_
82
83 def post(self, resource_path, *args, **kwargs):
84 r"""
85 Perform a POST request.
86
87 Description of argument(s):
88 resource_path URI resource relative path
89 (e.g. "Systems/1/Actions/ComputerSystem.Reset").
90 args/kwargs These are passed directly to the corresponding
91 RestClientBase method.
92 """
93 self._rest_response_ = self._robj_.post('/redfish/v1/' + resource_path,
94 *args, **kwargs)
95 if self._rest_response_.status != 200:
96 raise HTTPSBadRequestError("POST Session location: %s, "
97 "return code: %d"
98 % (self._session_location_,
99 self._rest_response_.status))
100 return self._rest_response_
101
102 def patch(self, resource_path, *args, **kwargs):
103 r"""
104 Perform a POST request.
105
106 Description of argument(s):
107 resource_path URI resource relative path
108 args/kwargs These are passed directly to the corresponding
109 RestClientBase method.
110 """
111 self._rest_response_ = self._robj_.patch('/redfish/v1/' + resource_path,
112 *args, **kwargs)
113 if self._rest_response_.status != 200:
114 raise HTTPSBadRequestError("PATCH Session location: %s, "
115 "return code: %d"
116 % (self._session_location_,
117 self._rest_response_.status))
118 return self._rest_response_
119
120 def put(self, resource_path, actions, attr_data):
121 r"""
122 Perform a PUT request.
123
124 Description of argument(s):
125 resource_path URI resource relative path.
126 args/kwargs These are passed directly to the corresponding
127 RestClientBase method.
128 """
129 self._rest_response_ = self._robj_.put('/redfish/v1/' + resource_path,
130 *args, **kwargs)
131 if self._rest_response_.status != 200:
132 raise HTTPSBadRequestError("PUT Session location: %s, "
133 "return code: %d"
134 % (self._session_location_,
135 self._rest_response_.status))
136 return self._rest_response_
137
138 def delete(self, resource_path):
139 r"""
140 Perform a DELETE request.
141
142 Description of argument(s):
143 resource_path URI resource absoulute path
144 (e.g. "/redfish/v1/SessionService/Sessions/8d1a9wiiNL").
145 """
146 self._rest_response_ = self._robj_.delete(resource_path)
147 if self._rest_response_.status != 200:
148 raise HTTPSBadRequestError("Session location: %s, "
149 "return code: %d"
150 % (self._session_location_,
151 self._rest_response_.status))
152 return self._rest_response_
153
154 def logout(self):
155 r"""
156 Logout redfish connection session.
157 """
158 self._robj_.logout()
159
160 def list_request(self, resource_path):
161 r"""
162 Perform a GET list request and return available resource paths.
163
164 Description of argument(s):
165 resource_path URI resource relative path (e.g. "Systems/1").
166 """
167
168 self._rest_response_ = self._robj_.get('/redfish/v1/' + resource_path)
169
170 global resource_list
171 resource_list = []
172 self.walk_nested_dict(self._rest_response_.dict)
173
174 if not resource_list:
175 return uri_path
176
177 for resource in resource_list:
178 self._rest_response_ = self._robj_.get(resource)
179 if self._rest_response_.status != 200:
180 continue
181 self.walk_nested_dict(self._rest_response_.dict)
182
183 resource_list.sort()
184 return json.dumps(resource_list, sort_keys=True,
185 indent=4, separators=(',', ': '))
186
187 def enumerate_request(self, resource_path):
188 r"""
189 Perform a GET enumerate request and return available resource paths.
190
191 Description of argument(s):
192 resource_path URI resource relative path (e.g. "Systems/1").
193 """
194
195 self._rest_response_ = self.list_request(resource_path)
196
197 resource_dict = {}
198 for resource in json.loads(self._rest_response_):
199 self._rest_response_ = self._robj_.get(resource)
200 if self._rest_response_.status != 200:
201 continue
202 resource_dict[resource] = self._rest_response_.dict
203
204 return json.dumps(resource_dict, sort_keys=True,
205 indent=4, separators=(',', ': '))
206
207 def walk_nested_dict(self, data):
208 r"""
209 Parse through the nested dictionary and get the resource id paths.
210
211 Description of argument(s):
212 data Nested dictionary data from response message.
213 """
214
215 for key, value in data.items():
216 if isinstance(value, dict):
217 self.walk_nested_dict(value)
218 else:
219 if 'Members' == key:
220 if isinstance(value, list):
221 for index in value:
222 if index['@odata.id'] not in resource_list:
223 resource_list.append(index['@odata.id'])
224 if '@odata.id' == key:
225 if value not in resource_list and not value.endswith('/'):
226 resource_list.append(value)