blob: ba1b7d7d7c8ea391aeec26c41c74298ff6093c8b [file] [log] [blame]
#!/usr/bin/env python
r"""
Using python based redfish library.
Refer: https://github.com/DMTF/python-redfish-library
"""
import redfish
import json
from robot.libraries.BuiltIn import BuiltIn
class HTTPSBadRequestError(Exception):
r"""
BMC redfish generic raised method for error(s).
"""
pass
class bmc_redfish(object):
ROBOT_LIBRARY_SCOPE = "GLOBAL"
def __init__(self, hostname, username, password, *args, **kwargs):
r"""
Establish session connection to host.
Description of argument(s):
hostname The host name or IP address of the server.
username The username to be used to connect to the server.
password The password to be used to connect to the server.
args/kwargs Additional parms which are passed directly
to the redfish_client function.
"""
self._base_url_ = "https://" + hostname
self._username_ = username
self._password_ = password
self._default_prefix_ = "/redfish/v1"
def __enter__(self):
return self
def __exit__(self, exception_type, exception_value, traceback):
self._robj_.logout()
def login(self, *args, **kwargs):
r"""
Call the corresponding RestClientBase method and return the result.
Description of argument(s):
args/kwargs These are passed directly to the corresponding
RestClientBase method.
"""
for arg in args:
hostname = self._base_url_.strip("https://")
# Class object constructor reinitialized.
self.__init__(hostname=hostname,
username=arg['username'],
password=arg['password'])
self._robj_ = redfish.redfish_client(base_url=self._base_url_,
username=self._username_,
password=self._password_,
default_prefix=self._default_prefix_)
self._robj_.login(auth=redfish.AuthMethod.SESSION)
self._session_location_ = self._robj_.get_session_location()
def get(self, resource_path, *args, **kwargs):
r"""
Perform a GET request and return response.
Description of argument(s):
resource_path URI resource absolute path (e.g. "/redfish/v1/Systems/1").
args/kwargs These are passed directly to the corresponding
RestClientBase method.
"""
self._rest_response_ = self._robj_.get(resource_path, *args, **kwargs)
return self._rest_response_
def post(self, resource_path, *args, **kwargs):
r"""
Perform a POST request.
Description of argument(s):
resource_path URI resource relative path
(e.g. "Systems/1/Actions/ComputerSystem.Reset").
args/kwargs These are passed directly to the corresponding
RestClientBase method.
"""
self._rest_response_ = self._robj_.post('/redfish/v1/' + resource_path,
*args, **kwargs)
return self._rest_response_
def patch(self, resource_path, *args, **kwargs):
r"""
Perform a POST request.
Description of argument(s):
resource_path URI resource relative path
args/kwargs These are passed directly to the corresponding
RestClientBase method.
"""
self._rest_response_ = self._robj_.patch('/redfish/v1/' + resource_path,
*args, **kwargs)
return self._rest_response_
def put(self, resource_path, actions, attr_data):
r"""
Perform a PUT request.
Description of argument(s):
resource_path URI resource relative path.
args/kwargs These are passed directly to the corresponding
RestClientBase method.
"""
self._rest_response_ = self._robj_.put('/redfish/v1/' + resource_path,
*args, **kwargs)
return self._rest_response_
def delete(self, resource_path):
r"""
Perform a DELETE request.
Description of argument(s):
resource_path URI resource absoulute path
(e.g. "/redfish/v1/SessionService/Sessions/8d1a9wiiNL").
"""
self._rest_response_ = self._robj_.delete(resource_path)
return self._rest_response_
def logout(self):
r"""
Logout redfish connection session.
"""
self._robj_.logout()
def get_attribute(self, resource_path, attribute):
r"""
Perform a GET request and return attribute value.
Description of argument(s):
resource_path URI resource absolute path (e.g. "/redfish/v1/Systems/1").
attribute Property name (e.g. "PowerState").
"""
resp = self._robj_.get(resource_path)
if attribute in resp.dict:
return resp.dict[attribute]
return None
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 relative path (e.g. "Systems/1").
"""
global resource_list
resource_list = []
self._rest_response_ = self._robj_.get('/redfish/v1/' + resource_path)
# 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._robj_.get(resource)
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 relative path (e.g. "Systems/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:
self._rest_response_ = self._robj_.get(resource)
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)