health: Add option to disable health-populate

The Health populate calls GetManagedObjects at `/` which can take a lot
of time. Add the option to disable to improve performance if it is not
needed.

Tested:
```
$  meson build -Dhealth-populate=disabled
...
 User defined options
    backend                               : ninja
    health-populate                       : disabled
```

Build passed.

Health Status removed. Some resource still create HealthPopulate, but
does not populate. It will require further refactoring to clean it out.

Testing on `/redfish/v1/Chassis?$expand=.($levels=1)`

On 14 chassis, from about 2.5 seconds to 400 ms. :)

Before:
```
Getting times for chassis
Getting good line count with wget -q -O- localhost:80/redfish/v1/Chassis?$expand=.($levels=1)
Line count: 980
17:05:56: real 0m2.908s user 0m0.000s sys 0m0.030s
17:05:59: real 0m2.414s user 0m0.010s sys 0m0.010s
17:05:03: real 0m3.410s user 0m0.000s sys 0m0.020s
17:05:09: real 0m2.372s user 0m0.000s sys 0m0.010s
17:05:13: real 0m3.407s user 0m0.010s sys 0m0.000s
17:05:19: real 0m2.420s user 0m0.010s sys 0m0.000s
17:05:23: real 0m3.463s user 0m0.010s sys 0m0.000s
17:05:29: real 0m2.414s user 0m0.000s sys 0m0.010s
17:05:33: real 0m2.843s user 0m0.010s sys 0m0.010s
17:05:38: real 0m2.512s user 0m0.000s sys 0m0.020s
17:05:42: real 0m2.474s user 0m0.000s sys 0m0.010s
17:05:47: real 0m2.557s user 0m0.010s sys 0m0.010s
17:05:52: real 0m2.439s user 0m0.020s sys 0m0.000s
17:05:56: real 0m3.127s user 0m0.010s sys 0m0.000s
17:05:01: real 0m2.563s user 0m0.020s sys 0m0.000s
17:05:06: real 0m2.392s user 0m0.020s sys 0m0.020s
17:05:10: real 0m2.405s user 0m0.020s sys 0m0.000s
17:05:15: real 0m2.514s user 0m0.010s sys 0m0.010s
17:05:19: real 0m2.809s user 0m0.020s sys 0m0.010s
17:05:24: real 0m2.944s user 0m0.010s sys 0m0.010s
17:05:29: real 0m2.537s user 0m0.010s sys 0m0.000s
17:05:34: real 0m3.290s user 0m0.000s sys 0m0.000s
17:05:39: real 0m2.601s user 0m0.040s sys 0m0.000s
17:05:43: real 0m2.398s user 0m0.010s sys 0m0.040s
17:05:48: real 0m2.664s user 0m0.000s sys 0m0.020s
17:05:53: real 0m2.323s user 0m0.010s sys 0m0.000s
17:05:57: real 0m3.033s user 0m0.000s sys 0m0.010s
17:05:02: real 0m3.243s user 0m0.000s sys 0m0.010s
17:05:07: real 0m2.604s user 0m0.010s sys 0m0.010s
17:05:12: real 0m2.813s user 0m0.010s sys 0m0.010s
17:05:17: real 0m2.325s user 0m0.020s sys 0m0.000s
17:05:21: real 0m2.577s user 0m0.010s sys 0m0.000s
17:05:26: real 0m2.882s user 0m0.030s sys 0m0.000s
17:05:31: real 0m2.572s user 0m0.000s sys 0m0.020s
17:05:35: real 0m2.678s user 0m0.010s sys 0m0.010s
17:05:40: real 0m2.656s user 0m0.010s sys 0m0.010s
17:05:45: real 0m2.921s user 0m0.020s sys 0m0.000s
17:05:49: real 0m2.723s user 0m0.000s sys 0m0.020s
17:05:54: real 0m2.910s user 0m0.010s sys 0m0.010s
17:05:59: real 0m2.601s user 0m0.020s sys 0m0.000s
17:05:04: real 0m2.615s user 0m0.000s sys 0m0.000s
```

