1a51fc2d2SSui Chen #pragma once 2a51fc2d2SSui Chen 33ccb3adbSEd Tanous #include "app.hpp" 43ccb3adbSEd Tanous #include "async_resp.hpp" 53ccb3adbSEd Tanous #include "http_request.hpp" 63ccb3adbSEd Tanous #include "privileges.hpp" 73ccb3adbSEd Tanous #include "query.hpp" 83ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 93ccb3adbSEd Tanous #include "routing.hpp" 103ccb3adbSEd Tanous 11*e610b316SJagpal Singh Gill #include <boost/system/error_code.hpp> 12*e610b316SJagpal Singh Gill #include <boost/system/linux_error.hpp> 13a51fc2d2SSui Chen #include <nlohmann/json.hpp> 145ace29d2SEd Tanous #include <sdbusplus/asio/property.hpp> 15a51fc2d2SSui Chen 16*e610b316SJagpal Singh Gill #include <functional> 17*e610b316SJagpal Singh Gill #include <limits> 18*e610b316SJagpal Singh Gill #include <memory> 19a51fc2d2SSui Chen #include <string> 20a51fc2d2SSui Chen 21a51fc2d2SSui Chen namespace redfish 22a51fc2d2SSui Chen { 23a51fc2d2SSui Chen 24*e610b316SJagpal Singh Gill static constexpr auto healthMonitorServiceName = 25*e610b316SJagpal Singh Gill "xyz.openbmc_project.HealthMon"; 26*e610b316SJagpal Singh Gill static constexpr auto valueInterface = "xyz.openbmc_project.Metric.Value"; 27*e610b316SJagpal Singh Gill static constexpr auto valueProperty = "Value"; 28*e610b316SJagpal Singh Gill 29*e610b316SJagpal Singh Gill inline bool checkErrors( 30*e610b316SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 31*e610b316SJagpal Singh Gill const boost::system::error_code& ec, 32*e610b316SJagpal Singh Gill const std::source_location src = std::source_location::current()) 33*e610b316SJagpal Singh Gill { 34*e610b316SJagpal Singh Gill if (ec.value() == boost::asio::error::basic_errors::host_unreachable) 35*e610b316SJagpal Singh Gill { 36*e610b316SJagpal Singh Gill BMCWEB_LOG_WARNING("Failed to find server, Dbus error {}", ec); 37*e610b316SJagpal Singh Gill return true; 38*e610b316SJagpal Singh Gill } 39*e610b316SJagpal Singh Gill if (ec.value() == boost::system::linux_error::bad_request_descriptor) 40*e610b316SJagpal Singh Gill { 41*e610b316SJagpal Singh Gill BMCWEB_LOG_WARNING("Invalid Path, Dbus error {}", ec); 42*e610b316SJagpal Singh Gill return true; 43*e610b316SJagpal Singh Gill } 44*e610b316SJagpal Singh Gill if (ec) 45*e610b316SJagpal Singh Gill { 46*e610b316SJagpal Singh Gill BMCWEB_LOG_ERROR("{} failed, error {}", src.function_name(), ec); 47*e610b316SJagpal Singh Gill messages::internalError(asyncResp->res); 48*e610b316SJagpal Singh Gill return true; 49*e610b316SJagpal Singh Gill } 50*e610b316SJagpal Singh Gill return false; 51*e610b316SJagpal Singh Gill } 52*e610b316SJagpal Singh Gill 53*e610b316SJagpal Singh Gill inline void 54*e610b316SJagpal Singh Gill setBytesProperty(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 55*e610b316SJagpal Singh Gill const nlohmann::json::json_pointer& jPtr, 56*e610b316SJagpal Singh Gill const boost::system::error_code& ec, double bytes) 57*e610b316SJagpal Singh Gill { 58*e610b316SJagpal Singh Gill if (checkErrors(asyncResp, ec)) 59*e610b316SJagpal Singh Gill { 60*e610b316SJagpal Singh Gill return; 61*e610b316SJagpal Singh Gill } 62*e610b316SJagpal Singh Gill if (!std::isfinite(bytes)) 63*e610b316SJagpal Singh Gill { 64*e610b316SJagpal Singh Gill BMCWEB_LOG_WARNING("Property read for {} was not finite", 65*e610b316SJagpal Singh Gill jPtr.to_string()); 66*e610b316SJagpal Singh Gill asyncResp->res.jsonValue[jPtr] = nullptr; 67*e610b316SJagpal Singh Gill return; 68*e610b316SJagpal Singh Gill } 69*e610b316SJagpal Singh Gill // If the param is in Kib, make it Kib. Redfish uses this as a naming 70*e610b316SJagpal Singh Gill // DBus represents as bytes 71*e610b316SJagpal Singh Gill if (std::string_view(jPtr.back()).ends_with("KiB")) 72*e610b316SJagpal Singh Gill { 73*e610b316SJagpal Singh Gill bytes /= 1024.0; 74*e610b316SJagpal Singh Gill } 75*e610b316SJagpal Singh Gill 76*e610b316SJagpal Singh Gill asyncResp->res.jsonValue[jPtr] = static_cast<int64_t>(bytes); 77*e610b316SJagpal Singh Gill } 78*e610b316SJagpal Singh Gill 79*e610b316SJagpal Singh Gill inline void managerGetStorageStatistics( 80*e610b316SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 81*e610b316SJagpal Singh Gill { 82*e610b316SJagpal Singh Gill constexpr auto freeStorageObjPath = 83*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/storage/rw"; 84*e610b316SJagpal Singh Gill 85*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 86*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 87*e610b316SJagpal Singh Gill freeStorageObjPath, valueInterface, valueProperty, 88*e610b316SJagpal Singh Gill std::bind_front(setBytesProperty, asyncResp, 89*e610b316SJagpal Singh Gill nlohmann::json::json_pointer("/FreeStorageSpaceKiB"))); 90*e610b316SJagpal Singh Gill } 91*e610b316SJagpal Singh Gill 92*e610b316SJagpal Singh Gill inline void 93*e610b316SJagpal Singh Gill setPercentProperty(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 94*e610b316SJagpal Singh Gill const nlohmann::json::json_pointer& jPtr, 95*e610b316SJagpal Singh Gill const boost::system::error_code& ec, double userCPU) 96*e610b316SJagpal Singh Gill { 97*e610b316SJagpal Singh Gill if (checkErrors(asyncResp, ec)) 98*e610b316SJagpal Singh Gill { 99*e610b316SJagpal Singh Gill return; 100*e610b316SJagpal Singh Gill } 101*e610b316SJagpal Singh Gill if (!std::isfinite(userCPU)) 102*e610b316SJagpal Singh Gill { 103*e610b316SJagpal Singh Gill asyncResp->res.jsonValue[jPtr] = nullptr; 104*e610b316SJagpal Singh Gill return; 105*e610b316SJagpal Singh Gill } 106*e610b316SJagpal Singh Gill 107*e610b316SJagpal Singh Gill static constexpr double roundFactor = 10000; // 4 decimal places 108*e610b316SJagpal Singh Gill asyncResp->res.jsonValue[jPtr] = std::round(userCPU * roundFactor) / 109*e610b316SJagpal Singh Gill roundFactor; 110*e610b316SJagpal Singh Gill } 111*e610b316SJagpal Singh Gill 112*e610b316SJagpal Singh Gill inline void managerGetProcessorStatistics( 113*e610b316SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 114*e610b316SJagpal Singh Gill { 115*e610b316SJagpal Singh Gill constexpr auto kernelCPUObjPath = 116*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/cpu/kernel"; 117*e610b316SJagpal Singh Gill constexpr auto userCPUObjPath = "/xyz/openbmc_project/metric/bmc/cpu/user"; 118*e610b316SJagpal Singh Gill 119*e610b316SJagpal Singh Gill using json_pointer = nlohmann::json::json_pointer; 120*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 121*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 122*e610b316SJagpal Singh Gill kernelCPUObjPath, valueInterface, valueProperty, 123*e610b316SJagpal Singh Gill std::bind_front(setPercentProperty, asyncResp, 124*e610b316SJagpal Singh Gill json_pointer("/ProcessorStatistics/KernelPercent"))); 125*e610b316SJagpal Singh Gill 126*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 127*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, userCPUObjPath, 128*e610b316SJagpal Singh Gill valueInterface, valueProperty, 129*e610b316SJagpal Singh Gill std::bind_front(setPercentProperty, asyncResp, 130*e610b316SJagpal Singh Gill json_pointer("/ProcessorStatistics/UserPercent"))); 131*e610b316SJagpal Singh Gill } 132*e610b316SJagpal Singh Gill 133*e610b316SJagpal Singh Gill inline void managerGetMemoryStatistics( 134*e610b316SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 135*e610b316SJagpal Singh Gill { 136*e610b316SJagpal Singh Gill using json_pointer = nlohmann::json::json_pointer; 137*e610b316SJagpal Singh Gill constexpr auto availableMemoryObjPath = 138*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/memory/available"; 139*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 140*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 141*e610b316SJagpal Singh Gill availableMemoryObjPath, valueInterface, valueProperty, 142*e610b316SJagpal Singh Gill std::bind_front(setBytesProperty, asyncResp, 143*e610b316SJagpal Singh Gill json_pointer("/MemoryStatistics/AvailableBytes"))); 144*e610b316SJagpal Singh Gill 145*e610b316SJagpal Singh Gill constexpr auto bufferedAndCachedMemoryObjPath = 146*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/memory/buffered_and_cached"; 147*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 148*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 149*e610b316SJagpal Singh Gill bufferedAndCachedMemoryObjPath, valueInterface, valueProperty, 150*e610b316SJagpal Singh Gill std::bind_front( 151*e610b316SJagpal Singh Gill setBytesProperty, asyncResp, 152*e610b316SJagpal Singh Gill json_pointer("/MemoryStatistics/BuffersAndCacheBytes"))); 153*e610b316SJagpal Singh Gill 154*e610b316SJagpal Singh Gill constexpr auto freeMemoryObjPath = 155*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/memory/free"; 156*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 157*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 158*e610b316SJagpal Singh Gill freeMemoryObjPath, valueInterface, valueProperty, 159*e610b316SJagpal Singh Gill std::bind_front(setBytesProperty, asyncResp, 160*e610b316SJagpal Singh Gill json_pointer("/MemoryStatistics/FreeBytes"))); 161*e610b316SJagpal Singh Gill 162*e610b316SJagpal Singh Gill constexpr auto sharedMemoryObjPath = 163*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/memory/shared"; 164*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 165*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 166*e610b316SJagpal Singh Gill sharedMemoryObjPath, valueInterface, valueProperty, 167*e610b316SJagpal Singh Gill std::bind_front(setBytesProperty, asyncResp, 168*e610b316SJagpal Singh Gill json_pointer("/MemoryStatistics/SharedBytes"))); 169*e610b316SJagpal Singh Gill 170*e610b316SJagpal Singh Gill constexpr auto totalMemoryObjPath = 171*e610b316SJagpal Singh Gill "/xyz/openbmc_project/metric/bmc/memory/total"; 172*e610b316SJagpal Singh Gill sdbusplus::asio::getProperty<double>( 173*e610b316SJagpal Singh Gill *crow::connections::systemBus, healthMonitorServiceName, 174*e610b316SJagpal Singh Gill totalMemoryObjPath, valueInterface, valueProperty, 175*e610b316SJagpal Singh Gill std::bind_front(setBytesProperty, asyncResp, 176*e610b316SJagpal Singh Gill json_pointer("/MemoryStatistics/TotalBytes"))); 177*e610b316SJagpal Singh Gill } 178*e610b316SJagpal Singh Gill 179ac106bf6SEd Tanous inline void afterGetManagerStartTime( 180ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 181ac106bf6SEd Tanous const boost::system::error_code& ec, uint64_t bmcwebResetTime) 1825ace29d2SEd Tanous { 1835ace29d2SEd Tanous if (ec) 1845ace29d2SEd Tanous { 1855ace29d2SEd Tanous // Not all servers will be running in systemd, so ignore the error. 1865ace29d2SEd Tanous return; 1875ace29d2SEd Tanous } 1885ace29d2SEd Tanous using std::chrono::steady_clock; 1895ace29d2SEd Tanous 1905ace29d2SEd Tanous std::chrono::duration<steady_clock::rep, std::micro> usReset{ 1915ace29d2SEd Tanous bmcwebResetTime}; 1925ace29d2SEd Tanous steady_clock::time_point resetTime{usReset}; 1935ace29d2SEd Tanous 1945ace29d2SEd Tanous steady_clock::time_point now = steady_clock::now(); 1955ace29d2SEd Tanous 1965ace29d2SEd Tanous steady_clock::duration runTime = now - resetTime; 1975ace29d2SEd Tanous 1985ace29d2SEd Tanous if (runTime < steady_clock::duration::zero()) 1995ace29d2SEd Tanous { 20062598e31SEd Tanous BMCWEB_LOG_CRITICAL("Uptime was negative????"); 201ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2025ace29d2SEd Tanous return; 2035ace29d2SEd Tanous } 2045ace29d2SEd Tanous 2055ace29d2SEd Tanous // Floor to the closest millisecond 2065ace29d2SEd Tanous using Milli = std::chrono::duration<steady_clock::rep, std::milli>; 2075ace29d2SEd Tanous Milli milli = std::chrono::floor<Milli>(runTime); 2085ace29d2SEd Tanous 2095ace29d2SEd Tanous using SecondsFloat = std::chrono::duration<double>; 2105ace29d2SEd Tanous SecondsFloat sec = std::chrono::duration_cast<SecondsFloat>(milli); 2115ace29d2SEd Tanous 212ac106bf6SEd Tanous asyncResp->res.jsonValue["ServiceRootUptimeSeconds"] = sec.count(); 2135ace29d2SEd Tanous } 2145ace29d2SEd Tanous 215ac106bf6SEd Tanous inline void managerGetServiceRootUptime( 216ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 2175ace29d2SEd Tanous { 2185ace29d2SEd Tanous sdbusplus::asio::getProperty<uint64_t>( 2195ace29d2SEd Tanous *crow::connections::systemBus, "org.freedesktop.systemd1", 2205ace29d2SEd Tanous "/org/freedesktop/systemd1/unit/bmcweb_2eservice", 2215ace29d2SEd Tanous "org.freedesktop.systemd1.Unit", "ActiveEnterTimestampMonotonic", 222ac106bf6SEd Tanous std::bind_front(afterGetManagerStartTime, asyncResp)); 2235ace29d2SEd Tanous } 224a51fc2d2SSui Chen /** 225a51fc2d2SSui Chen * handleManagerDiagnosticData supports ManagerDiagnosticData. 226a51fc2d2SSui Chen * It retrieves BMC health information from various DBus resources and returns 227a51fc2d2SSui Chen * the information through the response. 228a51fc2d2SSui Chen */ 229a51fc2d2SSui Chen inline void handleManagerDiagnosticDataGet( 230a51fc2d2SSui Chen crow::App& app, const crow::Request& req, 231a51fc2d2SSui Chen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 232a51fc2d2SSui Chen { 233a51fc2d2SSui Chen if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 234a51fc2d2SSui Chen { 235a51fc2d2SSui Chen return; 236a51fc2d2SSui Chen } 237a51fc2d2SSui Chen asyncResp->res.jsonValue["@odata.type"] = 2385ace29d2SEd Tanous "#ManagerDiagnosticData.v1_2_0.ManagerDiagnosticData"; 239a51fc2d2SSui Chen asyncResp->res.jsonValue["@odata.id"] = 240a51fc2d2SSui Chen "/redfish/v1/Managers/bmc/ManagerDiagnosticData"; 241a51fc2d2SSui Chen asyncResp->res.jsonValue["Id"] = "ManagerDiagnosticData"; 242a51fc2d2SSui Chen asyncResp->res.jsonValue["Name"] = "Manager Diagnostic Data"; 2435ace29d2SEd Tanous 2445ace29d2SEd Tanous managerGetServiceRootUptime(asyncResp); 245*e610b316SJagpal Singh Gill managerGetProcessorStatistics(asyncResp); 246*e610b316SJagpal Singh Gill managerGetMemoryStatistics(asyncResp); 247*e610b316SJagpal Singh Gill managerGetStorageStatistics(asyncResp); 248a51fc2d2SSui Chen } 249a51fc2d2SSui Chen 250a51fc2d2SSui Chen inline void requestRoutesManagerDiagnosticData(App& app) 251a51fc2d2SSui Chen { 252a51fc2d2SSui Chen BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/ManagerDiagnosticData") 253a51fc2d2SSui Chen .privileges(redfish::privileges::getManagerDiagnosticData) 254a51fc2d2SSui Chen .methods(boost::beast::http::verb::get)( 255a51fc2d2SSui Chen std::bind_front(handleManagerDiagnosticDataGet, std::ref(app))); 256a51fc2d2SSui Chen } 257a51fc2d2SSui Chen 258a51fc2d2SSui Chen } // namespace redfish 259