Redfish: Set AutomaticRetry (AutoReboot)

"AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways, and
RetryAttempts. OpenBMC only supports Disabled and RetryAttempts.
Use AllowableValues to show this.

"AutomaticRetryAttempts" is hardcoded in OpenBMC.
"RemainingAutomaticRetryAttempts" is readonly in Redfish.

Tested: Validator passes.
        PATCHing "Boot" "BootSourceOverrideEnabled" and
        "BootSourceOverrideTarget" still work.

curl -k https://$bmc/redfish/v1/Systems/system
...
  "Boot": {
    "AutomaticRetryAttempts": 3,
    "AutomaticRetryConfig": "RetryAttempts",
    "AutomaticRetryConfig@Redfish.AllowableValues": [
      "Disabled",
      "RetryAttempts"
    ],

Can see the following two set correctly on Redfish and D-Bus:
curl -k -v  -X PATCH https://${bmc}/redfish/v1/Systems/system -d \
'{"Boot":{"AutomaticRetryConfig": "Disabled"}}'
...
< HTTP/1.1 204 No Content

curl -k -v  -X PATCH https://${bmc}/redfish/v1/Systems/system -d \
'{"Boot":{"AutomaticRetryConfig": "RetryAttempts"}}'
...
< HTTP/1.1 204 No Content

Handles bad data:
curl -k -v  -X PATCH https://${bmc}/redfish/v1/Systems/system -d \
'{"Boot":{"AutomaticRetryConfig": "BadValue"}}'
...

< HTTP/1.1 400 Bad Request
...
  "AutomaticRetryConfig@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_0_0.Message",
      "Message": "The value BadValue for the property AutomaticRetryConfig is not in the list of acceptable values.",
      "MessageArgs": [
        "BadValue",
        "AutomaticRetryConfig"
      ],
      "MessageId": "Base.1.4.0.PropertyValueNotInList",

Change-Id: I603ccce1a682ac40f2e496cba9172e2a6dfdb58d
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 628c51a..338bdc3 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -993,6 +993,13 @@
             // Not on D-Bus. Hardcoded here:
             // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
             aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
+
+            // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
+            // and RetryAttempts. OpenBMC only supports Disabled and
+            // RetryAttempts.
+            aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
+                                         "AllowableValues"] = {"Disabled",
+                                                               "RetryAttempts"};
         },
         "xyz.openbmc_project.Settings",
         "/xyz/openbmc_project/control/host0/auto_reboot",
@@ -1187,9 +1194,9 @@
  *
  * @return Integer error code.
  */
-static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
-                              std::optional<std::string> bootSource,
-                              std::optional<std::string> bootEnable)
+static void setBootSourceProperties(std::shared_ptr<AsyncResp> aResp,
+                                    std::optional<std::string> bootSource,
+                                    std::optional<std::string> bootEnable)
 {
     BMCWEB_LOG_DEBUG << "Set boot information.";
 
@@ -1224,6 +1231,55 @@
 }
 
 /**
+ * @brief Sets automaticRetry (Auto Reboot)
+ *
+ * @param[in] aResp   Shared pointer for generating response message.
+ * @param[in] automaticRetryConfig  "AutomaticRetryConfig" from request.
+ *
+ * @return None.
+ */
+static void setAutomaticRetry(std::shared_ptr<AsyncResp> aResp,
+                              const std::string &&automaticRetryConfig)
+{
+    BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
+
+    // OpenBMC only supports "Disabled" and "RetryAttempts".
+    bool autoRebootEnabled;
+
+    if (automaticRetryConfig == "Disabled")
+    {
+        autoRebootEnabled = false;
+    }
+    else if (automaticRetryConfig == "RetryAttempts")
+    {
+        autoRebootEnabled = true;
+    }
+    else
+    {
+        BMCWEB_LOG_DEBUG << "Invalid property value for "
+                            "AutomaticRetryConfig: "
+                         << automaticRetryConfig;
+        messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
+                                         "AutomaticRetryConfig");
+        return;
+    }
+
+    crow::connections::systemBus->async_method_call(
+        [aResp](const boost::system::error_code ec) {
+            if (ec)
+            {
+                messages::internalError(aResp->res);
+                return;
+            }
+        },
+        "xyz.openbmc_project.Settings",
+        "/xyz/openbmc_project/control/host0/auto_reboot",
+        "org.freedesktop.DBus.Properties", "Set",
+        "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
+        std::variant<bool>(autoRebootEnabled));
+}
+
+/**
  * @brief Sets power restore policy properties.
  *
  * @param[in] aResp   Shared pointer for generating response message.
@@ -1899,15 +1955,24 @@
         {
             std::optional<std::string> bootSource;
             std::optional<std::string> bootEnable;
+            std::optional<std::string> automaticRetryConfig;
 
-            if (!json_util::readJson(*bootProps, asyncResp->res,
-                                     "BootSourceOverrideTarget", bootSource,
-                                     "BootSourceOverrideEnabled", bootEnable))
+            if (!json_util::readJson(
+                    *bootProps, asyncResp->res, "BootSourceOverrideTarget",
+                    bootSource, "BootSourceOverrideEnabled", bootEnable,
+                    "AutomaticRetryConfig", automaticRetryConfig))
             {
                 return;
             }
-            setBootProperties(asyncResp, std::move(bootSource),
-                              std::move(bootEnable));
+            if (bootSource || bootEnable)
+            {
+                setBootSourceProperties(asyncResp, std::move(bootSource),
+                                        std::move(bootEnable));
+            }
+            if (automaticRetryConfig)
+            {
+                setAutomaticRetry(asyncResp, std::move(*automaticRetryConfig));
+            }
         }
 
         if (indicatorLed)