Find valid target entries from the redfish resource dictionary

Changes:
    - Added get target actions function.
    - Added function to recursive walk the nested dictionary.

Resolves  openbmc/openbmc-test-automation#1649

Change-Id: I45fb2d9d9bcd15c5b740e97435686e790261742b
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
diff --git a/lib/bmc_redfish_utils.py b/lib/bmc_redfish_utils.py
index daa09e1..492a1a3 100644
--- a/lib/bmc_redfish_utils.py
+++ b/lib/bmc_redfish_utils.py
@@ -58,6 +58,48 @@
         resp = self._redfish_.get(resource_path)
         return resp.dict
 
+    def get_target_actions(self, resource_path, target_attribute):
+        r"""
+        Returns resource target entry of the searched target attribute.
+
+        Description of argument(s):
+        resource_path      URI resource absolute path
+                           (e.g. "/redfish/v1/Systems/system").
+        target_attribute   Name of the attribute (e.g. 'ComputerSystem.Reset').
+
+        Example:
+         "Actions": {
+         "#ComputerSystem.Reset": {
+          "ResetType@Redfish.AllowableValues": [
+            "On",
+            "ForceOff",
+            "GracefulRestart",
+            "GracefulShutdown"
+          ],
+          "target": "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"
+          }
+         }
+        """
+
+        global target_list
+        target_list = []
+
+        resp_dict = self.get_attribute(resource_path, "Actions")
+        if resp_dict is None:
+            return None
+
+        # Recursively search the "target" key in the nested dictionary.
+        # Populate the target_list of target entries.
+        self.get_key_value_nested_dict(resp_dict, "target")
+
+        # Return the matching target URL entry.
+        for target in target_list:
+            # target "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"
+            if target_attribute in target:
+                return target
+
+        return None
+
     def list_request(self, resource_path):
         r"""
         Perform a GET list request and return available resource paths.
@@ -140,3 +182,19 @@
                 if '@odata.id' == key:
                     if value not in resource_list and not value.endswith('/'):
                         resource_list.append(value)
+
+    def get_key_value_nested_dict(self, data, key):
+        r"""
+        Parse through the nested dictionary and get the searched key value.
+
+        Description of argument(s):
+        data    Nested dictionary data from response message.
+        key     Search dictionary key element.
+        """
+
+        for k, v in data.items():
+            if isinstance(v, dict):
+                self.get_key_value_nested_dict(v, key)
+
+            if k == key:
+                target_list.append(v)