Redfish: Manager: ResetToDefault

ResetToDefaults, called factory reset in OpenBMC, was added in
2020.1.

Calls BMC code updater factory reset since BMC code updater factory
reset wipes the whole BMC read-write filesystem which includes things
like the network settings.

OpenBMC only supports ResetToDefaultsType "ResetAll".

Depends on
https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-bmc-code-mgmt/+/32989

Tested: Along with 32989, validator passes and was able to
        factory reset.

curl -k https://$bmc/redfish/v1/Managers/bmc
{
  "@odata.id": "/redfish/v1/Managers/bmc",
  "@odata.type": "#Manager.v1_8_0.Manager",
  "Actions": {
    "#Manager.Reset": {
      "ResetType@Redfish.AllowableValues": [
        "GracefulRestart"
      ],
      "target": "/redfish/v1/Managers/bmc/Actions/Manager.Reset"
    },
    "#Manager.ResetToDefaults": {
      "ResetType@Redfish.AllowableValues": [
        "ResetAll"
      ],
      "target": "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults"
    }
  },
...

curl -k -X POST \
https://${bmc}/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults \
-d '{"ResetToDefaultsType": "ResetAll"}'
{
  "@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_0_0.Message",
      "Message": "Successfully Completed Request",
      "MessageArgs": [],
      "MessageId": "Base.1.4.0.Success",
      "Resolution": "None",
      "Severity": "OK"
    }
  ]
}

Change-Id: Ia830fd05dc15fd6311f84dff191a3718c645c040
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 92245aa..19cd0b8 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -75,6 +75,7 @@
         nodes.emplace_back(std::make_unique<ManagerCollection>(app));
         nodes.emplace_back(std::make_unique<Manager>(app));
         nodes.emplace_back(std::make_unique<ManagerResetAction>(app));
+        nodes.emplace_back(std::make_unique<ManagerResetToDefaultsAction>(app));
         nodes.emplace_back(std::make_unique<Power>(app));
         nodes.emplace_back(std::make_unique<ChassisCollection>(app));
         nodes.emplace_back(std::make_unique<Chassis>(app));
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 65de109..8a74ed2 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -110,6 +110,78 @@
     }
 };
 
+/**
+ * ManagerResetToDefaultsAction class supports POST method for factory reset
+ * action.
+ */
+class ManagerResetToDefaultsAction : public Node
+{
+  public:
+    ManagerResetToDefaultsAction(CrowApp& app) :
+        Node(app, "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults/")
+    {
+        entityPrivileges = {
+            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+    }
+
+  private:
+    /**
+     * Function handles ResetToDefaults POST method request.
+     *
+     * Analyzes POST body message and factory resets BMC by calling
+     * BMC code updater factory reset followed by a BMC reboot.
+     *
+     * BMC code updater factory reset wipes the whole BMC read-write
+     * filesystem which includes things like the network settings.
+     *
+     * OpenBMC only supports ResetToDefaultsType "ResetAll".
+     */
+    void doPost(crow::Response& res, const crow::Request& req,
+                const std::vector<std::string>& params) override
+    {
+        BMCWEB_LOG_DEBUG << "Post ResetToDefaults.";
+
+        std::string resetType;
+        auto asyncResp = std::make_shared<AsyncResp>(res);
+
+        if (!json_util::readJson(req, asyncResp->res, "ResetToDefaultsType",
+                                 resetType))
+        {
+            BMCWEB_LOG_DEBUG << "Missing property ResetToDefaultsType.";
+
+            messages::actionParameterMissing(asyncResp->res, "ResetToDefaults",
+                                             "ResetToDefaultsType");
+            return;
+        }
+
+        if (resetType != "ResetAll")
+        {
+            BMCWEB_LOG_DEBUG << "Invalid property value for "
+                                "ResetToDefaultsType: "
+                             << resetType;
+            messages::actionParameterNotSupported(asyncResp->res, resetType,
+                                                  "ResetToDefaultsType");
+            return;
+        }
+
+        crow::connections::systemBus->async_method_call(
+            [asyncResp](const boost::system::error_code ec) {
+                if (ec)
+                {
+                    BMCWEB_LOG_DEBUG << "Failed to ResetToDefaults: " << ec;
+                    messages::internalError(asyncResp->res);
+                    return;
+                }
+                // Factory Reset doesn't actually happen until a reboot
+                // Can't erase what the BMC is running on
+                doBMCGracefulRestart(asyncResp);
+            },
+            "xyz.openbmc_project.Software.BMC.Updater",
+            "/xyz/openbmc_project/software",
+            "xyz.openbmc_project.Common.FactoryReset", "Reset");
+    }
+};
+
 static constexpr const char* objectManagerIface =
     "org.freedesktop.DBus.ObjectManager";
 static constexpr const char* pidConfigurationIface =
@@ -1561,7 +1633,7 @@
                const std::vector<std::string>& params) override
     {
         res.jsonValue["@odata.id"] = "/redfish/v1/Managers/bmc";
-        res.jsonValue["@odata.type"] = "#Manager.v1_3_0.Manager";
+        res.jsonValue["@odata.type"] = "#Manager.v1_8_0.Manager";
         res.jsonValue["Id"] = "bmc";
         res.jsonValue["Name"] = "OpenBmc Manager";
         res.jsonValue["Description"] = "Baseboard Management Controller";
@@ -1604,6 +1676,15 @@
             "/redfish/v1/Managers/bmc/Actions/Manager.Reset";
         managerReset["ResetType@Redfish.AllowableValues"] = {"GracefulRestart"};
 
+        // ResetToDefaults (Factory Reset) has values like
+        // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
+        // on OpenBMC
+        nlohmann::json& resetToDefaults =
+            res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
+        resetToDefaults["target"] =
+            "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults";
+        resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"};
+
         res.jsonValue["DateTime"] = crow::utility::dateTimeNow();
 
         // Fill in SerialConsole info