After:
```
Getting times for chassis
Getting good line count with wget -q -O- localhost:80/redfish/v1/Chassis?$expand=.($levels=1)
Line count: 980
16:04:43: real 0m0.188s user 0m0.020s sys 0m0.000s
16:04:43: real 0m0.195s user 0m0.010s sys 0m0.000s
16:04:45: real 0m0.219s user 0m0.010s sys 0m0.000s
16:04:48: real 0m0.226s user 0m0.020s sys 0m0.000s
16:04:50: real 0m0.208s user 0m0.020s sys 0m0.010s
16:04:52: real 0m0.226s user 0m0.010s sys 0m0.010s
16:04:54: real 0m0.419s user 0m0.000s sys 0m0.010s
16:04:57: real 0m0.222s user 0m0.010s sys 0m0.020s
16:04:59: real 0m0.194s user 0m0.000s sys 0m0.010s
16:04:01: real 0m0.191s user 0m0.010s sys 0m0.010s
16:04:04: real 0m0.276s user 0m0.010s sys 0m0.020s
16:04:06: real 0m0.183s user 0m0.020s sys 0m0.000s
16:04:08: real 0m0.193s user 0m0.040s sys 0m0.000s
16:04:10: real 0m0.406s user 0m0.020s sys 0m0.010s
16:04:13: real 0m0.317s user 0m0.000s sys 0m0.000s
16:04:15: real 0m0.442s user 0m0.005s sys 0m0.005s
16:04:18: real 0m0.226s user 0m0.010s sys 0m0.000s
16:04:20: real 0m0.217s user 0m0.020s sys 0m0.000s
16:04:22: real 0m0.200s user 0m0.010s sys 0m0.030s
16:04:24: real 0m0.423s user 0m0.010s sys 0m0.010s
16:04:27: real 0m0.203s user 0m0.020s sys 0m0.010s
16:04:29: real 0m0.433s user 0m0.000s sys 0m0.000s
16:04:31: real 0m0.318s user 0m0.020s sys 0m0.000s
16:04:34: real 0m1.206s user 0m0.000s sys 0m0.010s
16:04:37: real 0m0.403s user 0m0.000s sys 0m0.020s
16:04:39: real 0m0.353s user 0m0.010s sys 0m0.000s
16:04:42: real 0m0.291s user 0m0.000s sys 0m0.030s
16:04:44: real 0m0.742s user 0m0.020s sys 0m0.010s
16:04:47: real 0m0.369s user 0m0.010s sys 0m0.000s
16:04:49: real 0m0.215s user 0m0.020s sys 0m0.000s
16:04:52: real 0m0.204s user 0m0.000s sys 0m0.010s
16:04:54: real 0m0.418s user 0m0.000s sys 0m0.000s
16:04:56: real 0m0.215s user 0m0.000s sys 0m0.010s
16:04:58: real 0m0.202s user 0m0.010s sys 0m0.010s
16:04:01: real 0m0.202s user 0m0.010s sys 0m0.010s
16:04:03: real 0m0.212s user 0m0.010s sys 0m0.000s
16:04:05: real 0m0.694s user 0m0.010s sys 0m0.010s
16:04:08: real 0m0.201s user 0m0.010s sys 0m0.010s
16:04:10: real 0m0.230s user 0m0.000s sys 0m0.020s
16:04:12: real 0m0.206s user 0m0.010s sys 0m0.010s
16:04:15: real 0m0.446s user 0m0.010s sys 0m0.010s
```

Change-Id: I90b242e2cd24973420de871fedf9793dd1e310f3
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/config/bmcweb_config.h.in b/config/bmcweb_config.h.in
index ae98675..1290bd6 100644
--- a/config/bmcweb_config.h.in
+++ b/config/bmcweb_config.h.in
@@ -16,4 +16,7 @@
 constexpr const bool bmcwebInsecureEnableHttpPushStyleEventing = @BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING@ == 1;
 
 constexpr const char* bmcwebLoggingLevel = "@BMCWEB_LOGGING_LEVEL@";
