Add HostWatchdogTimer attribute in redfish

Add HostWatchdogTimer attribute in redfish

Based on redfish spec, add HostWatchdogTimer property in
redfish/v1/Systems/system.

This object describes the Host Watchdog Timer functionality,
including FunctionEnabled, Status and TimeoutActionproperties:
"HostWatchdogTimer": {
        "FunctionEnabled": false,
        "Status": {
            "State": "Enabled"
        },
        "TimeoutAction": "None"
    }

Tested:
Validator checking for HostWatchdogTimer in below test cases:
  Set different timeout actions reset|poweroff|cycle|none:
  ipmitool mc watchdog set action=reset timeout=1000 int=msg use=oem
  Start watchdog: ipmitool mc watchdog reset

ComputerSystem.v1_5_0.ComputerSystem:HostWatchdogTimer
	value: OrderedDict([('FunctionEnabled', False),
	('Status', OrderedDict([('State', 'Enabled')])),
	('TimeoutAction', 'None')]) <class 'collections.OrderedDict'>
	has Type: ComputerSystem.v1_5_0.WatchdogTimer complex
	is Optional
	***going into Complex
ComputerSystem.v1_5_0.WatchdogTimer:FunctionEnabled
	value: False <class 'bool'>
	has Type: Edm.Boolean Edm.Boolean
	Mandatory Test: OK
	permission OData.Permission/ReadWrite
	Success
ComputerSystem.v1_5_0.WatchdogTimer:WarningAction
	value: n/a <class 'str'>
	has Type: ComputerSystem.v1_5_0.WatchdogWarningActions enum
	is Optional
	prop Does not exist, skip...
ComputerSystem.v1_5_0.WatchdogTimer:TimeoutAction
	value: None <class 'str'>
	has Type: ComputerSystem.v1_5_0.WatchdogTimeoutActions enum
	Mandatory Test: OK
	permission OData.Permission/ReadWrite
	Success
ComputerSystem.v1_5_0.WatchdogTimer:Status
	value: OrderedDict([('State', 'Enabled')])
	<class 'collections.OrderedDict'>
	has Type: Resource.Status complex
	is Optional
	***going into Complex
Resource.Status:State
	value: Enabled <class 'str'>
	has Type: Resource.State enum
	is Optional
	permission OData.Permission/Read
	Success

HostWatchdogTimer.FunctionEnabled                        PASS
HostWatchdogTimer.WarningAction                      Optional
HostWatchdogTimer.TimeoutAction                          PASS
HostWatchdogTimer.Status                             complex
HostWatchdogTimer.Status.State                           PASS

Watchdog service is stopped, no such property in redfish

Change-Id: I883e4b739a3fe525080ed486d2ca8e461fddf212
Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index b91296f..145537b 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -1158,6 +1158,106 @@
 }
 
 /**
+ * @brief Translates watchdog timeout action DBUS property value to redfish.
+ *
+ * @param[in] dbusAction    The watchdog timeout action in D-BUS.
+ *
+ * @return Returns as a string, the timeout action in Redfish terms. If
+ * translation cannot be done, returns an empty string.
+ */
+static std::string dbusToRfWatchdogAction(const std::string &dbusAction)
+{
+    if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
+    {
+        return "None";
+    }
+    else if (dbusAction ==
+             "xyz.openbmc_project.State.Watchdog.Action.HardReset")
+    {
+        return "ResetSystem";
+    }
+    else if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
+    {
+        return "PowerDown";
+    }
+    else if (dbusAction ==
+             "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
+    {
+        return "PowerCycle";
+    }
+
+    return "";
+}
+
+/**
+ * @brief Retrieves host watchdog timer properties over DBUS
+ *
+ * @param[in] aResp     Shared pointer for completing asynchronous calls.
+ *
+ * @return None.
+ */
+void getHostWatchdogTimer(std::shared_ptr<AsyncResp> aResp)
+{
+    BMCWEB_LOG_DEBUG << "Get host watchodg";
+    crow::connections::systemBus->async_method_call(
+        [aResp](const boost::system::error_code ec,
+                PropertiesType &properties) {
+            if (ec)
+            {
+                // watchdog service is stopped
+                BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+                return;
+            }
+
+            BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
+
+            nlohmann::json &hostWatchdogTimer =
+                aResp->res.jsonValue["HostWatchdogTimer"];
+
+            // watchdog service is running/enabled
+            hostWatchdogTimer["Status"]["State"] = "Enabled";
+
+            for (const auto &property : properties)
+            {
+                BMCWEB_LOG_DEBUG << "prop=" << property.first;
+                if (property.first == "Enabled")
+                {
+                    const bool *state = std::get_if<bool>(&property.second);
+
+                    if (!state)
+                    {
+                        messages::internalError(aResp->res);
+                        continue;
+                    }
+
+                    hostWatchdogTimer["FunctionEnabled"] = *state;
+                }
+                else if (property.first == "ExpireAction")
+                {
+                    const std::string *s =
+                        std::get_if<std::string>(&property.second);
+                    if (!s)
+                    {
+                        messages::internalError(aResp->res);
+                        continue;
+                    }
+
+                    std::string action = dbusToRfWatchdogAction(*s);
+                    if (action.empty())
+                    {
+                        messages::internalError(aResp->res);
+                        continue;
+                    }
+                    hostWatchdogTimer["TimeoutAction"] = action;
+                }
+            }
+        },
+        "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
+        "org.freedesktop.DBus.Properties", "GetAll",
+        "xyz.openbmc_project.State.Watchdog");
+}
+
+/**
  * SystemsCollection derived class for delivering ComputerSystems Collection
  * Schema
  */
@@ -1472,6 +1572,7 @@
         getHostState(asyncResp);
         getBootProperties(asyncResp);
         getPCIeDeviceList(asyncResp);
+        getHostWatchdogTimer(asyncResp);
     }
 
     void doPatch(crow::Response &res, const crow::Request &req,