Systems: Update LocationIndicatorActive property

Modify get/set of LocationIndicatorActive property for Systems to use
identifying association instead of hard-coding led group.[1]

History: Almost 5 years ago IBM added support for this property to the
Systems.[2] That original implementation assumed the system and chassis
shared the same LED and just looked at the enclosure_identify_blink and
enclosure_identify like the existing IndicatorLED property did.

IBM renamed these functions getSystemLocationIndicatorActive and
setSystemLocationIndicatorActive.[3]

The interest from other companies has mostly been around IndicatorLED
(old deprecated LED property).[4]

Today, LEDs have the association documented above and used elsewhere
like PowerSupplies, Fans, etc. Switching to this association: 1) follows
the design 2) allows multiple chassis support 3) doesn't assume your
system led is your chassis led.

This is the last caller of the getSystemLocationIndicatorActive() and
setSystemLocationIndicatorActive() functions so they are being removed.

[1] https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/58299
[2] https://gerrit.openbmc.org/c/openbmc/bmcweb/+/36886
[3] https://gerrit.openbmc.org/c/openbmc/bmcweb/+/57765
[4] https://gerrit.openbmc.org/c/openbmc/bmcweb/+/27301

Tested:
 - Redfish Service Validator passes
 - Confirm able to set and get LED

1. Get for Systems
```
curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Systems/system
{
{
  "@odata.id": "/redfish/v1/Systems/system",
  "@odata.type": "#ComputerSystem.v1_22_0.ComputerSystem",
  ...
  "LocationIndicatorActive": false,
  ...
}
```

2. Set for Systems
```
curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X PATCH -d '{"LocationIndicatorActive": true}' https://${bmc}/redfish/v1/Systems/system

curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Systems/system
{
  "@odata.id": "/redfish/v1/Systems/system",
  "@odata.type": "#ComputerSystem.v1_22_0.ComputerSystem",
  ...
  "LocationIndicatorActive": true,
  ...
}
```
Change-Id: I1c06621586148d4b299b1f8e1ee1fb0ccdc51f10
Signed-off-by: George Liu <liuxiwei@inspur.com>
Signed-off-by: Janet Adkins <janeta@us.ibm.com>
Co-authored-by: George Liu <liuxiwei@inspur.com>
diff --git a/redfish-core/include/utils/systems_utils.hpp b/redfish-core/include/utils/systems_utils.hpp
index 4f61490..2d510d5 100644
--- a/redfish-core/include/utils/systems_utils.hpp
+++ b/redfish-core/include/utils/systems_utils.hpp
@@ -258,4 +258,62 @@
 
     return chassisStateService;
 }
+
+namespace systems_utils
+{
+
+inline void afterGetValidSystemsPath(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& systemId,
+    const std::function<void(const std::optional<std::string>&)>& callback,
+    const boost::system::error_code& ec,
+    const dbus::utility::MapperGetSubTreePathsResponse& systemsPaths)
+{
+    if (ec)
+    {
+        if (ec == boost::system::errc::io_error)
+        {
+            BMCWEB_LOG_DEBUG("No systems found");
+            callback(std::nullopt);
+            return;
+        }
+        BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value());
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    for (const std::string& system : systemsPaths)
+    {
+        sdbusplus::message::object_path path(system);
+        if (path.filename() == systemId)
+        {
+            callback(path);
+            return;
+        }
+    }
+    BMCWEB_LOG_DEBUG("No system named {} found", systemId);
+    callback(std::nullopt);
+}
+
+inline void getValidSystemsPath(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& systemId,
+    std::function<void(const std::optional<std::string>&)>&& callback)
+{
+    BMCWEB_LOG_DEBUG("Get path for {}", systemId);
+
+    constexpr std::array<std::string_view, 2> interfaces = {
+        "xyz.openbmc_project.Inventory.Decorator.ManagedHost",
+        "xyz.openbmc_project.Inventory.Item.System"};
+    dbus::utility::getSubTreePaths(
+        "/xyz/openbmc_project/inventory", 0, interfaces,
+        [asyncResp, systemId, callback{std::move(callback)}](
+            const boost::system::error_code& ec,
+            const dbus::utility::MapperGetSubTreePathsResponse& systemsPaths) {
+            afterGetValidSystemsPath(asyncResp, systemId, callback, ec,
+                                     systemsPaths);
+        });
+}
+
+} // namespace systems_utils
 } // namespace redfish
diff --git a/redfish-core/lib/led.hpp b/redfish-core/lib/led.hpp
index b74dc4d..32e9725 100644
--- a/redfish-core/lib/led.hpp
+++ b/redfish-core/lib/led.hpp
@@ -153,96 +153,6 @@
         });
 }
 
