Manager:Add ForceRestart to ResetType

Add ForceRestart in Action/#Manager.Reset/ResetType@AllowableValues,
as it is a mandatory parameter in the OCP Redfish Profile v1.0.

Tested:
1. Verified redfish validator passed
2. Verified details from Redfish
GET: https://<BMC-IP>/redfish/v1/Managers/bmc/ResetActionInfo
Response:
{
  "@odata.id": "/redfish/v1/Managers/bmc/ResetActionInfo",
  "@odata.type": "#ActionInfo.v1_1_2.ActionInfo",
  "Id": "ResetActionInfo",
  "Name": "Reset Action Info",
  "Parameters": [
    {
      "AllowableValues": [
        "GracefulRestart",
        "ForceRestart"
      ],
      "DataType": "String",
      "Name": "ResetType",
      "Required": true
    }
  ]
}

Case 1: ForceRestart:
POST: https://<BMC-IP>/redfish/v1/Managers/bmc/Actions/Manager.Reset
Body:
{
  "ResetType": "ForceRestart"
}
Response:
{
  "@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_0_0.Message",
      "Message": "Successfully Completed Request",
      "MessageArgs": [],
      "MessageId": "Base.1.4.0.Success",
      "Resolution": "None",
      "Severity": "OK"
    }
  ]
}
Case 2: GracefulRestart:
POST: https://<BMC-IP>/redfish/v1/Managers/bmc/Actions/Manager.Reset
Body:
{
  "ResetType": "GracefulRestart"
}
Response: Success

Case 3: Negative test case
POST: https://<BMC-IP>/redfish/v1/Managers/bmc/Actions/Manager.Reset
Body:
{
  "ResetType": "Test1"
}
Response:
{
  "error": {
    "@Message.ExtendedInfo": [
      {
        "@odata.type": "#Message.v1_0_0.Message",
        "Message": "The parameter Test1 for the action ResetType is not
                    supported on the target resource.",
        "MessageArgs": [
          "Test1",
          "ResetType"
        ],
        "MessageId": "Base.1.4.0.ActionParameterNotSupported",
        "Resolution": "Remove the parameter supplied and resubmit the
                       request if the operation failed.",
        "Severity": "Warning"
      }
    "code": "Base.1.4.0.ActionParameterNotSupported",
    "message": "The parameter Test1 for the action ResetType is not
                supported on the target resource."
  }
}

Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Change-Id: I84f4942ddabc564a267d7db8e582ad8c11b5399b
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 56abdcf..1d13cd3 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -66,6 +66,34 @@
         interfaceName, destProperty, dbusPropertyValue);
 }
 
+void doBMCForceRestart(std::shared_ptr<AsyncResp> asyncResp)
+{
+    const char* processName = "xyz.openbmc_project.State.BMC";
+    const char* objectPath = "/xyz/openbmc_project/state/bmc0";
+    const char* interfaceName = "xyz.openbmc_project.State.BMC";
+    const std::string& propertyValue =
+        "xyz.openbmc_project.State.BMC.Transition.HardReboot";
+    const char* destProperty = "RequestedBMCTransition";
+
+    // Create the D-Bus variant for D-Bus call.
+    VariantType dbusPropertyValue(propertyValue);
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp](const boost::system::error_code ec) {
+            // Use "Set" method to set the property value.
+            if (ec)
+            {
+                BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
+                messages::internalError(asyncResp->res);
+                return;
+            }
+
+            messages::success(asyncResp->res);
+        },
+        processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
+        interfaceName, destProperty, dbusPropertyValue);
+}
+
 /**
  * ManagerResetAction class supports the POST method for the Reset (reboot)
  * action.
@@ -84,7 +112,7 @@
     /**
      * Function handles POST method request.
      * Analyzes POST body before sending Reset (Reboot) request data to D-Bus.
-     * OpenBMC only supports ResetType "GracefulRestart".
+     * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart".
      */
     void doPost(crow::Response& res, const crow::Request& req,
                 const std::vector<std::string>&) override
@@ -99,7 +127,19 @@
             return;
         }
 
-        if (resetType != "GracefulRestart")
+        if (resetType == "GracefulRestart")
+        {
+            BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
+            doBMCGracefulRestart(asyncResp);
+            return;
+        }
+        else if (resetType == "ForceRestart")
+        {
+            BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
+            doBMCForceRestart(asyncResp);
+            return;
+        }
+        else
         {
             BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
                              << resetType;
@@ -108,7 +148,6 @@
 
             return;
         }
-        doBMCGracefulRestart(asyncResp);
     }
 };
 
@@ -222,7 +261,7 @@
              {{{"Name", "ResetType"},
                {"Required", true},
                {"DataType", "String"},
-               {"AllowableValues", {"GracefulRestart"}}}}}};
+               {"AllowableValues", {"GracefulRestart", "ForceRestart"}}}}}};
         res.end();
     }
 };