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_attribute(self, resource_path, attribute):
21        r"""
22        Get resource attribute.
23
24        Description of argument(s):
25        resource_path    URI resource absolute path (e.g. "/redfish/v1/Systems/1").
26        attribute        Name of the attribute (e.g. 'PowerState').
27        """
28
29        resp = self._redfish_.get(resource_path)
30        if attribute in resp.dict:
31            return resp.dict[attribute]
32
33        return None
34
35    def get_properties(self, resource_path):
36        r"""
37        Returns dictionary of attributes for the resource.
38
39        Description of argument(s):
40        resource_path    URI resource absolute path (e.g. "/redfish/v1/Systems/1").
41        """
42
43        resp = self._redfish_.get(resource_path)
44        return resp.dict
45
46    def list_request(self, resource_path):
47        r"""
48        Perform a GET list request and return available resource paths.
49
50        Description of argument(s):
51        resource_path  URI resource absolute path
52                       (e.g. "/redfish/v1/SessionService/Sessions").
53        """
54
55        global resource_list
56        resource_list = []
57
58        self._rest_response_ = self._redfish_.get(resource_path)
59
60        # Return empty list.
61        if self._rest_response_.status != 200:
62            return resource_list
63
64        self.walk_nested_dict(self._rest_response_.dict)
65
66        if not resource_list:
67            return uri_path
68
69        for resource in resource_list:
70            self._rest_response_ = self._redfish_.get(resource)
71            if self._rest_response_.status != 200:
72                continue
73            self.walk_nested_dict(self._rest_response_.dict)
74
75        resource_list.sort()
76        return resource_list
77
78    def enumerate_request(self, resource_path):
79        r"""
80        Perform a GET enumerate request and return available resource paths.
81
82        Description of argument(s):
83        resource_path  URI resource absolute path
84                       (e.g. "/redfish/v1/SessionService/Sessions").
85        """
86
87        url_list = self.list_request(resource_path)
88
89        resource_dict = {}
90
91        # Return empty dict.
92        if not url_list:
93            return resource_dict
94
95        for resource in url_list:
96            # JsonSchemas data are not required in enumeration.
97            # Example: '/redfish/v1/JsonSchemas/' and sub resources.
98            if 'JsonSchemas' in resource:
99                continue
100            self._rest_response_ = self._redfish_.get(resource)
101            if self._rest_response_.status != 200:
102                continue
103            resource_dict[resource] = self._rest_response_.dict
104
105        return json.dumps(resource_dict, sort_keys=True,
106                          indent=4, separators=(',', ': '))
107
108    def walk_nested_dict(self, data):
109        r"""
110        Parse through the nested dictionary and get the resource id paths.
111
112        Description of argument(s):
113        data    Nested dictionary data from response message.
114        """
115
116        for key, value in data.items():
117            if isinstance(value, dict):
118                self.walk_nested_dict(value)
119            else:
120                if 'Members' == key:
121                    if isinstance(value, list):
122                        for index in value:
123                            if index['@odata.id'] not in resource_list:
124                                resource_list.append(index['@odata.id'])
125                if '@odata.id' == key:
126                    if value not in resource_list and not value.endswith('/'):
127                        resource_list.append(value)
128