-/**
- * @brief Retrieves identify system led group properties over dbus
- *
- * @param[in] asyncResp     Shared pointer for generating response message.
- *
- * @return None.
- */
-inline void getSystemLocationIndicatorActive(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
-    BMCWEB_LOG_DEBUG("Get LocationIndicatorActive");
-    dbus::utility::getProperty<bool>(
-        "xyz.openbmc_project.LED.GroupManager",
-        "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
-        "xyz.openbmc_project.Led.Group", "Asserted",
-        [asyncResp](const boost::system::error_code& ec, const bool blinking) {
-            // Some systems may not have enclosure_identify_blink object so
-            // proceed to get enclosure_identify state.
-            if (ec == boost::system::errc::invalid_argument)
-            {
-                BMCWEB_LOG_DEBUG(
-                    "Get identity blinking LED failed, mismatch in property type");
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            // Blinking ON, no need to check enclosure_identify assert.
-            if (!ec && blinking)
-            {
-                asyncResp->res.jsonValue["LocationIndicatorActive"] = true;
-                return;
-            }
-
-            dbus::utility::getProperty<bool>(
-                "xyz.openbmc_project.LED.GroupManager",
-                "/xyz/openbmc_project/led/groups/enclosure_identify",
-                "xyz.openbmc_project.Led.Group", "Asserted",
-                [asyncResp](const boost::system::error_code& ec2,
-                            const bool ledOn) {
-                    if (ec2 == boost::system::errc::invalid_argument)
-                    {
-                        BMCWEB_LOG_DEBUG(
-                            "Get enclosure identity led failed, mismatch in property type");
-                        messages::internalError(asyncResp->res);
-                        return;
-                    }
-
-                    if (ec2)
-                    {
-                        return;
-                    }
-
-                    asyncResp->res.jsonValue["LocationIndicatorActive"] = ledOn;
-                });
-        });
-}
-
-/**
- * @brief Sets identify system led group properties
- *
- * @param[in] asyncResp     Shared pointer for generating response message.
- * @param[in] ledState  LED state passed from request
- *
- * @return None.
- */
-inline void setSystemLocationIndicatorActive(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool ledState)
-{
-    BMCWEB_LOG_DEBUG("Set LocationIndicatorActive");
-
-    sdbusplus::asio::setProperty(
-        *crow::connections::systemBus, "xyz.openbmc_project.LED.GroupManager",
-        "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
-        "xyz.openbmc_project.Led.Group", "Asserted", ledState,
-        [asyncResp, ledState](const boost::system::error_code& ec) {
-            if (ec)
-            {
-                // Some systems may not have enclosure_identify_blink object so
-                // lets set enclosure_identify state also if
-                // enclosure_identify_blink failed
-                setDbusProperty(
-                    asyncResp, "LocationIndicatorActive",
-                    "xyz.openbmc_project.LED.GroupManager",
-                    sdbusplus::message::object_path(
-                        "/xyz/openbmc_project/led/groups/enclosure_identify"),
-                    "xyz.openbmc_project.Led.Group", "Asserted", ledState);
-            }
-        });
-}
-
 inline void handleLedGroupSubtree(
     const std::string& objPath, const boost::system::error_code& ec,
     const dbus::utility::MapperGetSubTreeResponse& subtree,
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 2be5dde..e006b9a 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -3114,7 +3114,16 @@
             aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
         });
 
-    getSystemLocationIndicatorActive(asyncResp);
+    systems_utils::getValidSystemsPath(
+        asyncResp, systemName,
+        [asyncResp,
+         systemName](const std::optional<std::string>& validSystemsPath) {
+            if (validSystemsPath)
+            {
+                getLocationIndicatorActive(asyncResp, *validSystemsPath);
+            }
+        });
+
     // TODO (Gunnar): Remove IndicatorLED after enough time has passed
     getIndicatorLedState(asyncResp);
     getComputerSystem(asyncResp);
@@ -3248,7 +3257,20 @@
 
     if (locationIndicatorActive)
     {
-        setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
+        systems_utils::getValidSystemsPath(
+            asyncResp, systemName,
+            [asyncResp, systemName,
+             locationIndicatorActive{*locationIndicatorActive}](
+                const std::optional<std::string>& validSystemsPath) {
+                if (!validSystemsPath)
+                {
+                    messages::resourceNotFound(asyncResp->res, "Systems",
+                                               systemName);
+                    return;
+                }
+                setLocationIndicatorActive(asyncResp, *validSystemsPath,
+                                           locationIndicatorActive);
+            });
     }
 
     // TODO (Gunnar): Remove IndicatorLED after enough time has