Add LocationIndicatorActive for fabric adapters

This adds the GET and PATCH support for LocationIndicatorActive
to fabric adapters.

Tested:
- GET

```
curl -k -H "X-Auth-Token: $token" -X  GET \
     https://${bmc}/redfish/v1/Systems/system/FabricAdapters/disk_backplane0
```

- PATCH and GET

```
curl -k -H "Content-Type: application/json" -X  PATCH -d '{"LocationIndicatorActive":true}' \
     https://${bmc}/redfish/v1/Systems/system/FabricAdapters/disk_backplane0

curl -k -H "X-Auth-Token: $token" -X  GET \
     https://${bmc}/redfish/v1/Systems/system/FabricAdapters/disk_backplane0

```

Change-Id: I02349b68bbc23ffd98b195bc399a25f94790bc55
Signed-off-by: Jim Allen <jpallen@us.ibm.com>
Signed-off-by: Myung Bae <myungbae@us.ibm.com>
diff --git a/Redfish.md b/Redfish.md
index 1f7d79e..0a49af2 100644
--- a/Redfish.md
+++ b/Redfish.md
@@ -843,6 +843,7 @@
 #### FabricAdapter
 
 - Location
+- LocationIndicatorActive
 - Model
 - PartNumber
 - SerialNumber
diff --git a/redfish-core/lib/fabric_adapters.hpp b/redfish-core/lib/fabric_adapters.hpp
index acd6d8f..52213c7 100644
--- a/redfish-core/lib/fabric_adapters.hpp
+++ b/redfish-core/lib/fabric_adapters.hpp
@@ -10,11 +10,13 @@
 #include "error_messages.hpp"
 #include "generated/enums/resource.hpp"
 #include "http_request.hpp"
+#include "led.hpp"
 #include "logging.hpp"
 #include "query.hpp"
 #include "registries/privilege_registry.hpp"
 #include "utils/collection.hpp"
 #include "utils/dbus_utils.hpp"
+#include "utils/json_utils.hpp"
 
 #include <asm-generic/errno.h>
 
@@ -27,6 +29,7 @@
 #include <array>
 #include <functional>
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <utility>
@@ -192,6 +195,7 @@
     getFabricAdapterAsset(asyncResp, serviceName, fabricAdapterPath);
     getFabricAdapterState(asyncResp, serviceName, fabricAdapterPath);
     getFabricAdapterHealth(asyncResp, serviceName, fabricAdapterPath);
+    getLocationIndicatorActive(asyncResp, fabricAdapterPath);
 }
 
 inline void afterGetValidFabricAdapterPath(
@@ -293,6 +297,76 @@
                                    systemName, adapterId));
 }
 
+inline void afterHandleFabricAdapterPatch(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& adapterId, std::optional<bool> locationIndicatorActive,
+    const boost::system::error_code& ec, const std::string& fabricAdapterPath,
+    const std::string& serviceName)
+{
+    if (ec)
+    {
+        if (ec.value() == boost::system::errc::io_error)
+        {
+            messages::resourceNotFound(asyncResp->res, "FabricAdapter",
+                                       adapterId);
+            return;
+        }
+
+        BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value());
+        messages::internalError(asyncResp->res);
+        return;
+    }
+    if (fabricAdapterPath.empty() || serviceName.empty())
+    {
+        BMCWEB_LOG_WARNING("Adapter {} not found", adapterId);
+        messages::resourceNotFound(asyncResp->res, "FabricAdapter", adapterId);
+        return;
+    }
+
+    if (locationIndicatorActive)
+    {
+        setLocationIndicatorActive(asyncResp, fabricAdapterPath,
+                                   *locationIndicatorActive);
+    }
+}
+
+inline void handleFabricAdapterPatch(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& systemName, const std::string& adapterId)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+    {
+        // Option currently returns no systems.  TBD
+        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                   systemName);
+        return;
+    }
+    if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                   systemName);
+        return;
+    }
+
+    std::optional<bool> locationIndicatorActive;
+
+    if (!json_util::readJsonPatch(req, asyncResp->res,
+                                  "LocationIndicatorActive",
+                                  locationIndicatorActive))
+    {
+        return;
+    }
+
+    getValidFabricAdapterPath(
+        adapterId, std::bind_front(afterHandleFabricAdapterPatch, asyncResp,
+                                   adapterId, locationIndicatorActive));
+}
+
 inline void handleFabricAdapterCollectionGet(
     crow::App& app, const crow::Request& req,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -442,5 +516,10 @@
         .privileges(redfish::privileges::headFabricAdapter)
         .methods(boost::beast::http::verb::head)(
             std::bind_front(handleFabricAdapterHead, std::ref(app)));
+
+    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
+        .privileges(redfish::privileges::patchFabricAdapter)
+        .methods(boost::beast::http::verb::patch)(
+            std::bind_front(handleFabricAdapterPatch, std::ref(app)));
 }
 } // namespace redfish