+
+constexpr const bool bmcwebEnableHealthPopulate = @BMCWEB_ENABLE_HEALTH_POPULATE@ == 1;
+
 // clang-format on
diff --git a/config/meson.build b/config/meson.build
index b13a023..bd8aada 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -12,6 +12,9 @@
 conf_data.set10('BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING', insecure_push_style_notification.enabled())
 conf_data.set('MESON_INSTALL_PREFIX', get_option('prefix'))
 conf_data.set('HTTPS_PORT', get_option('https_port'))
+conf_data.set('HTTPS_PORT', get_option('https_port'))
+enable_health_populate = get_option('health-populate')
+conf_data.set10('BMCWEB_ENABLE_HEALTH_POPULATE', enable_health_populate.enabled())
 
 # Logging level
 loglvlopt = get_option('bmcweb-logging')
diff --git a/meson_options.txt b/meson_options.txt
index 3c2d3f7..3f37f9e 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -325,3 +325,11 @@
                     enable on production systems at this time.  Other query
                     parameters such as only are not controlled by this option.'''
 )
+
+option(
+    'health-populate',
+    type: 'feature',
+    value: 'enabled',
+    description: '''Enables HealthPopulate and generate the Status property for
+                    the resource'''
+)
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index a274421..32eb29b 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_utility.hpp"
 #include "health.hpp"
@@ -252,18 +254,21 @@
 
             auto health = std::make_shared<HealthPopulate>(asyncResp);
 
-            dbus::utility::getAssociationEndPoints(
-                path + "/all_sensors",
-                [health](const boost::system::error_code& ec2,
-                         const dbus::utility::MapperEndPoints& resp) {
-                if (ec2)
-                {
-                    return; // no sensors = no failures
-                }
-                health->inventory = resp;
-                });
+            if constexpr (bmcwebEnableHealthPopulate)
+            {
+                dbus::utility::getAssociationEndPoints(
+                    path + "/all_sensors",
+                    [health](const boost::system::error_code& ec2,
+                             const dbus::utility::MapperEndPoints& resp) {
+                    if (ec2)
+                    {
+                        return; // no sensors = no failures
+                    }
+                    health->inventory = resp;
+                    });
 
-            health->populate();
+                health->populate();
+            }
 
             if (connectionNames.empty())
             {
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 330e68e..5330be1 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_singleton.hpp"
 #include "dbus_utility.hpp"
@@ -1559,30 +1561,31 @@
                        const std::vector<IPv4AddressData>& ipv4Data,
                        const std::vector<IPv6AddressData>& ipv6Data)
 {
-    constexpr std::array<std::string_view, 1> inventoryForEthernet = {
-        "xyz.openbmc_project.Inventory.Item.Ethernet"};
-
     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
     jsonResponse["Id"] = ifaceId;
     jsonResponse["@odata.id"] = boost::urls::format(
         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
 
-    auto health = std::make_shared<HealthPopulate>(asyncResp);
+    if constexpr (bmcwebEnableHealthPopulate)
+    {
+        constexpr std::array<std::string_view, 1> inventoryForEthernet = {
+            "xyz.openbmc_project.Inventory.Item.Ethernet"};
+        auto health = std::make_shared<HealthPopulate>(asyncResp);
+        dbus::utility::getSubTreePaths(
+            "/", 0, inventoryForEthernet,
+            [health](const boost::system::error_code& ec,
+                     const dbus::utility::MapperGetSubTreePathsResponse& resp) {
+            if (ec)
+            {
+                return;
+            }
 
-    dbus::utility::getSubTreePaths(
-        "/", 0, inventoryForEthernet,
-        [health](const boost::system::error_code& ec,
-                 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
-        if (ec)
-        {
-            return;
-        }
+            health->inventory = resp;
+            });
 
-        health->inventory = resp;
-        });
-
-    health->populate();
+        health->populate();
+    }
 
     if (ethData.nicEnabled)
     {
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index b08ee51..827cfdb 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_utility.hpp"
 #include "health.hpp"
@@ -2015,9 +2017,12 @@
         asyncResp->res.jsonValue["Links"]["ManagerForServers"] =
             std::move(managerForServers);
 
-        auto health = std::make_shared<HealthPopulate>(asyncResp);
-        health->isManagersHealth = true;
-        health->populate();
+        if constexpr (bmcwebEnableHealthPopulate)
+        {
+            auto health = std::make_shared<HealthPopulate>(asyncResp);
+            health->isManagersHealth = true;
+            health->populate();
+        }
 
         sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
                                              "FirmwareVersion", true);
diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp
index 46b35d5..1f554cc 100644
--- a/redfish-core/lib/memory.hpp
+++ b/redfish-core/lib/memory.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_utility.hpp"
 #include "health.hpp"
@@ -601,9 +603,12 @@
                                  const std::string& service,
                                  const std::string& objPath)
 {
-    auto health = std::make_shared<HealthPopulate>(aResp);
-    health->selfPath = objPath;
-    health->populate();
+    if constexpr (bmcwebEnableHealthPopulate)
+    {
+        auto health = std::make_shared<HealthPopulate>(aResp);
+        health->selfPath = objPath;
+        health->populate();
+    }
 
     BMCWEB_LOG_DEBUG << "Get available system components.";
     sdbusplus::asio::getAllProperties(
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index a77bb91..5ec6b5c 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_utility.hpp"
 #include "generated/enums/drive.hpp"
@@ -92,8 +94,11 @@
         auto& count = asyncResp->res.jsonValue["Drives@odata.count"];
         count = 0;
 
-        health->inventory.insert(health->inventory.end(), driveList.begin(),
-                                 driveList.end());
+        if constexpr (bmcwebEnableHealthPopulate)
+        {
+            health->inventory.insert(health->inventory.end(), driveList.begin(),
+                                     driveList.end());
+        }
 
         for (const std::string& drive : driveList)
         {
@@ -240,21 +245,24 @@
                 });
         }
 
-        // this is done after we know the json array will no longer
-        // be resized, as json::array uses vector underneath and we
-        // need references to its members that won't change
-        size_t count = 0;
-        // Pointer based on |asyncResp->res.jsonValue|
-        nlohmann::json::json_pointer rootPtr =
-            "/StorageControllers"_json_pointer;
-        for (const auto& [path, interfaceDict] : subtree)
+        if constexpr (bmcwebEnableHealthPopulate)
         {
-            auto subHealth = std::make_shared<HealthPopulate>(
-                asyncResp, rootPtr / count / "Status");
-            subHealth->inventory.emplace_back(path);
-            health->inventory.emplace_back(path);
-            health->children.emplace_back(subHealth);
-            count++;
+            // this is done after we know the json array will no longer
+            // be resized, as json::array uses vector underneath and we
+            // need references to its members that won't change
+            size_t count = 0;
+            // Pointer based on |asyncResp->res.jsonValue|
+            nlohmann::json::json_pointer rootPtr =
+                "/StorageControllers"_json_pointer;
+            for (const auto& [path, interfaceDict] : subtree)
+            {
+                auto subHealth = std::make_shared<HealthPopulate>(
+                    asyncResp, rootPtr / count / "Status");
+                subHealth->inventory.emplace_back(path);
+                health->inventory.emplace_back(path);
+                health->children.emplace_back(subHealth);
+                count++;
+            }
         }
         });
 }
@@ -278,7 +286,10 @@
         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
 
         auto health = std::make_shared<HealthPopulate>(asyncResp);
-        health->populate();
+        if constexpr (bmcwebEnableHealthPopulate)
+        {
+            health->populate();
+        }
 
         getDrives(asyncResp, health);
         getStorageControllers(asyncResp, health);
@@ -703,9 +714,12 @@
             // default it to Enabled
             asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
 
-            auto health = std::make_shared<HealthPopulate>(asyncResp);
-            health->inventory.emplace_back(path);
-            health->populate();
+            if constexpr (bmcwebEnableHealthPopulate)
+            {
+                auto health = std::make_shared<HealthPopulate>(asyncResp);
+                health->inventory.emplace_back(path);
+                health->populate();
+            }
 
             addAllDriveInfo(asyncResp, connectionNames[0].first, path,
                             connectionNames[0].second);
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 4a60748..8d978f1 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "bmcweb_config.h"
+
 #include "app.hpp"
 #include "dbus_singleton.hpp"
 #include "dbus_utility.hpp"
@@ -380,8 +382,11 @@
             auto cpuHealth = std::make_shared<HealthPopulate>(
                 aResp, "/ProcessorSummary/Status"_json_pointer);
 
-            systemHealth->children.emplace_back(memoryHealth);
-            systemHealth->children.emplace_back(cpuHealth);
+            if constexpr (bmcwebEnableHealthPopulate)
+            {
+                systemHealth->children.emplace_back(memoryHealth);
+                systemHealth->children.emplace_back(cpuHealth);
+            }
 
             // This is not system, so check if it's cpu, dimm, UUID or
             // BiosVer
@@ -3107,27 +3112,30 @@
             nlohmann::json::array_t({"KVMIP"});
 
 #endif // BMCWEB_ENABLE_KVM
-        constexpr std::array<std::string_view, 4> inventoryForSystems{
-            "xyz.openbmc_project.Inventory.Item.Dimm",
-            "xyz.openbmc_project.Inventory.Item.Cpu",
-            "xyz.openbmc_project.Inventory.Item.Drive",
-            "xyz.openbmc_project.Inventory.Item.StorageController"};
 
         auto health = std::make_shared<HealthPopulate>(asyncResp);
-        dbus::utility::getSubTreePaths(
-            "/", 0, inventoryForSystems,
-            [health](const boost::system::error_code& ec,
-                     const std::vector<std::string>& resp) {
-            if (ec)
-            {
-                // no inventory
-                return;
-            }
+        if constexpr (bmcwebEnableHealthPopulate)
+        {
+            constexpr std::array<std::string_view, 4> inventoryForSystems{
+                "xyz.openbmc_project.Inventory.Item.Dimm",
+                "xyz.openbmc_project.Inventory.Item.Cpu",
+                "xyz.openbmc_project.Inventory.Item.Drive",
+                "xyz.openbmc_project.Inventory.Item.StorageController"};
 
-            health->inventory = resp;
-            });
+            dbus::utility::getSubTreePaths(
+                "/", 0, inventoryForSystems,
+                [health](const boost::system::error_code& ec,
+                         const std::vector<std::string>& resp) {
+                if (ec)
+                {
+                    // no inventory
+                    return;
+                }
 
-        health->populate();
+                health->inventory = resp;
+                });
+            health->populate();
+        }
 
         getMainChassisId(asyncResp,
                          [](const std::string& chassisId,
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 78817ff..050b75c 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -14,6 +14,7 @@
 // limitations under the License.
 */
 #pragma once
+#include "bmcweb_config.h"
 
 #include "app.hpp"
 #include "dbus_utility.hpp"
@@ -490,8 +491,11 @@
 
         asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true;
 
-        auto health = std::make_shared<HealthPopulate>(asyncResp);
-        health->populate();
+        if constexpr (bmcwebEnableHealthPopulate)
+        {
+            auto health = std::make_shared<HealthPopulate>(asyncResp);
+            health->populate();
+        }
         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
         asyncResp->res.jsonValue["ServiceEnabled"] = true;
         asyncResp->res.jsonValue["Tasks"]["@odata.id"] =