blob: 73fbf93e87a1cdfa1b524a5db6921c5dccaec5d2 [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)
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
143 self._rest_response_ = self._robj_.get('/redfish/v1/' + resource_path)
George Keishing5a73ee02019-01-28 08:21:47 -0600144 if self._rest_response_.status != 200:
145 return self._rest_response_
George Keishinge62d8b02018-11-29 12:01:56 -0600146
147 global resource_list
148 resource_list = []
149 self.walk_nested_dict(self._rest_response_.dict)
150
151 if not resource_list:
152 return uri_path
153
154 for resource in resource_list:
155 self._rest_response_ = self._robj_.get(resource)
156 if self._rest_response_.status != 200:
157 continue
158 self.walk_nested_dict(self._rest_response_.dict)
159
160 resource_list.sort()
George Keishing5a73ee02019-01-28 08:21:47 -0600161 return resource_list
George Keishinge62d8b02018-11-29 12:01:56 -0600162
163 def enumerate_request(self, resource_path):
164 r"""
165 Perform a GET enumerate request and return available resource paths.
166
167 Description of argument(s):
168 resource_path URI resource relative path (e.g. "Systems/1").
169 """
170
171 self._rest_response_ = self.list_request(resource_path)
George Keishing5a73ee02019-01-28 08:21:47 -0600172 if self._rest_response_.status != 200:
173 return self._rest_response_
George Keishinge62d8b02018-11-29 12:01:56 -0600174
175 resource_dict = {}
176 for resource in json.loads(self._rest_response_):
177 self._rest_response_ = self._robj_.get(resource)
178 if self._rest_response_.status != 200:
179 continue
180 resource_dict[resource] = self._rest_response_.dict
181
182 return json.dumps(resource_dict, sort_keys=True,
183 indent=4, separators=(',', ': '))
184
185 def walk_nested_dict(self, data):
186 r"""
187 Parse through the nested dictionary and get the resource id paths.
188
189 Description of argument(s):
190 data Nested dictionary data from response message.
191 """
192
193 for key, value in data.items():
194 if isinstance(value, dict):
195 self.walk_nested_dict(value)
196 else:
197 if 'Members' == key:
198 if isinstance(value, list):
199 for index in value:
200 if index['@odata.id'] not in resource_list:
201 resource_list.append(index['@odata.id'])
202 if '@odata.id' == key:
203 if value not in resource_list and not value.endswith('/'):
204 resource_list.append(value)